xref: /illumos-gate/usr/src/uts/sun4u/io/pmubus.c (revision cd21e7c5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5903a11ebSrh  * Common Development and Distribution License (the "License").
6903a11ebSrh  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22903a11ebSrh  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
25*cd21e7c5SGarrett D'Amore /*
26*cd21e7c5SGarrett D'Amore  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
27*cd21e7c5SGarrett D'Amore  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <sys/conf.h>
327c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
337c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
357c478bd9Sstevel@tonic-gate #include <sys/ddi_subrdefs.h>
367c478bd9Sstevel@tonic-gate #include <sys/pci.h>
377c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate #include <sys/errno.h>
407c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
417c478bd9Sstevel@tonic-gate #include <sys/debug.h>
427c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
437c478bd9Sstevel@tonic-gate #include <sys/pmubus.h>
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #include <sys/nexusdebug.h>
467c478bd9Sstevel@tonic-gate /* Bitfield debugging definitions for this file */
477c478bd9Sstevel@tonic-gate #define	PMUBUS_MAP_DEBUG	0x1
487c478bd9Sstevel@tonic-gate #define	PMUBUS_REGACCESS_DEBUG	0x2
497c478bd9Sstevel@tonic-gate #define	PMUBUS_RW_DEBUG		0x4
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate  * The pmubus nexus is used to manage a shared register space.  Rather
537c478bd9Sstevel@tonic-gate  * than having several driver's physically alias register mappings and
547c478bd9Sstevel@tonic-gate  * have potential problems with register collisions, this nexus will
557c478bd9Sstevel@tonic-gate  * serialize the access to this space.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * There are two types of sharing going on here:
587c478bd9Sstevel@tonic-gate  * 1) Registers within the address space may be shared, however the registers
597c478bd9Sstevel@tonic-gate  * themselves are unique.  The upper bit of the child's high address being zero
607c478bd9Sstevel@tonic-gate  * signifies this register type.
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  * 2) The second type of register is one where a device may only own a few
637c478bd9Sstevel@tonic-gate  * bits in the register.  I'll term this as "bit lane" access.  This is a more
647c478bd9Sstevel@tonic-gate  * complicated scenario.  The drivers themselves are responsible for knowing
657c478bd9Sstevel@tonic-gate  * which bit lanes in the register they own.  The read of a register only
667c478bd9Sstevel@tonic-gate  * guarantees that those bits the driver is interested in are valid.  If a
677c478bd9Sstevel@tonic-gate  * driver needs to set bits in a register, a read must be done first to
687c478bd9Sstevel@tonic-gate  * identify the state of the drivers bits.  Depending on which way a bit needs
697c478bd9Sstevel@tonic-gate  * to be driven, the driver will write a 1 to the bit to toggle it.  If a bit
707c478bd9Sstevel@tonic-gate  * is to remain unchanged, a 0 is written to the bit.  So the access to the
717c478bd9Sstevel@tonic-gate  * bit lane is an xor operation.
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate  * Function prototypes for busops routines:
757c478bd9Sstevel@tonic-gate  */
767c478bd9Sstevel@tonic-gate static int pmubus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
777c478bd9Sstevel@tonic-gate     off_t off, off_t len, caddr_t *addrp);
787c478bd9Sstevel@tonic-gate static int pmubus_ctlops(dev_info_t *dip, dev_info_t *rdip,
797c478bd9Sstevel@tonic-gate     ddi_ctl_enum_t op, void *arg, void *result);
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * function prototypes for dev ops routines:
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate static int pmubus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
857c478bd9Sstevel@tonic-gate static int pmubus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * general function prototypes:
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate  * bus ops and dev ops structures:
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate static struct bus_ops pmubus_bus_ops = {
957c478bd9Sstevel@tonic-gate 	BUSO_REV,
967c478bd9Sstevel@tonic-gate 	pmubus_map,
977c478bd9Sstevel@tonic-gate 	NULL,
987c478bd9Sstevel@tonic-gate 	NULL,
997c478bd9Sstevel@tonic-gate 	NULL,
1007c478bd9Sstevel@tonic-gate 	i_ddi_map_fault,
101*cd21e7c5SGarrett D'Amore 	NULL,
1027c478bd9Sstevel@tonic-gate 	ddi_dma_allochdl,
1037c478bd9Sstevel@tonic-gate 	ddi_dma_freehdl,
1047c478bd9Sstevel@tonic-gate 	ddi_dma_bindhdl,
1057c478bd9Sstevel@tonic-gate 	ddi_dma_unbindhdl,
1067c478bd9Sstevel@tonic-gate 	ddi_dma_flush,
1077c478bd9Sstevel@tonic-gate 	ddi_dma_win,
1087c478bd9Sstevel@tonic-gate 	ddi_dma_mctl,
1097c478bd9Sstevel@tonic-gate 	pmubus_ctlops,
1107c478bd9Sstevel@tonic-gate 	ddi_bus_prop_op,
1117c478bd9Sstevel@tonic-gate 	0,			/* (*bus_get_eventcookie)();	*/
1127c478bd9Sstevel@tonic-gate 	0,			/* (*bus_add_eventcall)();	*/
1137c478bd9Sstevel@tonic-gate 	0,			/* (*bus_remove_eventcall)();	*/
1147c478bd9Sstevel@tonic-gate 	0,			/* (*bus_post_event)();		*/
1157c478bd9Sstevel@tonic-gate 	0,			/* interrupt control		*/
1167c478bd9Sstevel@tonic-gate 	0,			/* bus_config			*/
1177c478bd9Sstevel@tonic-gate 	0,			/* bus_unconfig			*/
1187c478bd9Sstevel@tonic-gate 	0,			/* bus_fm_init			*/
1197c478bd9Sstevel@tonic-gate 	0,			/* bus_fm_fini			*/
1207c478bd9Sstevel@tonic-gate 	0,			/* bus_fm_access_enter		*/
1217c478bd9Sstevel@tonic-gate 	0,			/* bus_fm_access_exit		*/
1227c478bd9Sstevel@tonic-gate 	0,			/* bus_power			*/
1237c478bd9Sstevel@tonic-gate 	i_ddi_intr_ops		/* bus_intr_op			*/
1247c478bd9Sstevel@tonic-gate };
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate static struct dev_ops pmubus_ops = {
1277c478bd9Sstevel@tonic-gate 	DEVO_REV,
1287c478bd9Sstevel@tonic-gate 	0,
1297c478bd9Sstevel@tonic-gate 	ddi_no_info,
1307c478bd9Sstevel@tonic-gate 	nulldev,
1317c478bd9Sstevel@tonic-gate 	0,
1327c478bd9Sstevel@tonic-gate 	pmubus_attach,
1337c478bd9Sstevel@tonic-gate 	pmubus_detach,
1347c478bd9Sstevel@tonic-gate 	nodev,
1357c478bd9Sstevel@tonic-gate 	(struct cb_ops *)0,
13619397407SSherry Moore 	&pmubus_bus_ops,
13719397407SSherry Moore 	NULL,
13819397407SSherry Moore 	ddi_quiesce_not_needed,		/* quiesce */
1397c478bd9Sstevel@tonic-gate };
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * module definitions:
1437c478bd9Sstevel@tonic-gate  */
1447c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
1457c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1487c478bd9Sstevel@tonic-gate 	&mod_driverops, 	/* Type of module.  This one is a driver */
1497c478bd9Sstevel@tonic-gate 	"pmubus nexus driver",	/* Name of module. */
1507c478bd9Sstevel@tonic-gate 	&pmubus_ops,		/* driver ops */
1517c478bd9Sstevel@tonic-gate };
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1547c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1557c478bd9Sstevel@tonic-gate };
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * driver global data:
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate static void *per_pmubus_state;		/* per-pmubus soft state pointer */
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate int
_init(void)1637c478bd9Sstevel@tonic-gate _init(void)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	int e;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	/*
1687c478bd9Sstevel@tonic-gate 	 * Initialize per-pmubus soft state pointer.
1697c478bd9Sstevel@tonic-gate 	 */
1707c478bd9Sstevel@tonic-gate 	e = ddi_soft_state_init(&per_pmubus_state,
1717c478bd9Sstevel@tonic-gate 	    sizeof (pmubus_devstate_t), 1);
1727c478bd9Sstevel@tonic-gate 	if (e != 0)
1737c478bd9Sstevel@tonic-gate 		return (e);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * Install the module.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	e = mod_install(&modlinkage);
1797c478bd9Sstevel@tonic-gate 	if (e != 0)
1807c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&per_pmubus_state);
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 	return (e);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate int
_fini(void)1867c478bd9Sstevel@tonic-gate _fini(void)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	int e;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	/*
1917c478bd9Sstevel@tonic-gate 	 * Remove the module.
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 	e = mod_remove(&modlinkage);
1947c478bd9Sstevel@tonic-gate 	if (e != 0)
1957c478bd9Sstevel@tonic-gate 		return (e);
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	/*
1987c478bd9Sstevel@tonic-gate 	 * Free the soft state info.
1997c478bd9Sstevel@tonic-gate 	 */
2007c478bd9Sstevel@tonic-gate 	ddi_soft_state_fini(&per_pmubus_state);
2017c478bd9Sstevel@tonic-gate 	return (e);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2057c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate /* device driver entry points */
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate  * attach entry point:
2147c478bd9Sstevel@tonic-gate  *
2157c478bd9Sstevel@tonic-gate  * normal attach:
2167c478bd9Sstevel@tonic-gate  *
2177c478bd9Sstevel@tonic-gate  *	create soft state structure (dip, reg, nreg and state fields)
2187c478bd9Sstevel@tonic-gate  *	map in configuration header
2197c478bd9Sstevel@tonic-gate  *	make sure device is properly configured
2207c478bd9Sstevel@tonic-gate  *	report device
2217c478bd9Sstevel@tonic-gate  */
2227c478bd9Sstevel@tonic-gate static int
pmubus_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2237c478bd9Sstevel@tonic-gate pmubus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2247c478bd9Sstevel@tonic-gate {
2257c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *pmubusp;	/* per pmubus state pointer */
2267c478bd9Sstevel@tonic-gate 	int32_t instance;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	switch (cmd) {
2297c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
2307c478bd9Sstevel@tonic-gate 		/*
2317c478bd9Sstevel@tonic-gate 		 * Allocate soft state for this instance.
2327c478bd9Sstevel@tonic-gate 		 */
2337c478bd9Sstevel@tonic-gate 		instance = ddi_get_instance(dip);
2347c478bd9Sstevel@tonic-gate 		if (ddi_soft_state_zalloc(per_pmubus_state, instance) !=
2357c478bd9Sstevel@tonic-gate 		    DDI_SUCCESS) {
2367c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_attach: Can't allocate soft "
2377c478bd9Sstevel@tonic-gate 			    "state.\n");
2387c478bd9Sstevel@tonic-gate 			goto fail_exit;
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 		pmubusp = ddi_get_soft_state(per_pmubus_state, instance);
2427c478bd9Sstevel@tonic-gate 		pmubusp->pmubus_dip = dip;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		/* Cache our register property */
245a3282898Scth 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2467c478bd9Sstevel@tonic-gate 		    "reg", (caddr_t)&pmubusp->pmubus_regp,
2477c478bd9Sstevel@tonic-gate 		    &pmubusp->pmubus_reglen) != DDI_SUCCESS) {
2487c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_attach: Can't acquire reg "
2497c478bd9Sstevel@tonic-gate 			    "property.\n");
2507c478bd9Sstevel@tonic-gate 			goto fail_get_regs;
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		/* Cache our ranges property */
254a3282898Scth 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2557c478bd9Sstevel@tonic-gate 		    "ranges", (caddr_t)&pmubusp->pmubus_rangep,
2567c478bd9Sstevel@tonic-gate 		    &pmubusp->pmubus_rnglen) != DDI_SUCCESS) {
2577c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_attach: Can't acquire the "
2587c478bd9Sstevel@tonic-gate 			    "ranges property.\n");
2597c478bd9Sstevel@tonic-gate 			goto fail_get_ranges;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 		}
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		/* Calculate the number of ranges */
2647c478bd9Sstevel@tonic-gate 		pmubusp->pmubus_nranges =
2657c478bd9Sstevel@tonic-gate 		    pmubusp->pmubus_rnglen / sizeof (pmu_rangespec_t);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		/* Set up the mapping to our registers */
2687c478bd9Sstevel@tonic-gate 		if (pci_config_setup(dip, &pmubusp->pmubus_reghdl) !=
2697c478bd9Sstevel@tonic-gate 		    DDI_SUCCESS) {
2707c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_attach: Can't map in "
2717c478bd9Sstevel@tonic-gate 			    "register space.\n");
2727c478bd9Sstevel@tonic-gate 			goto fail_map_regs;
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 		/* Initialize our register access mutex */
2767c478bd9Sstevel@tonic-gate 		mutex_init(&pmubusp->pmubus_reg_access_lock, NULL,
2777c478bd9Sstevel@tonic-gate 		    MUTEX_DRIVER, NULL);
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 		ddi_report_dev(dip);
2807c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
2837c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate fail_map_regs:
2877c478bd9Sstevel@tonic-gate 	kmem_free(pmubusp->pmubus_rangep, pmubusp->pmubus_rnglen);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate fail_get_ranges:
2907c478bd9Sstevel@tonic-gate 	kmem_free(pmubusp->pmubus_regp, pmubusp->pmubus_reglen);
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate fail_get_regs:
2937c478bd9Sstevel@tonic-gate 	ddi_soft_state_free(per_pmubus_state, instance);
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate fail_exit:
2967c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate  * detach entry point:
3017c478bd9Sstevel@tonic-gate  */
3027c478bd9Sstevel@tonic-gate static int
pmubus_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3037c478bd9Sstevel@tonic-gate pmubus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
3067c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *pmubusp = ddi_get_soft_state(per_pmubus_state,
3077c478bd9Sstevel@tonic-gate 	    instance);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	switch (cmd) {
3107c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
3117c478bd9Sstevel@tonic-gate 		mutex_destroy(&pmubusp->pmubus_reg_access_lock);
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		/* Tear down our register mappings */
3147c478bd9Sstevel@tonic-gate 		pci_config_teardown(&pmubusp->pmubus_reghdl);
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 		/* Free our ranges property */
3177c478bd9Sstevel@tonic-gate 		kmem_free(pmubusp->pmubus_rangep, pmubusp->pmubus_rnglen);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		/* Free the register property */
3207c478bd9Sstevel@tonic-gate 		kmem_free(pmubusp->pmubus_regp, pmubusp->pmubus_reglen);
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 		ddi_soft_state_free(per_pmubus_state, instance);
3237c478bd9Sstevel@tonic-gate 		break;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
3267c478bd9Sstevel@tonic-gate 	default:
3277c478bd9Sstevel@tonic-gate 		break;
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3347c478bd9Sstevel@tonic-gate void
pmubus_norep_get8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)3357c478bd9Sstevel@tonic-gate pmubus_norep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3367c478bd9Sstevel@tonic-gate     uint8_t *dev_addr, size_t repcount, uint_t flags)
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3417c478bd9Sstevel@tonic-gate void
pmubus_norep_get16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)3427c478bd9Sstevel@tonic-gate pmubus_norep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3437c478bd9Sstevel@tonic-gate     uint16_t *dev_addr, size_t repcount, uint_t flags)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3487c478bd9Sstevel@tonic-gate void
pmubus_norep_get32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)3497c478bd9Sstevel@tonic-gate pmubus_norep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3507c478bd9Sstevel@tonic-gate     uint32_t *dev_addr, size_t repcount, uint_t flags)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3557c478bd9Sstevel@tonic-gate void
pmubus_norep_get64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)3567c478bd9Sstevel@tonic-gate pmubus_norep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
3577c478bd9Sstevel@tonic-gate     uint64_t *dev_addr, size_t repcount, uint_t flags)
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3627c478bd9Sstevel@tonic-gate void
pmubus_norep_put8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)3637c478bd9Sstevel@tonic-gate pmubus_norep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
3647c478bd9Sstevel@tonic-gate     uint8_t *dev_addr, size_t repcount, uint_t flags)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3697c478bd9Sstevel@tonic-gate void
pmubus_norep_put16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)3707c478bd9Sstevel@tonic-gate pmubus_norep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
3717c478bd9Sstevel@tonic-gate     uint16_t *dev_addr, size_t repcount, uint_t flags)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3767c478bd9Sstevel@tonic-gate void
pmubus_norep_put32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)3777c478bd9Sstevel@tonic-gate pmubus_norep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
3787c478bd9Sstevel@tonic-gate     uint32_t *dev_addr, size_t repcount, uint_t flags)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3837c478bd9Sstevel@tonic-gate void
pmubus_norep_put64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)3847c478bd9Sstevel@tonic-gate pmubus_norep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
3857c478bd9Sstevel@tonic-gate     uint64_t *dev_addr, size_t repcount, uint_t flags)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3907c478bd9Sstevel@tonic-gate uint8_t
pmubus_get8(ddi_acc_impl_t * hdlp,uint8_t * addr)3917c478bd9Sstevel@tonic-gate pmubus_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	ddi_acc_hdl_t *hp = (ddi_acc_hdl_t *)hdlp;
3947c478bd9Sstevel@tonic-gate 	pmubus_mapreq_t *pmubus_mapreqp = hp->ah_bus_private;
3957c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *softsp = pmubus_mapreqp->mapreq_softsp;
3967c478bd9Sstevel@tonic-gate 	off_t offset;
3977c478bd9Sstevel@tonic-gate 	uint8_t value;
3987c478bd9Sstevel@tonic-gate 	uint8_t mask;
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	offset = pmubus_mapreqp->mapreq_addr + (uintptr_t)addr;
4017c478bd9Sstevel@tonic-gate 	offset &= PMUBUS_REGOFFSET;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	if ((pmubus_mapreqp->mapreq_flags) & MAPREQ_SHARED_BITS) {
4047c478bd9Sstevel@tonic-gate 		if (addr != 0 ||
4057c478bd9Sstevel@tonic-gate 		    pmubus_mapreqp->mapreq_size != sizeof (value)) {
4067c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_get8: load discarded, "
4077c478bd9Sstevel@tonic-gate 			    "incorrect access addr/size");
4087c478bd9Sstevel@tonic-gate 			return ((uint8_t)-1);
4097c478bd9Sstevel@tonic-gate 		}
4107c478bd9Sstevel@tonic-gate 		mask = pmubus_mapreqp->mapreq_mask;
4117c478bd9Sstevel@tonic-gate 	} else {
4127c478bd9Sstevel@tonic-gate 		mask = (uint8_t)-1;
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/* gets are simple, we just issue them no locking necessary */
4167c478bd9Sstevel@tonic-gate 	value = pci_config_get8(softsp->pmubus_reghdl, offset) & mask;
4177c478bd9Sstevel@tonic-gate 
418f47a9c50Smathue 	DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_get8: addr=%p offset=%lx value=%x "
419903a11ebSrh 	    "mask=%x\n", (void *)addr, offset, value, mask));
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	return (value);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4267c478bd9Sstevel@tonic-gate uint16_t
pmubus_noget16(ddi_acc_impl_t * hdlp,uint16_t * addr)4277c478bd9Sstevel@tonic-gate pmubus_noget16(ddi_acc_impl_t *hdlp, uint16_t *addr)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	return ((uint16_t)-1);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4337c478bd9Sstevel@tonic-gate uint32_t
pmubus_get32(ddi_acc_impl_t * hdlp,uint32_t * addr)4347c478bd9Sstevel@tonic-gate pmubus_get32(ddi_acc_impl_t *hdlp, uint32_t *addr)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	ddi_acc_hdl_t *hp = (ddi_acc_hdl_t *)hdlp;
4377c478bd9Sstevel@tonic-gate 	pmubus_mapreq_t *pmubus_mapreqp = hp->ah_bus_private;
4387c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *softsp = pmubus_mapreqp->mapreq_softsp;
4397c478bd9Sstevel@tonic-gate 	off_t offset = (uintptr_t)addr & PMUBUS_REGOFFSET;
4407c478bd9Sstevel@tonic-gate 	uint32_t value;
4417c478bd9Sstevel@tonic-gate 	uint32_t mask;
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	offset = pmubus_mapreqp->mapreq_addr + (uintptr_t)addr;
4447c478bd9Sstevel@tonic-gate 	offset &= PMUBUS_REGOFFSET;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	if ((pmubus_mapreqp->mapreq_flags) & MAPREQ_SHARED_BITS) {
4477c478bd9Sstevel@tonic-gate 		if (addr != 0 ||
4487c478bd9Sstevel@tonic-gate 		    pmubus_mapreqp->mapreq_size != sizeof (value)) {
4497c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_get32: load discarded, "
4507c478bd9Sstevel@tonic-gate 			    "incorrect access addr/size");
4517c478bd9Sstevel@tonic-gate 			return ((uint32_t)-1);
4527c478bd9Sstevel@tonic-gate 		}
4537c478bd9Sstevel@tonic-gate 		mask = pmubus_mapreqp->mapreq_mask;
4547c478bd9Sstevel@tonic-gate 	} else {
4557c478bd9Sstevel@tonic-gate 		mask = (uint32_t)-1;
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/* gets are simple, we just issue them no locking necessary */
4597c478bd9Sstevel@tonic-gate 	value = pci_config_get32(softsp->pmubus_reghdl, offset) & mask;
4607c478bd9Sstevel@tonic-gate 
461f47a9c50Smathue 	DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_get32: addr=%p offset=%lx value=%x "
462903a11ebSrh 	    "mask=%x\n", (void *)addr, offset, value, mask));
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	return (value);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4687c478bd9Sstevel@tonic-gate uint64_t
pmubus_noget64(ddi_acc_impl_t * hdlp,uint64_t * addr)4697c478bd9Sstevel@tonic-gate pmubus_noget64(ddi_acc_impl_t *hdlp, uint64_t *addr)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate 	return ((uint64_t)-1);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4757c478bd9Sstevel@tonic-gate void
pmubus_put8(ddi_acc_impl_t * hdlp,uint8_t * addr,uint8_t value)4767c478bd9Sstevel@tonic-gate pmubus_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate 	ddi_acc_hdl_t *hp = (ddi_acc_hdl_t *)hdlp;
4797c478bd9Sstevel@tonic-gate 	pmubus_mapreq_t *pmubus_mapreqp = hp->ah_bus_private;
4807c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *softsp = pmubus_mapreqp->mapreq_softsp;
4817c478bd9Sstevel@tonic-gate 	off_t offset;
4827c478bd9Sstevel@tonic-gate 	uint8_t tmp;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	offset = pmubus_mapreqp->mapreq_addr + (uintptr_t)addr;
4857c478bd9Sstevel@tonic-gate 	offset &= PMUBUS_REGOFFSET;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if ((pmubus_mapreqp->mapreq_flags) & MAPREQ_SHARED_BITS) {
4887c478bd9Sstevel@tonic-gate 		/*
4897c478bd9Sstevel@tonic-gate 		 * Process "bit lane" register
4907c478bd9Sstevel@tonic-gate 		 */
491f47a9c50Smathue 		DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_put8: addr=%p offset=%lx "
492903a11ebSrh 		    "value=%x mask=%lx\n", (void *)addr, offset, value,
4937c478bd9Sstevel@tonic-gate 		    pmubus_mapreqp->mapreq_mask));
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 		if (addr != 0 ||
4967c478bd9Sstevel@tonic-gate 		    pmubus_mapreqp->mapreq_size != sizeof (value)) {
4977c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_put8: store discarded, "
4987c478bd9Sstevel@tonic-gate 			    "incorrect access addr/size");
4997c478bd9Sstevel@tonic-gate 			return;
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 		mutex_enter(&softsp->pmubus_reg_access_lock);
5037c478bd9Sstevel@tonic-gate 		tmp = pci_config_get8(softsp->pmubus_reghdl, offset);
5047c478bd9Sstevel@tonic-gate 		tmp &= ~pmubus_mapreqp->mapreq_mask;
5057c478bd9Sstevel@tonic-gate 		value &= pmubus_mapreqp->mapreq_mask;
5067c478bd9Sstevel@tonic-gate 		tmp |= value;
5077c478bd9Sstevel@tonic-gate 		pci_config_put8(softsp->pmubus_reghdl, offset, tmp);
5087c478bd9Sstevel@tonic-gate 		mutex_exit(&softsp->pmubus_reg_access_lock);
5097c478bd9Sstevel@tonic-gate 	} else {
5107c478bd9Sstevel@tonic-gate 		/*
5117c478bd9Sstevel@tonic-gate 		 * Process shared register
5127c478bd9Sstevel@tonic-gate 		 */
513f47a9c50Smathue 		DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_put8: addr=%p offset=%lx "
514903a11ebSrh 		    "value=%x\n", (void *)addr, offset, value));
5157c478bd9Sstevel@tonic-gate 		pci_config_put8(softsp->pmubus_reghdl, offset, value);
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	/* Flush store buffers XXX Should let drivers do this. */
5197c478bd9Sstevel@tonic-gate 	tmp = pci_config_get8(softsp->pmubus_reghdl, offset);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5237c478bd9Sstevel@tonic-gate void
pmubus_noput16(ddi_acc_impl_t * hdlp,uint16_t * addr,uint16_t value)5247c478bd9Sstevel@tonic-gate pmubus_noput16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5297c478bd9Sstevel@tonic-gate void
pmubus_put32(ddi_acc_impl_t * hdlp,uint32_t * addr,uint32_t value)5307c478bd9Sstevel@tonic-gate pmubus_put32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	ddi_acc_hdl_t *hp = (ddi_acc_hdl_t *)hdlp;
5337c478bd9Sstevel@tonic-gate 	pmubus_mapreq_t *pmubus_mapreqp = hp->ah_bus_private;
5347c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *softsp = pmubus_mapreqp->mapreq_softsp;
5357c478bd9Sstevel@tonic-gate 	off_t offset;
5367c478bd9Sstevel@tonic-gate 	uint32_t tmp;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	offset = pmubus_mapreqp->mapreq_addr + (uintptr_t)addr;
5397c478bd9Sstevel@tonic-gate 	offset &= PMUBUS_REGOFFSET;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	if ((pmubus_mapreqp->mapreq_flags) & MAPREQ_SHARED_BITS) {
5427c478bd9Sstevel@tonic-gate 		/*
5437c478bd9Sstevel@tonic-gate 		 * Process "bit lane" register
5447c478bd9Sstevel@tonic-gate 		 */
545f47a9c50Smathue 		DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_put32: addr=%p offset=%lx "
546903a11ebSrh 		    "value=%x mask=%lx\n", (void *)addr, offset, value,
5477c478bd9Sstevel@tonic-gate 		    pmubus_mapreqp->mapreq_mask));
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 		if (addr != 0 ||
5507c478bd9Sstevel@tonic-gate 		    pmubus_mapreqp->mapreq_size != sizeof (value)) {
5517c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "pmubus_put32: store discarded, "
5527c478bd9Sstevel@tonic-gate 			    "incorrect access addr/size");
5537c478bd9Sstevel@tonic-gate 			return;
5547c478bd9Sstevel@tonic-gate 		}
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 		mutex_enter(&softsp->pmubus_reg_access_lock);
5577c478bd9Sstevel@tonic-gate 		tmp = pci_config_get32(softsp->pmubus_reghdl, offset);
5587c478bd9Sstevel@tonic-gate 		tmp &= ~pmubus_mapreqp->mapreq_mask;
5597c478bd9Sstevel@tonic-gate 		value &= pmubus_mapreqp->mapreq_mask;
5607c478bd9Sstevel@tonic-gate 		tmp |= value;
5617c478bd9Sstevel@tonic-gate 		pci_config_put32(softsp->pmubus_reghdl, offset, tmp);
5627c478bd9Sstevel@tonic-gate 		mutex_exit(&softsp->pmubus_reg_access_lock);
5637c478bd9Sstevel@tonic-gate 	} else {
5647c478bd9Sstevel@tonic-gate 		/*
5657c478bd9Sstevel@tonic-gate 		 * Process shared register
5667c478bd9Sstevel@tonic-gate 		 */
567f47a9c50Smathue 		DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_put32: addr=%p offset=%lx "
568903a11ebSrh 		    "value=%x\n", (void *)addr, offset, value));
5697c478bd9Sstevel@tonic-gate 		pci_config_put32(softsp->pmubus_reghdl, offset, value);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	/* Flush store buffers XXX Should let drivers do this. */
5737c478bd9Sstevel@tonic-gate 	tmp = pci_config_get32(softsp->pmubus_reghdl, offset);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5777c478bd9Sstevel@tonic-gate void
pmubus_noput64(ddi_acc_impl_t * hdlp,uint64_t * addr,uint64_t value)5787c478bd9Sstevel@tonic-gate pmubus_noput64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate  * This routine is used to translate our children's register properties.
5847c478bd9Sstevel@tonic-gate  * The return value specifies which type of register has been translated.
5857c478bd9Sstevel@tonic-gate  */
5867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5877c478bd9Sstevel@tonic-gate int
pmubus_apply_range(pmubus_devstate_t * pmubusp,dev_info_t * rdip,pmubus_regspec_t * regp,pci_regspec_t * pci_regp)5887c478bd9Sstevel@tonic-gate pmubus_apply_range(pmubus_devstate_t *pmubusp, dev_info_t *rdip,
5897c478bd9Sstevel@tonic-gate     pmubus_regspec_t *regp, pci_regspec_t *pci_regp)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	pmu_rangespec_t *rangep;
5927c478bd9Sstevel@tonic-gate 	int nranges = pmubusp->pmubus_nranges;
5937c478bd9Sstevel@tonic-gate 	int i;
5947c478bd9Sstevel@tonic-gate 	off_t offset;
5957c478bd9Sstevel@tonic-gate 	int ret = DDI_ME_REGSPEC_RANGE;
5967c478bd9Sstevel@tonic-gate 	uint64_t addr;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	addr = regp->reg_addr & ~MAPPING_SHARED_BITS_MASK;
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	/* Scan the ranges for a match */
6017c478bd9Sstevel@tonic-gate 	for (i = 0, rangep = pmubusp->pmubus_rangep; i < nranges; i++, rangep++)
6027c478bd9Sstevel@tonic-gate 		if ((rangep->rng_child <= addr) &&
6037c478bd9Sstevel@tonic-gate 		    ((addr + regp->reg_size) <=
6047c478bd9Sstevel@tonic-gate 		    (rangep->rng_child + rangep->rng_size))) {
6057c478bd9Sstevel@tonic-gate 			ret = DDI_SUCCESS;
6067c478bd9Sstevel@tonic-gate 			break;
6077c478bd9Sstevel@tonic-gate 		}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS)
6107c478bd9Sstevel@tonic-gate 		return (ret);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	/* Get the translated register */
6137c478bd9Sstevel@tonic-gate 	offset = addr - rangep->rng_child;
6147c478bd9Sstevel@tonic-gate 	pci_regp->pci_phys_hi = rangep->rng_parent_hi;
6157c478bd9Sstevel@tonic-gate 	pci_regp->pci_phys_mid = rangep->rng_parent_mid;
6167c478bd9Sstevel@tonic-gate 	pci_regp->pci_phys_low = rangep->rng_parent_low + offset;
6177c478bd9Sstevel@tonic-gate 	pci_regp->pci_size_hi = 0;
6187c478bd9Sstevel@tonic-gate 	pci_regp->pci_size_low = MIN(regp->reg_size, rangep->rng_size);
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	/* Figure out the type of reg space we have */
6217c478bd9Sstevel@tonic-gate 	if (pci_regp->pci_phys_hi == pmubusp->pmubus_regp->pci_phys_hi) {
6227c478bd9Sstevel@tonic-gate 		ret = MAPREQ_SHARED_REG;
6237c478bd9Sstevel@tonic-gate 		if (regp->reg_addr & MAPPING_SHARED_BITS_MASK)
6247c478bd9Sstevel@tonic-gate 			ret |= MAPREQ_SHARED_BITS;
6257c478bd9Sstevel@tonic-gate 	}
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	return (ret);
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate static uint64_t
pmubus_mask(pmubus_obpregspec_t * regs,int32_t rnumber,uint64_t * masks)6317c478bd9Sstevel@tonic-gate pmubus_mask(pmubus_obpregspec_t *regs, int32_t rnumber,
6327c478bd9Sstevel@tonic-gate     uint64_t *masks)
6337c478bd9Sstevel@tonic-gate {
6347c478bd9Sstevel@tonic-gate 	int i;
6357c478bd9Sstevel@tonic-gate 	long n = -1;
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	for (i = 0; i <= rnumber; i++)
6387c478bd9Sstevel@tonic-gate 		if (regs[i].reg_addr_hi & 0x80000000)
6397c478bd9Sstevel@tonic-gate 			n++;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if (n == -1) {
6427c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "pmubus_mask: missing mask");
6437c478bd9Sstevel@tonic-gate 		return (0);
6447c478bd9Sstevel@tonic-gate 	}
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	return (masks[n]);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate  * The pmubus_map routine determines if it's child is attempting to map a
6517c478bd9Sstevel@tonic-gate  * shared reg.  If it is, it installs it's own vectors and bus private pointer.
6527c478bd9Sstevel@tonic-gate  */
6537c478bd9Sstevel@tonic-gate static int
pmubus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t off,off_t len,caddr_t * addrp)6547c478bd9Sstevel@tonic-gate pmubus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
6557c478bd9Sstevel@tonic-gate 	off_t off, off_t len, caddr_t *addrp)
6567c478bd9Sstevel@tonic-gate {
6577c478bd9Sstevel@tonic-gate 	pmubus_devstate_t *pmubusp = ddi_get_soft_state(per_pmubus_state,
6587c478bd9Sstevel@tonic-gate 	    ddi_get_instance(dip));
6597c478bd9Sstevel@tonic-gate 	dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent;
6607c478bd9Sstevel@tonic-gate 	pmubus_regspec_t pmubus_rp;
6617c478bd9Sstevel@tonic-gate 	pmubus_obpregspec_t *pmubus_regs = NULL;
6627c478bd9Sstevel@tonic-gate 	int pmubus_regs_size;
6637c478bd9Sstevel@tonic-gate 	uint64_t *pmubus_regmask = NULL;
6647c478bd9Sstevel@tonic-gate 	int pmubus_regmask_size;
6657c478bd9Sstevel@tonic-gate 	pci_regspec_t pci_reg;
6667c478bd9Sstevel@tonic-gate 	int32_t rnumber = mp->map_obj.rnumber;
6677c478bd9Sstevel@tonic-gate 	pmubus_mapreq_t *pmubus_mapreqp;
6687c478bd9Sstevel@tonic-gate 	int ret = DDI_SUCCESS;
6697c478bd9Sstevel@tonic-gate 	char *map_fail1 = "Map Type Unknown";
6707c478bd9Sstevel@tonic-gate 	char *map_fail2 = "DDI_MT_REGSPEC";
6717c478bd9Sstevel@tonic-gate 	char *s = map_fail1;
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	*addrp = NULL;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	/*
6767c478bd9Sstevel@tonic-gate 	 * Handle the mapping according to its type.
6777c478bd9Sstevel@tonic-gate 	 */
678f47a9c50Smathue 	DPRINTF(PMUBUS_MAP_DEBUG, ("rdip=%s%d: off=%lx len=%lx\n",
6797c478bd9Sstevel@tonic-gate 	    ddi_get_name(rdip), ddi_get_instance(rdip), off, len));
6807c478bd9Sstevel@tonic-gate 	switch (mp->map_type) {
6817c478bd9Sstevel@tonic-gate 	case DDI_MT_RNUMBER: {
6827c478bd9Sstevel@tonic-gate 		int n;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		/*
6857c478bd9Sstevel@tonic-gate 		 * Get the "reg" property from the device node and convert
6867c478bd9Sstevel@tonic-gate 		 * it to our parent's format.
6877c478bd9Sstevel@tonic-gate 		 */
6887c478bd9Sstevel@tonic-gate 		rnumber = mp->map_obj.rnumber;
6897c478bd9Sstevel@tonic-gate 		DPRINTF(PMUBUS_MAP_DEBUG, ("rdip=%s%d: rnumber=%x "
690f47a9c50Smathue 		    "handlep=%p\n", ddi_get_name(rdip), ddi_get_instance(rdip),
691903a11ebSrh 		    rnumber, (void *)mp->map_handlep));
6927c478bd9Sstevel@tonic-gate 
693a3282898Scth 		if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
6947c478bd9Sstevel@tonic-gate 		    "reg", (caddr_t)&pmubus_regs, &pmubus_regs_size) !=
6957c478bd9Sstevel@tonic-gate 		    DDI_SUCCESS) {
6967c478bd9Sstevel@tonic-gate 			DPRINTF(PMUBUS_MAP_DEBUG, ("can't get reg "
6977c478bd9Sstevel@tonic-gate 			    "property\n"));
6987c478bd9Sstevel@tonic-gate 			ret = DDI_ME_RNUMBER_RANGE;
6997c478bd9Sstevel@tonic-gate 			goto done;
7007c478bd9Sstevel@tonic-gate 		}
7017c478bd9Sstevel@tonic-gate 		n = pmubus_regs_size / sizeof (pmubus_obpregspec_t);
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 		if (rnumber < 0 || rnumber >= n) {
7047c478bd9Sstevel@tonic-gate 			DPRINTF(PMUBUS_MAP_DEBUG, ("rnumber out of range\n"));
7057c478bd9Sstevel@tonic-gate 			ret = DDI_ME_RNUMBER_RANGE;
7067c478bd9Sstevel@tonic-gate 			goto done;
7077c478bd9Sstevel@tonic-gate 		}
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 		pmubus_rp.reg_addr = ((uint64_t)
7107c478bd9Sstevel@tonic-gate 		    pmubus_regs[rnumber].reg_addr_hi << 32) |
7117c478bd9Sstevel@tonic-gate 		    (uint64_t)pmubus_regs[rnumber].reg_addr_lo;
7127c478bd9Sstevel@tonic-gate 		pmubus_rp.reg_size = pmubus_regs[rnumber].reg_size;
7137c478bd9Sstevel@tonic-gate 
714a3282898Scth 		(void) ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
7157c478bd9Sstevel@tonic-gate 		    "register-mask", (caddr_t)&pmubus_regmask,
7167c478bd9Sstevel@tonic-gate 		    &pmubus_regmask_size);
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 		/* Create our own mapping private structure */
7197c478bd9Sstevel@tonic-gate 		break;
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	}
7227c478bd9Sstevel@tonic-gate 	case DDI_MT_REGSPEC:
7237c478bd9Sstevel@tonic-gate 		/*
7247c478bd9Sstevel@tonic-gate 		 * This bus has no bus children that have to map in an address
7257c478bd9Sstevel@tonic-gate 		 * space, so we can assume that we'll never see an
7267c478bd9Sstevel@tonic-gate 		 * DDI_MT_REGSPEC request
7277c478bd9Sstevel@tonic-gate 		 */
7287c478bd9Sstevel@tonic-gate 		s = map_fail2;
7297c478bd9Sstevel@tonic-gate 		ret = DDI_ME_REGSPEC_RANGE;
7307c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
7317c478bd9Sstevel@tonic-gate 
7327c478bd9Sstevel@tonic-gate 	default:
7337c478bd9Sstevel@tonic-gate 		if (ret == DDI_SUCCESS)
7347c478bd9Sstevel@tonic-gate 			ret = DDI_ME_INVAL;
7357c478bd9Sstevel@tonic-gate 		DPRINTF(PMUBUS_MAP_DEBUG, ("rdip=%s%d: pmubus_map: "
7367c478bd9Sstevel@tonic-gate 		    "%s is an invalid map type.\nmap request handlep=0x%p\n",
737903a11ebSrh 		    ddi_get_name(rdip), ddi_get_instance(rdip), s, (void *)mp));
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 		ret = DDI_ME_RNUMBER_RANGE;
7407c478bd9Sstevel@tonic-gate 		goto done;
7417c478bd9Sstevel@tonic-gate 	}
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	/* Adjust our reg property with offset and length */
7447c478bd9Sstevel@tonic-gate 	if ((pmubus_rp.reg_addr + off) >
7457c478bd9Sstevel@tonic-gate 	    (pmubus_rp.reg_addr + pmubus_rp.reg_size)) {
7467c478bd9Sstevel@tonic-gate 		ret = DDI_ME_INVAL;
7477c478bd9Sstevel@tonic-gate 		goto done;
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	pmubus_rp.reg_addr += off;
7517c478bd9Sstevel@tonic-gate 	if (len && (len < pmubus_rp.reg_size))
7527c478bd9Sstevel@tonic-gate 		pmubus_rp.reg_size = len;
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	/* Translate our child regspec into our parents address domain */
7557c478bd9Sstevel@tonic-gate 	ret = pmubus_apply_range(pmubusp, rdip, &pmubus_rp, &pci_reg);
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	/* Check if the apply range failed */
7587c478bd9Sstevel@tonic-gate 	if (ret < DDI_SUCCESS)
7597c478bd9Sstevel@tonic-gate 		goto done;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	/*
7627c478bd9Sstevel@tonic-gate 	 * If our childs xlated address falls into our shared address range,
7637c478bd9Sstevel@tonic-gate 	 * setup our mapping handle.
7647c478bd9Sstevel@tonic-gate 	 */
7657c478bd9Sstevel@tonic-gate 	if (ret > DDI_SUCCESS) {
7667c478bd9Sstevel@tonic-gate 		/* Figure out if we're mapping or unmapping */
7677c478bd9Sstevel@tonic-gate 		switch (mp->map_op) {
7687c478bd9Sstevel@tonic-gate 		case DDI_MO_MAP_LOCKED: {
7697c478bd9Sstevel@tonic-gate 			ddi_acc_impl_t *hp = (ddi_acc_impl_t *)mp->map_handlep;
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 			pmubus_mapreqp = kmem_alloc(sizeof (*pmubus_mapreqp),
7727c478bd9Sstevel@tonic-gate 			    KM_SLEEP);
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 			pmubus_mapreqp->mapreq_flags = ret;
7757c478bd9Sstevel@tonic-gate 			pmubus_mapreqp->mapreq_softsp = pmubusp;
7767c478bd9Sstevel@tonic-gate 			pmubus_mapreqp->mapreq_addr = pmubus_rp.reg_addr;
7777c478bd9Sstevel@tonic-gate 			pmubus_mapreqp->mapreq_size = pmubus_rp.reg_size;
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 			if (ret & MAPREQ_SHARED_BITS) {
7807c478bd9Sstevel@tonic-gate 				pmubus_mapreqp->mapreq_mask =
7817c478bd9Sstevel@tonic-gate 				    pmubus_mask(pmubus_regs, rnumber,
7827c478bd9Sstevel@tonic-gate 				    pmubus_regmask);
7837c478bd9Sstevel@tonic-gate 				DPRINTF(PMUBUS_MAP_DEBUG, ("rnumber=%d "
784f47a9c50Smathue 				    "mask=%lx\n", rnumber,
7857c478bd9Sstevel@tonic-gate 				    pmubus_mapreqp->mapreq_mask));
7867c478bd9Sstevel@tonic-gate 				if (pmubus_mapreqp->mapreq_mask == 0) {
7877c478bd9Sstevel@tonic-gate 					kmem_free(pmubus_mapreqp,
7887c478bd9Sstevel@tonic-gate 					    sizeof (pmubus_mapreq_t));
7897c478bd9Sstevel@tonic-gate 					ret = DDI_ME_INVAL;
7907c478bd9Sstevel@tonic-gate 					break;
7917c478bd9Sstevel@tonic-gate 				}
7927c478bd9Sstevel@tonic-gate 			}
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 			hp->ahi_common.ah_bus_private = pmubus_mapreqp;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 			/* Initialize the access vectors */
7977c478bd9Sstevel@tonic-gate 			hp->ahi_get8 = pmubus_get8;
7987c478bd9Sstevel@tonic-gate 			hp->ahi_get16 = pmubus_noget16;
7997c478bd9Sstevel@tonic-gate 			hp->ahi_get32 = pmubus_get32;
8007c478bd9Sstevel@tonic-gate 			hp->ahi_get64 = pmubus_noget64;
8017c478bd9Sstevel@tonic-gate 			hp->ahi_put8 = pmubus_put8;
8027c478bd9Sstevel@tonic-gate 			hp->ahi_put16 = pmubus_noput16;
8037c478bd9Sstevel@tonic-gate 			hp->ahi_put32 = pmubus_put32;
8047c478bd9Sstevel@tonic-gate 			hp->ahi_put64 = pmubus_noput64;
8057c478bd9Sstevel@tonic-gate 			hp->ahi_rep_get8 = pmubus_norep_get8;
8067c478bd9Sstevel@tonic-gate 			hp->ahi_rep_get16 = pmubus_norep_get16;
8077c478bd9Sstevel@tonic-gate 			hp->ahi_rep_get32 = pmubus_norep_get32;
8087c478bd9Sstevel@tonic-gate 			hp->ahi_rep_get64 = pmubus_norep_get64;
8097c478bd9Sstevel@tonic-gate 			hp->ahi_rep_put8 = pmubus_norep_put8;
8107c478bd9Sstevel@tonic-gate 			hp->ahi_rep_put16 = pmubus_norep_put16;
8117c478bd9Sstevel@tonic-gate 			hp->ahi_rep_put32 = pmubus_norep_put32;
8127c478bd9Sstevel@tonic-gate 			hp->ahi_rep_put64 = pmubus_norep_put64;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 			ret = DDI_SUCCESS;
8157c478bd9Sstevel@tonic-gate 			break;
8167c478bd9Sstevel@tonic-gate 		}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 		case DDI_MO_UNMAP: {
8197c478bd9Sstevel@tonic-gate 			ddi_acc_impl_t *hp = (ddi_acc_impl_t *)mp->map_handlep;
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 			pmubus_mapreqp = hp->ahi_common.ah_bus_private;
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 			/* Free the our map request struct */
8247c478bd9Sstevel@tonic-gate 			kmem_free(pmubus_mapreqp, sizeof (pmubus_mapreq_t));
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 			ret = DDI_SUCCESS;
8277c478bd9Sstevel@tonic-gate 			break;
8287c478bd9Sstevel@tonic-gate 		}
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 		default:
8317c478bd9Sstevel@tonic-gate 			ret = DDI_ME_UNSUPPORTED;
8327c478bd9Sstevel@tonic-gate 		}
8337c478bd9Sstevel@tonic-gate 	} else {
8347c478bd9Sstevel@tonic-gate 		/* Prepare the map request struct for a call to our parent */
8357c478bd9Sstevel@tonic-gate 		mp->map_type = DDI_MT_REGSPEC;
8367c478bd9Sstevel@tonic-gate 		mp->map_obj.rp = (struct regspec *)&pci_reg;
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 		/* Pass the mapping operation up the device tree */
8397c478bd9Sstevel@tonic-gate 		ret = (DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)
8407c478bd9Sstevel@tonic-gate 		    (pdip, rdip, mp, off, len, addrp);
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate done:
8447c478bd9Sstevel@tonic-gate 	if (pmubus_regs != NULL)
8457c478bd9Sstevel@tonic-gate 		kmem_free(pmubus_regs, pmubus_regs_size);
8467c478bd9Sstevel@tonic-gate 	if (pmubus_regmask != NULL)
8477c478bd9Sstevel@tonic-gate 		kmem_free(pmubus_regmask, pmubus_regmask_size);
8487c478bd9Sstevel@tonic-gate 	return (ret);
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate static int
pmubus_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)8527c478bd9Sstevel@tonic-gate pmubus_ctlops(dev_info_t *dip, dev_info_t *rdip,
8537c478bd9Sstevel@tonic-gate     ddi_ctl_enum_t op, void *arg, void *result)
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate 	dev_info_t *child = (dev_info_t *)arg;
8567c478bd9Sstevel@tonic-gate 	pmubus_obpregspec_t *pmubus_rp;
8577c478bd9Sstevel@tonic-gate 	char name[9];
8587c478bd9Sstevel@tonic-gate 	int reglen;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	switch (op) {
8617c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_INITCHILD:
8627c478bd9Sstevel@tonic-gate 
863a3282898Scth 		if (ddi_getlongprop(DDI_DEV_T_ANY, child,
8647c478bd9Sstevel@tonic-gate 		    DDI_PROP_DONTPASS, "reg", (caddr_t)&pmubus_rp,
8657c478bd9Sstevel@tonic-gate 		    &reglen) != DDI_SUCCESS) {
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
8687c478bd9Sstevel@tonic-gate 		}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 		if ((reglen % sizeof (pmubus_obpregspec_t)) != 0) {
8717c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN,
8727c478bd9Sstevel@tonic-gate 			    "pmubus: reg property not well-formed for "
8737c478bd9Sstevel@tonic-gate 			    "%s size=%d\n", ddi_node_name(child), reglen);
8747c478bd9Sstevel@tonic-gate 			kmem_free(pmubus_rp, reglen);
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
8777c478bd9Sstevel@tonic-gate 		}
8787c478bd9Sstevel@tonic-gate 		(void) snprintf(name, sizeof (name), "%x,%x",
8797c478bd9Sstevel@tonic-gate 		    pmubus_rp->reg_addr_hi, pmubus_rp->reg_addr_lo);
8807c478bd9Sstevel@tonic-gate 		ddi_set_name_addr(child, name);
8817c478bd9Sstevel@tonic-gate 		kmem_free(pmubus_rp, reglen);
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_UNINITCHILD:
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 		ddi_set_name_addr(child, NULL);
8887c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node(child, NULL);
8897c478bd9Sstevel@tonic-gate 		impl_rem_dev_props(child);
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8927c478bd9Sstevel@tonic-gate 	default:
8937c478bd9Sstevel@tonic-gate 		break;
8947c478bd9Sstevel@tonic-gate 	}
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	return (ddi_ctlops(dip, rdip, op, arg, result));
8977c478bd9Sstevel@tonic-gate }
898