xref: /onnv-gate/usr/src/uts/sun4u/starcat/io/sc_gptwocfg.c (revision 11311:639e7bc0b42f)
11708Sstevel /*
21708Sstevel  * CDDL HEADER START
31708Sstevel  *
41708Sstevel  * The contents of this file are subject to the terms of the
51708Sstevel  * Common Development and Distribution License (the "License").
61708Sstevel  * You may not use this file except in compliance with the License.
71708Sstevel  *
81708Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91708Sstevel  * or http://www.opensolaris.org/os/licensing.
101708Sstevel  * See the License for the specific language governing permissions
111708Sstevel  * and limitations under the License.
121708Sstevel  *
131708Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
141708Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151708Sstevel  * If applicable, add the following below this CDDL HEADER, with the
161708Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
171708Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
181708Sstevel  *
191708Sstevel  * CDDL HEADER END
201708Sstevel  */
211708Sstevel 
221708Sstevel /*
23*11311SSurya.Prakki@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
241708Sstevel  * Use is subject to license terms.
251708Sstevel  */
261708Sstevel 
271708Sstevel /*
281708Sstevel  *     Starcat Specific Glue for Safari Configurator
291708Sstevel  */
301708Sstevel 
311708Sstevel #include <sys/isa_defs.h>
321708Sstevel #include <sys/conf.h>
331708Sstevel #include <sys/kmem.h>
341708Sstevel #include <sys/debug.h>
351708Sstevel #include <sys/modctl.h>
361708Sstevel #include <sys/autoconf.h>
371708Sstevel #include <sys/hwconf.h>
381708Sstevel #include <sys/ddi_impldefs.h>
391708Sstevel #include <sys/ddi.h>
401708Sstevel #include <sys/sunddi.h>
411708Sstevel #include <sys/sunndi.h>
421708Sstevel #include <sys/ndi_impldefs.h>
431708Sstevel #include <sys/safari_pcd.h>
441708Sstevel #include <sys/gp2cfg.h>
451708Sstevel #include <sys/gptwo_cpu.h>
461708Sstevel #include <sys/gptwo_pci.h>
471708Sstevel #include <sys/sc_gptwocfg.h>
481708Sstevel #include <post/scat_dcd.h>
491708Sstevel #include <sys/machsystm.h>
501708Sstevel 
511708Sstevel int sc_gptwocfg_debug = 0;
521708Sstevel 
531708Sstevel #define	SC_DEBUG(level, args) if (sc_gptwocfg_debug >= level) cmn_err args
541708Sstevel 
551708Sstevel typedef struct sc_gptwocfg_config {
561708Sstevel 	int				board;
571708Sstevel 	struct gptwocfg_config		*port_cookie;
581708Sstevel 	gptwo_aid_t			portid;
591708Sstevel 	struct sc_gptwocfg_config	*link;
601708Sstevel 	struct sc_gptwocfg_config	*next;
611708Sstevel } sc_gptwocfg_config_t;
621708Sstevel 
631708Sstevel static kmutex_t sc_gptwo_config_list_lock;
641708Sstevel static sc_gptwocfg_config_t *sc_gptwo_config_list;
651708Sstevel static dev_info_t *sc_find_axq_node(uint_t);
661708Sstevel static sc_gptwocfg_cookie_t sc_configure(uint_t, int);
671708Sstevel static spcd_t *sc_get_common_pcd(uint_t, uint_t);
681708Sstevel static void sc_free_common_pcd(spcd_t *);
691708Sstevel static gptwo_new_nodes_t *sc_gptwocfg_configure_axq(dev_info_t *, uint_t, int);
701708Sstevel static gptwocfg_config_t *sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *);
711708Sstevel static void dump_config(sc_gptwocfg_config_t *);
721708Sstevel static void dump_pcd(spcd_t *);
731708Sstevel static uint_t sc_get_agent_id(spcd_t *, uint_t, uint_t, uint_t);
741708Sstevel static char *rsv_string(prdrsv_t);
751708Sstevel 
761708Sstevel extern gptwo_new_nodes_t *gptwocfg_allocate_node_list(int);
771708Sstevel extern void gptwocfg_free_node_list(gptwo_new_nodes_t *);
781708Sstevel 
791708Sstevel static uint8_t *get_memlayout(uint32_t, uint32_t *);
801708Sstevel 
811708Sstevel #ifdef NO_IOSRAM
821708Sstevel int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
831708Sstevel #else
841708Sstevel extern int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
851708Sstevel #endif
861708Sstevel extern void gptwocfg_devi_attach_to_parent(dev_info_t *);
871708Sstevel 
881708Sstevel /*
891708Sstevel  * Module control operations
901708Sstevel  */
911708Sstevel 
921708Sstevel extern struct mod_ops mod_miscops;
931708Sstevel 
941708Sstevel static struct modlmisc modlmisc = {
951708Sstevel 	&mod_miscops, /* Type of module */
967799SRichard.Bean@Sun.COM 	"Sun Fire 15000 gptwocfg"
971708Sstevel };
981708Sstevel 
991708Sstevel static struct modlinkage modlinkage = {
1001708Sstevel 	MODREV_1, (void *)&modlmisc, NULL
1011708Sstevel };
1021708Sstevel 
1031708Sstevel int
_init()1041708Sstevel _init()
1051708Sstevel {
1061708Sstevel 	int err = 0;
1071708Sstevel 
1081708Sstevel 	mutex_init(&sc_gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL);
1091708Sstevel 	sc_gptwo_config_list = NULL;
1101708Sstevel 
1111708Sstevel 	/*
1121708Sstevel 	 * CPU/PCI devices are already registered by their respective modules,
1131708Sstevel 	 * so all we need to do now is install.
1141708Sstevel 	 */
1151708Sstevel 	if ((err = mod_install(&modlinkage)) != 0) {
1161708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg failed to load, error=%d\n",
1177799SRichard.Bean@Sun.COM 		    err));
1181708Sstevel 		mutex_destroy(&sc_gptwo_config_list_lock);
1191708Sstevel 	} else {
1201708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg has been loaded.\n"));
1211708Sstevel 	}
1221708Sstevel 	return (err);
1231708Sstevel }
1241708Sstevel 
1251708Sstevel int
_fini(void)1261708Sstevel _fini(void)
1271708Sstevel {
1281708Sstevel 	mutex_destroy(&sc_gptwo_config_list_lock);
1291708Sstevel 	return (mod_remove(&modlinkage));
1301708Sstevel }
1311708Sstevel 
1321708Sstevel int
_info(modinfop)1331708Sstevel _info(modinfop)
1341708Sstevel struct modinfo *modinfop;
1351708Sstevel {
1361708Sstevel 	return (mod_info(&modlinkage, modinfop));
1371708Sstevel }
1381708Sstevel 
1391708Sstevel static spcd_t *
sc_get_common_pcd(uint_t expander,uint_t prd_slot)1401708Sstevel sc_get_common_pcd(uint_t expander, uint_t prd_slot)
1411708Sstevel {
1421708Sstevel 	spcd_t *pcd;
1431708Sstevel 	gdcd_t *gdcd;
1441708Sstevel 	int portid;
1451708Sstevel 	int i, j, slot;
1461708Sstevel 	int dimm;
1471708Sstevel 	char *label1, *label2;
1481708Sstevel 
1491708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_get_common_pcd() expander=%d prd_slot=%d\n",
1501708Sstevel 	    expander, prd_slot));
1511708Sstevel 
1521708Sstevel 	gdcd = (gdcd_t *)kmem_zalloc(sizeof (gdcd_t), KM_SLEEP);
1531708Sstevel 
1541708Sstevel 	/*
1551708Sstevel 	 * Get the Starcat Specific Global DCD Structure from the golden
1561708Sstevel 	 * IOSRAM.
1571708Sstevel 	 */
1581708Sstevel 	if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
1591708Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: Unable To Read GDCD "
1601708Sstevel 		    "From IOSRAM\n");
1611708Sstevel 		kmem_free(gdcd, sizeof (gdcd_t));
1621708Sstevel 		return (NULL);
1631708Sstevel 	}
1641708Sstevel 
1651708Sstevel 	if (gdcd->h.dcd_magic != GDCD_MAGIC) {
1661708Sstevel 
1671708Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Magic 0x%x\n",
1681708Sstevel 		    gdcd->h.dcd_magic);
1691708Sstevel 
1701708Sstevel 		kmem_free(gdcd, sizeof (gdcd_t));
1711708Sstevel 		return (NULL);
1721708Sstevel 	}
1731708Sstevel 
1741708Sstevel 	if (gdcd->h.dcd_version != DCD_VERSION) {
1751708Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Version: "
1761708Sstevel 		    "GDCD Version 0x%x Expecting 0x%x\n",
1771708Sstevel 		    gdcd->h.dcd_version, DCD_VERSION);
1781708Sstevel 
1791708Sstevel 		kmem_free(gdcd, sizeof (gdcd_t));
1801708Sstevel 		return (NULL);
1811708Sstevel 	}
1821708Sstevel 
1831708Sstevel 	pcd = (spcd_t *)kmem_zalloc(sizeof (spcd_t), KM_SLEEP);
1841708Sstevel 
1851708Sstevel 	/*
1861708Sstevel 	 * Copy various information from the platform specific Port
1871708Sstevel 	 * Resource Descriptor (PRD) To the platform independent
1881708Sstevel 	 * Port Configuration Descriptor.
1891708Sstevel 	 */
1901708Sstevel 	pcd->spcd_magic = PCD_MAGIC;
1911708Sstevel 	pcd->spcd_version = PCD_VERSION;
1921708Sstevel 	pcd->spcd_ptype = gdcd->dcd_prd[expander][prd_slot].prd_ptype;
1931708Sstevel 	pcd->spcd_ver_reg = gdcd->dcd_prd[expander][prd_slot].prd_ver_reg;
1941708Sstevel 
1951708Sstevel 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
1961708Sstevel 		/*
1971708Sstevel 		 * This will calculate the cpu speed based on the
1981708Sstevel 		 * the actual frequency ratio * interconnect frequency
1991708Sstevel 		 * converted to Mhz.
2001708Sstevel 		 */
2011708Sstevel 		pcd->spcd_afreq = gdcd->dcd_prd[expander][prd_slot].
2021708Sstevel 		    prd_afreq_ratio *
2031708Sstevel 		    (uint16_t)((gdcd->dcd_intercon_freq + 500000) / 1000000);
2041708Sstevel 	} else {
2051708Sstevel 		/*
2061708Sstevel 		 * For non-cpu devices, just pass through the frequency
2071708Sstevel 		 * unchanged.
2081708Sstevel 		 */
2091708Sstevel 		pcd->spcd_afreq =
2101708Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_afreq_ratio;
2111708Sstevel 	}
2121708Sstevel 
2131708Sstevel 	pcd->spcd_cache = gdcd->dcd_prd[expander][prd_slot].prd_cache;
2141708Sstevel 
2151708Sstevel 	SC_DEBUG(1, (CE_WARN, "Safari Device Status status=0x%x\n",
2161708Sstevel 	    gdcd->dcd_prd[expander][prd_slot].prd_prsv));
2171708Sstevel 
2181708Sstevel 	/*
2191708Sstevel 	 * Fill in the entire port status.
2201708Sstevel 	 */
2211708Sstevel 	if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].prd_prsv)) {
2221708Sstevel 		pcd->spcd_prsv = SPCD_RSV_PASS;
2231708Sstevel 	} else {
2241708Sstevel 		pcd->spcd_prsv = SPCD_RSV_FAIL;
2251708Sstevel 	}
2261708Sstevel 
2271708Sstevel 	/*
2281708Sstevel 	 * Fill in the per agent status.
2291708Sstevel 	 */
2301708Sstevel 	if (gdcd->dcd_prd[expander][prd_slot].prd_agent[1] == RSV_UNKNOWN) {
2311708Sstevel 		pcd->spcd_agent[0] = pcd->spcd_prsv;
2321708Sstevel 		pcd->spcd_agent[1] = SPCD_RSV_FAIL;
2331708Sstevel 	} else {
2341708Sstevel 		for (i = 0; i < AGENTS_PER_PORT; i++) {
2351708Sstevel 
2361708Sstevel 			if (RSV_GOOD(
2371708Sstevel 			    gdcd->dcd_prd[expander][prd_slot].prd_agent[i]))
2381708Sstevel 				pcd->spcd_agent[i] = SPCD_RSV_PASS;
2391708Sstevel 			else
2401708Sstevel 				pcd->spcd_agent[i] = SPCD_RSV_FAIL;
2411708Sstevel 		}
2421708Sstevel 	}
2431708Sstevel 
2441708Sstevel 	/*
2451708Sstevel 	 * If this is a CPU device calculate the cpuid for it.  For Starcat
2461708Sstevel 	 * the cpuid is in the following format.
2471708Sstevel 	 *
2481708Sstevel 	 * EEEEEPPAPP
2491708Sstevel 	 *
2501708Sstevel 	 * where:	EEEEE is the expander
2511708Sstevel 	 *		PP_PP is the portid
2521708Sstevel 	 *		__A__ is the sub-agent identifier.
2531708Sstevel 	 */
2541708Sstevel 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
2551708Sstevel 		for (i = 0; i < AGENTS_PER_PORT; i++) {
2561708Sstevel 			switch (prd_slot) {
2571708Sstevel 			case 0:
2581708Sstevel 			case 1:
2591708Sstevel 			case 2:
2601708Sstevel 			case 3:
2611708Sstevel 				portid = (expander << 5) | prd_slot;
2621708Sstevel 				break;
2631708Sstevel 			case 4: /* Maxcat */
2641708Sstevel 				portid = (expander << 5) | 8;
2651708Sstevel 				break;
2661708Sstevel 			case 5: /* Maxcat */
2671708Sstevel 				portid = (expander << 5) | 9;
2681708Sstevel 				break;
2691708Sstevel 			default:
2701708Sstevel 				cmn_err(CE_WARN, "sc_gptwocfg: invalid "
2711708Sstevel 				    "prd_slot=%d\n", prd_slot);
2721708Sstevel 			}
2731708Sstevel 			pcd->spcd_cpuid[i] = (i << 2) | portid;
2741708Sstevel 		}
2751708Sstevel 	}
2761708Sstevel 
2771708Sstevel 	/*
2781708Sstevel 	 * Starcat does not have ports with UPA devices so
2791708Sstevel 	 * spcd_upadev structure will not be filled in.
2801708Sstevel 	 */
2811708Sstevel 
2821708Sstevel 	/*
2831708Sstevel 	 * Fill in IO Bus Status
2841708Sstevel 	 */
2851708Sstevel 	for (i = 0; i < IOBUS_PER_PORT; i++) {
2861708Sstevel 
2871708Sstevel 		SC_DEBUG(1, (CE_WARN, "   IO Bus Status "
2881708Sstevel 		    "bus=%d status=0x%x\n", i,
2891708Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i]));
2901708Sstevel 
2911708Sstevel 		if (RSV_GOOD(
2921708Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i])) {
2931708Sstevel 			pcd->spcd_iobus_rsv[i] = SPCD_RSV_PASS;
2941708Sstevel 		} else {
2951708Sstevel 			pcd->spcd_iobus_rsv[i] = SPCD_RSV_FAIL;
2961708Sstevel 		}
2971708Sstevel 
2981708Sstevel 		for (j = 0; j < IOCARD_PER_BUS; j++)
2991708Sstevel 			pcd->spcd_iocard_rsv[i][j] = SPCD_RSV_FAIL;
3001708Sstevel 
3011708Sstevel 		/*
3021708Sstevel 		 * Fill in IO Card Status
3031708Sstevel 		 */
3041708Sstevel 		for (j = 0; j < IOCARD_PER_BUS; j++) {
3051708Sstevel 
3061708Sstevel 			SC_DEBUG(1, (CE_WARN, "       Card Status bus=%d "
3071708Sstevel 			    "slot=%d status=0x%x\n", i, j,
3081708Sstevel 			    gdcd->dcd_prd[expander][prd_slot].
3091708Sstevel 			    prd_iocard_rsv[i][j]));
3101708Sstevel 
3111708Sstevel 			if (j == 1)
3121708Sstevel 				continue;
3131708Sstevel 
3141708Sstevel 			if (j == 0)
3151708Sstevel 				slot = 1;
3161708Sstevel 			else
3171708Sstevel 				slot = j;
3181708Sstevel 
3191708Sstevel 			/*
3201708Sstevel 			 * If POST marked the card as GOOD or if the slot
3211708Sstevel 			 * is empty, we want to probe for the device.
3221708Sstevel 			 */
3231708Sstevel 			if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].
3241708Sstevel 			    prd_iocard_rsv[i][j]) ||
3251708Sstevel 			    (gdcd->dcd_prd[expander][prd_slot].
3261708Sstevel 			    prd_iocard_rsv[i][j] == RSV_MISS) ||
3271708Sstevel 			    (gdcd->dcd_prd[expander][prd_slot].
3281708Sstevel 			    prd_iocard_rsv[i][j] == RSV_EMPTY_CASSETTE))
3291708Sstevel 				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_PASS;
3301708Sstevel 			else
3311708Sstevel 				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_FAIL;
3321708Sstevel 		}
3331708Sstevel 	}
3341708Sstevel 
3351708Sstevel 	/*
3361708Sstevel 	 * Fill in WIC Link Status
3371708Sstevel 	 */
3381708Sstevel 	for (i = 0; i < LINKS_PER_PORT; i++) {
3391708Sstevel 		if (RSV_GOOD(
3401708Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_wic_links[i])) {
3411708Sstevel 			pcd->spcd_wic_links[i] = SPCD_RSV_PASS;
3421708Sstevel 
3431708Sstevel 		} else {
3441708Sstevel 			pcd->spcd_wic_links[i] = SPCD_RSV_FAIL;
3451708Sstevel 		}
3461708Sstevel 	}
3471708Sstevel 
3481708Sstevel 	/*
3491708Sstevel 	 * Get data for the "bank-status" property.
3501708Sstevel 	 */
3511708Sstevel 	pcd->sprd_bank_rsv[0] =
3521708Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][0]);
3531708Sstevel 	pcd->sprd_bank_rsv[1] =
3541708Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][0]);
3551708Sstevel 	pcd->sprd_bank_rsv[2] =
3561708Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][1]);
3571708Sstevel 	pcd->sprd_bank_rsv[3] =
3581708Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][1]);
3591708Sstevel 
3601708Sstevel 	dimm = 0;
3611708Sstevel 	for (i = 0; i < PMBANKS_PER_PORT; i++) {
3621708Sstevel 		for (j = 0; j < DIMMS_PER_PMBANK; j++) {
3631708Sstevel 			if (dimm < MAX_DIMMS_PER_PORT) {
3641708Sstevel 				pcd->sprd_dimm[dimm] = rsv_string(
3651708Sstevel 				    gdcd->dcd_prd[expander][prd_slot].
3661708Sstevel 				    prd_dimm[i][j]);
3671708Sstevel 				dimm++;
3681708Sstevel 			}
3691708Sstevel 		}
3701708Sstevel 	}
3711708Sstevel 
3721708Sstevel 	/*
3731708Sstevel 	 * Get data for the "ecache-dimm-label" property.
3741708Sstevel 	 *
3751708Sstevel 	 * Right now it is hardcoded, but we should eventually get this
3761708Sstevel 	 * from the SC.
3771708Sstevel 	 */
3781708Sstevel 	label1 = NULL;
3791708Sstevel 	label2 = NULL;
3801708Sstevel 
3811708Sstevel 	switch (prd_slot) {
3821708Sstevel 	case 0:
3831708Sstevel 		label1 = "4400";
3841708Sstevel 		label2 = "4300";
3851708Sstevel 		break;
3861708Sstevel 	case 1:
3871708Sstevel 		label1 = "5400";
3881708Sstevel 		label2 = "5300";
3891708Sstevel 		break;
3901708Sstevel 	case 2:
3911708Sstevel 		label1 = "6400";
3921708Sstevel 		label2 = "6300";
3931708Sstevel 		break;
3941708Sstevel 	case 3:
3951708Sstevel 		label1 = "7400";
3961708Sstevel 		label2 = "7300";
3971708Sstevel 		break;
3981708Sstevel 
3991708Sstevel 	/*
4001708Sstevel 	 * Maxcat labels.
4011708Sstevel 	 */
4021708Sstevel 	case 4:
4031708Sstevel 		label1 = "6400";
4041708Sstevel 		label2 = "6300";
4051708Sstevel 		break;
4061708Sstevel 	case 5:
4071708Sstevel 		label1 = "7400";
4081708Sstevel 		label2 = "7300";
4091708Sstevel 		break;
4101708Sstevel 	}
4111708Sstevel 
4121708Sstevel 	i = 0;
4131708Sstevel 	if (label1) {
4141708Sstevel 		pcd->sprd_ecache_dimm_label[i] =
4151708Sstevel 		    kmem_alloc(strlen(label1) + 1, KM_SLEEP);
4161708Sstevel 
4171708Sstevel 		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label1);
4181708Sstevel 
4191708Sstevel 		i++;
4201708Sstevel 	}
4211708Sstevel 	if (label2) {
4221708Sstevel 		pcd->sprd_ecache_dimm_label[i] =
4231708Sstevel 		    kmem_alloc(strlen(label2) + 1, KM_SLEEP);
4241708Sstevel 
4251708Sstevel 		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label2);
4261708Sstevel 
4271708Sstevel 		i++;
4281708Sstevel 
4291708Sstevel 	}
4301708Sstevel 
4311708Sstevel 	kmem_free(gdcd, sizeof (gdcd_t));
4321708Sstevel 
4331708Sstevel #ifdef DEBUG
4341708Sstevel 	dump_pcd(pcd);
4351708Sstevel #endif
4361708Sstevel 
4371708Sstevel 	return (pcd);
4381708Sstevel }
4391708Sstevel 
4401708Sstevel void
sc_free_common_pcd(spcd_t * pcd)4411708Sstevel sc_free_common_pcd(spcd_t *pcd)
4421708Sstevel {
4431708Sstevel 	int i;
4441708Sstevel 
445*11311SSurya.Prakki@Sun.COM 	SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd pcd=%p\n", (void *)pcd));
4461708Sstevel 
4471708Sstevel 	if (pcd->memory_layout && pcd->memory_layout_size) {
4481708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd: memory_layout %p "
449*11311SSurya.Prakki@Sun.COM 		    "size=%x", (void *)pcd->memory_layout,
450*11311SSurya.Prakki@Sun.COM 		    pcd->memory_layout_size));
4511708Sstevel 		kmem_free(pcd->memory_layout, pcd->memory_layout_size);
4521708Sstevel 	}
4531708Sstevel 
4541708Sstevel 	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
4551708Sstevel 		if (pcd->sprd_bank_rsv[i]) {
4561708Sstevel 			kmem_free(pcd->sprd_bank_rsv[i],
4571708Sstevel 			    strlen(pcd->sprd_bank_rsv[i]) + 1);
4581708Sstevel 
4591708Sstevel 			pcd->sprd_bank_rsv[i] = NULL;
4601708Sstevel 		}
4611708Sstevel 	}
4621708Sstevel 
4631708Sstevel 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
4641708Sstevel 		if (pcd->sprd_dimm[i]) {
4651708Sstevel 			kmem_free(pcd->sprd_dimm[i],
4661708Sstevel 			    strlen(pcd->sprd_dimm[i]) + 1);
4671708Sstevel 
4681708Sstevel 			pcd->sprd_dimm[i] = NULL;
4691708Sstevel 		}
4701708Sstevel 		if (pcd->sprd_ecache_dimm_label[i]) {
4711708Sstevel 			kmem_free(pcd->sprd_ecache_dimm_label[i],
4721708Sstevel 			    strlen(pcd->sprd_ecache_dimm_label[i]) + 1);
4731708Sstevel 
4741708Sstevel 			pcd->sprd_ecache_dimm_label[i] = NULL;
4751708Sstevel 		}
4761708Sstevel 	}
4771708Sstevel 
4781708Sstevel 	kmem_free(pcd, sizeof (spcd_t));
4791708Sstevel }
4801708Sstevel 
4811708Sstevel sc_gptwocfg_cookie_t
sc_probe_board(uint_t board)4821708Sstevel sc_probe_board(uint_t board)
4831708Sstevel {
4841708Sstevel 	return (sc_configure(board, 1));
4851708Sstevel }
4861708Sstevel 
4871708Sstevel static sc_gptwocfg_cookie_t
sc_configure(uint_t board,int create_nodes)4881708Sstevel sc_configure(uint_t board, int create_nodes)
4891708Sstevel {
4901708Sstevel 	spcd_t *pcd;
4911708Sstevel 	dev_info_t *ap, *axq_dip;
4921708Sstevel 	uint_t agent_id;
4931708Sstevel 	uint_t prd_slot, prd_slot_start, prd_slot_end;
4941708Sstevel 	uint_t expander, slot;
4951708Sstevel 	gptwo_new_nodes_t *new_nodes;
4961708Sstevel 	gptwocfg_config_t *port_cookie;
4971708Sstevel 	struct sc_gptwocfg_config *board_config, *last, *new;
4981708Sstevel 	int created_node = 0;
4991708Sstevel 	uint32_t size;
5001708Sstevel 
5011708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: board=%d, create_nodes=%d\n",
5027799SRichard.Bean@Sun.COM 	    board, create_nodes));
5031708Sstevel 
5041708Sstevel 	if (board > 35) {
5051708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg - probe_board - "
5061708Sstevel 		    "invalid board 0x%x\n", board));
5071708Sstevel 		return (NULL);
5081708Sstevel 	}
5091708Sstevel 
5101708Sstevel 	slot = board & 1;	/* Extract Slot Number */
5111708Sstevel 	expander = board >> 1;	/* Extract Expander Number */
5121708Sstevel 
5131708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: exp=0x%x slot=0x%x\n",
5141708Sstevel 	    expander, slot));
5151708Sstevel 
5161708Sstevel 	/*
5171708Sstevel 	 * Get the Attachment Point.  For Starcat the parent of all
5181708Sstevel 	 * Safari children is root node.
5191708Sstevel 	 */
5201708Sstevel 	ap = ddi_root_node();
5211708Sstevel 
5221708Sstevel 	/*
5231708Sstevel 	 * Get the agent id of the AXQ.
5241708Sstevel 	 */
5251708Sstevel 	agent_id = (expander << 5) | 0x1e | slot;
5261708Sstevel 
5271708Sstevel 	/*
5281708Sstevel 	 * Look to see if the board is already configured by searching for
5291708Sstevel 	 * its AXQ.
5301708Sstevel 	 */
5311708Sstevel 	if (create_nodes && (axq_dip = sc_find_axq_node(agent_id))) {
5321708Sstevel 		ddi_release_devi(axq_dip);
5331708Sstevel 		cmn_err(CE_WARN, "Board %d AXQ is already configured\n",
5341708Sstevel 		    board);
5351708Sstevel 		return (NULL);
5361708Sstevel 	}
5371708Sstevel 
5381708Sstevel 	/*
5391708Sstevel 	 * Probe AXQ first
5401708Sstevel 	 */
5411708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: Probing AXQ exp=0x%x brd=0x%x\n",
5421708Sstevel 	    expander, slot));
5431708Sstevel 
5441708Sstevel 	/*
5451708Sstevel 	 * The generic gptwocfg does not support the AXQ, so we need
5461708Sstevel 	 * to configure it. The AXQ branch is returned held.
5471708Sstevel 	 */
5481708Sstevel 	new_nodes = sc_gptwocfg_configure_axq(ap, agent_id, create_nodes);
5491708Sstevel 
5501708Sstevel 	if (new_nodes == NULL) {
5511708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_configure: Can not probe AXQ\n"));
5521708Sstevel 		return (NULL);
5531708Sstevel 	}
5541708Sstevel 
5551708Sstevel 	port_cookie = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP);
5561708Sstevel 
5571708Sstevel 	/*
5581708Sstevel 	 * Build a cookie for the AXQ.
5591708Sstevel 	 */
5601708Sstevel 	port_cookie->gptwo_ap = ap;
5611708Sstevel 	port_cookie->gptwo_portid = agent_id;
5621708Sstevel 	port_cookie->gptwo_nodes = new_nodes;
5631708Sstevel 
5641708Sstevel 	board_config = kmem_zalloc(sizeof (sc_gptwocfg_config_t), KM_SLEEP);
5651708Sstevel 
5661708Sstevel 	board_config->port_cookie = port_cookie;
5671708Sstevel 	board_config->board = board;
5681708Sstevel 	board_config->portid = agent_id;
5691708Sstevel 	board_config->link = NULL;
5701708Sstevel 	last = board_config;
5711708Sstevel 
5721708Sstevel 	mutex_enter(&sc_gptwo_config_list_lock);
5731708Sstevel 	board_config->next = sc_gptwo_config_list;
5741708Sstevel 	sc_gptwo_config_list = board_config;
5751708Sstevel 	mutex_exit(&sc_gptwo_config_list_lock);
5761708Sstevel 
5771708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: AXQ Probing Complete. "
5781708Sstevel 	    "%d nodes added\n", new_nodes->gptwo_number_of_nodes));
5791708Sstevel 
5801708Sstevel 	/*
5811708Sstevel 	 * Determine the starting ending slots of the PRD array.
5821708Sstevel 	 */
5831708Sstevel 	switch (slot) {
5841708Sstevel 	case 0:		/* Full Bandwidth Slot */
5851708Sstevel 		prd_slot_start = 0;
5861708Sstevel 		prd_slot_end = 3;
5871708Sstevel 		break;
5881708Sstevel 	case 1:		/* Half Bandwidth Slot */
5891708Sstevel 		prd_slot_start = 4;
5901708Sstevel 		prd_slot_end = 5;
5911708Sstevel 		break;
5921708Sstevel 	default:
5931708Sstevel 		SC_DEBUG(1, (CE_WARN, "Unknown Board Address - "
5941708Sstevel 		    "Can not probe\n"));
5951708Sstevel 		return (board_config);
5961708Sstevel 	}
5971708Sstevel 
5981708Sstevel 	/*
5991708Sstevel 	 * For each valid PRD entry, determine the agent id which is based
6001708Sstevel 	 * on what type of device is described by the slot, and then
6011708Sstevel 	 * call the safari configurator.
6021708Sstevel 	 */
6031708Sstevel 	for (prd_slot = prd_slot_start; prd_slot <= prd_slot_end; prd_slot++) {
6041708Sstevel 
6051708Sstevel 		pcd = sc_get_common_pcd(expander, prd_slot);
6061708Sstevel 
6071708Sstevel 		if (pcd == NULL) {
6081708Sstevel 
6091708Sstevel 			/*
6101708Sstevel 			 * We can not get a PCD for this port so skip it.
6111708Sstevel 			 */
6121708Sstevel 			cmn_err(CE_WARN, "sc_gptwocfg: Can not get PCD "
6131708Sstevel 			    "expander 0x%x prd slot 0x%x\n",
6141708Sstevel 			    expander, prd_slot);
6151708Sstevel 
6161708Sstevel 			return (board_config);
6171708Sstevel 		}
6181708Sstevel 
6191708Sstevel 		/*
6201708Sstevel 		 * Only configure good devices.
6211708Sstevel 		 */
6221708Sstevel 		if (pcd->spcd_prsv == SPCD_RSV_PASS) {
6231708Sstevel 			/*
6241708Sstevel 			 * Determine the agent id.
6251708Sstevel 			 */
6261708Sstevel 			agent_id = sc_get_agent_id(
6271708Sstevel 			    pcd, expander, slot, prd_slot);
6281708Sstevel 
6291708Sstevel 			pcd->memory_layout = get_memlayout(agent_id, &size);
6301708Sstevel 			pcd->memory_layout_size = size;
6311708Sstevel 
6321708Sstevel 			/*
6331708Sstevel 			 * Call Platform Independent gptwo configurator to
6341708Sstevel 			 * create node and properties.
6351708Sstevel 			 */
6361708Sstevel 			if (create_nodes) {
6371708Sstevel 				port_cookie =
6381708Sstevel 				    gptwocfg_configure(ap, pcd, agent_id);
6391708Sstevel 				if (port_cookie)
6401708Sstevel 					created_node++;
6411708Sstevel 			}
6421708Sstevel 
6431708Sstevel 			new = kmem_zalloc
6441708Sstevel 			    (sizeof (sc_gptwocfg_config_t), KM_SLEEP);
6451708Sstevel 
6461708Sstevel 			/*
6471708Sstevel 			 * XXX Shouldn't port_cookie be NULL if
6481708Sstevel 			 * !create_nodes ?
6491708Sstevel 			 */
6501708Sstevel 			new->port_cookie = port_cookie;
6511708Sstevel 			new->portid = agent_id;
6521708Sstevel 			new->link = NULL;
6531708Sstevel 			last->link = new;
6541708Sstevel 			last = new;
6551708Sstevel 		} else {
6561708Sstevel 			SC_DEBUG(1, (CE_WARN, "sc_configure: Bad Agent "
6571708Sstevel 			    "Exp=0x%x PRD Slot=0x%x  prsv Status=0x%x\n",
6581708Sstevel 			    expander, prd_slot, pcd->spcd_prsv));
6591708Sstevel 		}
6601708Sstevel 
6611708Sstevel 		sc_free_common_pcd(pcd);
6621708Sstevel 
6631708Sstevel 	} /* for loop */
6641708Sstevel 
6651708Sstevel 	dump_config(board_config);
6661708Sstevel 
6671708Sstevel 	if (create_nodes && !created_node) {
6681708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_configure: GPTWO Devices failed "
6691708Sstevel 		    "to configure - unprobing board %d\n", board));
6701708Sstevel 		board_config = sc_unprobe_board(board);
6711708Sstevel 	}
6721708Sstevel 
6731708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: Returning 0x%p\n",
674*11311SSurya.Prakki@Sun.COM 	    (void *)board_config));
6751708Sstevel 
6761708Sstevel 	return (board_config);
6771708Sstevel }
6781708Sstevel 
6791708Sstevel sc_gptwocfg_cookie_t
sc_unprobe_board(uint_t board)6801708Sstevel sc_unprobe_board(uint_t board)
6811708Sstevel {
6821708Sstevel 	sc_gptwocfg_config_t *board_config, *axq_config, *prior_config;
6831708Sstevel 	gptwocfg_cookie_t port_cookie;
6841708Sstevel 
6851708Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: board=%d\n", board));
6861708Sstevel 
6871708Sstevel 	if (board > 35) {
6881708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
6891708Sstevel 		    "invalid board 0x%x\n", board));
6901708Sstevel 		return (NULL);
6911708Sstevel 	}
6921708Sstevel 	mutex_enter(&sc_gptwo_config_list_lock);
6931708Sstevel 	board_config = sc_gptwo_config_list;
6941708Sstevel 	while (board_config != NULL) {
6951708Sstevel 		if (board_config->board == board) {
6961708Sstevel 			break;
6971708Sstevel 		}
6981708Sstevel 		board_config = board_config->next;
6991708Sstevel 	}
7001708Sstevel 	mutex_exit(&sc_gptwo_config_list_lock);
7011708Sstevel 
7021708Sstevel 	if (board_config == NULL) {
7031708Sstevel 
7041708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: No "
7051708Sstevel 		    "config structure board=0x%x\n", board));
7061708Sstevel 
7071708Sstevel 		/*
7081708Sstevel 		 * Configure the board without creating nodes.
7091708Sstevel 		 */
7101708Sstevel 		board_config = sc_configure(board, 0);
7111708Sstevel 
7121708Sstevel 		if (board_config == NULL) {
7131708Sstevel 
7141708Sstevel 			cmn_err(CE_WARN, "sc_gptwocfg: sc_unprobe_board: "
7151708Sstevel 			    "Unable to unconfigure board %d - board is not "
7161708Sstevel 			    "configured\n", board);
7171708Sstevel 
7181708Sstevel 			return (NULL);
7191708Sstevel 		}
7201708Sstevel 	}
7211708Sstevel 
7221708Sstevel 	axq_config = board_config;
7231708Sstevel 
7241708Sstevel 	/*
7251708Sstevel 	 * Walk the link of ports on this board and unconfigure them.
7261708Sstevel 	 * Save the AXQ for last.
7271708Sstevel 	 */
7281708Sstevel 	while (board_config->link != NULL) {
7291708Sstevel 		prior_config = board_config;
7301708Sstevel 		board_config = board_config->link;
7311708Sstevel 
7321708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
7331708Sstevel 		    "calling gptwocfg_unconfigure(ap=0x%p portid=0x%x)\n",
734*11311SSurya.Prakki@Sun.COM 		    (void *)ddi_root_node(), board_config->portid));
7351708Sstevel 
7361708Sstevel 		port_cookie = gptwocfg_unconfigure(ddi_root_node(),
7371708Sstevel 		    board_config->portid);
7381708Sstevel 
7391708Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
7401708Sstevel 		    "gptwocfg_unconfigure returned cookie=0x%p\n",
7411708Sstevel 		    port_cookie));
7421708Sstevel 
7431708Sstevel 		if (port_cookie == NULL) {
7441708Sstevel 			/*
7451708Sstevel 			 * Can be removed from list.
7461708Sstevel 			 */
7471708Sstevel 			prior_config->link = board_config->link;
7481708Sstevel 			kmem_free(board_config, sizeof (sc_gptwocfg_config_t));
7491708Sstevel 			board_config = prior_config;
7501708Sstevel 		} else {
7511708Sstevel 			board_config->port_cookie = port_cookie;
7521708Sstevel 		}
7531708Sstevel 	}
7541708Sstevel 
7551708Sstevel 	if (axq_config->link == NULL) {
7561708Sstevel 
7571708Sstevel 		/*
7581708Sstevel 		 * If all the other Safari devices have been successfully
7591708Sstevel 		 * unconfigured, then the AXQ can be unconfigured.
7601708Sstevel 		 */
7611708Sstevel 		axq_config->port_cookie =
7621708Sstevel 		    sc_gptwocfg_unconfigure_axq(axq_config->port_cookie);
7631708Sstevel 
7641708Sstevel 		if (axq_config->port_cookie == NULL) {
7651708Sstevel 
7661708Sstevel 			/*
7671708Sstevel 			 * If the AXQ was successfully unconfigured, then
7681708Sstevel 			 * the board is removed from the configured list.
7691708Sstevel 			 */
7701708Sstevel 			mutex_enter(&sc_gptwo_config_list_lock);
7711708Sstevel 			if (sc_gptwo_config_list == axq_config) {
7721708Sstevel 				sc_gptwo_config_list = axq_config->next;
7731708Sstevel 			} else {
7741708Sstevel 				board_config = sc_gptwo_config_list;
7751708Sstevel 				while (board_config->next != axq_config) {
7761708Sstevel 					board_config = board_config->next;
7771708Sstevel 				}
7781708Sstevel 				board_config->next = axq_config->next;
7791708Sstevel 			}
7801708Sstevel 			mutex_exit(&sc_gptwo_config_list_lock);
7811708Sstevel 			kmem_free(axq_config, sizeof (sc_gptwocfg_config_t));
7821708Sstevel 			axq_config = NULL;
7831708Sstevel 		}
7841708Sstevel 	}
7851708Sstevel 	dump_config(axq_config);
7861708Sstevel 	return (axq_config);
7871708Sstevel }
7881708Sstevel 
7891708Sstevel int
sc_next_node(sc_gptwocfg_cookie_t c,dev_info_t * previous,dev_info_t ** next)7901708Sstevel sc_next_node(sc_gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next)
7911708Sstevel {
7921708Sstevel 	dev_info_t *dip;
7931708Sstevel 	sc_gptwocfg_config_t *cookie;
7941708Sstevel 
7951708Sstevel 	SC_DEBUG(1, (CE_WARN, "sccfg: sccfg_next_node"
796*11311SSurya.Prakki@Sun.COM 	    "(c=0x%p, previous=0x%p, next=0x%p)\n", (void *)c,
797*11311SSurya.Prakki@Sun.COM 	    (void *)previous, (void *)next));
7981708Sstevel 
7991708Sstevel 	cookie = (sc_gptwocfg_config_t *)c;
8001708Sstevel 
8011708Sstevel 	if (cookie == NULL) {
8021708Sstevel 		cmn_err(CE_WARN, "sccfg: sccfg_next_node - "
8031708Sstevel 		    "Invalid Cookie\n");
8041708Sstevel 		return (0);
8051708Sstevel 	}
8061708Sstevel 	if (previous == NULL) {
8071708Sstevel 		/*
8081708Sstevel 		 * Start with the AXQ node.
8091708Sstevel 		 */
8101708Sstevel 		if (gptwocfg_next_node(cookie->port_cookie, NULL, &dip)) {
8111708Sstevel 			*next = dip;
8121708Sstevel 			return (1);
8131708Sstevel 		} else {
8141708Sstevel 			return (0);
8151708Sstevel 		}
8161708Sstevel 	}
8171708Sstevel 
8181708Sstevel 	while (cookie != NULL) {
8191708Sstevel 		if (gptwocfg_next_node(cookie->port_cookie, previous, &dip)) {
8201708Sstevel 			if ((dip == NULL) && (cookie->link == NULL)) {
8211708Sstevel 				*next = NULL;
8221708Sstevel 				return (1);
8231708Sstevel 			}
8241708Sstevel 			if (dip != NULL) {
8251708Sstevel 				*next = dip;
8261708Sstevel 				return (1);
8271708Sstevel 			}
8281708Sstevel 
8291708Sstevel 			/* dip == NULL */
8301708Sstevel 
8311708Sstevel 			previous = NULL;
8321708Sstevel 		}
8331708Sstevel 		cookie = cookie->link;
8341708Sstevel 	}
8351708Sstevel 
8361708Sstevel 	return (0);
8371708Sstevel }
8381708Sstevel 
8391708Sstevel static dev_info_t *
sc_find_axq_node(uint_t axq_id)8401708Sstevel sc_find_axq_node(uint_t axq_id)
8411708Sstevel {
8421708Sstevel 	char *name;
8431708Sstevel 	int size;
8441708Sstevel 	gptwo_regspec_t *reg;
8451708Sstevel 	dev_info_t *dip;
8461708Sstevel 	uint_t id;
8471708Sstevel 	int circ;
8481708Sstevel 
8491708Sstevel 	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: id=0x%x\n", axq_id));
8501708Sstevel 
8511708Sstevel 	/*
8521708Sstevel 	 * Hold root node busy to walk its child list
8531708Sstevel 	 */
8541708Sstevel 	ndi_devi_enter(ddi_root_node(), &circ);
8551708Sstevel 
8561708Sstevel 	dip = ddi_get_child(ddi_root_node());
8571708Sstevel 
8581708Sstevel 	while (dip != NULL) {
8591708Sstevel 
8601708Sstevel 		SC_DEBUG(1, (CE_CONT, "Searching dip=0x%p for our AXQ\n",
861*11311SSurya.Prakki@Sun.COM 		    (void *)dip));
8621708Sstevel 
8631708Sstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
8641708Sstevel 		    DDI_PROP_DONTPASS, "name", (caddr_t)&name, &size)
8651708Sstevel 		    != DDI_PROP_SUCCESS) {
8661708Sstevel 
8671708Sstevel 			/*
8681708Sstevel 			 * This node does not have a name property.
8691708Sstevel 			 */
8701708Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p does not have a "
871*11311SSurya.Prakki@Sun.COM 			    "'name' property\n", (void *)dip));
8721708Sstevel 
8731708Sstevel 			dip = ddi_get_next_sibling(dip);
8741708Sstevel 			continue;
8751708Sstevel 		}
8761708Sstevel 
877*11311SSurya.Prakki@Sun.COM 		SC_DEBUG(1, (CE_CONT, "dip=0x%p name=%s\n", (void *)dip, name));
8781708Sstevel 
8791708Sstevel 		if (strcmp(name, "address-extender-queue")) {
8801708Sstevel 
8811708Sstevel 			/*
8821708Sstevel 			 * This node is not a AXQ node.
8831708Sstevel 			 */
8841708Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p is not an AXQ "
885*11311SSurya.Prakki@Sun.COM 			    "node\n", (void *)dip));
8861708Sstevel 			kmem_free(name, size);
8871708Sstevel 			dip = ddi_get_next_sibling(dip);
8881708Sstevel 			continue;
8891708Sstevel 		}
8901708Sstevel 		kmem_free(name, size);
8911708Sstevel 
8921708Sstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
8931708Sstevel 		    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &size)
8941708Sstevel 		    != DDI_PROP_SUCCESS) {
8951708Sstevel 
8961708Sstevel 			/*
8971708Sstevel 			 * This AXQ node does not have a reg property.
8981708Sstevel 			 */
8991708Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p (AXQ Node) does "
900*11311SSurya.Prakki@Sun.COM 			    "have a 'reg' property\n", (void *)dip));
9011708Sstevel 			dip = ddi_get_next_sibling(dip);
9021708Sstevel 			continue;
9031708Sstevel 		}
9041708Sstevel 
9051708Sstevel 		id = ((reg[0].gptwo_phys_hi & 1) << 9) |
9061708Sstevel 		    ((reg[0].gptwo_phys_low & 0xff800000) >> 23);
9071708Sstevel 
9081708Sstevel 		kmem_free(reg, size);
9091708Sstevel 
9101708Sstevel 		if (axq_id != id) {
9111708Sstevel 
9121708Sstevel 			/*
9131708Sstevel 			 * This is the wrong AXQ node.
9141708Sstevel 			 */
9151708Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p Wrong node id=0x%x\n",
916*11311SSurya.Prakki@Sun.COM 			    (void *)dip, id));
9171708Sstevel 
9181708Sstevel 			dip = ddi_get_next_sibling(dip);
9191708Sstevel 			continue;
9201708Sstevel 
9211708Sstevel 		}
9221708Sstevel 
9231708Sstevel 		/*
9241708Sstevel 		 * The correct AXQ node was found.
9251708Sstevel 		 */
926*11311SSurya.Prakki@Sun.COM 		SC_DEBUG(1, (CE_CONT, "dip=0x%p Found AXQ Node\n",
927*11311SSurya.Prakki@Sun.COM 		    (void *)dip));
9281708Sstevel 		ndi_hold_devi(dip);
9291708Sstevel 		break;
9301708Sstevel 	}
9311708Sstevel 	ndi_devi_exit(ddi_root_node(), circ);
9321708Sstevel 
933*11311SSurya.Prakki@Sun.COM 	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: Returning 0x%p\n",
934*11311SSurya.Prakki@Sun.COM 	    (void *)dip));
9351708Sstevel 
9361708Sstevel 	return (dip);
9371708Sstevel }
9381708Sstevel 
9391708Sstevel struct axq_arg {
9401708Sstevel 	uint_t id;
9411708Sstevel 	dev_info_t *axq_dip;
9421708Sstevel };
9431708Sstevel 
9441708Sstevel /*ARGSUSED*/
9451708Sstevel static int
axq_set_prop(dev_info_t * axq_dip,void * arg,uint_t flags)9461708Sstevel axq_set_prop(dev_info_t *axq_dip, void *arg, uint_t flags)
9471708Sstevel {
9481708Sstevel 	struct axq_arg *aqp = (struct axq_arg *)arg;
9491708Sstevel 	gptwo_regspec_t	reg[2];
9501708Sstevel 	uint_t		id;
9511708Sstevel 
9521708Sstevel 	ASSERT(aqp);
9531708Sstevel 
9541708Sstevel 	id = aqp->id;
9551708Sstevel 
9561708Sstevel 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
9571708Sstevel 	    "name", "address-extender-queue") != DDI_SUCCESS) {
9581708Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
9591708Sstevel 		    "to create name property\n"));
9601708Sstevel 		return (DDI_WALK_ERROR);
9611708Sstevel 	}
9621708Sstevel 
9631708Sstevel 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
9641708Sstevel 	    "device_type", "address-extender-queue") != DDI_SUCCESS) {
9651708Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
9661708Sstevel 		    "to create device_type property\n"));
9671708Sstevel 		return (DDI_WALK_ERROR);
9681708Sstevel 	}
9691708Sstevel 
9701708Sstevel 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
9711708Sstevel 	    "compatible", "SUNW,axq") != DDI_SUCCESS) {
9721708Sstevel 		SC_DEBUG(1, (CE_CONT, "sc_gptwocfg: failed "
9731708Sstevel 		    "to create compatible property\n"));
9741708Sstevel 		return (DDI_WALK_ERROR);
9751708Sstevel 	}
9761708Sstevel 
9771708Sstevel 	if (ndi_prop_update_int(DDI_DEV_T_NONE, axq_dip,
9781708Sstevel 	    "portid", id) != DDI_SUCCESS) {
9791708Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
9801708Sstevel 		    "to create portid property\n"));
9811708Sstevel 		return (DDI_WALK_ERROR);
9821708Sstevel 	}
9831708Sstevel 
9841708Sstevel 	reg[0].gptwo_phys_hi = 0x400 | (id >> 9);
9851708Sstevel 	reg[0].gptwo_phys_low = (id << 23);
9861708Sstevel 	reg[0].gptwo_size_hi = 0;
9871708Sstevel 	reg[0].gptwo_size_low = 0x520;
9881708Sstevel 
9891708Sstevel 	reg[1].gptwo_phys_hi = 0x401;
9901708Sstevel 	reg[1].gptwo_phys_low = 0xf0000000;
9911708Sstevel 	reg[1].gptwo_size_hi = 0;
9921708Sstevel 	reg[1].gptwo_size_low = 0x520;
9931708Sstevel 
9941708Sstevel 	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
9951708Sstevel 	    axq_dip, "reg", (int *)&reg,
9961708Sstevel 	    (sizeof (gptwo_regspec_t) * 2)/sizeof (int)) != DDI_SUCCESS) {
9971708Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
9981708Sstevel 		    "to create reg property\n"));
9991708Sstevel 		return (DDI_WALK_ERROR);
10001708Sstevel 	}
10011708Sstevel 
10021708Sstevel 	return (DDI_WALK_TERMINATE);
10031708Sstevel }
10041708Sstevel 
10051708Sstevel /*ARGSUSED*/
10061708Sstevel static void
get_axq_dip(dev_info_t * rdip,void * arg,uint_t flags)10071708Sstevel get_axq_dip(dev_info_t *rdip, void *arg, uint_t flags)
10081708Sstevel {
10091708Sstevel 	struct axq_arg *aqp = (struct axq_arg *)arg;
10101708Sstevel 
10111708Sstevel 	ASSERT(aqp);
10121708Sstevel 
10131708Sstevel 	aqp->axq_dip = rdip;
10141708Sstevel }
10151708Sstevel 
10161708Sstevel static gptwo_new_nodes_t *
sc_gptwocfg_configure_axq(dev_info_t * ap,uint_t id,int create_nodes)10171708Sstevel sc_gptwocfg_configure_axq(dev_info_t *ap, uint_t id, int create_nodes)
10181708Sstevel {
10191708Sstevel 	struct axq_arg arg = {0};
10201708Sstevel 	devi_branch_t b = {0};
10211708Sstevel 	dev_info_t *axq_dip, *fdip = NULL;
10221708Sstevel 	gptwo_new_nodes_t *new_nodes = NULL;
10231708Sstevel 	int rv;
10241708Sstevel 
10251708Sstevel 	SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: id=0x%x "
10261708Sstevel 	    "create_nodes=%d\n", id, create_nodes));
10271708Sstevel 
10281708Sstevel 	if (!create_nodes) {
10291708Sstevel 		axq_dip = sc_find_axq_node(id);
10301708Sstevel 
10311708Sstevel 		if (axq_dip) {
10321708Sstevel 			new_nodes = gptwocfg_allocate_node_list(1);
10331708Sstevel 			new_nodes->gptwo_nodes[0] = axq_dip;
10341708Sstevel 			ASSERT(!e_ddi_branch_held(axq_dip));
10351708Sstevel 			e_ddi_branch_hold(axq_dip);
10361708Sstevel 			/*
10371708Sstevel 			 * Release hold from sc_find_axq_node()
10381708Sstevel 			 */
10391708Sstevel 			ddi_release_devi(axq_dip);
10401708Sstevel 		}
10411708Sstevel 
10421708Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: "
1043*11311SSurya.Prakki@Sun.COM 		    "Returning 0x%p\n", (void *)new_nodes));
10441708Sstevel 
10451708Sstevel 		return (new_nodes);
10461708Sstevel 	}
10471708Sstevel 
10481708Sstevel 	arg.id = id;
10491708Sstevel 	arg.axq_dip = NULL;
10501708Sstevel 
10511708Sstevel 	b.arg = &arg;
10521708Sstevel 	b.type = DEVI_BRANCH_SID;
10531708Sstevel 	b.create.sid_branch_create = axq_set_prop;
10541708Sstevel 	b.devi_branch_callback = get_axq_dip;
10551708Sstevel 
10561708Sstevel 	rv = e_ddi_branch_create(ap, &b, &fdip, DEVI_BRANCH_CONFIGURE);
10571708Sstevel 	if (rv != 0) {
10581708Sstevel 		char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
10591708Sstevel 
10601708Sstevel 		/*
10611708Sstevel 		 * If non-NULL, fdip is held and must be released.
10621708Sstevel 		 */
10631708Sstevel 		if (fdip != NULL) {
10641708Sstevel 			(void) ddi_pathname(fdip, path);
10651708Sstevel 			ddi_release_devi(fdip);
10661708Sstevel 		} else {
10671708Sstevel 			(void) ddi_pathname(ap, path);
10681708Sstevel 		}
10691708Sstevel 
10701708Sstevel 		SC_DEBUG(1, (CE_WARN, "e_ddi_branch_create failed: "
10711708Sstevel 		    "path=%s, dip=%p, rv=%d", path, fdip ? (void *)fdip :
10721708Sstevel 		    (void *)ap, rv));
10731708Sstevel 
10741708Sstevel 		kmem_free(path, MAXPATHLEN);
10751708Sstevel 
10761708Sstevel 		return (NULL);
10771708Sstevel 	}
10781708Sstevel 
10791708Sstevel 	axq_dip = arg.axq_dip;
10801708Sstevel 
10811708Sstevel 	new_nodes = gptwocfg_allocate_node_list(1);
10821708Sstevel 	new_nodes->gptwo_nodes[0] = axq_dip;
10831708Sstevel 
10841708Sstevel 	return (new_nodes);
10851708Sstevel }
10861708Sstevel 
10871708Sstevel static gptwocfg_config_t *
sc_gptwocfg_unconfigure_axq(gptwocfg_config_t * config)10881708Sstevel sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *config)
10891708Sstevel {
10901708Sstevel 	int i;
10911708Sstevel 	int failure = 0;
10921708Sstevel 	dev_info_t *saf_dip;
10931708Sstevel 
10941708Sstevel 	if (config == NULL) {
10951708Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: sc_gptwocfg_unconfigure_axq: "
10961708Sstevel 		    "Invalid AXQ\n");
10971708Sstevel 		return (NULL);
10981708Sstevel 	}
10991708Sstevel 	for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) {
11001708Sstevel 		int rv;
11011708Sstevel 		dev_info_t *fdip = NULL;
11021708Sstevel 
11031708Sstevel 		saf_dip = config->gptwo_nodes->gptwo_nodes[i];
11041708Sstevel 		ASSERT(e_ddi_branch_held(saf_dip));
11051708Sstevel 		rv = e_ddi_branch_destroy(saf_dip, &fdip, 0);
11061708Sstevel 		if (rv != 0) {
11071708Sstevel 			char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
11081708Sstevel 
11091708Sstevel 			/*
11101708Sstevel 			 * If non-NULL, fdip is held and must be released.
11111708Sstevel 			 */
11121708Sstevel 			if (fdip != NULL) {
11131708Sstevel 				(void) ddi_pathname(fdip, path);
11141708Sstevel 				ddi_release_devi(fdip);
11151708Sstevel 			} else {
11161708Sstevel 				(void) ddi_pathname(saf_dip, path);
11171708Sstevel 			}
11181708Sstevel 
11191708Sstevel 			cmn_err(CE_CONT, "AXQ node removal failed: "
11201708Sstevel 			    "path=%s, dip=%p, rv=%d\n", path,
11211708Sstevel 			    fdip ? (void *)fdip : (void *)saf_dip, rv);
11221708Sstevel 
11231708Sstevel 			kmem_free(path, MAXPATHLEN);
11241708Sstevel 			failure = 1;
11251708Sstevel 		} else {
11261708Sstevel 			config->gptwo_nodes->gptwo_nodes[i] = NULL;
11271708Sstevel 		}
11281708Sstevel 	}
11291708Sstevel 	if (!failure) {
11301708Sstevel 		gptwocfg_free_node_list(config->gptwo_nodes);
11311708Sstevel 
11321708Sstevel 		kmem_free(config, sizeof (gptwocfg_config_t));
11331708Sstevel 		config = NULL;
11341708Sstevel 	}
11351708Sstevel 	return (config);
11361708Sstevel }
11371708Sstevel 
11381708Sstevel static uint_t
sc_get_agent_id(spcd_t * pcd,uint_t expander,uint_t slot,uint_t prd_slot)11391708Sstevel sc_get_agent_id(spcd_t *pcd, uint_t expander, uint_t slot, uint_t prd_slot)
11401708Sstevel {
11411708Sstevel 	uint_t agent_id;
11421708Sstevel 
11431708Sstevel 	switch (pcd->spcd_ptype) {
11441708Sstevel 	case SAFPTYPE_CPU:
11451708Sstevel 		if (slot == 0) {
11461708Sstevel 			agent_id = prd_slot;
11471708Sstevel 		} else {
11481708Sstevel 			if (prd_slot == 4) {
11491708Sstevel 				agent_id = 8;
11501708Sstevel 			} else {
11511708Sstevel 				agent_id = 9;
11521708Sstevel 			}
11531708Sstevel 		}
11541708Sstevel 		break;
11551708Sstevel 
11561708Sstevel 	case SAFPTYPE_sPCI:
11571708Sstevel 	case SAFPTYPE_cPCI:
11581708Sstevel 	case SAFPTYPE_PCIX:
11591708Sstevel 		if (prd_slot == 4) {
11601708Sstevel 			agent_id = 0x1c;
11611708Sstevel 		} else {
11621708Sstevel 			agent_id = 0x1d;
11631708Sstevel 		}
11641708Sstevel 		break;
11651708Sstevel 	case SAFPTYPE_WCI:
11661708Sstevel 		agent_id = 0x1d;
11671708Sstevel 		break;
11681708Sstevel 	default:
11691708Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: Invalid Safari Port "
11701708Sstevel 		    "Type 0x%x Slot 0x%x\n",
11711708Sstevel 		    pcd->spcd_ptype, prd_slot);
11721708Sstevel 	} /* switch */
11731708Sstevel 
11741708Sstevel 	agent_id |= (expander << 5);
11751708Sstevel 
11761708Sstevel 	SC_DEBUG(1, (CE_CONT, "sc_get_agent_id(pcd=0x%p, expander=0x%x, "
1177*11311SSurya.Prakki@Sun.COM 	    "prd_slot=0x%x) Returning agent_id=0x%x\n", (void *)pcd, expander,
11781708Sstevel 	    prd_slot, agent_id));
11791708Sstevel 
11801708Sstevel 	return (agent_id);
11811708Sstevel }
11821708Sstevel 
11831708Sstevel static void
dump_config(sc_gptwocfg_config_t * board_config)11841708Sstevel dump_config(sc_gptwocfg_config_t *board_config)
11851708Sstevel {
11861708Sstevel 	gptwocfg_config_t *port;
11871708Sstevel 
1188*11311SSurya.Prakki@Sun.COM 	SC_DEBUG(1, (CE_CONT, "dump_config 0x%p", (void *)board_config));
11891708Sstevel 	while (board_config != NULL) {
11901708Sstevel 		SC_DEBUG(1, (CE_CONT, "************* 0x%p ************\n",
1191*11311SSurya.Prakki@Sun.COM 		    (void *)board_config));
11921708Sstevel 		SC_DEBUG(1, (CE_CONT, "port_cookie - 0x%p\n",
1193*11311SSurya.Prakki@Sun.COM 		    (void *)board_config->port_cookie));
11941708Sstevel 
11951708Sstevel 		port = board_config->port_cookie;
11961708Sstevel 		if (port) {
11971708Sstevel 			SC_DEBUG(1, (CE_CONT, "     ap     - 0x%p\n",
1198*11311SSurya.Prakki@Sun.COM 			    (void *)port->gptwo_ap));
11991708Sstevel 			SC_DEBUG(1, (CE_CONT, "     portid - 0x%x\n",
12001708Sstevel 			    port->gptwo_portid));
12011708Sstevel 		}
12021708Sstevel 		SC_DEBUG(1, (CE_CONT, "portid      - 0x%x\n",
12031708Sstevel 		    board_config->portid));
12041708Sstevel 		SC_DEBUG(1, (CE_CONT, "board      - 0x%x\n",
12051708Sstevel 		    board_config->board));
12061708Sstevel 		SC_DEBUG(1, (CE_CONT, "link        - 0x%p\n",
1207*11311SSurya.Prakki@Sun.COM 		    (void *)board_config->link));
12081708Sstevel 		SC_DEBUG(1, (CE_CONT, "next        - 0x%p\n",
1209*11311SSurya.Prakki@Sun.COM 		    (void *)board_config->next));
12101708Sstevel 		board_config = board_config->link;
12111708Sstevel 	}
12121708Sstevel }
12131708Sstevel 
12141708Sstevel static void
dump_pcd(spcd_t * pcd)12151708Sstevel dump_pcd(spcd_t *pcd)
12161708Sstevel {
12171708Sstevel 	int i;
12181708Sstevel 
1219*11311SSurya.Prakki@Sun.COM 	SC_DEBUG(1, (CE_CONT, "dump_pcd 0x%p", (void *)pcd));
12201708Sstevel 	SC_DEBUG(1, (CE_CONT, "     magic   - 0x%x\n", pcd->spcd_magic));
12211708Sstevel 	SC_DEBUG(1, (CE_CONT, "     version - 0x%x\n", pcd->spcd_version));
12221708Sstevel 	SC_DEBUG(1, (CE_CONT, "     ver.reg - 0x%lx\n", pcd->spcd_ver_reg));
12231708Sstevel 	SC_DEBUG(1, (CE_CONT, "     afreq   - %d\n", pcd->spcd_afreq));
12241708Sstevel 	switch (pcd->spcd_ptype) {
12251708Sstevel 	case SAFPTYPE_CPU:
12261708Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - CPU\n"));
12271708Sstevel 		break;
12281708Sstevel 	case SAFPTYPE_sPCI:
12291708Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI\n"));
12301708Sstevel 		break;
12311708Sstevel 	case SAFPTYPE_cPCI:
12321708Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - cPCI\n"));
12331708Sstevel 		break;
12341708Sstevel 	case SAFPTYPE_PCIX:
12351708Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI+\n"));
12361708Sstevel 		break;
12371708Sstevel 	case SAFPTYPE_WCI:
12381708Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - WIC\n"));
12391708Sstevel 		break;
12401708Sstevel 	default:
12411708Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - 0x%x\n",
12421708Sstevel 		    pcd->spcd_ptype));
12431708Sstevel 		break;
12441708Sstevel 	}
12451708Sstevel 	SC_DEBUG(1, (CE_CONT, "     cache   - %d\n", pcd->spcd_cache));
12461708Sstevel 
12471708Sstevel 	if (pcd->spcd_prsv == SPCD_RSV_PASS) {
12481708Sstevel 		SC_DEBUG(1, (CE_CONT, "     prsv    - SPCD_RSV_PASS\n"));
12491708Sstevel 	} else {
12501708Sstevel 		SC_DEBUG(1, (CE_CONT, "     prsv    - 0x%x (FAIL)\n",
12511708Sstevel 		    pcd->spcd_prsv));
12521708Sstevel 	}
12531708Sstevel 
12541708Sstevel 	for (i = 0; i < AGENTS_PER_PORT; i++) {
12551708Sstevel 		if (pcd->spcd_agent[i] == SPCD_RSV_PASS) {
12561708Sstevel 			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
12571708Sstevel 			    "- SPCD_RSV_PASS\n", i));
12581708Sstevel 		} else {
12591708Sstevel 			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
12601708Sstevel 			    "- 0x%x (FAIL)\n", i, pcd->spcd_agent[i]));
12611708Sstevel 		}
12621708Sstevel 	}
12631708Sstevel 
12641708Sstevel 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
12651708Sstevel 		for (i = 0; i < AGENTS_PER_PORT; i++) {
12661708Sstevel 			SC_DEBUG(1, (CE_CONT, "     cpuid[%d] - 0x%x\n",
12671708Sstevel 			    i, pcd->spcd_cpuid[i]));
12681708Sstevel 		}
12691708Sstevel 	}
12701708Sstevel 
12711708Sstevel 	SC_DEBUG(1, (CE_CONT, "     Banks\n"));
12721708Sstevel 	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
12731708Sstevel 		if (pcd->sprd_bank_rsv[i]) {
12741708Sstevel 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
12751708Sstevel 			    pcd->sprd_bank_rsv[i]));
12761708Sstevel 		}
12771708Sstevel 	}
12781708Sstevel 
12791708Sstevel 	SC_DEBUG(1, (CE_CONT, "     Dimms\n"));
12801708Sstevel 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
12811708Sstevel 		if (pcd->sprd_dimm[i]) {
12821708Sstevel 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
12831708Sstevel 			    pcd->sprd_dimm[i]));
12841708Sstevel 		}
12851708Sstevel 	}
12861708Sstevel 	SC_DEBUG(1, (CE_CONT, "     Ecache Dimm Labels\n"));
12871708Sstevel 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
12881708Sstevel 		if (pcd->sprd_ecache_dimm_label[i]) {
12891708Sstevel 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
12901708Sstevel 			    pcd->sprd_ecache_dimm_label[i]));
12911708Sstevel 		}
12921708Sstevel 	}
12931708Sstevel }
12941708Sstevel 
12951708Sstevel 
12961708Sstevel typedef struct {
12971708Sstevel 	char Jnumber[8][8];
12981708Sstevel 	uint8_t sym_flag;
12991708Sstevel 	uint8_t d_dimmtable[144];
13001708Sstevel 	uint8_t d_pintable[576];
13011708Sstevel }m_layout;
13021708Sstevel 
13031708Sstevel /*
13041708Sstevel  * Use 2 bits to represent each bit at a cache line. The table
13051708Sstevel  * is in big endian order, i.e.
13061708Sstevel  *      dimmtable[0], ... , dimmtable[143]
13071708Sstevel  * Q0:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
13081708Sstevel  *                      .
13091708Sstevel  *                      .
13101708Sstevel  * Q3:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
13111708Sstevel  */
13121708Sstevel uint8_t J_dimm_pinTable[] = {
13131708Sstevel /* Jnumber */
13141708Sstevel /*  0 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x30, 0x00, 0x00,
13151708Sstevel /*  1 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x30, 0x00, 0x00,
13161708Sstevel /*  2 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x30, 0x00, 0x00,
13171708Sstevel /*  3 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x30, 0x00, 0x00,
13181708Sstevel /*  4 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x31, 0x00, 0x00,
13191708Sstevel /*  5 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x31, 0x00, 0x00,
13201708Sstevel /*  6 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x31, 0x00, 0x00,
13211708Sstevel /*  7 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x31, 0x00, 0x00,
13221708Sstevel /* flag */	0x01,
13231708Sstevel /*  -- Q0 --  */
13241708Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
13251708Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
13261708Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
13271708Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
13281708Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
13291708Sstevel /*  -- Q1 --  */
13301708Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
13311708Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
13321708Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
13331708Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
13341708Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
13351708Sstevel /*  -- Q2 --  */
13361708Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
13371708Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
13381708Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
13391708Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
13401708Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
13411708Sstevel /*  -- Q3 --  */
13421708Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
13431708Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
13441708Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
13451708Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
13461708Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
13471708Sstevel /*
13481708Sstevel  * In the following order
13491708Sstevel  *      pintable[0], ..., pintable[575]
13501708Sstevel  * Quadword3, Quadword2, Quadword1, Quadword0
13511708Sstevel  *      MtagEcc, Mtag, Ecc, Data
13521708Sstevel  */
13531708Sstevel /* -- Q3 -- */
13541708Sstevel /*  0  */	227, 227, 227, 227, 111, 111, 111,  22,
13551708Sstevel /*  1  */	22,  32, 138, 222,  81, 117, 117, 117,
13561708Sstevel /*  2  */	111, 222, 106, 222, 222, 106, 106, 106,
13571708Sstevel /*  3  */	217, 101, 212,  96, 217, 101, 212,  96,
13581708Sstevel /*  4  */	217, 101, 212,  96, 217, 101, 212,  96,
13591708Sstevel /*  5  */	207,  91, 202,  86, 187,  71, 158,  42,
13601708Sstevel /*  6  */	187,  71, 158,  42, 153,  37, 148,  32,
13611708Sstevel /*  7  */	153,  37, 148,  32, 153,  37, 148,  32,
13621708Sstevel /*  8  */	153,  37, 148, 143,  27, 138, 143,  27,
13631708Sstevel /*  9  */	143,  27, 138,  22, 207,  91, 202,  86,
13641708Sstevel /*  10 */	207,  91, 202,  86, 207,  91, 202,  86,
13651708Sstevel /*  11 */	192,  76,  81, 192,  76,  81, 192,  76,
13661708Sstevel /*  12 */	197,  81, 192,  76, 187,  71, 158,  42,
13671708Sstevel /*  13 */	187,  71, 158,  42, 143,  27, 138,  22,
13681708Sstevel /*  14 */	133,  17, 128,  12, 133,  17, 128,  12,
13691708Sstevel /*  15 */	133,  17, 128,  12, 133,  17, 128,  12,
13701708Sstevel /*  16 */	123,  07, 118,   2, 123,  07, 118,   2,
13711708Sstevel /*  17 */	123,  07, 118,   2, 123,  07, 118,   2,
13721708Sstevel /* -- Q2 -- */
13731708Sstevel /*  0  */	228, 228, 228, 228, 112, 112, 112,  23,
13741708Sstevel /*  1  */	23,  33, 139, 223,  82, 118, 118, 118,
13751708Sstevel /*  2  */	112, 223, 107, 223, 223, 107, 107, 107,
13761708Sstevel /*  3  */	218, 102, 213,  97, 218, 102, 213,  97,
13771708Sstevel /*  4  */	218, 102, 213,  97, 218, 102, 213,  97,
13781708Sstevel /*  5  */	208,  92, 203,  87, 188,  72, 159,  43,
13791708Sstevel /*  6  */	188,  72, 159,  43, 154,  38, 149,  33,
13801708Sstevel /*  7  */	154,  38, 149,  33, 154,  38, 149,  33,
13811708Sstevel /*  8  */	154,  38, 149, 144,  28, 139, 144,  28,
13821708Sstevel /*  9  */	144,  28, 139,  23, 208,  92, 203,  87,
13831708Sstevel /*  10 */	208,  92, 203,  87, 208,  92, 203,  87,
13841708Sstevel /*  11 */	193,  77,  82, 193,  77,  82, 193,  77,
13851708Sstevel /*  12 */	198,  82, 193,  77, 188,  72, 159,  43,
13861708Sstevel /*  13 */	188,  72, 159,  43, 144,  28, 139,  23,
13871708Sstevel /*  14 */	134,  18, 129,  13, 134,  18, 129,  13,
13881708Sstevel /*  15 */	134,  18, 129,  13, 134,  18, 129,  13,
13891708Sstevel /*  16 */	124,   8, 119,   3, 124,   8, 119,   3,
13901708Sstevel /*  17 */	124,   8, 119,   3, 124,   8, 119,   3,
13911708Sstevel /* -- Q1 -- */
13921708Sstevel /*  0  */	229, 229, 229, 229, 113, 113, 113,  24,
13931708Sstevel /*  1  */	24,  34, 140, 224,  83, 119, 119, 119,
13941708Sstevel /*  2  */	113, 224, 108, 224, 224, 108, 108, 108,
13951708Sstevel /*  3  */	219, 103, 214,  98, 219, 103, 214,  98,
13961708Sstevel /*  4  */	219, 103, 214,  98, 219, 103, 214,  98,
13971708Sstevel /*  5  */	209,  93, 204,  88, 189,  73, 160,  44,
13981708Sstevel /*  6  */	189,  73, 160,  44, 155,  39, 150,  34,
13991708Sstevel /*  7  */	155,  39, 150,  34, 155,  39, 150,  34,
14001708Sstevel /*  8  */	155,  39, 150, 145,  29, 140, 145,  29,
14011708Sstevel /*  9  */	145,  29, 140,  24, 209,  93, 204,  88,
14021708Sstevel /*  10 */	209,  93, 204,  88, 209,  93, 204,  88,
14031708Sstevel /*  11 */	194,  78,  83, 194,  78,  83, 194,  78,
14041708Sstevel /*  12 */	199,  83, 194,  78, 189,  73, 160,  44,
14051708Sstevel /*  13 */	189,  73, 160,  44, 145,  29, 140,  24,
14061708Sstevel /*  14 */	135,  19, 130,  14, 135,  19, 130,  14,
14071708Sstevel /*  15 */	135,  19, 130,  14, 135,  19, 130,  14,
14081708Sstevel /*  16 */	125,   9, 120,   4, 125,   9, 120,   4,
14091708Sstevel /*  17 */	125,   9, 120,   4, 125,   9, 120,   4,
14101708Sstevel /* -- Q0 -- */
14111708Sstevel /*  0  */	230, 230, 230, 230, 114, 114, 114,  25,
14121708Sstevel /*  1  */	25,  35, 141, 225,  84, 200, 200, 200,
14131708Sstevel /*  2  */	114, 225, 109, 225, 225, 109, 109, 109,
14141708Sstevel /*  3  */	220, 104, 215,  99, 220, 104, 215,  99,
14151708Sstevel /*  4  */	220, 104, 215,  99, 220, 104, 215,  99,
14161708Sstevel /*  5  */	210,  94, 205,  89, 190,  74, 161,  45,
14171708Sstevel /*  6  */	190,  74, 161,  45, 156,  40, 151,  35,
14181708Sstevel /*  7  */	156,  40, 151,  35, 156,  40, 151,  35,
14191708Sstevel /*  8  */	156,  40, 151, 146,  30, 141, 146,  30,
14201708Sstevel /*  9  */	146,  30, 141,  25, 210,  94, 205,  89,
14211708Sstevel /*  10 */	210,  94, 205,  89, 210,  94, 205,  89,
14221708Sstevel /*  11 */	195,  79,  84, 195,  79,  84, 195,  79,
14231708Sstevel /*  12 */	200,  84, 195,  79, 190,  74, 161,  45,
14241708Sstevel /*  13 */	190,  74, 161,  45, 146,  30, 141,  25,
14251708Sstevel /*  14 */	136,  20, 131,  15, 136,  20, 131,  15,
14261708Sstevel /*  15 */	136,  20, 131,  15, 136,  20, 131,  15,
14271708Sstevel /*  16 */	126,  10, 121,   5, 126,  10, 121,   5,
14281708Sstevel /*  17 */	126,  10, 121,   5, 126,  10, 121,   5
14291708Sstevel };
14301708Sstevel 
14311708Sstevel /*
14321708Sstevel  *  This table is for internal reference
14331708Sstevel  *
14341708Sstevel  * pintable_internal[]= {
14351708Sstevel  * -- Q0 --
14361708Sstevel  * 0  143,143,143,143,139,139,139,35
14371708Sstevel  * 1  35,51,39,135,91,95,95,95
14381708Sstevel  * 2  139,135,131,135,135,131,131,131
14391708Sstevel  * 3  127,123,119,115,127,123,119,115
14401708Sstevel  * 4  127,123,119,115,127,123,119,115
14411708Sstevel  * 5  111,107,103,99,79,75,71,67
14421708Sstevel  * 6  79,75,71,67,63,59,55,51
14431708Sstevel  * 7  63,59,55,51,63,59,55,51
14441708Sstevel  * 8  63,59,55,47,43,39,47,43
14451708Sstevel  * 9  47,43,39,35,111,107,103,99
14461708Sstevel  * 10  111,107,103,99,111,107,103,99
14471708Sstevel  * 11  87,83,91,87,83,91,87,83
14481708Sstevel  * 12  95,91,87,83,79,75,71,67
14491708Sstevel  * 13  79,75,71,67,47,43,39,35
14501708Sstevel  * 14  31,27,23,19,31,27,23,19
14511708Sstevel  * 15  31,27,23,19,31,27,23,19
14521708Sstevel  * 16  15,11,7,3,15,11,7,3
14531708Sstevel  * 17  15,11,7,3,15,11,7,3
14541708Sstevel  * }
14551708Sstevel  */
14561708Sstevel 
14571708Sstevel char *dimm_Jno[] = {
14581708Sstevel /* P0 */	"J13300", "J13400", "J13500", "J13600",
14591708Sstevel 		"J13301", "J13401", "J13501", "J13601",
14601708Sstevel /* P1 */	"J14300", "J14400", "J14500", "J14600",
14611708Sstevel 		"J14301", "J14401", "J14501", "J14601",
14621708Sstevel /* P2 */	"J15300", "J15400", "J15500", "J15600",
14631708Sstevel 		"J15301", "J15401", "J15501", "J15601",
14641708Sstevel /* P3 */	"J16300", "J16400", "J16500", "J16600",
14651708Sstevel 		"J16301", "J16401", "J16501", "J16601",
14661708Sstevel 		NULL
14671708Sstevel 	};
14681708Sstevel 
14691708Sstevel 
14701708Sstevel static uint8_t *
get_memlayout(uint32_t cpuid,uint32_t * len)14711708Sstevel get_memlayout(uint32_t cpuid, uint32_t *len)
14721708Sstevel {
14731708Sstevel 	m_layout *LayoutBuf;
14741708Sstevel 
14751708Sstevel 	if ((LayoutBuf = (m_layout *)kmem_zalloc(sizeof (m_layout),
14761708Sstevel 	    KM_SLEEP)) == NULL) {
14771708Sstevel 		*len = 0;
14781708Sstevel 		return (NULL);
14791708Sstevel 	}
14801708Sstevel 
14811708Sstevel 	bcopy(J_dimm_pinTable, LayoutBuf, sizeof (m_layout));
14821708Sstevel 
14831708Sstevel 	*len = sizeof (m_layout);
14841708Sstevel 	cpuid &= 0x03;	/* last 2 bits of a 10 bit number */
14851708Sstevel 
14861708Sstevel 	bcopy(dimm_Jno[cpuid << 3], LayoutBuf->Jnumber[0], 64);
14871708Sstevel 
14881708Sstevel 	return ((uint8_t *)LayoutBuf);
14891708Sstevel }
14901708Sstevel 
14911708Sstevel static char *
rsv_string(prdrsv_t rsv)14921708Sstevel rsv_string(prdrsv_t rsv)
14931708Sstevel {
14941708Sstevel 	char *buffer;
14951708Sstevel 	char *status;
14961708Sstevel 
14971708Sstevel 	switch (rsv) {
14981708Sstevel 	case RSV_UNKNOWN:
14991708Sstevel 		buffer = "unknown";
15001708Sstevel 		break;
15011708Sstevel 	case RSV_PRESENT:
15021708Sstevel 		buffer = "okay";
15031708Sstevel 		break;
15041708Sstevel 	case RSV_CRUNCH:
15051708Sstevel 		buffer = "disabled";
15061708Sstevel 		break;
15071708Sstevel 	case RSV_UNDEFINED:
15081708Sstevel 		buffer = "undefined";
15091708Sstevel 		break;
15101708Sstevel 	case RSV_MISS:
15111708Sstevel 		buffer = "missing";
15121708Sstevel 		break;
15131708Sstevel 	case RSV_EMPTY_CASSETTE:
15141708Sstevel 		buffer = "disabled";
15151708Sstevel 		break;
15161708Sstevel 	case RSV_MISCONFIG:
15171708Sstevel 		buffer = "misconfigured";
15181708Sstevel 		break;
15191708Sstevel 	case RSV_FAIL_OBP:
15201708Sstevel 		buffer = "fail-obp";
15211708Sstevel 		break;
15221708Sstevel 	case RSV_BLACK:
15231708Sstevel 		buffer = "blacklisted";
15241708Sstevel 		break;
15251708Sstevel 	case RSV_RED:
15261708Sstevel 		buffer = "redlisted";
15271708Sstevel 		break;
15281708Sstevel 	case RSV_EXCLUDED:
15291708Sstevel 		buffer = "disabled";
15301708Sstevel 		break;
15311708Sstevel 	case RSV_UNCONFIG:
15321708Sstevel 		buffer = "disabled";
15331708Sstevel 		break;
15341708Sstevel 	case RSV_PASS:
15351708Sstevel 		buffer = "okay";
15361708Sstevel 		break;
15371708Sstevel 	case RSV_FAIL:
15381708Sstevel 	default:
15391708Sstevel 		buffer = "fail";
15401708Sstevel 		break;
15411708Sstevel 	}
15421708Sstevel 
15431708Sstevel 	status = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
15441708Sstevel 	(void) strcpy(status, buffer);
15451708Sstevel 
15461708Sstevel 	return (status);
15471708Sstevel }
1548