xref: /titanic_52/usr/src/uts/sun4u/io/upa64s.c (revision a195726fa33097e56cf1c25c31feddb827e140f0)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/conf.h>
317c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
337c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
357c478bd9Sstevel@tonic-gate #include <sys/ddi_subrdefs.h>
367c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
377c478bd9Sstevel@tonic-gate #include <sys/errno.h>
387c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
397c478bd9Sstevel@tonic-gate #include <sys/debug.h>
407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
417c478bd9Sstevel@tonic-gate #include <sys/spl.h>
427c478bd9Sstevel@tonic-gate #include <sys/async.h>
437c478bd9Sstevel@tonic-gate #include <sys/dvma.h>
447c478bd9Sstevel@tonic-gate #include <sys/upa64s.h>
457c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * driver global data:
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate static void *per_upa64s_state;		/* soft state pointer */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * function prototypes for bus ops routines:
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate static int
567c478bd9Sstevel@tonic-gate upa64s_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
577c478bd9Sstevel@tonic-gate     off_t offset, off_t len, caddr_t *addrp);
587c478bd9Sstevel@tonic-gate static int
597c478bd9Sstevel@tonic-gate upa64s_ctlops(dev_info_t *dip, dev_info_t *rdip,
607c478bd9Sstevel@tonic-gate     ddi_ctl_enum_t op, void *arg, void *result);
617c478bd9Sstevel@tonic-gate static int
627c478bd9Sstevel@tonic-gate upa64_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
637c478bd9Sstevel@tonic-gate     ddi_intr_handle_impl_t *hdlp, void *result);
647c478bd9Sstevel@tonic-gate static int
657c478bd9Sstevel@tonic-gate upa64s_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
667c478bd9Sstevel@tonic-gate     ddi_intr_handle_impl_t *hdlp);
677c478bd9Sstevel@tonic-gate static int
687c478bd9Sstevel@tonic-gate upa64s_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
697c478bd9Sstevel@tonic-gate     ddi_intr_handle_impl_t *hdlp);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * function prototypes for dev ops routines:
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate static int upa64s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
757c478bd9Sstevel@tonic-gate static int upa64s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
767c478bd9Sstevel@tonic-gate static int upa64s_power(dev_info_t *dip, int component, int level);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * bus ops and dev ops structures:
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate static struct bus_ops upa64s_bus_ops = {
827c478bd9Sstevel@tonic-gate 	BUSO_REV,
837c478bd9Sstevel@tonic-gate 	upa64s_map,
847c478bd9Sstevel@tonic-gate 	0,
857c478bd9Sstevel@tonic-gate 	0,
867c478bd9Sstevel@tonic-gate 	0,
877c478bd9Sstevel@tonic-gate 	i_ddi_map_fault,
887c478bd9Sstevel@tonic-gate 	ddi_no_dma_map,
897c478bd9Sstevel@tonic-gate 	ddi_no_dma_allochdl,
907c478bd9Sstevel@tonic-gate 	ddi_no_dma_freehdl,
917c478bd9Sstevel@tonic-gate 	ddi_no_dma_bindhdl,
927c478bd9Sstevel@tonic-gate 	ddi_no_dma_unbindhdl,
937c478bd9Sstevel@tonic-gate 	ddi_no_dma_flush,
947c478bd9Sstevel@tonic-gate 	ddi_no_dma_win,
957c478bd9Sstevel@tonic-gate 	ddi_no_dma_mctl,
967c478bd9Sstevel@tonic-gate 	upa64s_ctlops,
977c478bd9Sstevel@tonic-gate 	ddi_bus_prop_op,
987c478bd9Sstevel@tonic-gate 	0,
997c478bd9Sstevel@tonic-gate 	0,
1007c478bd9Sstevel@tonic-gate 	0,
1017c478bd9Sstevel@tonic-gate 	0,
1027c478bd9Sstevel@tonic-gate 	0,
1037c478bd9Sstevel@tonic-gate 	0,
1047c478bd9Sstevel@tonic-gate 	0,
1057c478bd9Sstevel@tonic-gate 	0,
1067c478bd9Sstevel@tonic-gate 	0,
1077c478bd9Sstevel@tonic-gate 	0,
1087c478bd9Sstevel@tonic-gate 	0,
1097c478bd9Sstevel@tonic-gate 	0,
1107c478bd9Sstevel@tonic-gate 	upa64_intr_ops
1117c478bd9Sstevel@tonic-gate };
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate static struct dev_ops upa64s_ops = {
1147c478bd9Sstevel@tonic-gate 	DEVO_REV,
1157c478bd9Sstevel@tonic-gate 	0,
1167c478bd9Sstevel@tonic-gate 	ddi_no_info,
1177c478bd9Sstevel@tonic-gate 	nulldev,
1187c478bd9Sstevel@tonic-gate 	0,
1197c478bd9Sstevel@tonic-gate 	upa64s_attach,
1207c478bd9Sstevel@tonic-gate 	upa64s_detach,
1217c478bd9Sstevel@tonic-gate 	nodev,
1227c478bd9Sstevel@tonic-gate 	(struct cb_ops *)0,
1237c478bd9Sstevel@tonic-gate 	&upa64s_bus_ops,
1247c478bd9Sstevel@tonic-gate 	upa64s_power
1257c478bd9Sstevel@tonic-gate };
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate /*
1287c478bd9Sstevel@tonic-gate  * module definitions:
1297c478bd9Sstevel@tonic-gate  */
1307c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
1317c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1347c478bd9Sstevel@tonic-gate 	&mod_driverops, 		/* type of module */
1357c478bd9Sstevel@tonic-gate 	"UPA64S nexus driver %I%",	/* name of module */
1367c478bd9Sstevel@tonic-gate 	&upa64s_ops,			/* driver ops */
1377c478bd9Sstevel@tonic-gate };
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1407c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1417c478bd9Sstevel@tonic-gate };
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate int
1447c478bd9Sstevel@tonic-gate _init(void)
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate 	int e;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/*
1497c478bd9Sstevel@tonic-gate 	 * Initialize per instance bus soft state pointer.
1507c478bd9Sstevel@tonic-gate 	 */
1517c478bd9Sstevel@tonic-gate 	if (e = ddi_soft_state_init(&per_upa64s_state,
1527c478bd9Sstevel@tonic-gate 	    sizeof (upa64s_devstate_t), 2))
1537c478bd9Sstevel@tonic-gate 		return (e);
1547c478bd9Sstevel@tonic-gate 	/*
1557c478bd9Sstevel@tonic-gate 	 * Install the module.
1567c478bd9Sstevel@tonic-gate 	 */
1577c478bd9Sstevel@tonic-gate 	if (e = mod_install(&modlinkage))
1587c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&per_upa64s_state);
1597c478bd9Sstevel@tonic-gate 	return (e);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate int
1637c478bd9Sstevel@tonic-gate _fini(void)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	int e = mod_remove(&modlinkage);
1667c478bd9Sstevel@tonic-gate 	if (e)
1677c478bd9Sstevel@tonic-gate 		return (e);
1687c478bd9Sstevel@tonic-gate 	ddi_soft_state_fini(&per_upa64s_state);
1697c478bd9Sstevel@tonic-gate 	return (e);
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate int
1737c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * forward declarations:
1817c478bd9Sstevel@tonic-gate  */
1827c478bd9Sstevel@tonic-gate static void upa64s_intrdist(void *arg);
1837c478bd9Sstevel@tonic-gate static int init_child(dev_info_t *child);
1847c478bd9Sstevel@tonic-gate static int report_dev(dev_info_t *dip);
1857c478bd9Sstevel@tonic-gate static int get_properties(upa64s_devstate_t *upa64s_p, dev_info_t *dip);
1867c478bd9Sstevel@tonic-gate static void save_state(upa64s_devstate_t *upa64s_p);
1877c478bd9Sstevel@tonic-gate static void restore_state(upa64s_devstate_t *upa64s_p);
1887c478bd9Sstevel@tonic-gate static int xlate_reg_prop(dev_info_t *dip, upa64s_regspec_t *upa64s_rp,
1897c478bd9Sstevel@tonic-gate     off_t off, off_t len, struct regspec *rp);
1907c478bd9Sstevel@tonic-gate static int get_reg_set(dev_info_t *dip, dev_info_t *child, int rnumber,
1917c478bd9Sstevel@tonic-gate     off_t off, off_t len, struct regspec *rp);
1927c478bd9Sstevel@tonic-gate static off_t get_reg_set_size(dev_info_t *child, int rnumber);
1937c478bd9Sstevel@tonic-gate static uint_t get_nreg_set(dev_info_t *child);
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /* device driver entry points */
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate /*
1997c478bd9Sstevel@tonic-gate  * attach entry point:
2007c478bd9Sstevel@tonic-gate  */
2017c478bd9Sstevel@tonic-gate static int
2027c478bd9Sstevel@tonic-gate upa64s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate 	upa64s_devstate_t *upa64s_p;	/* per upa64s state pointer */
2057c478bd9Sstevel@tonic-gate 	ddi_device_acc_attr_t attr;
2067c478bd9Sstevel@tonic-gate 	int instance;
2077c478bd9Sstevel@tonic-gate 	char *pmc[] = { "NAME=Framebuffer Power", "0=Off", "1=On", NULL };
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	switch (cmd) {
2107c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
2117c478bd9Sstevel@tonic-gate 		/*
2127c478bd9Sstevel@tonic-gate 		 * Allocate and get the per instance soft state structure.
2137c478bd9Sstevel@tonic-gate 		 */
2147c478bd9Sstevel@tonic-gate 		instance = ddi_get_instance(dip);
2157c478bd9Sstevel@tonic-gate 		if (alloc_upa64s_soft_state(instance) != DDI_SUCCESS) {
2167c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: can't allocate upa64s state",
2177c478bd9Sstevel@tonic-gate 			    ddi_get_name(dip), instance);
2187c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
2197c478bd9Sstevel@tonic-gate 		}
2207c478bd9Sstevel@tonic-gate 		upa64s_p = get_upa64s_soft_state(instance);
2217c478bd9Sstevel@tonic-gate 		upa64s_p->dip = dip;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 		/*
2247c478bd9Sstevel@tonic-gate 		 * Get key properties of the bridge node.
2257c478bd9Sstevel@tonic-gate 		 */
2267c478bd9Sstevel@tonic-gate 		if (get_properties(upa64s_p, dip) != DDI_SUCCESS)
2277c478bd9Sstevel@tonic-gate 			goto fail;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		/*
2307c478bd9Sstevel@tonic-gate 		 * Create "pm-components" property for the purpose of
2317c478bd9Sstevel@tonic-gate 		 * doing Power Management.
2327c478bd9Sstevel@tonic-gate 		 */
2337c478bd9Sstevel@tonic-gate 		if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
2347c478bd9Sstevel@tonic-gate 		    "pm-components", pmc, ((sizeof (pmc)/sizeof (char *)) - 1))
2357c478bd9Sstevel@tonic-gate 		    != DDI_PROP_SUCCESS) {
2367c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: failed to create pm-components "
2377c478bd9Sstevel@tonic-gate 			    "property.", ddi_get_name(dip), instance);
2387c478bd9Sstevel@tonic-gate 			goto fail;
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 		/* Map in the UPA's registers */
2427c478bd9Sstevel@tonic-gate 		attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
2437c478bd9Sstevel@tonic-gate 		attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
2447c478bd9Sstevel@tonic-gate 		attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
2457c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 0,
2467c478bd9Sstevel@tonic-gate 		    (caddr_t *)&upa64s_p->config_base, 0, 0, &attr,
2477c478bd9Sstevel@tonic-gate 		    &upa64s_p->config_base_ah) != DDI_SUCCESS) {
2487c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: failed to map reg1.",
2497c478bd9Sstevel@tonic-gate 			    ddi_get_name(dip), instance);
2507c478bd9Sstevel@tonic-gate 			goto fail;
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		upa64s_p->upa0_config = (uint64_t *)(upa64s_p->config_base +
2547c478bd9Sstevel@tonic-gate 		    UPA64S_UPA0_CONFIG_OFFSET);
2557c478bd9Sstevel@tonic-gate 		upa64s_p->upa1_config = (uint64_t *)(upa64s_p->config_base +
2567c478bd9Sstevel@tonic-gate 		    UPA64S_UPA1_CONFIG_OFFSET);
2577c478bd9Sstevel@tonic-gate 		upa64s_p->if_config = (uint64_t *)(upa64s_p->config_base +
2587c478bd9Sstevel@tonic-gate 		    UPA64S_IF_CONFIG_OFFSET);
2597c478bd9Sstevel@tonic-gate 		upa64s_p->estar = (uint64_t *)(upa64s_p->config_base +
2607c478bd9Sstevel@tonic-gate 		    UPA64S_ESTAR_OFFSET);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 1, (caddr_t *)&upa64s_p->imr[0],
2637c478bd9Sstevel@tonic-gate 		    0, 0, &attr, &upa64s_p->imr_ah[0]) != DDI_SUCCESS) {
2647c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: failed to map reg2.",
2657c478bd9Sstevel@tonic-gate 			    ddi_get_name(dip), instance);
2667c478bd9Sstevel@tonic-gate 			goto fail1;
2677c478bd9Sstevel@tonic-gate 		}
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 2, (caddr_t *)&upa64s_p->imr[1],
2707c478bd9Sstevel@tonic-gate 		    0, 0, &attr, &upa64s_p->imr_ah[1]) != DDI_SUCCESS) {
2717c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: failed to map reg3.",
2727c478bd9Sstevel@tonic-gate 			    ddi_get_name(dip), instance);
2737c478bd9Sstevel@tonic-gate 			goto fail2;
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 		/*
2777c478bd9Sstevel@tonic-gate 		 * Power level of a component is unknown at attach time.
2787c478bd9Sstevel@tonic-gate 		 * Bring the power level to what is needed for normal operation.
2797c478bd9Sstevel@tonic-gate 		 */
2807c478bd9Sstevel@tonic-gate 		upa64s_p->power_level = UPA64S_PM_UNKNOWN;
2817c478bd9Sstevel@tonic-gate 		if (pm_raise_power(dip, UPA64S_PM_COMP, UPA64S_PM_NORMOP) !=
2827c478bd9Sstevel@tonic-gate 		    DDI_SUCCESS) {
2837c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: failed to raise the power.",
2847c478bd9Sstevel@tonic-gate 			    ddi_get_name(dip), instance);
2857c478bd9Sstevel@tonic-gate 			goto fail3;
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 		intr_dist_add(upa64s_intrdist, dip);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 		ddi_report_dev(dip);
2917c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		upa64s_p = get_upa64s_soft_state(ddi_get_instance(dip));
2967c478bd9Sstevel@tonic-gate 		DBG(D_ATTACH, dip, "DDI_RESUME\n");
2977c478bd9Sstevel@tonic-gate 		restore_state(upa64s_p);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		/*
3007c478bd9Sstevel@tonic-gate 		 * Power level of a component is unknown at resume time.
3017c478bd9Sstevel@tonic-gate 		 * Bring the power level to what it was before suspend.
3027c478bd9Sstevel@tonic-gate 		 */
3037c478bd9Sstevel@tonic-gate 		upa64s_p->power_level = UPA64S_PM_UNKNOWN;
3047c478bd9Sstevel@tonic-gate 		if (pm_raise_power(dip, UPA64S_PM_COMP,
3057c478bd9Sstevel@tonic-gate 		    upa64s_p->saved_power_level) != DDI_SUCCESS)
3067c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "%s%d: failed to change power level "
3077c478bd9Sstevel@tonic-gate 			    "during resume!", ddi_get_name(dip), instance);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	default:
3127c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate fail3:
3167c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&upa64s_p->imr_ah[1]);
3177c478bd9Sstevel@tonic-gate fail2:
3187c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&upa64s_p->imr_ah[0]);
3197c478bd9Sstevel@tonic-gate fail1:
3207c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&upa64s_p->config_base_ah);
3217c478bd9Sstevel@tonic-gate fail:
3227c478bd9Sstevel@tonic-gate 	free_upa64s_soft_state(instance);
3237c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate /*
3287c478bd9Sstevel@tonic-gate  * detach entry point:
3297c478bd9Sstevel@tonic-gate  */
3307c478bd9Sstevel@tonic-gate static int
3317c478bd9Sstevel@tonic-gate upa64s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
3347c478bd9Sstevel@tonic-gate 	upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance);
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	switch (cmd) {
3377c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 		DBG(D_DETACH, dip, "DDI_DETACH\n");
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 		/*
3427c478bd9Sstevel@tonic-gate 		 * Power down the device.
3437c478bd9Sstevel@tonic-gate 		 */
3447c478bd9Sstevel@tonic-gate 		if (pm_lower_power(dip, UPA64S_PM_COMP, UPA64S_PM_RESET) !=
3457c478bd9Sstevel@tonic-gate 		    DDI_SUCCESS)
3467c478bd9Sstevel@tonic-gate 			DBG(D_DETACH, dip, "failed to power off!\n");
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 		intr_dist_rem(upa64s_intrdist, dip);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&upa64s_p->config_base_ah);
3517c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&upa64s_p->imr_ah[0]);
3527c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&upa64s_p->imr_ah[1]);
3537c478bd9Sstevel@tonic-gate 		free_upa64s_soft_state(instance);
3547c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		DBG(D_DETACH, dip, "DDI_SUSPEND\n");
3597c478bd9Sstevel@tonic-gate 		save_state(upa64s_p);
3607c478bd9Sstevel@tonic-gate 		upa64s_p->saved_power_level = upa64s_p->power_level;
3617c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
3627c478bd9Sstevel@tonic-gate 	}
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * power entry point:
3697c478bd9Sstevel@tonic-gate  *
3707c478bd9Sstevel@tonic-gate  * This entry point is called by Power Management framework to
3717c478bd9Sstevel@tonic-gate  * reset upa bus and slow down/speed up the upa interface of
3727c478bd9Sstevel@tonic-gate  * Schizo chip.
3737c478bd9Sstevel@tonic-gate  */
3747c478bd9Sstevel@tonic-gate static int
3757c478bd9Sstevel@tonic-gate upa64s_power(dev_info_t *dip, int component, int level)
3767c478bd9Sstevel@tonic-gate {
3777c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
3787c478bd9Sstevel@tonic-gate 	upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance);
3797c478bd9Sstevel@tonic-gate 	volatile uint64_t uint64_data;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	DBG2(D_POWER, dip, "component=%d, level=%d\n", component, level);
3827c478bd9Sstevel@tonic-gate 	if (component != UPA64S_PM_COMP ||
3837c478bd9Sstevel@tonic-gate 	    level < UPA64S_PM_RESET || level > UPA64S_PM_NORMOP)
3847c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	/*
3877c478bd9Sstevel@tonic-gate 	 * We can't set the hardware to the state that it is
3887c478bd9Sstevel@tonic-gate 	 * already in.  So if the power state is not known, inquire the
3897c478bd9Sstevel@tonic-gate 	 * state of the hardware.  If it is already in that state,
3907c478bd9Sstevel@tonic-gate 	 * record and return, otherwise make the state change.
3917c478bd9Sstevel@tonic-gate 	 */
3927c478bd9Sstevel@tonic-gate 	if (upa64s_p->power_level == UPA64S_PM_UNKNOWN) {
3937c478bd9Sstevel@tonic-gate 		uint64_data = ddi_get64(upa64s_p->config_base_ah,
3947c478bd9Sstevel@tonic-gate 		    upa64s_p->if_config);
3957c478bd9Sstevel@tonic-gate 		if ((level == UPA64S_PM_RESET &&
3967c478bd9Sstevel@tonic-gate 		    uint64_data == UPA64S_NOT_POK_RST_L) ||
3977c478bd9Sstevel@tonic-gate 		    (level == UPA64S_PM_NORMOP &&
3987c478bd9Sstevel@tonic-gate 		    uint64_data == UPA64S_POK_NOT_RST_L)) {
3997c478bd9Sstevel@tonic-gate 			upa64s_p->power_level = level;
4007c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
4017c478bd9Sstevel@tonic-gate 		}
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (level == upa64s_p->power_level) {
4057c478bd9Sstevel@tonic-gate 		DBG1(D_POWER, dip, "device is already at power level %d\n",
4067c478bd9Sstevel@tonic-gate 		    level);
4077c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
4087c478bd9Sstevel@tonic-gate 	}
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	if (level == UPA64S_PM_RESET) {
4127c478bd9Sstevel@tonic-gate 		/*
4137c478bd9Sstevel@tonic-gate 		 * Assert UPA64S_RESET
4147c478bd9Sstevel@tonic-gate 		 */
4157c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config,
4167c478bd9Sstevel@tonic-gate 		    UPA64S_POK_RST_L);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 		/*
4197c478bd9Sstevel@tonic-gate 		 * Deassert UPA64S_POK.  Flush the store buffer.
4207c478bd9Sstevel@tonic-gate 		 */
4217c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config,
4227c478bd9Sstevel@tonic-gate 		    UPA64S_NOT_POK_RST_L);
4237c478bd9Sstevel@tonic-gate 		uint64_data = ddi_get64(upa64s_p->config_base_ah,
4247c478bd9Sstevel@tonic-gate 		    upa64s_p->if_config);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 		/*
4277c478bd9Sstevel@tonic-gate 		 * Internal UPA clock to 1/2 speed
4287c478bd9Sstevel@tonic-gate 		 */
4297c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar,
4307c478bd9Sstevel@tonic-gate 		    UPA64S_1_2_SPEED);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 		/*
4337c478bd9Sstevel@tonic-gate 		 * Internal UPA clock to 1/64 speed.  Flush the store buffer.
4347c478bd9Sstevel@tonic-gate 		 */
4357c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar,
4367c478bd9Sstevel@tonic-gate 		    UPA64S_1_64_SPEED);
4377c478bd9Sstevel@tonic-gate 		uint64_data = ddi_get64(upa64s_p->config_base_ah,
4387c478bd9Sstevel@tonic-gate 		    upa64s_p->estar);
4397c478bd9Sstevel@tonic-gate 	} else {
4407c478bd9Sstevel@tonic-gate 		/*
4417c478bd9Sstevel@tonic-gate 		 * Internal UPA clock to 1/2 speed
4427c478bd9Sstevel@tonic-gate 		 */
4437c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar,
4447c478bd9Sstevel@tonic-gate 		    UPA64S_1_2_SPEED);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 		/*
4477c478bd9Sstevel@tonic-gate 		 * Internal UPA clock to full speed.  Flush the store buffer.
4487c478bd9Sstevel@tonic-gate 		 */
4497c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->estar,
4507c478bd9Sstevel@tonic-gate 		    UPA64S_FULL_SPEED);
4517c478bd9Sstevel@tonic-gate 		uint64_data = ddi_get64(upa64s_p->config_base_ah,
4527c478bd9Sstevel@tonic-gate 		    upa64s_p->estar);
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 		/*
4557c478bd9Sstevel@tonic-gate 		 * Assert UPA64S_POK.  Flush the store buffer before
4567c478bd9Sstevel@tonic-gate 		 * the wait delay.
4577c478bd9Sstevel@tonic-gate 		 */
4587c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config,
4597c478bd9Sstevel@tonic-gate 		    UPA64S_POK_RST_L);
4607c478bd9Sstevel@tonic-gate 		uint64_data = ddi_get64(upa64s_p->config_base_ah,
4617c478bd9Sstevel@tonic-gate 		    upa64s_p->if_config);
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		/*
4647c478bd9Sstevel@tonic-gate 		 * Delay 20 milliseconds for the signals to settle down.
4657c478bd9Sstevel@tonic-gate 		 */
4667c478bd9Sstevel@tonic-gate 		delay(drv_usectohz(20*1000));
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		/*
4697c478bd9Sstevel@tonic-gate 		 * Deassert UPA64S_RESET.  Flush the store buffer.
4707c478bd9Sstevel@tonic-gate 		 */
4717c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->config_base_ah, upa64s_p->if_config,
4727c478bd9Sstevel@tonic-gate 		    UPA64S_POK_NOT_RST_L);
4737c478bd9Sstevel@tonic-gate 		uint64_data = ddi_get64(upa64s_p->config_base_ah,
4747c478bd9Sstevel@tonic-gate 		    upa64s_p->if_config);
4757c478bd9Sstevel@tonic-gate 	}
4767c478bd9Sstevel@tonic-gate 	upa64s_p->power_level = level;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate /* bus driver entry points */
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate /*
4847c478bd9Sstevel@tonic-gate  * bus map entry point:
4857c478bd9Sstevel@tonic-gate  *
4867c478bd9Sstevel@tonic-gate  * 	if map request is for an rnumber
4877c478bd9Sstevel@tonic-gate  *		get the corresponding regspec from device node
4887c478bd9Sstevel@tonic-gate  * 	build a new regspec in our parent's format
4897c478bd9Sstevel@tonic-gate  *	build a new map_req with the new regspec
4907c478bd9Sstevel@tonic-gate  *	call up the tree to complete the mapping
4917c478bd9Sstevel@tonic-gate  */
4927c478bd9Sstevel@tonic-gate static int
4937c478bd9Sstevel@tonic-gate upa64s_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
4947c478bd9Sstevel@tonic-gate     off_t off, off_t len, caddr_t *addrp)
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate 	struct regspec regspec;
4977c478bd9Sstevel@tonic-gate 	ddi_map_req_t p_map_request;
4987c478bd9Sstevel@tonic-gate 	int rnumber, rval;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	DBG4(D_MAP, dip, "upa64s_map() mp=%x.%x addrp=%x.%08x\n",
5017c478bd9Sstevel@tonic-gate 	    HI32(mp), LO32(mp), HI32(addrp), LO32(addrp));
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	/*
5047c478bd9Sstevel@tonic-gate 	 * User level mappings are not supported yet.
5057c478bd9Sstevel@tonic-gate 	 */
5067c478bd9Sstevel@tonic-gate 	if (mp->map_flags & DDI_MF_USER_MAPPING) {
5077c478bd9Sstevel@tonic-gate 		DBG2(D_MAP, dip, "rdip=%s%d: no user level mappings yet!\n",
5087c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip));
5097c478bd9Sstevel@tonic-gate 		return (DDI_ME_UNIMPLEMENTED);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	/*
5137c478bd9Sstevel@tonic-gate 	 * Now handle the mapping according to its type.
5147c478bd9Sstevel@tonic-gate 	 */
5157c478bd9Sstevel@tonic-gate 	switch (mp->map_type) {
5167c478bd9Sstevel@tonic-gate 	case DDI_MT_REGSPEC:
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 		/*
5197c478bd9Sstevel@tonic-gate 		 * We assume the register specification is in PCI format.
5207c478bd9Sstevel@tonic-gate 		 * We must convert it into a regspec of our parent's
5217c478bd9Sstevel@tonic-gate 		 * and pass the request to our parent.
5227c478bd9Sstevel@tonic-gate 		 */
5237c478bd9Sstevel@tonic-gate 		DBG3(D_MAP, dip, "rdip=%s%d: REGSPEC - handlep=%x\n",
5247c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip),
5257c478bd9Sstevel@tonic-gate 		    mp->map_handlep);
5267c478bd9Sstevel@tonic-gate 		rval = xlate_reg_prop(dip, (upa64s_regspec_t *)mp->map_obj.rp,
5277c478bd9Sstevel@tonic-gate 		    off, len, &regspec);
5287c478bd9Sstevel@tonic-gate 		break;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	case DDI_MT_RNUMBER:
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 		/*
5337c478bd9Sstevel@tonic-gate 		 * Get the "reg" property from the device node and convert
5347c478bd9Sstevel@tonic-gate 		 * it to our parent's format.
5357c478bd9Sstevel@tonic-gate 		 */
5367c478bd9Sstevel@tonic-gate 		DBG4(D_MAP, dip, "rdip=%s%d: rnumber=%x handlep=%x\n",
5377c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip),
5387c478bd9Sstevel@tonic-gate 		    mp->map_obj.rnumber, mp->map_handlep);
5397c478bd9Sstevel@tonic-gate 		rnumber = mp->map_obj.rnumber;
5407c478bd9Sstevel@tonic-gate 		if (rnumber < 0)
5417c478bd9Sstevel@tonic-gate 			return (DDI_ME_RNUMBER_RANGE);
5427c478bd9Sstevel@tonic-gate 		rval = get_reg_set(dip, rdip,  rnumber, off, len, &regspec);
5437c478bd9Sstevel@tonic-gate 		break;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	default:
5467c478bd9Sstevel@tonic-gate 		return (DDI_ME_INVAL);
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 	if (rval != DDI_SUCCESS) {
5507c478bd9Sstevel@tonic-gate 		DBG(D_MAP, dip, "failed on regspec\n\n");
5517c478bd9Sstevel@tonic-gate 		return (rval);
5527c478bd9Sstevel@tonic-gate 	}
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/*
5557c478bd9Sstevel@tonic-gate 	 * Now we have a copy of the upa64s regspec converted to our parent's
5567c478bd9Sstevel@tonic-gate 	 * format.  Build a new map request based on this regspec and pass
5577c478bd9Sstevel@tonic-gate 	 * it to our parent.
5587c478bd9Sstevel@tonic-gate 	 */
5597c478bd9Sstevel@tonic-gate 	p_map_request = *mp;
5607c478bd9Sstevel@tonic-gate 	p_map_request.map_type = DDI_MT_REGSPEC;
5617c478bd9Sstevel@tonic-gate 	p_map_request.map_obj.rp = &regspec;
5627c478bd9Sstevel@tonic-gate 	rval = ddi_map(dip, &p_map_request, 0, 0, addrp);
5637c478bd9Sstevel@tonic-gate 	DBG3(D_MAP, dip, "ddi_map returns: rval=%x addrp=%x.%08x\n\n",
5647c478bd9Sstevel@tonic-gate 	    rval, HI32(*addrp), LO32(*addrp));
5657c478bd9Sstevel@tonic-gate 	return (rval);
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate /*
5697c478bd9Sstevel@tonic-gate  * Translate the UPA devices interrupt property.  This is the only case I
5707c478bd9Sstevel@tonic-gate  * know of where the interrupts property is meaningless.  As a result, we
5717c478bd9Sstevel@tonic-gate  * just use UPA_BASE_INO as our interrupt value and add to it the upa port id.
5727c478bd9Sstevel@tonic-gate  * UPA portid is returned too.
5737c478bd9Sstevel@tonic-gate  */
5747c478bd9Sstevel@tonic-gate #define	UPA_BASE_INO	0x2a
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate static int
577*a195726fSgovinda upa64s_xlate_intr(dev_info_t *rdip, int32_t safariport, uint32_t *intr)
5787c478bd9Sstevel@tonic-gate {
5797c478bd9Sstevel@tonic-gate 	uint32_t ino = UPA_BASE_INO;
5807c478bd9Sstevel@tonic-gate 	int32_t portid;
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	/* Clear the ffb's interrupts property, it's meaningless */
583*a195726fSgovinda 	*intr = 0;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	if ((portid = ddi_getprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
5867c478bd9Sstevel@tonic-gate 	    "upa-portid", -1)) == -1)
5877c478bd9Sstevel@tonic-gate 		return (-1);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	ino += portid;
5907c478bd9Sstevel@tonic-gate 
591*a195726fSgovinda 	*intr = UPA64S_MAKE_MONDO(safariport, ino);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	DBG5(D_A_ISPEC, rdip, "upa64s_xlate_intr: rdip=%s%d: upa portid %d "
5947c478bd9Sstevel@tonic-gate 	    "ino=%x mondo 0x%x\n", ddi_get_name(rdip), ddi_get_instance(rdip),
595*a195726fSgovinda 	    portid, ino, *intr);
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	return (portid);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate /*
6017c478bd9Sstevel@tonic-gate  * bus add intrspec entry point:
6027c478bd9Sstevel@tonic-gate  */
6037c478bd9Sstevel@tonic-gate static int
6047c478bd9Sstevel@tonic-gate upa64s_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
6057c478bd9Sstevel@tonic-gate     ddi_intr_handle_impl_t *hdlp)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	int upaport, instance = ddi_get_instance(dip);
6087c478bd9Sstevel@tonic-gate 	upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance);
6097c478bd9Sstevel@tonic-gate #ifdef DEBUG
6107c478bd9Sstevel@tonic-gate 	uint_t (*int_handler)(caddr_t, caddr_t) = hdlp->ih_cb_func;
6117c478bd9Sstevel@tonic-gate 	caddr_t int_handler_arg1 = hdlp->ih_cb_arg1;
6127c478bd9Sstevel@tonic-gate #endif /* DEBUG */
6137c478bd9Sstevel@tonic-gate 	uint_t cpu_id;
6147c478bd9Sstevel@tonic-gate 	volatile uint64_t imr_data;
6157c478bd9Sstevel@tonic-gate 
616*a195726fSgovinda 	upaport = upa64s_xlate_intr(rdip, upa64s_p->safari_id,
617*a195726fSgovinda 	    (uint32_t *)&hdlp->ih_vector);
6187c478bd9Sstevel@tonic-gate 
619*a195726fSgovinda 	if (hdlp->ih_vector == 0)
6207c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	DBG3(D_A_ISPEC, dip,
6237c478bd9Sstevel@tonic-gate 	    "rdip=%s%d - IDDI_INTR_TYPE_NORMAL, mondo=%x\n",
624*a195726fSgovinda 	    ddi_driver_name(rdip), ddi_get_instance(rdip), hdlp->ih_vector);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 	/*
6277c478bd9Sstevel@tonic-gate 	 * Make sure an interrupt handler isn't already installed.
6287c478bd9Sstevel@tonic-gate 	 */
6297c478bd9Sstevel@tonic-gate 	if (upa64s_p->ino_state[upaport] != INO_FREE) {
6307c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6317c478bd9Sstevel@tonic-gate 	}
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	/*
6347c478bd9Sstevel@tonic-gate 	 * Install the handler in the system table.
6357c478bd9Sstevel@tonic-gate 	 */
6367c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6377c478bd9Sstevel@tonic-gate 	DBG2(D_A_ISPEC, dip, "i_ddi_add_ivintr: hdlr=%p arg=%p\n",
6387c478bd9Sstevel@tonic-gate 	    int_handler, int_handler_arg1);
6397c478bd9Sstevel@tonic-gate #endif
6407c478bd9Sstevel@tonic-gate 	if (i_ddi_add_ivintr(hdlp) != DDI_SUCCESS)
6417c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	cpu_id = intr_dist_cpuid();
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	/*
6467c478bd9Sstevel@tonic-gate 	 * Enable the interrupt through its interrupt mapping register.
6477c478bd9Sstevel@tonic-gate 	 */
6487c478bd9Sstevel@tonic-gate 	imr_data = UPA64S_CPUID_TO_IMR(cpu_id);
6497c478bd9Sstevel@tonic-gate 	imr_data = UPA64S_GET_MAP_REG(hdlp->ih_vector, imr_data);
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	DBG4(D_A_ISPEC, dip, "IMR [upaport=%d mapping reg 0x%p] = %x.%x\n",
6527c478bd9Sstevel@tonic-gate 	    upaport, upa64s_p->imr[upaport], HI32(imr_data), LO32(imr_data));
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	ddi_put64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport], imr_data);
6557c478bd9Sstevel@tonic-gate 	/* Read the data back to flush store buffers. */
6567c478bd9Sstevel@tonic-gate 	imr_data = ddi_get64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport]);
6577c478bd9Sstevel@tonic-gate 	upa64s_p->ino_state[upaport] = INO_INUSE;
6587c478bd9Sstevel@tonic-gate 
659*a195726fSgovinda 	DBG(D_A_ISPEC, dip, "add_intr success!\n");
6607c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate /*
6657c478bd9Sstevel@tonic-gate  * bus remove intrspec entry point
6667c478bd9Sstevel@tonic-gate  */
6677c478bd9Sstevel@tonic-gate static int
6687c478bd9Sstevel@tonic-gate upa64s_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
6697c478bd9Sstevel@tonic-gate     ddi_intr_handle_impl_t *hdlp)
6707c478bd9Sstevel@tonic-gate {
6717c478bd9Sstevel@tonic-gate 	upa64s_devstate_t *upa64s_p =
6727c478bd9Sstevel@tonic-gate 	    get_upa64s_soft_state(ddi_get_instance(dip));
6737c478bd9Sstevel@tonic-gate 	int upaport;
6747c478bd9Sstevel@tonic-gate #ifndef lint
6757c478bd9Sstevel@tonic-gate 	volatile uint64_t tmp;
6767c478bd9Sstevel@tonic-gate #endif
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	/*
6797c478bd9Sstevel@tonic-gate 	 * Make sure the mondo is valid.
6807c478bd9Sstevel@tonic-gate 	 */
681*a195726fSgovinda 	upaport = upa64s_xlate_intr(rdip, upa64s_p->safari_id,
682*a195726fSgovinda 	    (uint32_t *)&hdlp->ih_vector);
6837c478bd9Sstevel@tonic-gate 
684*a195726fSgovinda 	if (hdlp->ih_vector == 0)
6857c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 	DBG3(D_R_ISPEC, dip,
6887c478bd9Sstevel@tonic-gate 	    "rdip=%s%d - IDDI_INTR_TYPE_NORMAL, mondo=%x\n",
689*a195726fSgovinda 	    ddi_driver_name(rdip), ddi_get_instance(rdip), hdlp->ih_vector);
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	if (upa64s_p->ino_state[upaport] != INO_INUSE) {
6927c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/* Call up to our parent to handle the removal */
6967c478bd9Sstevel@tonic-gate 	i_ddi_rem_ivintr(hdlp);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	ddi_put64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport], 0);
6997c478bd9Sstevel@tonic-gate #ifndef lint
7007c478bd9Sstevel@tonic-gate 	/* Flush store buffers */
7017c478bd9Sstevel@tonic-gate 	tmp = ddi_get64(upa64s_p->imr_ah[upaport], upa64s_p->imr[upaport]);
7027c478bd9Sstevel@tonic-gate #endif
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	upa64s_p->ino_state[upaport] = INO_FREE;
7057c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate /* new intr_ops structure */
7107c478bd9Sstevel@tonic-gate static int
7117c478bd9Sstevel@tonic-gate upa64_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
7127c478bd9Sstevel@tonic-gate     ddi_intr_handle_impl_t *hdlp, void *result)
7137c478bd9Sstevel@tonic-gate {
7147c478bd9Sstevel@tonic-gate 	int	ret = DDI_SUCCESS;
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	switch (intr_op) {
7177c478bd9Sstevel@tonic-gate 	case DDI_INTROP_GETCAP:
718*a195726fSgovinda 		*(int *)result = DDI_INTR_FLAG_EDGE;
7197c478bd9Sstevel@tonic-gate 		break;
7207c478bd9Sstevel@tonic-gate 	case DDI_INTROP_ALLOC:
7217c478bd9Sstevel@tonic-gate 		*(int *)result = hdlp->ih_scratch1;
7227c478bd9Sstevel@tonic-gate 		break;
7237c478bd9Sstevel@tonic-gate 	case DDI_INTROP_FREE:
7247c478bd9Sstevel@tonic-gate 		break;
7257c478bd9Sstevel@tonic-gate 	case DDI_INTROP_GETPRI:
7267c478bd9Sstevel@tonic-gate 		/*
7277c478bd9Sstevel@tonic-gate 		 * We only have slave UPA devices so force the PIL to 5.
7287c478bd9Sstevel@tonic-gate 		 * this is done since all slave UPA devices have historically
7297c478bd9Sstevel@tonic-gate 		 * had their PILs set to 5.  Only do it if the PIL is not
7307c478bd9Sstevel@tonic-gate 		 * being preset.
7317c478bd9Sstevel@tonic-gate 		 */
732*a195726fSgovinda 		*(int *)result = hdlp->ih_pri ? hdlp->ih_pri : 5;
7337c478bd9Sstevel@tonic-gate 		break;
7347c478bd9Sstevel@tonic-gate 	case DDI_INTROP_SETPRI:
7357c478bd9Sstevel@tonic-gate 		break;
7367c478bd9Sstevel@tonic-gate 	case DDI_INTROP_ADDISR:
7377c478bd9Sstevel@tonic-gate 		ret = upa64s_add_intr_impl(dip, rdip, hdlp);
7387c478bd9Sstevel@tonic-gate 		break;
7397c478bd9Sstevel@tonic-gate 	case DDI_INTROP_REMISR:
7407c478bd9Sstevel@tonic-gate 		ret = upa64s_remove_intr_impl(dip, rdip, hdlp);
7417c478bd9Sstevel@tonic-gate 		break;
7427c478bd9Sstevel@tonic-gate 	case DDI_INTROP_ENABLE:
7437c478bd9Sstevel@tonic-gate 	case DDI_INTROP_DISABLE:
7447c478bd9Sstevel@tonic-gate 		break;
7457c478bd9Sstevel@tonic-gate 	case DDI_INTROP_NINTRS:
7467c478bd9Sstevel@tonic-gate 	case DDI_INTROP_NAVAIL:
7477c478bd9Sstevel@tonic-gate 		*(int *)result = i_ddi_get_nintrs(rdip);
7487c478bd9Sstevel@tonic-gate 		break;
7497c478bd9Sstevel@tonic-gate 	case DDI_INTROP_SETCAP:
7507c478bd9Sstevel@tonic-gate 	case DDI_INTROP_SETMASK:
7517c478bd9Sstevel@tonic-gate 	case DDI_INTROP_CLRMASK:
7527c478bd9Sstevel@tonic-gate 	case DDI_INTROP_GETPENDING:
7537c478bd9Sstevel@tonic-gate 		ret = DDI_ENOTSUP;
7547c478bd9Sstevel@tonic-gate 		break;
7557c478bd9Sstevel@tonic-gate 	case DDI_INTROP_SUPPORTED_TYPES:
7567c478bd9Sstevel@tonic-gate 		/* only support fixed interrupts */
7577c478bd9Sstevel@tonic-gate 		*(int *)result = i_ddi_get_nintrs(rdip) ?
7587c478bd9Sstevel@tonic-gate 		    DDI_INTR_TYPE_FIXED : 0;
7597c478bd9Sstevel@tonic-gate 		break;
7607c478bd9Sstevel@tonic-gate 	default:
7617c478bd9Sstevel@tonic-gate 		ret = i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result);
7627c478bd9Sstevel@tonic-gate 		break;
7637c478bd9Sstevel@tonic-gate 	}
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	return (ret);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate #ifdef DEBUG
7697c478bd9Sstevel@tonic-gate uint_t upa64s_debug_flags = (uint_t)0;
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate extern void prom_printf(const char *, ...);
7727c478bd9Sstevel@tonic-gate #endif
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate /*
7757c478bd9Sstevel@tonic-gate  * control ops entry point:
7767c478bd9Sstevel@tonic-gate  *
7777c478bd9Sstevel@tonic-gate  * Requests handled completely:
7787c478bd9Sstevel@tonic-gate  *	DDI_CTLOPS_INITCHILD	see init_child() for details
7797c478bd9Sstevel@tonic-gate  *	DDI_CTLOPS_UNINITCHILD
7807c478bd9Sstevel@tonic-gate  *	DDI_CTLOPS_REPORTDEV	see report_dev() for details
7817c478bd9Sstevel@tonic-gate  *	DDI_CTLOPS_REGSIZE
7827c478bd9Sstevel@tonic-gate  *	DDI_CTLOPS_NREGS
7837c478bd9Sstevel@tonic-gate  *
7847c478bd9Sstevel@tonic-gate  * All others passed to parent.
7857c478bd9Sstevel@tonic-gate  */
7867c478bd9Sstevel@tonic-gate static int
7877c478bd9Sstevel@tonic-gate upa64s_ctlops(dev_info_t *dip, dev_info_t *rdip,
7887c478bd9Sstevel@tonic-gate     ddi_ctl_enum_t op, void *arg, void *result)
7897c478bd9Sstevel@tonic-gate {
7907c478bd9Sstevel@tonic-gate 	DBG5(D_CTLOPS, dip, "dip=%x.%x rdip=%x.%x op=%x",
7917c478bd9Sstevel@tonic-gate 	    HI32(dip), LO32(dip), HI32(rdip), LO32(rdip), op);
7927c478bd9Sstevel@tonic-gate 	DBG4(D_CTLOPS|D_CONT, dip, " arg=%x.%x result=%x.%x\n",
7937c478bd9Sstevel@tonic-gate 	    HI32(arg), LO32(arg), HI32(result), LO32(result));
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	switch (op) {
7967c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_INITCHILD:
7977c478bd9Sstevel@tonic-gate 		DBG2(D_CTLOPS, dip, "DDI_CTLOPS_INITCHILD: rdip=%s%d\n",
7987c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip));
7997c478bd9Sstevel@tonic-gate 		return (init_child((dev_info_t *)arg));
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_UNINITCHILD:
8027c478bd9Sstevel@tonic-gate 		DBG2(D_CTLOPS, dip, "DDI_CTLOPS_UNINITCHILD: rdip=%s%d\n",
8037c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip));
8047c478bd9Sstevel@tonic-gate 		ddi_set_name_addr((dev_info_t *)arg, NULL);
8057c478bd9Sstevel@tonic-gate 		ddi_remove_minor_node((dev_info_t *)arg, NULL);
8067c478bd9Sstevel@tonic-gate 		impl_rem_dev_props((dev_info_t *)arg);
8077c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_REPORTDEV:
8107c478bd9Sstevel@tonic-gate 		DBG2(D_CTLOPS, dip, "DDI_CTLOPS_REPORTDEV: rdip=%s%d\n",
8117c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip));
8127c478bd9Sstevel@tonic-gate 		return (report_dev(rdip));
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_REGSIZE:
8157c478bd9Sstevel@tonic-gate 		DBG2(D_CTLOPS, dip, "DDI_CTLOPS_REGSIZE: rdip=%s%d\n",
8167c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip));
8177c478bd9Sstevel@tonic-gate 		*((off_t *)result) = get_reg_set_size(rdip, *((int *)arg));
8187c478bd9Sstevel@tonic-gate 		return (*((off_t *)result) == -1 ? DDI_FAILURE : DDI_SUCCESS);
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	case DDI_CTLOPS_NREGS:
8217c478bd9Sstevel@tonic-gate 		DBG2(D_CTLOPS, dip, "DDI_CTLOPS_NREGS: rdip=%s%d\n",
8227c478bd9Sstevel@tonic-gate 		    ddi_get_name(rdip), ddi_get_instance(rdip));
8237c478bd9Sstevel@tonic-gate 		*((uint_t *)result) = get_nreg_set(rdip);
8247c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
8257c478bd9Sstevel@tonic-gate 	}
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	/*
8287c478bd9Sstevel@tonic-gate 	 * Now pass the request up to our parent.
8297c478bd9Sstevel@tonic-gate 	 */
8307c478bd9Sstevel@tonic-gate 	DBG3(D_CTLOPS, dip, "passing request to parent: rdip=%s%d op=%x\n\n",
8317c478bd9Sstevel@tonic-gate 	    ddi_get_name(rdip), ddi_get_instance(rdip), op);
8327c478bd9Sstevel@tonic-gate 	return (ddi_ctlops(dip, rdip, op, arg, result));
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate /* support routines */
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate /*
8397c478bd9Sstevel@tonic-gate  * get_properties
8407c478bd9Sstevel@tonic-gate  *
8417c478bd9Sstevel@tonic-gate  * This function is called from the attach routine to get the key
8427c478bd9Sstevel@tonic-gate  * properties of the upa64s node.
8437c478bd9Sstevel@tonic-gate  *
8447c478bd9Sstevel@tonic-gate  * used by: upa64s_attach()
8457c478bd9Sstevel@tonic-gate  *
8467c478bd9Sstevel@tonic-gate  * return value: none
8477c478bd9Sstevel@tonic-gate  */
8487c478bd9Sstevel@tonic-gate static int
8497c478bd9Sstevel@tonic-gate get_properties(upa64s_devstate_t *upa64s_p, dev_info_t *dip)
8507c478bd9Sstevel@tonic-gate {
8517c478bd9Sstevel@tonic-gate 	int safari_id;
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	/*
8547c478bd9Sstevel@tonic-gate 	 * Get the device's safari id.
8557c478bd9Sstevel@tonic-gate 	 */
8567c478bd9Sstevel@tonic-gate 	safari_id = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
8577c478bd9Sstevel@tonic-gate 	    "portid", -1);
8587c478bd9Sstevel@tonic-gate 	if (safari_id == -1) {
8597c478bd9Sstevel@tonic-gate 		int instance = ddi_get_instance(dip);
8607c478bd9Sstevel@tonic-gate 		panic("%s%d: no portid property", ddi_get_name(dip), instance);
8617c478bd9Sstevel@tonic-gate 	}
8627c478bd9Sstevel@tonic-gate 	upa64s_p->safari_id = safari_id;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate /*
8697c478bd9Sstevel@tonic-gate  * save_state
8707c478bd9Sstevel@tonic-gate  *
8717c478bd9Sstevel@tonic-gate  * This routine saves a copy of the upa64s register state.
8727c478bd9Sstevel@tonic-gate  *
8737c478bd9Sstevel@tonic-gate  * used by: upa64s_detach() on a suspend operation
8747c478bd9Sstevel@tonic-gate  */
8757c478bd9Sstevel@tonic-gate static void
8767c478bd9Sstevel@tonic-gate save_state(upa64s_devstate_t *upa64s_p)
8777c478bd9Sstevel@tonic-gate {
8787c478bd9Sstevel@tonic-gate 	upa64s_p->imr_data[0] = ddi_get64(upa64s_p->imr_ah[0],
8797c478bd9Sstevel@tonic-gate 	    upa64s_p->imr[0]);
8807c478bd9Sstevel@tonic-gate 	upa64s_p->imr_data[1] = ddi_get64(upa64s_p->imr_ah[1],
8817c478bd9Sstevel@tonic-gate 	    upa64s_p->imr[1]);
8827c478bd9Sstevel@tonic-gate }
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate /*
8867c478bd9Sstevel@tonic-gate  * restore_state
8877c478bd9Sstevel@tonic-gate  *
8887c478bd9Sstevel@tonic-gate  * This routine restores a copy of the upa64s register state.
8897c478bd9Sstevel@tonic-gate  *
8907c478bd9Sstevel@tonic-gate  * used by: upa64s_attach() on a resume operation
8917c478bd9Sstevel@tonic-gate  */
8927c478bd9Sstevel@tonic-gate static void
8937c478bd9Sstevel@tonic-gate restore_state(upa64s_devstate_t *upa64s_p)
8947c478bd9Sstevel@tonic-gate {
8957c478bd9Sstevel@tonic-gate #ifndef lint
8967c478bd9Sstevel@tonic-gate 	volatile uint64_t tmp;
8977c478bd9Sstevel@tonic-gate #endif
8987c478bd9Sstevel@tonic-gate 	ddi_put64(upa64s_p->imr_ah[0], upa64s_p->imr[0],
8997c478bd9Sstevel@tonic-gate 	    upa64s_p->imr_data[0]);
9007c478bd9Sstevel@tonic-gate 	ddi_put64(upa64s_p->imr_ah[1], upa64s_p->imr[1],
9017c478bd9Sstevel@tonic-gate 	    upa64s_p->imr_data[1]);
9027c478bd9Sstevel@tonic-gate #ifndef lint
9037c478bd9Sstevel@tonic-gate 	/* Flush the store buffer */
9047c478bd9Sstevel@tonic-gate 	tmp = ddi_get64(upa64s_p->imr_ah[0], upa64s_p->imr[0]);
9057c478bd9Sstevel@tonic-gate 	tmp = ddi_get64(upa64s_p->imr_ah[1], upa64s_p->imr[1]);
9067c478bd9Sstevel@tonic-gate #endif
9077c478bd9Sstevel@tonic-gate }
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate /*
9117c478bd9Sstevel@tonic-gate  * get_reg_set
9127c478bd9Sstevel@tonic-gate  *
9137c478bd9Sstevel@tonic-gate  * This routine will get a upa64s format regspec for a given
9147c478bd9Sstevel@tonic-gate  * device node and register number.
9157c478bd9Sstevel@tonic-gate  *
9167c478bd9Sstevel@tonic-gate  * used by: upa64s_map()
9177c478bd9Sstevel@tonic-gate  *
9187c478bd9Sstevel@tonic-gate  * return value:
9197c478bd9Sstevel@tonic-gate  *
9207c478bd9Sstevel@tonic-gate  *	DDI_SUCCESS		- on success
9217c478bd9Sstevel@tonic-gate  *	DDI_ME_INVAL		- regspec is invalid
9227c478bd9Sstevel@tonic-gate  *	DDI_ME_RNUMBER_RANGE	- rnumber out of range
9237c478bd9Sstevel@tonic-gate  */
9247c478bd9Sstevel@tonic-gate static int
9257c478bd9Sstevel@tonic-gate get_reg_set(dev_info_t *dip, dev_info_t *child, int rnumber,
9267c478bd9Sstevel@tonic-gate     off_t off, off_t len, struct regspec *rp)
9277c478bd9Sstevel@tonic-gate {
9287c478bd9Sstevel@tonic-gate 	upa64s_regspec_t *upa64s_rp;
9297c478bd9Sstevel@tonic-gate 	int i, n, rval;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	/*
9327c478bd9Sstevel@tonic-gate 	 * Get child device "reg" property
9337c478bd9Sstevel@tonic-gate 	 */
934a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg",
9357c478bd9Sstevel@tonic-gate 	    (caddr_t)&upa64s_rp, &i) != DDI_SUCCESS)
9367c478bd9Sstevel@tonic-gate 		return (DDI_ME_RNUMBER_RANGE);
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	n = i / (int)sizeof (upa64s_regspec_t);
9397c478bd9Sstevel@tonic-gate 	if (rnumber >= n) {
9407c478bd9Sstevel@tonic-gate 		kmem_free(upa64s_rp, i);
9417c478bd9Sstevel@tonic-gate 		return (DDI_ME_RNUMBER_RANGE);
9427c478bd9Sstevel@tonic-gate 	}
9437c478bd9Sstevel@tonic-gate 
9447c478bd9Sstevel@tonic-gate 	/*
9457c478bd9Sstevel@tonic-gate 	 * Convert each the upa64s format register specification to
9467c478bd9Sstevel@tonic-gate 	 * out parent format.
9477c478bd9Sstevel@tonic-gate 	 */
9487c478bd9Sstevel@tonic-gate 	rval = xlate_reg_prop(dip, &upa64s_rp[rnumber], off, len, rp);
9497c478bd9Sstevel@tonic-gate 	kmem_free(upa64s_rp, i);
9507c478bd9Sstevel@tonic-gate 	return (rval);
9517c478bd9Sstevel@tonic-gate }
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate /*
9557c478bd9Sstevel@tonic-gate  * xlate_reg_prop
9567c478bd9Sstevel@tonic-gate  *
9577c478bd9Sstevel@tonic-gate  * This routine converts a upa64s format regspec to a standard
9587c478bd9Sstevel@tonic-gate  * regspec containing the corresponding system address.
9597c478bd9Sstevel@tonic-gate  *
9607c478bd9Sstevel@tonic-gate  * used by: upa64s_map()
9617c478bd9Sstevel@tonic-gate  *
9627c478bd9Sstevel@tonic-gate  * return value:
9637c478bd9Sstevel@tonic-gate  *
9647c478bd9Sstevel@tonic-gate  *	DDI_SUCCESS
9657c478bd9Sstevel@tonic-gate  *	DDI_FAILURE	- off + len is beyond device address range
9667c478bd9Sstevel@tonic-gate  *	DDI_ME_INVAL	- regspec is invalid
9677c478bd9Sstevel@tonic-gate  */
9687c478bd9Sstevel@tonic-gate static int
9697c478bd9Sstevel@tonic-gate xlate_reg_prop(dev_info_t *dip, upa64s_regspec_t *child_rp, off_t off,
9707c478bd9Sstevel@tonic-gate     off_t len, struct regspec *rp)
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate 	int n_ranges, ranges_len, i;
9737c478bd9Sstevel@tonic-gate 	uint64_t child_beg, child_end;
9747c478bd9Sstevel@tonic-gate 	upa64s_ranges_t *range_p, *rng_p;
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	DBG4(D_MAP, dip, "upa64s regspec - ((%x,%x) (%x,%x))\n",
9777c478bd9Sstevel@tonic-gate 	    HI32(child_rp->upa64s_phys), LO32(child_rp->upa64s_phys),
9787c478bd9Sstevel@tonic-gate 	    HI32(child_rp->upa64s_size), LO32(child_rp->upa64s_size));
9797c478bd9Sstevel@tonic-gate 	DBG2(D_MAP, dip, "upa64s xlate_reg_prp - off=%lx len=%lx\n", off, len);
9807c478bd9Sstevel@tonic-gate #if 0
9817c478bd9Sstevel@tonic-gate 	/*
9827c478bd9Sstevel@tonic-gate 	 * both FFB and AFB have broken "reg" properties, all mapping
9837c478bd9Sstevel@tonic-gate 	 * requests are done through reg-0 with very long offsets.
9847c478bd9Sstevel@tonic-gate 	 * Hence this safety check is always violated.
9857c478bd9Sstevel@tonic-gate 	 */
9867c478bd9Sstevel@tonic-gate 	if (off + len > child_rp->upa64s_size) {
9877c478bd9Sstevel@tonic-gate 		DBG(D_MAP, dip, "upa64s xlate_reg_prp: bad off + len\n");
9887c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
9897c478bd9Sstevel@tonic-gate 	}
9907c478bd9Sstevel@tonic-gate #endif
9917c478bd9Sstevel@tonic-gate 	/*
9927c478bd9Sstevel@tonic-gate 	 * current "struct regspec" only supports 32-bit sizes.
9937c478bd9Sstevel@tonic-gate 	 */
9947c478bd9Sstevel@tonic-gate 	if (child_rp->upa64s_size >= (1ull << 32))
9957c478bd9Sstevel@tonic-gate 		panic("upa64s: reg size must be less than 4 Gb");
9967c478bd9Sstevel@tonic-gate 
997a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
9987c478bd9Sstevel@tonic-gate 	    "ranges", (caddr_t)&range_p, &ranges_len) != DDI_SUCCESS) {
9997c478bd9Sstevel@tonic-gate 		ranges_len = 0;
10007c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s%d: no ranges property",
10017c478bd9Sstevel@tonic-gate 		    ddi_get_name(dip), ddi_get_instance(dip));
10027c478bd9Sstevel@tonic-gate 	}
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	n_ranges = ranges_len / sizeof (upa64s_regspec_t);
10057c478bd9Sstevel@tonic-gate 	child_beg = child_rp->upa64s_phys;
10067c478bd9Sstevel@tonic-gate #if 0
10077c478bd9Sstevel@tonic-gate 	/*
10087c478bd9Sstevel@tonic-gate 	 * again, this safety checking can not be performed.
10097c478bd9Sstevel@tonic-gate 	 * Hack by adding a pratical max child reg bank length.
10107c478bd9Sstevel@tonic-gate 	 */
10117c478bd9Sstevel@tonic-gate 	child_end = child_beg + child_rp->upa64s_size;
10127c478bd9Sstevel@tonic-gate #else
10137c478bd9Sstevel@tonic-gate #define	UPA64S_MAX_CHILD_LEN	0xe000000
10147c478bd9Sstevel@tonic-gate 	child_end = child_beg + UPA64S_MAX_CHILD_LEN;
10157c478bd9Sstevel@tonic-gate #endif
10167c478bd9Sstevel@tonic-gate 	for (i = 0, rng_p = range_p; i < n_ranges; i++, rng_p++) {
10177c478bd9Sstevel@tonic-gate 		uint64_t rng_beg = rng_p->upa64s_child;
10187c478bd9Sstevel@tonic-gate 		uint64_t rng_end = rng_beg + rng_p->upa64s_size;
10197c478bd9Sstevel@tonic-gate 		if ((rng_beg <= child_beg) && (rng_end >= child_end)) {
10207c478bd9Sstevel@tonic-gate 			uint64_t addr = child_beg - rng_beg + off;
10217c478bd9Sstevel@tonic-gate 			addr += rng_p->upa64s_parent;
10227c478bd9Sstevel@tonic-gate 			rp->regspec_bustype = HI32(addr);
10237c478bd9Sstevel@tonic-gate 			rp->regspec_addr = LO32(addr);
10247c478bd9Sstevel@tonic-gate 			rp->regspec_size = len ? len : child_rp->upa64s_size;
10257c478bd9Sstevel@tonic-gate 			break;
10267c478bd9Sstevel@tonic-gate 		}
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 	if (ranges_len)
10297c478bd9Sstevel@tonic-gate 		kmem_free(range_p, ranges_len);
10307c478bd9Sstevel@tonic-gate 	DBG4(D_MAP, dip, "regspec (%x,%x,%x) i=%x\n",
10317c478bd9Sstevel@tonic-gate 	    rp->regspec_bustype, rp->regspec_addr, rp->regspec_size, i);
10327c478bd9Sstevel@tonic-gate 	return (i < n_ranges? DDI_SUCCESS : DDI_ME_INVAL);
10337c478bd9Sstevel@tonic-gate }
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate /*
10377c478bd9Sstevel@tonic-gate  * report_dev
10387c478bd9Sstevel@tonic-gate  *
10397c478bd9Sstevel@tonic-gate  * This function is called from our control ops routine on a
10407c478bd9Sstevel@tonic-gate  * DDI_CTLOPS_REPORTDEV request.
10417c478bd9Sstevel@tonic-gate  */
10427c478bd9Sstevel@tonic-gate static int
10437c478bd9Sstevel@tonic-gate report_dev(dev_info_t *dip)
10447c478bd9Sstevel@tonic-gate {
10457c478bd9Sstevel@tonic-gate 	if (dip == (dev_info_t *)0)
10467c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10477c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "?UPA64S-device: %s@%s, %s #%d\n",
10487c478bd9Sstevel@tonic-gate 	    ddi_node_name(dip), ddi_get_name_addr(dip),
10497c478bd9Sstevel@tonic-gate 	    ddi_major_to_name(ddi_name_to_major(ddi_get_name(dip))),
10507c478bd9Sstevel@tonic-gate 	    ddi_get_instance(dip));
10517c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
10527c478bd9Sstevel@tonic-gate }
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate /*
10567c478bd9Sstevel@tonic-gate  * init_child
10577c478bd9Sstevel@tonic-gate  *
10587c478bd9Sstevel@tonic-gate  * This function is called from our control ops routine on a
10597c478bd9Sstevel@tonic-gate  * DDI_CTLOPS_INITCHILD request.  It builds and sets the device's
10607c478bd9Sstevel@tonic-gate  * parent private data area.
10617c478bd9Sstevel@tonic-gate  *
10627c478bd9Sstevel@tonic-gate  * used by: upa64s_ctlops()
10637c478bd9Sstevel@tonic-gate  *
10647c478bd9Sstevel@tonic-gate  * return value: none
10657c478bd9Sstevel@tonic-gate  */
10667c478bd9Sstevel@tonic-gate static int
10677c478bd9Sstevel@tonic-gate init_child(dev_info_t *child)
10687c478bd9Sstevel@tonic-gate {
10697c478bd9Sstevel@tonic-gate 	upa64s_regspec_t *child_rp;
10707c478bd9Sstevel@tonic-gate 	int i;
10717c478bd9Sstevel@tonic-gate 	char addr[256];
10727c478bd9Sstevel@tonic-gate 	int32_t portid;
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate 	if ((portid = ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
10757c478bd9Sstevel@tonic-gate 	    "upa-portid", -1)) == -1)
10767c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	/*
10797c478bd9Sstevel@tonic-gate 	 * Set the address portion of the node name based on
10807c478bd9Sstevel@tonic-gate 	 * the function and device number.
10817c478bd9Sstevel@tonic-gate 	 */
1082a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg",
10837c478bd9Sstevel@tonic-gate 	    (caddr_t)&child_rp, &i) != DDI_SUCCESS) {
10847c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10857c478bd9Sstevel@tonic-gate 	}
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	(void) sprintf(addr, "%x,%x", portid, LO32(child_rp->upa64s_phys));
10887c478bd9Sstevel@tonic-gate 	ddi_set_name_addr(child, addr);
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 	ddi_set_parent_data(child, NULL);
10917c478bd9Sstevel@tonic-gate 	kmem_free(child_rp, i);
10927c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate /*
10977c478bd9Sstevel@tonic-gate  * get_reg_set_size
10987c478bd9Sstevel@tonic-gate  *
10997c478bd9Sstevel@tonic-gate  * Given a dev info pointer to a child and a register number, this
11007c478bd9Sstevel@tonic-gate  * routine returns the size element of that reg set property.
11017c478bd9Sstevel@tonic-gate  *
11027c478bd9Sstevel@tonic-gate  * used by: upa64s_ctlops() - DDI_CTLOPS_REGSIZE
11037c478bd9Sstevel@tonic-gate  *
11047c478bd9Sstevel@tonic-gate  * return value: size of reg set on success, -1 on error
11057c478bd9Sstevel@tonic-gate  */
11067c478bd9Sstevel@tonic-gate static off_t
11077c478bd9Sstevel@tonic-gate get_reg_set_size(dev_info_t *child, int rnumber)
11087c478bd9Sstevel@tonic-gate {
11097c478bd9Sstevel@tonic-gate 	upa64s_regspec_t *upa64s_rp;
11107c478bd9Sstevel@tonic-gate 	uint_t size;
11117c478bd9Sstevel@tonic-gate 	int i;
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 	if (rnumber < 0)
11147c478bd9Sstevel@tonic-gate 		return (-1);
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	/*
11177c478bd9Sstevel@tonic-gate 	 * Get the reg property for the device.
11187c478bd9Sstevel@tonic-gate 	 */
1119a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg",
11207c478bd9Sstevel@tonic-gate 	    (caddr_t)&upa64s_rp, &i) != DDI_SUCCESS)
11217c478bd9Sstevel@tonic-gate 		return (-1);
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	if (rnumber >= (i / (int)sizeof (upa64s_regspec_t))) {
11247c478bd9Sstevel@tonic-gate 		kmem_free(upa64s_rp, i);
11257c478bd9Sstevel@tonic-gate 		return (-1);
11267c478bd9Sstevel@tonic-gate 	}
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 	/*  >4G reg size not supported */
11297c478bd9Sstevel@tonic-gate 	size = (uint32_t)upa64s_rp[rnumber].upa64s_size;
11307c478bd9Sstevel@tonic-gate 	kmem_free(upa64s_rp, i);
11317c478bd9Sstevel@tonic-gate 	return (size);
11327c478bd9Sstevel@tonic-gate }
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate /*
11367c478bd9Sstevel@tonic-gate  * get_nreg_set
11377c478bd9Sstevel@tonic-gate  *
11387c478bd9Sstevel@tonic-gate  * Given a dev info pointer to a child, this routine returns the
11397c478bd9Sstevel@tonic-gate  * number of sets in its "reg" property.
11407c478bd9Sstevel@tonic-gate  *
11417c478bd9Sstevel@tonic-gate  * used by: upa64s_ctlops() - DDI_CTLOPS_NREGS
11427c478bd9Sstevel@tonic-gate  *
11437c478bd9Sstevel@tonic-gate  * return value: # of reg sets on success, zero on error
11447c478bd9Sstevel@tonic-gate  */
11457c478bd9Sstevel@tonic-gate static uint_t
11467c478bd9Sstevel@tonic-gate get_nreg_set(dev_info_t *child)
11477c478bd9Sstevel@tonic-gate {
11487c478bd9Sstevel@tonic-gate 	upa64s_regspec_t *upa64s_rp;
11497c478bd9Sstevel@tonic-gate 	int i, n;
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 	/*
11527c478bd9Sstevel@tonic-gate 	 * Get the reg property for the device.
11537c478bd9Sstevel@tonic-gate 	 */
1154a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg",
11557c478bd9Sstevel@tonic-gate 	    (caddr_t)&upa64s_rp, &i) != DDI_SUCCESS)
11567c478bd9Sstevel@tonic-gate 		return (0);
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	n =  i / (int)sizeof (upa64s_regspec_t);
11597c478bd9Sstevel@tonic-gate 	kmem_free(upa64s_rp, i);
11607c478bd9Sstevel@tonic-gate 	return (n);
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate /*
11657c478bd9Sstevel@tonic-gate  * upa64s_intrdist
11667c478bd9Sstevel@tonic-gate  *
11677c478bd9Sstevel@tonic-gate  * The following routine is the callback function for this nexus driver
11687c478bd9Sstevel@tonic-gate  * to support interrupt distribution on sun4u systems. When this
11697c478bd9Sstevel@tonic-gate  * function is called by the interrupt distribution framework, it will
11707c478bd9Sstevel@tonic-gate  * reprogram all the active the mondo registers.
11717c478bd9Sstevel@tonic-gate  */
11727c478bd9Sstevel@tonic-gate static void
11737c478bd9Sstevel@tonic-gate upa64s_intrdist(void *arg)
11747c478bd9Sstevel@tonic-gate {
11757c478bd9Sstevel@tonic-gate 	dev_info_t *dip = (dev_info_t *)arg;
11767c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
11777c478bd9Sstevel@tonic-gate 	upa64s_devstate_t *upa64s_p = get_upa64s_soft_state(instance);
11787c478bd9Sstevel@tonic-gate 	uint_t upaport;
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	for (upaport = 0; upaport < UPA64S_PORTS; upaport++) {
11817c478bd9Sstevel@tonic-gate 		volatile uint64_t *imr;
11827c478bd9Sstevel@tonic-gate 		volatile uint64_t imr_dat;
11837c478bd9Sstevel@tonic-gate 		uint_t mondo;
11847c478bd9Sstevel@tonic-gate 		uint32_t cpuid;
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 		if (upa64s_p->ino_state[upaport] != INO_INUSE)
11877c478bd9Sstevel@tonic-gate 			continue;
11887c478bd9Sstevel@tonic-gate 
11897c478bd9Sstevel@tonic-gate 		imr = upa64s_p->imr[upaport];
11907c478bd9Sstevel@tonic-gate 		mondo = UPA64S_IMR_TO_MONDO(*imr);
11917c478bd9Sstevel@tonic-gate 		cpuid = intr_dist_cpuid();
11927c478bd9Sstevel@tonic-gate 		imr_dat = UPA64S_CPUID_TO_IMR(cpuid);
11937c478bd9Sstevel@tonic-gate 		imr_dat = UPA64S_GET_MAP_REG(mondo, imr_dat);
11947c478bd9Sstevel@tonic-gate 
11957c478bd9Sstevel@tonic-gate 		/* Check and re-program cpu target if necessary */
11967c478bd9Sstevel@tonic-gate 		DBG2(D_INTRDIST, dip, "mondo=%x cpuid=%x\n", mondo, cpuid);
11977c478bd9Sstevel@tonic-gate 		if (UPA64S_IMR_TO_CPUID(*imr) == cpuid) {
11987c478bd9Sstevel@tonic-gate 			DBG(D_INTRDIST, dip, "same cpuid\n");
11997c478bd9Sstevel@tonic-gate 			continue;
12007c478bd9Sstevel@tonic-gate 		}
12017c478bd9Sstevel@tonic-gate 		ddi_put64(upa64s_p->imr_ah[upaport], (uint64_t *)imr, imr_dat);
12027c478bd9Sstevel@tonic-gate 		imr_dat = ddi_get64(upa64s_p->imr_ah[upaport], (uint64_t *)imr);
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate }
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate #ifdef DEBUG
12087c478bd9Sstevel@tonic-gate static void
12097c478bd9Sstevel@tonic-gate upa64s_debug(uint_t flag, dev_info_t *dip, char *fmt,
12107c478bd9Sstevel@tonic-gate     uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
12117c478bd9Sstevel@tonic-gate {
12127c478bd9Sstevel@tonic-gate 	char *s = NULL;
12137c478bd9Sstevel@tonic-gate 	uint_t cont = 0;
12147c478bd9Sstevel@tonic-gate 	if (flag & D_CONT) {
12157c478bd9Sstevel@tonic-gate 		flag &= ~D_CONT;
12167c478bd9Sstevel@tonic-gate 		cont = 1;
12177c478bd9Sstevel@tonic-gate 	}
12187c478bd9Sstevel@tonic-gate 	if (!(upa64s_debug_flags & flag))
12197c478bd9Sstevel@tonic-gate 		return;
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	switch (flag) {
12227c478bd9Sstevel@tonic-gate 	case D_ATTACH:		s = "attach";		break;
12237c478bd9Sstevel@tonic-gate 	case D_DETACH:		s = "detach";		break;
12247c478bd9Sstevel@tonic-gate 	case D_POWER:		s = "power";		break;
12257c478bd9Sstevel@tonic-gate 	case D_MAP:		s = "map";		break;
12267c478bd9Sstevel@tonic-gate 	case D_CTLOPS:		s = "ctlops";		break;
12277c478bd9Sstevel@tonic-gate 	case D_G_ISPEC:		s = "get_intrspec";	break;
12287c478bd9Sstevel@tonic-gate 	case D_A_ISPEC:		s = "add_intrspec";	break;
12297c478bd9Sstevel@tonic-gate 	case D_R_ISPEC:		s = "remove_intrspec";	break;
12307c478bd9Sstevel@tonic-gate 	case D_INIT_CLD:	s = "init_child";	break;
12317c478bd9Sstevel@tonic-gate 	case D_INTRDIST:	s = "intrdist";		break;
12327c478bd9Sstevel@tonic-gate 	}
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate 	if (s && cont == 0) {
12357c478bd9Sstevel@tonic-gate 		prom_printf("%s(%d): %s: ", ddi_get_name(dip),
12367c478bd9Sstevel@tonic-gate 		    ddi_get_instance(dip), s);
12377c478bd9Sstevel@tonic-gate 	}
12387c478bd9Sstevel@tonic-gate 	prom_printf(fmt, a1, a2, a3, a4, a5);
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate #endif
1241