xref: /onnv-gate/usr/src/uts/i86pc/io/acpi/acpinex/acpinex_drv.c (revision 12004:93f274d4a367)
110394SMichael.Corcoran@Sun.COM /*
210394SMichael.Corcoran@Sun.COM  * CDDL HEADER START
310394SMichael.Corcoran@Sun.COM  *
410394SMichael.Corcoran@Sun.COM  * The contents of this file are subject to the terms of the
510394SMichael.Corcoran@Sun.COM  * Common Development and Distribution License (the "License").
610394SMichael.Corcoran@Sun.COM  * You may not use this file except in compliance with the License.
710394SMichael.Corcoran@Sun.COM  *
810394SMichael.Corcoran@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910394SMichael.Corcoran@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010394SMichael.Corcoran@Sun.COM  * See the License for the specific language governing permissions
1110394SMichael.Corcoran@Sun.COM  * and limitations under the License.
1210394SMichael.Corcoran@Sun.COM  *
1310394SMichael.Corcoran@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410394SMichael.Corcoran@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510394SMichael.Corcoran@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610394SMichael.Corcoran@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710394SMichael.Corcoran@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810394SMichael.Corcoran@Sun.COM  *
1910394SMichael.Corcoran@Sun.COM  * CDDL HEADER END
2010394SMichael.Corcoran@Sun.COM  */
2110394SMichael.Corcoran@Sun.COM 
2210394SMichael.Corcoran@Sun.COM /*
2310394SMichael.Corcoran@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2410394SMichael.Corcoran@Sun.COM  * Use is subject to license terms.
2510394SMichael.Corcoran@Sun.COM  */
2610394SMichael.Corcoran@Sun.COM /*
27*12004Sjiang.liu@intel.com  * Copyright (c) 2009-2010, Intel Corporation.
2810394SMichael.Corcoran@Sun.COM  * All rights reserved.
2910394SMichael.Corcoran@Sun.COM  */
3010394SMichael.Corcoran@Sun.COM /*
3110394SMichael.Corcoran@Sun.COM  * This module implements a nexus driver for the ACPI virtual bus.
3210394SMichael.Corcoran@Sun.COM  * It does not handle any of the DDI functions passed up to it by the child
3310394SMichael.Corcoran@Sun.COM  * drivers, but instead allows them to bubble up to the root node.
3410394SMichael.Corcoran@Sun.COM  */
3510394SMichael.Corcoran@Sun.COM 
3610394SMichael.Corcoran@Sun.COM #include <sys/types.h>
3710394SMichael.Corcoran@Sun.COM #include <sys/cmn_err.h>
3810394SMichael.Corcoran@Sun.COM #include <sys/conf.h>
3910394SMichael.Corcoran@Sun.COM #include <sys/modctl.h>
4010394SMichael.Corcoran@Sun.COM #include <sys/ddi.h>
4110394SMichael.Corcoran@Sun.COM #include <sys/ddi_impldefs.h>
4210394SMichael.Corcoran@Sun.COM #include <sys/ddifm.h>
43*12004Sjiang.liu@intel.com #include <sys/note.h>
4410394SMichael.Corcoran@Sun.COM #include <sys/ndifm.h>
4510394SMichael.Corcoran@Sun.COM #include <sys/sunddi.h>
4610394SMichael.Corcoran@Sun.COM #include <sys/sunndi.h>
4710394SMichael.Corcoran@Sun.COM #include <sys/acpidev.h>
4810394SMichael.Corcoran@Sun.COM #include <sys/acpinex.h>
4910394SMichael.Corcoran@Sun.COM 
5010394SMichael.Corcoran@Sun.COM /* Patchable through /etc/system. */
5110394SMichael.Corcoran@Sun.COM #ifdef	DEBUG
5210394SMichael.Corcoran@Sun.COM int acpinex_debug = 1;
5310394SMichael.Corcoran@Sun.COM #else
5410394SMichael.Corcoran@Sun.COM int acpinex_debug = 0;
5510394SMichael.Corcoran@Sun.COM #endif
5610394SMichael.Corcoran@Sun.COM 
5710394SMichael.Corcoran@Sun.COM /*
5810394SMichael.Corcoran@Sun.COM  * Driver globals
5910394SMichael.Corcoran@Sun.COM  */
6010394SMichael.Corcoran@Sun.COM static kmutex_t acpinex_lock;
6110394SMichael.Corcoran@Sun.COM static void *acpinex_softstates;
6210394SMichael.Corcoran@Sun.COM 
6310394SMichael.Corcoran@Sun.COM static int acpinex_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
6410394SMichael.Corcoran@Sun.COM static int acpinex_attach(dev_info_t *, ddi_attach_cmd_t);
6510394SMichael.Corcoran@Sun.COM static int acpinex_detach(dev_info_t *, ddi_detach_cmd_t);
6610394SMichael.Corcoran@Sun.COM static int acpinex_open(dev_t *, int, int, cred_t *);
6710394SMichael.Corcoran@Sun.COM static int acpinex_close(dev_t, int, int, cred_t *);
6810394SMichael.Corcoran@Sun.COM static int acpinex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
6910394SMichael.Corcoran@Sun.COM static int acpinex_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
7010394SMichael.Corcoran@Sun.COM     off_t offset, off_t len, caddr_t *vaddrp);
7110394SMichael.Corcoran@Sun.COM static int acpinex_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
7210394SMichael.Corcoran@Sun.COM     void *);
7310394SMichael.Corcoran@Sun.COM static int acpinex_fm_init_child(dev_info_t *, dev_info_t *, int,
7410394SMichael.Corcoran@Sun.COM     ddi_iblock_cookie_t *);
7510394SMichael.Corcoran@Sun.COM static void acpinex_fm_init(acpinex_softstate_t *softsp);
7610394SMichael.Corcoran@Sun.COM static void acpinex_fm_fini(acpinex_softstate_t *softsp);
7710394SMichael.Corcoran@Sun.COM 
7810394SMichael.Corcoran@Sun.COM extern void make_ddi_ppd(dev_info_t *, struct ddi_parent_private_data **);
7910394SMichael.Corcoran@Sun.COM 
8010394SMichael.Corcoran@Sun.COM /*
8110394SMichael.Corcoran@Sun.COM  * Configuration data structures
8210394SMichael.Corcoran@Sun.COM  */
8310394SMichael.Corcoran@Sun.COM static struct bus_ops acpinex_bus_ops = {
8410394SMichael.Corcoran@Sun.COM 	BUSO_REV,			/* busops_rev */
8510394SMichael.Corcoran@Sun.COM 	acpinex_bus_map,		/* bus_map */
8610394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_get_intrspec */
8710394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_add_intrspec */
8810394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_remove_intrspec */
8910394SMichael.Corcoran@Sun.COM 	i_ddi_map_fault,		/* bus_map_fault */
9010394SMichael.Corcoran@Sun.COM 	ddi_dma_map,			/* bus_dma_map */
9110394SMichael.Corcoran@Sun.COM 	ddi_dma_allochdl,		/* bus_dma_allochdl */
9210394SMichael.Corcoran@Sun.COM 	ddi_dma_freehdl,		/* bus_dma_freehdl */
9310394SMichael.Corcoran@Sun.COM 	ddi_dma_bindhdl,		/* bus_dma_bindhdl */
9410394SMichael.Corcoran@Sun.COM 	ddi_dma_unbindhdl,		/* bus_dma_unbindhdl */
9510394SMichael.Corcoran@Sun.COM 	ddi_dma_flush,			/* bus_dma_flush */
9610394SMichael.Corcoran@Sun.COM 	ddi_dma_win,			/* bus_dma_win */
9710394SMichael.Corcoran@Sun.COM 	ddi_dma_mctl,			/* bus_dma_ctl */
9810394SMichael.Corcoran@Sun.COM 	acpinex_ctlops,			/* bus_ctl */
9910394SMichael.Corcoran@Sun.COM 	ddi_bus_prop_op,		/* bus_prop_op */
10010394SMichael.Corcoran@Sun.COM 	ndi_busop_get_eventcookie,	/* bus_get_eventcookie */
10110394SMichael.Corcoran@Sun.COM 	ndi_busop_add_eventcall,	/* bus_add_eventcall */
10210394SMichael.Corcoran@Sun.COM 	ndi_busop_remove_eventcall,	/* bus_remove_eventcall */
10310394SMichael.Corcoran@Sun.COM 	ndi_post_event,			/* bus_post_event */
10410394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_intr_ctl */
10510394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_config */
10610394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_unconfig */
10710394SMichael.Corcoran@Sun.COM 	acpinex_fm_init_child,		/* bus_fm_init */
10810394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_fm_fini */
10910394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_fm_access_enter */
11010394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_fm_access_exit */
11110394SMichael.Corcoran@Sun.COM 	NULL,				/* bus_power */
11210394SMichael.Corcoran@Sun.COM 	i_ddi_intr_ops			/* bus_intr_op */
11310394SMichael.Corcoran@Sun.COM };
11410394SMichael.Corcoran@Sun.COM 
11510394SMichael.Corcoran@Sun.COM static struct cb_ops acpinex_cb_ops = {
11610394SMichael.Corcoran@Sun.COM 	acpinex_open,			/* cb_open */
11710394SMichael.Corcoran@Sun.COM 	acpinex_close,			/* cb_close */
11810394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_strategy */
11910394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_print */
12010394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_dump */
12110394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_read */
12210394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_write */
12310394SMichael.Corcoran@Sun.COM 	acpinex_ioctl,			/* cb_ioctl */
12410394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_devmap */
12510394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_mmap */
12610394SMichael.Corcoran@Sun.COM 	nodev,				/* cb_segmap */
12710394SMichael.Corcoran@Sun.COM 	nochpoll,			/* cb_poll */
12810394SMichael.Corcoran@Sun.COM 	ddi_prop_op,			/* cb_prop_op */
12910394SMichael.Corcoran@Sun.COM 	NULL,				/* cb_str */
13010394SMichael.Corcoran@Sun.COM 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
13110394SMichael.Corcoran@Sun.COM 	CB_REV,				/* rev */
13210394SMichael.Corcoran@Sun.COM 	nodev,				/* int (*cb_aread)() */
13310394SMichael.Corcoran@Sun.COM 	nodev				/* int (*cb_awrite)() */
13410394SMichael.Corcoran@Sun.COM };
13510394SMichael.Corcoran@Sun.COM 
13610394SMichael.Corcoran@Sun.COM static struct dev_ops acpinex_ops = {
13710394SMichael.Corcoran@Sun.COM 	DEVO_REV,			/* devo_rev, */
13810394SMichael.Corcoran@Sun.COM 	0,				/* devo_refcnt */
13910394SMichael.Corcoran@Sun.COM 	acpinex_info,			/* devo_getinfo */
14010394SMichael.Corcoran@Sun.COM 	nulldev,			/* devo_identify */
14110394SMichael.Corcoran@Sun.COM 	nulldev,			/* devo_probe */
14210394SMichael.Corcoran@Sun.COM 	acpinex_attach,			/* devo_attach */
14310394SMichael.Corcoran@Sun.COM 	acpinex_detach,			/* devo_detach */
14410394SMichael.Corcoran@Sun.COM 	nulldev,			/* devo_reset */
14510394SMichael.Corcoran@Sun.COM 	&acpinex_cb_ops,		/* devo_cb_ops */
14610394SMichael.Corcoran@Sun.COM 	&acpinex_bus_ops,		/* devo_bus_ops */
14710394SMichael.Corcoran@Sun.COM 	nulldev,			/* devo_power */
14810394SMichael.Corcoran@Sun.COM 	ddi_quiesce_not_needed		/* devo_quiesce */
14910394SMichael.Corcoran@Sun.COM };
15010394SMichael.Corcoran@Sun.COM 
15110394SMichael.Corcoran@Sun.COM static struct modldrv modldrv = {
15210394SMichael.Corcoran@Sun.COM 	&mod_driverops,			/* Type of module */
15310394SMichael.Corcoran@Sun.COM 	"ACPI virtual bus driver",	/* name of module */
15410394SMichael.Corcoran@Sun.COM 	&acpinex_ops,			/* driver ops */
15510394SMichael.Corcoran@Sun.COM };
15610394SMichael.Corcoran@Sun.COM 
15710394SMichael.Corcoran@Sun.COM static struct modlinkage modlinkage = {
15810394SMichael.Corcoran@Sun.COM 	MODREV_1,			/* rev */
15910394SMichael.Corcoran@Sun.COM 	(void *)&modldrv,
16010394SMichael.Corcoran@Sun.COM 	NULL
16110394SMichael.Corcoran@Sun.COM };
16210394SMichael.Corcoran@Sun.COM 
16310394SMichael.Corcoran@Sun.COM /*
16410394SMichael.Corcoran@Sun.COM  * Module initialization routines.
16510394SMichael.Corcoran@Sun.COM  */
16610394SMichael.Corcoran@Sun.COM int
_init(void)16710394SMichael.Corcoran@Sun.COM _init(void)
16810394SMichael.Corcoran@Sun.COM {
16910394SMichael.Corcoran@Sun.COM 	int error;
17010394SMichael.Corcoran@Sun.COM 
17110394SMichael.Corcoran@Sun.COM 	/* Initialize soft state pointer. */
17210394SMichael.Corcoran@Sun.COM 	if ((error = ddi_soft_state_init(&acpinex_softstates,
17310394SMichael.Corcoran@Sun.COM 	    sizeof (acpinex_softstate_t), 8)) != 0) {
17410394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN,
17510394SMichael.Corcoran@Sun.COM 		    "acpinex: failed to initialize soft state structure.");
17610394SMichael.Corcoran@Sun.COM 		return (error);
17710394SMichael.Corcoran@Sun.COM 	}
17810394SMichael.Corcoran@Sun.COM 
179*12004Sjiang.liu@intel.com 	/* Initialize event subsystem. */
180*12004Sjiang.liu@intel.com 	acpinex_event_init();
181*12004Sjiang.liu@intel.com 
18210394SMichael.Corcoran@Sun.COM 	/* Install the module. */
18310394SMichael.Corcoran@Sun.COM 	if ((error = mod_install(&modlinkage)) != 0) {
18410394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN, "acpinex: failed to install module.");
18510394SMichael.Corcoran@Sun.COM 		ddi_soft_state_fini(&acpinex_softstates);
18610394SMichael.Corcoran@Sun.COM 		return (error);
18710394SMichael.Corcoran@Sun.COM 	}
18810394SMichael.Corcoran@Sun.COM 
18910394SMichael.Corcoran@Sun.COM 	mutex_init(&acpinex_lock, NULL, MUTEX_DRIVER, NULL);
19010394SMichael.Corcoran@Sun.COM 
19110394SMichael.Corcoran@Sun.COM 	return (0);
19210394SMichael.Corcoran@Sun.COM }
19310394SMichael.Corcoran@Sun.COM 
19410394SMichael.Corcoran@Sun.COM int
_fini(void)19510394SMichael.Corcoran@Sun.COM _fini(void)
19610394SMichael.Corcoran@Sun.COM {
19710394SMichael.Corcoran@Sun.COM 	int error;
19810394SMichael.Corcoran@Sun.COM 
19910394SMichael.Corcoran@Sun.COM 	/* Remove the module. */
20010394SMichael.Corcoran@Sun.COM 	if ((error = mod_remove(&modlinkage)) != 0) {
20110394SMichael.Corcoran@Sun.COM 		return (error);
20210394SMichael.Corcoran@Sun.COM 	}
20310394SMichael.Corcoran@Sun.COM 
204*12004Sjiang.liu@intel.com 	/* Shut down event subsystem. */
205*12004Sjiang.liu@intel.com 	acpinex_event_fini();
206*12004Sjiang.liu@intel.com 
20710394SMichael.Corcoran@Sun.COM 	/* Free the soft state info. */
20810394SMichael.Corcoran@Sun.COM 	ddi_soft_state_fini(&acpinex_softstates);
20910394SMichael.Corcoran@Sun.COM 
21010394SMichael.Corcoran@Sun.COM 	mutex_destroy(&acpinex_lock);
21110394SMichael.Corcoran@Sun.COM 
21210394SMichael.Corcoran@Sun.COM 	return (0);
21310394SMichael.Corcoran@Sun.COM }
21410394SMichael.Corcoran@Sun.COM 
21510394SMichael.Corcoran@Sun.COM int
_info(struct modinfo * modinfop)21610394SMichael.Corcoran@Sun.COM _info(struct modinfo *modinfop)
21710394SMichael.Corcoran@Sun.COM {
21810394SMichael.Corcoran@Sun.COM 	return (mod_info(&modlinkage, modinfop));
21910394SMichael.Corcoran@Sun.COM }
22010394SMichael.Corcoran@Sun.COM 
22110394SMichael.Corcoran@Sun.COM static int
acpinex_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)22210394SMichael.Corcoran@Sun.COM acpinex_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
22310394SMichael.Corcoran@Sun.COM {
224*12004Sjiang.liu@intel.com 	_NOTE(ARGUNUSED(dip));
225*12004Sjiang.liu@intel.com 
22610394SMichael.Corcoran@Sun.COM 	dev_t	dev;
22710394SMichael.Corcoran@Sun.COM 	int	instance;
22810394SMichael.Corcoran@Sun.COM 
22910394SMichael.Corcoran@Sun.COM 	if (infocmd == DDI_INFO_DEVT2INSTANCE) {
23010394SMichael.Corcoran@Sun.COM 		dev = (dev_t)arg;
23110394SMichael.Corcoran@Sun.COM 		instance = ACPINEX_GET_INSTANCE(getminor(dev));
23210394SMichael.Corcoran@Sun.COM 		*result = (void *)(uintptr_t)instance;
23310394SMichael.Corcoran@Sun.COM 		return (DDI_SUCCESS);
23410394SMichael.Corcoran@Sun.COM 	}
23510394SMichael.Corcoran@Sun.COM 
23610394SMichael.Corcoran@Sun.COM 	return (DDI_FAILURE);
23710394SMichael.Corcoran@Sun.COM }
23810394SMichael.Corcoran@Sun.COM 
23910394SMichael.Corcoran@Sun.COM static int
acpinex_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)24010394SMichael.Corcoran@Sun.COM acpinex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
24110394SMichael.Corcoran@Sun.COM {
24210394SMichael.Corcoran@Sun.COM 	int instance;
24310394SMichael.Corcoran@Sun.COM 	acpinex_softstate_t *softsp;
24410394SMichael.Corcoran@Sun.COM 
24510394SMichael.Corcoran@Sun.COM 	switch (cmd) {
24610394SMichael.Corcoran@Sun.COM 	case DDI_ATTACH:
24710394SMichael.Corcoran@Sun.COM 		break;
24810394SMichael.Corcoran@Sun.COM 
24910394SMichael.Corcoran@Sun.COM 	case DDI_RESUME:
25010394SMichael.Corcoran@Sun.COM 		return (DDI_SUCCESS);
25110394SMichael.Corcoran@Sun.COM 
25210394SMichael.Corcoran@Sun.COM 	default:
25310394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
25410394SMichael.Corcoran@Sun.COM 	}
25510394SMichael.Corcoran@Sun.COM 
25610394SMichael.Corcoran@Sun.COM 	/* Get and check instance number. */
25710394SMichael.Corcoran@Sun.COM 	instance = ddi_get_instance(devi);
25810394SMichael.Corcoran@Sun.COM 	if (instance >= ACPINEX_INSTANCE_MAX) {
25910394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN, "acpinex: instance number %d is out of range "
26010394SMichael.Corcoran@Sun.COM 		    "in acpinex_attach(), max %d.",
26110394SMichael.Corcoran@Sun.COM 		    instance, ACPINEX_INSTANCE_MAX - 1);
26210394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
26310394SMichael.Corcoran@Sun.COM 	}
26410394SMichael.Corcoran@Sun.COM 
26510394SMichael.Corcoran@Sun.COM 	/* Get soft state structure. */
26610394SMichael.Corcoran@Sun.COM 	if (ddi_soft_state_zalloc(acpinex_softstates, instance)
26710394SMichael.Corcoran@Sun.COM 	    != DDI_SUCCESS) {
26810394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN, "!acpinex: failed to allocate soft state "
26910394SMichael.Corcoran@Sun.COM 		    "object in acpinex_attach().");
27010394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
27110394SMichael.Corcoran@Sun.COM 	}
27210394SMichael.Corcoran@Sun.COM 	softsp = ddi_get_soft_state(acpinex_softstates, instance);
27310394SMichael.Corcoran@Sun.COM 
27410394SMichael.Corcoran@Sun.COM 	/* Initialize soft state structure */
27510394SMichael.Corcoran@Sun.COM 	softsp->ans_dip = devi;
27610394SMichael.Corcoran@Sun.COM 	(void) ddi_pathname(devi, softsp->ans_path);
27710394SMichael.Corcoran@Sun.COM 	if (ACPI_FAILURE(acpica_get_handle(devi, &softsp->ans_hdl))) {
27810394SMichael.Corcoran@Sun.COM 		ACPINEX_DEBUG(CE_WARN,
279*12004Sjiang.liu@intel.com 		    "!acpinex: failed to get ACPI handle for %s.",
28010394SMichael.Corcoran@Sun.COM 		    softsp->ans_path);
28110394SMichael.Corcoran@Sun.COM 		ddi_soft_state_free(acpinex_softstates, instance);
28210394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
28310394SMichael.Corcoran@Sun.COM 	}
28410394SMichael.Corcoran@Sun.COM 	mutex_init(&softsp->ans_lock, NULL, MUTEX_DRIVER, NULL);
28510394SMichael.Corcoran@Sun.COM 
286*12004Sjiang.liu@intel.com 	/* Install event handler for child/descendant objects. */
287*12004Sjiang.liu@intel.com 	if (acpinex_event_scan(softsp, B_TRUE) != DDI_SUCCESS) {
288*12004Sjiang.liu@intel.com 		cmn_err(CE_WARN, "!acpinex: failed to install event handler "
289*12004Sjiang.liu@intel.com 		    "for children of %s.", softsp->ans_path);
290*12004Sjiang.liu@intel.com 	}
291*12004Sjiang.liu@intel.com 
29210394SMichael.Corcoran@Sun.COM 	/* nothing to suspend/resume here */
29310394SMichael.Corcoran@Sun.COM 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
29410394SMichael.Corcoran@Sun.COM 	    "pm-hardware-state", "no-suspend-resume");
295*12004Sjiang.liu@intel.com 	(void) ddi_prop_update_int(DDI_DEV_T_NONE, devi,
296*12004Sjiang.liu@intel.com 	    DDI_NO_AUTODETACH, 1);
29710394SMichael.Corcoran@Sun.COM 
29810394SMichael.Corcoran@Sun.COM 	acpinex_fm_init(softsp);
29910394SMichael.Corcoran@Sun.COM 	ddi_report_dev(devi);
30010394SMichael.Corcoran@Sun.COM 
30110394SMichael.Corcoran@Sun.COM 	return (DDI_SUCCESS);
30210394SMichael.Corcoran@Sun.COM }
30310394SMichael.Corcoran@Sun.COM 
30410394SMichael.Corcoran@Sun.COM static int
acpinex_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)30510394SMichael.Corcoran@Sun.COM acpinex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
30610394SMichael.Corcoran@Sun.COM {
30710394SMichael.Corcoran@Sun.COM 	int instance;
30810394SMichael.Corcoran@Sun.COM 	acpinex_softstate_t *softsp;
30910394SMichael.Corcoran@Sun.COM 
31010394SMichael.Corcoran@Sun.COM 	instance = ddi_get_instance(devi);
31110394SMichael.Corcoran@Sun.COM 	if (instance >= ACPINEX_INSTANCE_MAX) {
31210394SMichael.Corcoran@Sun.COM 		cmn_err(CE_WARN, "acpinex: instance number %d is out of range "
31310394SMichael.Corcoran@Sun.COM 		    "in acpinex_detach(), max %d.",
31410394SMichael.Corcoran@Sun.COM 		    instance, ACPINEX_INSTANCE_MAX - 1);
31510394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
31610394SMichael.Corcoran@Sun.COM 	}
31710394SMichael.Corcoran@Sun.COM 
31810394SMichael.Corcoran@Sun.COM 	softsp = ddi_get_soft_state(acpinex_softstates, instance);
31910394SMichael.Corcoran@Sun.COM 	if (softsp == NULL) {
320*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to get soft state "
32110394SMichael.Corcoran@Sun.COM 		    "object for instance %d in acpinex_detach()", instance);
32210394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
32310394SMichael.Corcoran@Sun.COM 	}
32410394SMichael.Corcoran@Sun.COM 
32510394SMichael.Corcoran@Sun.COM 	switch (cmd) {
32610394SMichael.Corcoran@Sun.COM 	case DDI_DETACH:
327*12004Sjiang.liu@intel.com 		if (acpinex_event_scan(softsp, B_FALSE) != DDI_SUCCESS) {
328*12004Sjiang.liu@intel.com 			cmn_err(CE_WARN, "!acpinex: failed to uninstall event "
329*12004Sjiang.liu@intel.com 			    "handler for children of %s.", softsp->ans_path);
330*12004Sjiang.liu@intel.com 			return (DDI_FAILURE);
331*12004Sjiang.liu@intel.com 		}
33210394SMichael.Corcoran@Sun.COM 		ddi_remove_minor_node(devi, NULL);
33310394SMichael.Corcoran@Sun.COM 		acpinex_fm_fini(softsp);
33410394SMichael.Corcoran@Sun.COM 		mutex_destroy(&softsp->ans_lock);
33510394SMichael.Corcoran@Sun.COM 		ddi_soft_state_free(acpinex_softstates, instance);
336*12004Sjiang.liu@intel.com 		(void) ddi_prop_update_int(DDI_DEV_T_NONE, devi,
337*12004Sjiang.liu@intel.com 		    DDI_NO_AUTODETACH, 0);
33810394SMichael.Corcoran@Sun.COM 		return (DDI_SUCCESS);
33910394SMichael.Corcoran@Sun.COM 
34010394SMichael.Corcoran@Sun.COM 	case DDI_SUSPEND:
34110394SMichael.Corcoran@Sun.COM 		return (DDI_SUCCESS);
34210394SMichael.Corcoran@Sun.COM 
34310394SMichael.Corcoran@Sun.COM 	default:
34410394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
34510394SMichael.Corcoran@Sun.COM 	}
34610394SMichael.Corcoran@Sun.COM }
34710394SMichael.Corcoran@Sun.COM 
34810394SMichael.Corcoran@Sun.COM static int
name_child(dev_info_t * child,char * name,int namelen)34910394SMichael.Corcoran@Sun.COM name_child(dev_info_t *child, char *name, int namelen)
35010394SMichael.Corcoran@Sun.COM {
35110394SMichael.Corcoran@Sun.COM 	char *unitaddr;
35210394SMichael.Corcoran@Sun.COM 
35310394SMichael.Corcoran@Sun.COM 	ddi_set_parent_data(child, NULL);
35410394SMichael.Corcoran@Sun.COM 
35510394SMichael.Corcoran@Sun.COM 	name[0] = '\0';
35610394SMichael.Corcoran@Sun.COM 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
35710394SMichael.Corcoran@Sun.COM 	    ACPIDEV_PROP_NAME_UNIT_ADDR, &unitaddr) == DDI_SUCCESS) {
358*12004Sjiang.liu@intel.com 		(void) strlcpy(name, unitaddr, namelen);
35910394SMichael.Corcoran@Sun.COM 		ddi_prop_free(unitaddr);
36010394SMichael.Corcoran@Sun.COM 	} else {
361*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_NOTE, "!acpinex: failed to lookup child "
362*12004Sjiang.liu@intel.com 		    "unit-address prop for %p.", (void *)child);
36310394SMichael.Corcoran@Sun.COM 	}
36410394SMichael.Corcoran@Sun.COM 
36510394SMichael.Corcoran@Sun.COM 	return (DDI_SUCCESS);
36610394SMichael.Corcoran@Sun.COM }
36710394SMichael.Corcoran@Sun.COM 
36810394SMichael.Corcoran@Sun.COM static int
init_child(dev_info_t * child)36910394SMichael.Corcoran@Sun.COM init_child(dev_info_t *child)
37010394SMichael.Corcoran@Sun.COM {
37110394SMichael.Corcoran@Sun.COM 	char name[MAXNAMELEN];
37210394SMichael.Corcoran@Sun.COM 
37310394SMichael.Corcoran@Sun.COM 	(void) name_child(child, name, MAXNAMELEN);
37410394SMichael.Corcoran@Sun.COM 	ddi_set_name_addr(child, name);
37510394SMichael.Corcoran@Sun.COM 	if ((ndi_dev_is_persistent_node(child) == 0) &&
37610394SMichael.Corcoran@Sun.COM 	    (ndi_merge_node(child, name_child) == DDI_SUCCESS)) {
37710394SMichael.Corcoran@Sun.COM 		impl_ddi_sunbus_removechild(child);
37810394SMichael.Corcoran@Sun.COM 		return (DDI_FAILURE);
37910394SMichael.Corcoran@Sun.COM 	}
38010394SMichael.Corcoran@Sun.COM 
38110394SMichael.Corcoran@Sun.COM 	return (DDI_SUCCESS);
38210394SMichael.Corcoran@Sun.COM }
38310394SMichael.Corcoran@Sun.COM 
38410394SMichael.Corcoran@Sun.COM /*
38510394SMichael.Corcoran@Sun.COM  * Control ops entry point:
38610394SMichael.Corcoran@Sun.COM  *
38710394SMichael.Corcoran@Sun.COM  * Requests handled completely:
38810394SMichael.Corcoran@Sun.COM  *      DDI_CTLOPS_INITCHILD
38910394SMichael.Corcoran@Sun.COM  *      DDI_CTLOPS_UNINITCHILD
39010394SMichael.Corcoran@Sun.COM  * All others are passed to the parent.
39110394SMichael.Corcoran@Sun.COM  */
39210394SMichael.Corcoran@Sun.COM static int
acpinex_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)39310394SMichael.Corcoran@Sun.COM acpinex_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
39410394SMichael.Corcoran@Sun.COM     void *result)
39510394SMichael.Corcoran@Sun.COM {
39610394SMichael.Corcoran@Sun.COM 	int rval = DDI_SUCCESS;
39710394SMichael.Corcoran@Sun.COM 
39810394SMichael.Corcoran@Sun.COM 	switch (op) {
39910394SMichael.Corcoran@Sun.COM 	case DDI_CTLOPS_INITCHILD:
40010394SMichael.Corcoran@Sun.COM 		rval = init_child((dev_info_t *)arg);
40110394SMichael.Corcoran@Sun.COM 		break;
40210394SMichael.Corcoran@Sun.COM 
40310394SMichael.Corcoran@Sun.COM 	case DDI_CTLOPS_UNINITCHILD:
40410394SMichael.Corcoran@Sun.COM 		impl_ddi_sunbus_removechild((dev_info_t *)arg);
40510394SMichael.Corcoran@Sun.COM 		break;
40610394SMichael.Corcoran@Sun.COM 
40710394SMichael.Corcoran@Sun.COM 	case DDI_CTLOPS_REPORTDEV: {
40810394SMichael.Corcoran@Sun.COM 		if (rdip == (dev_info_t *)0)
40910394SMichael.Corcoran@Sun.COM 			return (DDI_FAILURE);
41010394SMichael.Corcoran@Sun.COM 		cmn_err(CE_CONT, "?acpinex: %s@%s, %s%d\n",
41110394SMichael.Corcoran@Sun.COM 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
41210394SMichael.Corcoran@Sun.COM 		    ddi_driver_name(rdip), ddi_get_instance(rdip));
41310394SMichael.Corcoran@Sun.COM 		break;
41410394SMichael.Corcoran@Sun.COM 	}
41510394SMichael.Corcoran@Sun.COM 
41610394SMichael.Corcoran@Sun.COM 	default:
41710394SMichael.Corcoran@Sun.COM 		rval = ddi_ctlops(dip, rdip, op, arg, result);
41810394SMichael.Corcoran@Sun.COM 		break;
41910394SMichael.Corcoran@Sun.COM 	}
42010394SMichael.Corcoran@Sun.COM 
42110394SMichael.Corcoran@Sun.COM 	return (rval);
42210394SMichael.Corcoran@Sun.COM }
42310394SMichael.Corcoran@Sun.COM 
42410394SMichael.Corcoran@Sun.COM /* ARGSUSED */
42510394SMichael.Corcoran@Sun.COM static int
acpinex_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)42610394SMichael.Corcoran@Sun.COM acpinex_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
42710394SMichael.Corcoran@Sun.COM     off_t offset, off_t len, caddr_t *vaddrp)
42810394SMichael.Corcoran@Sun.COM {
42910394SMichael.Corcoran@Sun.COM 	ACPINEX_DEBUG(CE_WARN,
430*12004Sjiang.liu@intel.com 	    "!acpinex: acpinex_bus_map called and it's unimplemented.");
43110394SMichael.Corcoran@Sun.COM 	return (DDI_ME_UNIMPLEMENTED);
43210394SMichael.Corcoran@Sun.COM }
43310394SMichael.Corcoran@Sun.COM 
43410394SMichael.Corcoran@Sun.COM static int
acpinex_open(dev_t * devi,int flags,int otyp,cred_t * credp)43510394SMichael.Corcoran@Sun.COM acpinex_open(dev_t *devi, int flags, int otyp, cred_t *credp)
43610394SMichael.Corcoran@Sun.COM {
437*12004Sjiang.liu@intel.com 	_NOTE(ARGUNUSED(flags, otyp, credp));
438*12004Sjiang.liu@intel.com 
43910394SMichael.Corcoran@Sun.COM 	minor_t minor, instance;
44010394SMichael.Corcoran@Sun.COM 	acpinex_softstate_t *softsp;
44110394SMichael.Corcoran@Sun.COM 
44210394SMichael.Corcoran@Sun.COM 	minor = getminor(*devi);
44310394SMichael.Corcoran@Sun.COM 	instance = ACPINEX_GET_INSTANCE(minor);
44410394SMichael.Corcoran@Sun.COM 	if (instance >= ACPINEX_INSTANCE_MAX) {
445*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_WARN, "!acpinex: instance number %d out of "
44610394SMichael.Corcoran@Sun.COM 		    "range in acpinex_open, max %d.",
44710394SMichael.Corcoran@Sun.COM 		    instance, ACPINEX_INSTANCE_MAX - 1);
44810394SMichael.Corcoran@Sun.COM 		return (EINVAL);
44910394SMichael.Corcoran@Sun.COM 	}
45010394SMichael.Corcoran@Sun.COM 
45110394SMichael.Corcoran@Sun.COM 	softsp = ddi_get_soft_state(acpinex_softstates, instance);
45210394SMichael.Corcoran@Sun.COM 	if (softsp == NULL) {
453*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to get soft state "
45410394SMichael.Corcoran@Sun.COM 		    "object for instance %d in acpinex_open().", instance);
45510394SMichael.Corcoran@Sun.COM 		return (EINVAL);
45610394SMichael.Corcoran@Sun.COM 	}
45710394SMichael.Corcoran@Sun.COM 
45810394SMichael.Corcoran@Sun.COM 	if (ACPINEX_IS_DEVCTL(minor)) {
45910394SMichael.Corcoran@Sun.COM 		return (0);
46010394SMichael.Corcoran@Sun.COM 	} else {
46110394SMichael.Corcoran@Sun.COM 		ACPINEX_DEBUG(CE_WARN,
462*12004Sjiang.liu@intel.com 		    "!acpinex: invalid minor number %d in acpinex_open().",
46310394SMichael.Corcoran@Sun.COM 		    minor);
46410394SMichael.Corcoran@Sun.COM 		return (EINVAL);
46510394SMichael.Corcoran@Sun.COM 	}
46610394SMichael.Corcoran@Sun.COM }
46710394SMichael.Corcoran@Sun.COM 
46810394SMichael.Corcoran@Sun.COM static int
acpinex_close(dev_t dev,int flags,int otyp,cred_t * credp)46910394SMichael.Corcoran@Sun.COM acpinex_close(dev_t dev, int flags, int otyp, cred_t *credp)
47010394SMichael.Corcoran@Sun.COM {
471*12004Sjiang.liu@intel.com 	_NOTE(ARGUNUSED(flags, otyp, credp));
472*12004Sjiang.liu@intel.com 
47310394SMichael.Corcoran@Sun.COM 	minor_t minor, instance;
47410394SMichael.Corcoran@Sun.COM 	acpinex_softstate_t *softsp;
47510394SMichael.Corcoran@Sun.COM 
47610394SMichael.Corcoran@Sun.COM 	minor = getminor(dev);
47710394SMichael.Corcoran@Sun.COM 	instance = ACPINEX_GET_INSTANCE(minor);
47810394SMichael.Corcoran@Sun.COM 	if (instance >= ACPINEX_INSTANCE_MAX) {
479*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_WARN, "!acpinex: instance number %d out of "
48010394SMichael.Corcoran@Sun.COM 		    "range in acpinex_close(), max %d.",
48110394SMichael.Corcoran@Sun.COM 		    instance, ACPINEX_INSTANCE_MAX - 1);
48210394SMichael.Corcoran@Sun.COM 		return (EINVAL);
48310394SMichael.Corcoran@Sun.COM 	}
48410394SMichael.Corcoran@Sun.COM 
48510394SMichael.Corcoran@Sun.COM 	softsp = ddi_get_soft_state(acpinex_softstates, instance);
48610394SMichael.Corcoran@Sun.COM 	if (softsp == NULL) {
487*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to get soft state "
48810394SMichael.Corcoran@Sun.COM 		    "object for instance %d in acpinex_close().", instance);
48910394SMichael.Corcoran@Sun.COM 		return (EINVAL);
49010394SMichael.Corcoran@Sun.COM 	}
49110394SMichael.Corcoran@Sun.COM 
49210394SMichael.Corcoran@Sun.COM 	if (ACPINEX_IS_DEVCTL(minor)) {
49310394SMichael.Corcoran@Sun.COM 		return (0);
49410394SMichael.Corcoran@Sun.COM 	} else {
49510394SMichael.Corcoran@Sun.COM 		ACPINEX_DEBUG(CE_WARN,
496*12004Sjiang.liu@intel.com 		    "!acpinex: invalid minor number %d in acpinex_close().",
49710394SMichael.Corcoran@Sun.COM 		    minor);
49810394SMichael.Corcoran@Sun.COM 		return (EINVAL);
49910394SMichael.Corcoran@Sun.COM 	}
50010394SMichael.Corcoran@Sun.COM }
50110394SMichael.Corcoran@Sun.COM 
50210394SMichael.Corcoran@Sun.COM static int
acpinex_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)50310394SMichael.Corcoran@Sun.COM acpinex_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
50410394SMichael.Corcoran@Sun.COM     int *rvalp)
50510394SMichael.Corcoran@Sun.COM {
506*12004Sjiang.liu@intel.com 	_NOTE(ARGUNUSED(cmd, arg, mode, credp, rvalp));
507*12004Sjiang.liu@intel.com 
50810394SMichael.Corcoran@Sun.COM 	int rv = 0;
50910394SMichael.Corcoran@Sun.COM 	minor_t minor, instance;
51010394SMichael.Corcoran@Sun.COM 	acpinex_softstate_t *softsp;
51110394SMichael.Corcoran@Sun.COM 
51210394SMichael.Corcoran@Sun.COM 	minor = getminor(dev);
51310394SMichael.Corcoran@Sun.COM 	instance = ACPINEX_GET_INSTANCE(minor);
51410394SMichael.Corcoran@Sun.COM 	if (instance >= ACPINEX_INSTANCE_MAX) {
515*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_NOTE, "!acpinex: instance number %d out of "
51610394SMichael.Corcoran@Sun.COM 		    "range in acpinex_ioctl(), max %d.",
51710394SMichael.Corcoran@Sun.COM 		    instance, ACPINEX_INSTANCE_MAX - 1);
51810394SMichael.Corcoran@Sun.COM 		return (EINVAL);
51910394SMichael.Corcoran@Sun.COM 	}
52010394SMichael.Corcoran@Sun.COM 	softsp = ddi_get_soft_state(acpinex_softstates, instance);
52110394SMichael.Corcoran@Sun.COM 	if (softsp == NULL) {
522*12004Sjiang.liu@intel.com 		ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to get soft state "
52310394SMichael.Corcoran@Sun.COM 		    "object for instance %d in acpinex_ioctl().", instance);
52410394SMichael.Corcoran@Sun.COM 		return (EINVAL);
52510394SMichael.Corcoran@Sun.COM 	}
52610394SMichael.Corcoran@Sun.COM 
52710394SMichael.Corcoran@Sun.COM 	rv = ENOTSUP;
52810394SMichael.Corcoran@Sun.COM 	ACPINEX_DEBUG(CE_WARN,
529*12004Sjiang.liu@intel.com 	    "!acpinex: invalid minor number %d in acpinex_ioctl().", minor);
53010394SMichael.Corcoran@Sun.COM 
53110394SMichael.Corcoran@Sun.COM 	return (rv);
53210394SMichael.Corcoran@Sun.COM }
53310394SMichael.Corcoran@Sun.COM 
53410394SMichael.Corcoran@Sun.COM /*
53510394SMichael.Corcoran@Sun.COM  * FMA error callback.
53610394SMichael.Corcoran@Sun.COM  * Register error handling callback with our parent. We will just call
53710394SMichael.Corcoran@Sun.COM  * our children's error callbacks and return their status.
53810394SMichael.Corcoran@Sun.COM  */
53910394SMichael.Corcoran@Sun.COM static int
acpinex_err_callback(dev_info_t * dip,ddi_fm_error_t * derr,const void * impl_data)54010394SMichael.Corcoran@Sun.COM acpinex_err_callback(dev_info_t *dip, ddi_fm_error_t *derr,
54110394SMichael.Corcoran@Sun.COM     const void *impl_data)
54210394SMichael.Corcoran@Sun.COM {
543*12004Sjiang.liu@intel.com 	_NOTE(ARGUNUSED(impl_data));
544*12004Sjiang.liu@intel.com 
54510394SMichael.Corcoran@Sun.COM 	/* Call our childrens error handlers */
54610394SMichael.Corcoran@Sun.COM 	return (ndi_fm_handler_dispatch(dip, NULL, derr));
54710394SMichael.Corcoran@Sun.COM }
54810394SMichael.Corcoran@Sun.COM 
54910394SMichael.Corcoran@Sun.COM /*
55010394SMichael.Corcoran@Sun.COM  * Initialize our FMA resources
55110394SMichael.Corcoran@Sun.COM  */
55210394SMichael.Corcoran@Sun.COM static void
acpinex_fm_init(acpinex_softstate_t * softsp)55310394SMichael.Corcoran@Sun.COM acpinex_fm_init(acpinex_softstate_t *softsp)
55410394SMichael.Corcoran@Sun.COM {
55510394SMichael.Corcoran@Sun.COM 	softsp->ans_fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE |
55610394SMichael.Corcoran@Sun.COM 	    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
55710394SMichael.Corcoran@Sun.COM 
55810394SMichael.Corcoran@Sun.COM 	/*
55910394SMichael.Corcoran@Sun.COM 	 * Request our capability level and get our parent's capability and ibc.
56010394SMichael.Corcoran@Sun.COM 	 */
56110394SMichael.Corcoran@Sun.COM 	ddi_fm_init(softsp->ans_dip, &softsp->ans_fm_cap, &softsp->ans_fm_ibc);
56210394SMichael.Corcoran@Sun.COM 	if (softsp->ans_fm_cap & DDI_FM_ERRCB_CAPABLE) {
56310394SMichael.Corcoran@Sun.COM 		/*
56410394SMichael.Corcoran@Sun.COM 		 * Register error callback with our parent if supported.
56510394SMichael.Corcoran@Sun.COM 		 */
56610394SMichael.Corcoran@Sun.COM 		ddi_fm_handler_register(softsp->ans_dip, acpinex_err_callback,
56710394SMichael.Corcoran@Sun.COM 		    softsp);
56810394SMichael.Corcoran@Sun.COM 	}
56910394SMichael.Corcoran@Sun.COM }
57010394SMichael.Corcoran@Sun.COM 
57110394SMichael.Corcoran@Sun.COM /*
57210394SMichael.Corcoran@Sun.COM  * Breakdown our FMA resources
57310394SMichael.Corcoran@Sun.COM  */
57410394SMichael.Corcoran@Sun.COM static void
acpinex_fm_fini(acpinex_softstate_t * softsp)57510394SMichael.Corcoran@Sun.COM acpinex_fm_fini(acpinex_softstate_t *softsp)
57610394SMichael.Corcoran@Sun.COM {
57710394SMichael.Corcoran@Sun.COM 	/* Clean up allocated fm structures */
57810394SMichael.Corcoran@Sun.COM 	if (softsp->ans_fm_cap & DDI_FM_ERRCB_CAPABLE) {
57910394SMichael.Corcoran@Sun.COM 		ddi_fm_handler_unregister(softsp->ans_dip);
58010394SMichael.Corcoran@Sun.COM 	}
58110394SMichael.Corcoran@Sun.COM 	ddi_fm_fini(softsp->ans_dip);
58210394SMichael.Corcoran@Sun.COM }
58310394SMichael.Corcoran@Sun.COM 
58410394SMichael.Corcoran@Sun.COM /*
58510394SMichael.Corcoran@Sun.COM  * Initialize FMA resources for child devices.
58610394SMichael.Corcoran@Sun.COM  * Called when child calls ddi_fm_init().
58710394SMichael.Corcoran@Sun.COM  */
58810394SMichael.Corcoran@Sun.COM static int
acpinex_fm_init_child(dev_info_t * dip,dev_info_t * tdip,int cap,ddi_iblock_cookie_t * ibc)58910394SMichael.Corcoran@Sun.COM acpinex_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap,
59010394SMichael.Corcoran@Sun.COM     ddi_iblock_cookie_t *ibc)
59110394SMichael.Corcoran@Sun.COM {
592*12004Sjiang.liu@intel.com 	_NOTE(ARGUNUSED(tdip, cap));
593*12004Sjiang.liu@intel.com 
59410394SMichael.Corcoran@Sun.COM 	acpinex_softstate_t *softsp = ddi_get_soft_state(acpinex_softstates,
59510394SMichael.Corcoran@Sun.COM 	    ddi_get_instance(dip));
59610394SMichael.Corcoran@Sun.COM 
59710394SMichael.Corcoran@Sun.COM 	*ibc = softsp->ans_fm_ibc;
59810394SMichael.Corcoran@Sun.COM 
59910394SMichael.Corcoran@Sun.COM 	return (softsp->ans_fm_cap);
60010394SMichael.Corcoran@Sun.COM }
601