03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore/*
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunndi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi_impldefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/obpdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysmacros.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/autoconf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/serengeti.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ssm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_mailbox.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgevents.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysevent.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysevent/dr.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysevent/eventdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ndi_impldefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddifm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ndifm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sbd_ioctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Useful debugging Stuff */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/nexusdebug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * module ssm.c
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This module is a nexus driver designed to support the ssm nexus driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and all children below it. This driver does not handle any of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI functions passed up to it by the ssm driver, but instead allows
03831d35f7499c87d51205817c93e9a8d42c4baestevel * them to bubble up to the root node.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function prototypes
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int plat_max_boards();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_open(dev_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_close(dev_t, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_make_nodes(dev_info_t *dip, int instance, int ssm_nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_generate_event(int node, int board, int hint);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FMA error callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register error handling callback with our parent. We will just call
03831d35f7499c87d51205817c93e9a8d42c4baestevel * our children's error callbacks and return their status.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_err_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fm_init busop to initialize our children
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_iblock_cookie_t *ibc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * init/fini routines to alloc/dealloc fm structures and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register/unregister our callback.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_fm_init(struct ssm_soft_state *softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_fm_fini(struct ssm_soft_state *softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DR event handlers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We want to register the event handlers once for all instances. In the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * other hand we have register them after the sbbc has been attached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event_initialize gives us the logic of only registering the events only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * once
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint event_initialized = 0;
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t ssm_dr_event_handler(char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Event lock and state
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t ssm_event_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint ssm_event_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DR event msg and payload
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbbc_msg_t event_msg;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sg_system_fru_descriptor_t payload;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct ssm_node2inst {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int nodeid; /* serengeti node #, NOT prom nodeid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int inst;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_node2inst *next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t ssm_node2inst_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct ssm_node2inst ssm_node2inst_map = {-1, -1, NULL};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Configuration data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct bus_ops ssm_bus_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel BUSO_REV,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_bus_map, /* map */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* get_intrspec */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* add_intrspec */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* remove_intrspec */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i_ddi_map_fault, /* map_fault */
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore 0, /* dma_map */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_allochdl,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_freehdl,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_bindhdl,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_unbindhdl,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_flush,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_win,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_dma_mctl, /* dma_ctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_ctlops, /* ctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_bus_prop_op, /* prop_op */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_busop_get_eventcookie,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_busop_add_eventcall,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_busop_remove_eventcall,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_post_event,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_fm_init_child,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel i_ddi_intr_ops
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct cb_ops ssm_cb_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_open, /* open */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_close, /* close */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* strategy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* print */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* dump */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* read */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* write */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_ioctl, /* ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* devmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* mmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* segmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nochpoll, /* poll */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_prop_op, /* cb_prop_op */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* streamtab */
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CB_REV, /* rev */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* int (*cb_aread)() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev /* int (*cb_awrite)() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct dev_ops ssm_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVO_REV, /* devo_rev, */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* refcnt */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_info, /* getinfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* identify */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* probe */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_attach, /* attach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_detach, /* detach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* reset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &ssm_cb_ops, /* driver operations */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &ssm_bus_ops, /* bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore nulldev, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver globals
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void *ssm_softstates; /* ssm soft state hook */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct mod_ops mod_driverops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modldrv modldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* Type of module. This one is a driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "SSM Nexus", /* name of module */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &ssm_ops, /* driver ops */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1, /* rev */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&modldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int ssm_loaded_sbd = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t ssm_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int init_child(dev_info_t *child);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are the module initialization routines.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel debug_print_level = 0x0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Initialize soft state pointer. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = ddi_soft_state_init(&ssm_softstates,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE sizeof (struct ssm_soft_state), SSM_MAX_INSTANCES)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Install the module. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mod_install(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&ssm_softstates);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&ssm_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Remove the module. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_remove(&modlinkage)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unregister the event handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sbbc_mbox_unreg_intr(MBOX_EVENT_GENERIC, ssm_dr_event_handler);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&ssm_event_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Free the soft state info. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&ssm_softstates);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&ssm_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&modlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* device driver entry points */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * info entry point:
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_t dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (infocmd == DDI_INFO_DEVT2INSTANCE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev = (dev_t)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = (getminor(dev) >> SSM_INSTANCE_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)(uintptr_t)instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * attach entry point:
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_soft_state *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_node2inst *prev, *sp, *tsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_ATTACH_DEBUG, ("ssm_attach\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_ATTACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_RESUME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_soft_state_zalloc(ssm_softstates, instance) != DDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp = ddi_get_soft_state(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Set the dip in the soft state */
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->dip = devi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->top_node = devi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&softsp->ssm_sft_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_ATTACH_DEBUG, ("ssm-%d: devi= 0x%p, softsp=0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki instance, (void *)devi, (void *)softsp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softsp->ssm_nodeid = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "nodeid", -1)) == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "ssm%d: unable to retrieve %s property",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, "nodeid");
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* nothing to suspend/resume here */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "pm-hardware-state", (caddr_t)"no-suspend-resume",
03831d35f7499c87d51205817c93e9a8d42c4baestevel strlen("no-suspend-resume") + 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(devi, "debug", S_IFCHR, instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ssm_make_nodes(devi, instance, softsp->ssm_nodeid)) {
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE cmn_err(CE_WARN, "ssm:%s:%d: failed to make nodes",
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE ddi_driver_name(devi), instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(devi, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_fm_init(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_report_dev(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (event_initialized == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register DR event handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&ssm_event_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_msg.msg_buf = (caddr_t)&payload;
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_msg.msg_len = sizeof (payload);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = sbbc_mbox_reg_intr(MBOX_EVENT_GENERIC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_dr_event_handler, &event_msg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint_t *)&ssm_event_state, &ssm_event_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == EINVAL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_initialized = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Preallocate to avoid sleeping with ssm_node2inst_lock held -
03831d35f7499c87d51205817c93e9a8d42c4baestevel * low level interrupts use this mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tsp = kmem_zalloc(sizeof (struct ssm_node2inst), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (prev = NULL, sp = &ssm_node2inst_map; sp != NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev = sp, sp = sp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sp->inst != instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sp->nodeid != softsp->ssm_nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp->inst == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(prev->next == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp = prev->next = tsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tsp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->inst = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->nodeid = softsp->ssm_nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tsp != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(tsp, sizeof (struct ssm_node2inst));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * detach entry point:
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance, rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*sbd_teardown_instance) (int, caddr_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_sbdp_info_t sbdp_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_soft_state *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_node2inst *prev, *sp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp = ddi_get_soft_state(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE "ssm_open bad instance number %d", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_DETACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(devi, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_teardown_instance = (int (*) (int, caddr_t))
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE modlookup("misc/sbd", "sbd_teardown_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!sbd_teardown_instance) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot find sbd_teardown_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_info.instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_info.wnode = softsp->ssm_nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*sbd_teardown_instance)(instance, (caddr_t)&sbdp_info);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot run sbd_teardown_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_fm_fini(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&softsp->ssm_sft_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (prev = NULL, sp = &ssm_node2inst_map; sp != NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev = sp, sp = sp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Only the head of the list can persist if unused */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(prev == NULL || sp->inst != -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp->inst == instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp != &ssm_node2inst_map) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev->next = sp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(sp, sizeof (struct ssm_node2inst));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Invalidate the head element, but retain the rest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of the list - "next" is still valid.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->nodeid = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->inst = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_SUSPEND:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern void make_ddi_ppd(dev_info_t *, struct ddi_parent_private_data **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct ddi_parent_private_data *init_regspec_64(dev_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelname_child(dev_info_t *child, char *name, int namelen)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct regspec *rp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ddi_parent_private_data *pdptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int regbase = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel extern uint_t root_phys_addr_lo_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel make_ddi_ppd(child, &pdptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_parent_data(child, pdptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel name[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sparc_pd_getnreg(child) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = sparc_pd_getreg(child, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid = ddi_prop_get_int(DDI_DEV_T_ANY, child,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "portid", -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "could not find portid property in %s",
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVI(child)->devi_node_name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel regbase = rp->regspec_addr & root_phys_addr_lo_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) snprintf(name, namelen, "%x,%x", portid, regbase);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelinit_child(dev_info_t *child)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) name_child(child, name, MAXNAMELEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_name_addr(child, name);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ndi_dev_is_persistent_node(child) == 0) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (ndi_merge_node(child, name_child) == DDI_SUCCESS)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl_ddi_sunbus_removechild(child);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) init_regspec_64(child);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Control ops entry point:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Requests handled completely:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI_CTLOPS_INITCHILD
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI_CTLOPS_UNINITCHILD
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI_CTLOPS_REPORTDEV
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All others are passed to the parent.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The name of the ssm node is ssm@nodeid,0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ssm is the equivalent of rootnex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_CTLOPS_INITCHILD: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_CTLOPS_DEBUG, ("DDI_CTLOPS_INITCHILD\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (init_child((dev_info_t *)arg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_CTLOPS_UNINITCHILD: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_CTLOPS_DEBUG, ("DDI_CTLOPS_UNINITCHILD\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel impl_ddi_sunbus_removechild((dev_info_t *)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_CTLOPS_REPORTDEV: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[80];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *p = buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *parent;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_CTLOPS_DEBUG, ("DDI_CTLOPS_REPORTDEV\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel parent = ddi_get_parent(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(p, "%s%d at %s%d", DEVI(rdip)->devi_name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVI(rdip)->devi_instance, ddi_get_name(parent),
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_get_instance(parent));
03831d35f7499c87d51205817c93e9a8d42c4baestevel p += strlen(p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Fetch Safari Extended Agent ID of this device. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid = (int)ddi_getprop(DDI_DEV_T_ANY, rdip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "portid", -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is one of the ssm children it will have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * portid property and its parent will be ssm.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In this case report Node number and Safari id.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (portid != -1 &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel strcmp("ssm", ddi_get_name(parent)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct regspec *rp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int node;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int safid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int n;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = sparc_pd_getreg(rdip, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel n = sparc_pd_getnreg(rdip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(n > 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel node = SG_PORTID_TO_NODEID(portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel safid = SG_PORTID_TO_SAFARI_ID(portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) strcpy(p, ": ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel p += strlen(p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(p, "Node %d Safari id %d 0x%x%s",
03831d35f7499c87d51205817c93e9a8d42c4baestevel node, safid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp->regspec_addr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (n > 1 ? "" : " ..."));
03831d35f7499c87d51205817c93e9a8d42c4baestevel p += strlen(p);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "?%s\n", buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = ddi_ctlops(dip, rdip, op, arg, result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_make_nodes(dev_info_t *dip, int instance, int ssm_nodeid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_t minor_num, bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel auto char filename[20];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (bd = 0; bd < plat_max_boards(); bd++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (SG_BOARD_IS_CPU_TYPE(bd))
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(filename, "N%d.SB%d", ssm_nodeid, bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(filename, "N%d.IB%d", ssm_nodeid, bd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_num = (instance << SSM_INSTANCE_SHIFT) | bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = ddi_create_minor_node(dip, filename, S_IFCHR,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE minor_num, DDI_NT_SBD_ATTACHMENT_POINT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE "ssm_make_nodes:%d: failed to create "
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE "minor node (%s, 0x%x)",
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE instance, filename, minor_num);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_open(dev_t *devi, int flags, int otyp, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_soft_state *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_t board, instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*sbd_setup_instance)(int, dev_info_t *, int, int, caddr_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_sbdp_info_t sbdp_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = (getminor(*devi) >> SSM_INSTANCE_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp = ddi_get_soft_state(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "ssm_open bad instance number %d", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel board = (getminor(*devi) & SSM_BOARD_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (board < 0 || board > plat_max_boards()) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&ssm_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (instance == 0 && ssm_loaded_sbd == FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (modload("misc", "sbd") == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "ssm_open: cannot load sbd");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&ssm_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_loaded_sbd = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&ssm_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softsp->ssm_sft_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp->initialized == FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp->top_node == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot find ssm top dnode");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->ssm_sft_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_setup_instance = (int (*)(int, dev_info_t *, int, int,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE caddr_t))modlookup("misc/sbd", "sbd_setup_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!sbd_setup_instance) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot find sbd_setup_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->ssm_sft_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_info.instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_info.wnode = softsp->ssm_nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*sbd_setup_instance)(instance, softsp->top_node,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE plat_max_boards(), softsp->ssm_nodeid,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE (caddr_t)&sbdp_info);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot run sbd_setup_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->ssm_sft_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->initialized = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->ssm_sft_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_close(dev_t dev, int flags, int otyp, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_soft_state *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_t board, instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = (getminor(dev) >> SSM_INSTANCE_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp = ddi_get_soft_state(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel board = (getminor(dev) & SSM_BOARD_MASK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (board < 0 || board > plat_max_boards())
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *rvalp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_soft_state *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct devctl_iocdata *dcp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance, rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*sbd_ioctl) (dev_t, int, intptr_t, int, char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = (getminor(dev) >> SSM_INSTANCE_SHIFT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp = ddi_get_soft_state(ssm_softstates, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DEVCTL_BUS_CONFIGURE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read devctl ioctl data
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel addr = ndi_dc_getaddr(dcp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DEVCTL_BUS_CONFIGURE: device id is %s\n", addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_dc_freehdl(dcp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DEVCTL_BUS_UNCONFIGURE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel addr = ndi_dc_getaddr(dcp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DEVCTL_BUS_UNCONFIGURE: device id is %s\n", addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndi_dc_freehdl(dcp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SSM_TEARDOWN_SBD: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_sbdp_info_t sbdp_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*sbd_teardown_instance) (int, caddr_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbd_teardown_instance = (int (*) (int, caddr_t))
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE modlookup("misc/sbd", "sbd_teardown_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!sbd_teardown_instance) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot find sbd_teardown_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_info.instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbdp_info.wnode = softsp->ssm_nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*sbd_teardown_instance)(instance, (caddr_t)&sbdp_info);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot run sbd_teardown_instance");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_loaded_sbd = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->initialized = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char event = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE sbd_ioctl = (int (*) (dev_t, int, intptr_t, int, char *))
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE modlookup("misc/sbd", "sbd_ioctl");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbd_ioctl)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = (*sbd_ioctl) (dev, cmd, arg, mode, &event);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cannot find sbd_ioctl");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if we need to send an event
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (event == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int hint = SE_NO_HINT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd == SBD_CMD_CONNECT ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd == SBD_CMD_CONFIGURE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = SE_HINT_INSERT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (cmd == SBD_CMD_UNCONFIGURE ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd == SBD_CMD_DISCONNECT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = SE_HINT_REMOVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot = (getminor(dev) & SSM_BOARD_MASK);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ssm_generate_event(softsp->ssm_nodeid, slot,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki hint);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_get_attch_pnt(int node, int board, char *attach_pnt)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_node2inst *sp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hold this mutex, until we are done so that ssm dip
03831d35f7499c87d51205817c93e9a8d42c4baestevel * doesn't detach.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (sp = &ssm_node2inst_map; sp != NULL; sp = sp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp->inst == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp->nodeid == node)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* We didn't find the ssm dip, return failure */
03831d35f7499c87d51205817c93e9a8d42c4baestevel attach_pnt[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we have the instance, and the board, construct the attch pnt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (SG_BOARD_IS_CPU_TYPE(board))
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(attach_pnt, "ssm%d:N%d.SB%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->inst, node, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(attach_pnt, "ssm%d:N%d.IB%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->inst, node, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&ssm_node2inst_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Generate an event to sysevent
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_generate_event(int node, int board, int hint)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_t *ev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_id_t eid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_value_t evnt_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_attr_list_t *evnt_attr_list = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char attach_pnt[MAXPATHLEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel attach_pnt[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel ssm_get_attch_pnt(node, board, attach_pnt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (attach_pnt[0] == '\0')
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ev = sysevent_alloc(EC_DR, ESC_DR_AP_STATE_CHANGE, EP_DDI,
03831d35f7499c87d51205817c93e9a8d42c4baestevel KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value_type = SE_DATA_TYPE_STRING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value.sv_string = attach_pnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = sysevent_add_attr(&evnt_attr_list, DR_AP_ID, &evnt_val, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s event",
03831d35f7499c87d51205817c93e9a8d42c4baestevel DR_AP_ID, EC_DR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free(ev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add the hint
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value_type = SE_DATA_TYPE_STRING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evnt_val.value.sv_string = SE_HINT2STR(hint);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = sysevent_add_attr(&evnt_attr_list, DR_HINT, &evnt_val, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Failed to add attr [%s] for %s event",
03831d35f7499c87d51205817c93e9a8d42c4baestevel DR_HINT, EC_DR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free_attr(evnt_attr_list);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free(ev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sysevent_attach_attributes(ev, evnt_attr_list) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Failed to attach attr list for %s event",
03831d35f7499c87d51205817c93e9a8d42c4baestevel EC_DR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free_attr(evnt_attr_list);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free(ev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = log_sysevent(ev, KM_NOSLEEP, &eid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rv != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "ssm_dr_event_handler: failed to log event");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysevent_free(ev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DR Event Handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_dr_event_handler(char *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sg_system_fru_descriptor_t *fdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int hint;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel fdp = (sg_system_fru_descriptor_t *)(((sbbc_msg_t *)arg)->msg_buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fdp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("ssm_dr_event_handler: ARG is null\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG, ("ssm_dr_event_handler called\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG, ("\tnode\t%d\n", fdp->node));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG, ("\tslot\t%d\n", fdp->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG, ("\tparent_hdl\t0x%lx\n", fdp->parent_hdl));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG, ("\tchild_hdl\t0x%lx\n", fdp->child_hdl));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(SSM_EVENT_DEBUG, ("\tevent_details\t%s\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel EVNT2STR(fdp->event_details)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (fdp->event_details) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SG_EVT_BOARD_ABSENT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = SE_HINT_REMOVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SG_EVT_BOARD_PRESENT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = SE_HINT_INSERT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel hint = SE_NO_HINT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ssm_generate_event(fdp->node, fdp->slot, hint);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize our FMA resources
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_fm_init(struct ssm_soft_state *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->ssm_fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE |
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Request or capability level and get our parents capability
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and ibc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_fm_init(softsp->dip, &softsp->ssm_fm_cap, &softsp->ssm_fm_ibc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((softsp->ssm_fm_cap & DDI_FM_EREPORT_CAPABLE) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (softsp->ssm_fm_cap & DDI_FM_ERRCB_CAPABLE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register error callback with our parent.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_fm_handler_register(softsp->dip, ssm_err_callback, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Breakdown our FMA resources
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_fm_fini(struct ssm_soft_state *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clean up allocated fm structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(softsp->ssm_fm_cap & DDI_FM_EREPORT_CAPABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_fm_handler_unregister(softsp->dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_fm_fini(softsp->dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize FMA resources for children devices. Called when
03831d35f7499c87d51205817c93e9a8d42c4baestevel * child calls ddi_fm_init().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_iblock_cookie_t *ibc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ssm_soft_state *softsp = ddi_get_soft_state(ssm_softstates,
447a706e88931283df447457121eadad3fb9ebbeVijay Balakrishna, SG-RPE ddi_get_instance(dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *ibc = softsp->ssm_fm_ibc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (softsp->ssm_fm_cap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FMA registered error callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelssm_err_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Call our children error handlers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ndi_fm_handler_dispatch(dip, NULL, derr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}