xref: /titanic_51/usr/src/uts/sun4u/starcat/io/sc_gptwocfg.c (revision 07d06da50d310a325b457d6330165aebab1e0064)
103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
503831d35Sstevel  * Common Development and Distribution License (the "License").
603831d35Sstevel  * You may not use this file except in compliance with the License.
703831d35Sstevel  *
803831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel  * See the License for the specific language governing permissions
1103831d35Sstevel  * and limitations under the License.
1203831d35Sstevel  *
1303831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel  *
1903831d35Sstevel  * CDDL HEADER END
2003831d35Sstevel  */
2103831d35Sstevel 
2203831d35Sstevel /*
23*07d06da5SSurya Prakki  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2403831d35Sstevel  * Use is subject to license terms.
2503831d35Sstevel  */
2603831d35Sstevel 
2703831d35Sstevel /*
2803831d35Sstevel  *     Starcat Specific Glue for Safari Configurator
2903831d35Sstevel  */
3003831d35Sstevel 
3103831d35Sstevel #include <sys/isa_defs.h>
3203831d35Sstevel #include <sys/conf.h>
3303831d35Sstevel #include <sys/kmem.h>
3403831d35Sstevel #include <sys/debug.h>
3503831d35Sstevel #include <sys/modctl.h>
3603831d35Sstevel #include <sys/autoconf.h>
3703831d35Sstevel #include <sys/hwconf.h>
3803831d35Sstevel #include <sys/ddi_impldefs.h>
3903831d35Sstevel #include <sys/ddi.h>
4003831d35Sstevel #include <sys/sunddi.h>
4103831d35Sstevel #include <sys/sunndi.h>
4203831d35Sstevel #include <sys/ndi_impldefs.h>
4303831d35Sstevel #include <sys/safari_pcd.h>
4403831d35Sstevel #include <sys/gp2cfg.h>
4503831d35Sstevel #include <sys/gptwo_cpu.h>
4603831d35Sstevel #include <sys/gptwo_pci.h>
4703831d35Sstevel #include <sys/sc_gptwocfg.h>
4803831d35Sstevel #include <post/scat_dcd.h>
4903831d35Sstevel #include <sys/machsystm.h>
5003831d35Sstevel 
5103831d35Sstevel int sc_gptwocfg_debug = 0;
5203831d35Sstevel 
5303831d35Sstevel #define	SC_DEBUG(level, args) if (sc_gptwocfg_debug >= level) cmn_err args
5403831d35Sstevel 
5503831d35Sstevel typedef struct sc_gptwocfg_config {
5603831d35Sstevel 	int				board;
5703831d35Sstevel 	struct gptwocfg_config		*port_cookie;
5803831d35Sstevel 	gptwo_aid_t			portid;
5903831d35Sstevel 	struct sc_gptwocfg_config	*link;
6003831d35Sstevel 	struct sc_gptwocfg_config	*next;
6103831d35Sstevel } sc_gptwocfg_config_t;
6203831d35Sstevel 
6303831d35Sstevel static kmutex_t sc_gptwo_config_list_lock;
6403831d35Sstevel static sc_gptwocfg_config_t *sc_gptwo_config_list;
6503831d35Sstevel static dev_info_t *sc_find_axq_node(uint_t);
6603831d35Sstevel static sc_gptwocfg_cookie_t sc_configure(uint_t, int);
6703831d35Sstevel static spcd_t *sc_get_common_pcd(uint_t, uint_t);
6803831d35Sstevel static void sc_free_common_pcd(spcd_t *);
6903831d35Sstevel static gptwo_new_nodes_t *sc_gptwocfg_configure_axq(dev_info_t *, uint_t, int);
7003831d35Sstevel static gptwocfg_config_t *sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *);
7103831d35Sstevel static void dump_config(sc_gptwocfg_config_t *);
7203831d35Sstevel static void dump_pcd(spcd_t *);
7303831d35Sstevel static uint_t sc_get_agent_id(spcd_t *, uint_t, uint_t, uint_t);
7403831d35Sstevel static char *rsv_string(prdrsv_t);
7503831d35Sstevel 
7603831d35Sstevel extern gptwo_new_nodes_t *gptwocfg_allocate_node_list(int);
7703831d35Sstevel extern void gptwocfg_free_node_list(gptwo_new_nodes_t *);
7803831d35Sstevel 
7903831d35Sstevel static uint8_t *get_memlayout(uint32_t, uint32_t *);
8003831d35Sstevel 
8103831d35Sstevel #ifdef NO_IOSRAM
8203831d35Sstevel int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
8303831d35Sstevel #else
8403831d35Sstevel extern int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
8503831d35Sstevel #endif
8603831d35Sstevel extern void gptwocfg_devi_attach_to_parent(dev_info_t *);
8703831d35Sstevel 
8803831d35Sstevel /*
8903831d35Sstevel  * Module control operations
9003831d35Sstevel  */
9103831d35Sstevel 
9203831d35Sstevel extern struct mod_ops mod_miscops;
9303831d35Sstevel 
9403831d35Sstevel static struct modlmisc modlmisc = {
9503831d35Sstevel 	&mod_miscops, /* Type of module */
96f500b196SRichard Bean 	"Sun Fire 15000 gptwocfg"
9703831d35Sstevel };
9803831d35Sstevel 
9903831d35Sstevel static struct modlinkage modlinkage = {
10003831d35Sstevel 	MODREV_1, (void *)&modlmisc, NULL
10103831d35Sstevel };
10203831d35Sstevel 
10303831d35Sstevel int
10403831d35Sstevel _init()
10503831d35Sstevel {
10603831d35Sstevel 	int err = 0;
10703831d35Sstevel 
10803831d35Sstevel 	mutex_init(&sc_gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL);
10903831d35Sstevel 	sc_gptwo_config_list = NULL;
11003831d35Sstevel 
11103831d35Sstevel 	/*
11203831d35Sstevel 	 * CPU/PCI devices are already registered by their respective modules,
11303831d35Sstevel 	 * so all we need to do now is install.
11403831d35Sstevel 	 */
11503831d35Sstevel 	if ((err = mod_install(&modlinkage)) != 0) {
11603831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg failed to load, error=%d\n",
11703831d35Sstevel 		    err));
11803831d35Sstevel 		mutex_destroy(&sc_gptwo_config_list_lock);
11903831d35Sstevel 	} else {
12003831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg has been loaded.\n"));
12103831d35Sstevel 	}
12203831d35Sstevel 	return (err);
12303831d35Sstevel }
12403831d35Sstevel 
12503831d35Sstevel int
12603831d35Sstevel _fini(void)
12703831d35Sstevel {
12803831d35Sstevel 	mutex_destroy(&sc_gptwo_config_list_lock);
12903831d35Sstevel 	return (mod_remove(&modlinkage));
13003831d35Sstevel }
13103831d35Sstevel 
13203831d35Sstevel int
13303831d35Sstevel _info(modinfop)
13403831d35Sstevel struct modinfo *modinfop;
13503831d35Sstevel {
13603831d35Sstevel 	return (mod_info(&modlinkage, modinfop));
13703831d35Sstevel }
13803831d35Sstevel 
13903831d35Sstevel static spcd_t *
14003831d35Sstevel sc_get_common_pcd(uint_t expander, uint_t prd_slot)
14103831d35Sstevel {
14203831d35Sstevel 	spcd_t *pcd;
14303831d35Sstevel 	gdcd_t *gdcd;
14403831d35Sstevel 	int portid;
14503831d35Sstevel 	int i, j, slot;
14603831d35Sstevel 	int dimm;
14703831d35Sstevel 	char *label1, *label2;
14803831d35Sstevel 
14903831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_get_common_pcd() expander=%d prd_slot=%d\n",
15003831d35Sstevel 	    expander, prd_slot));
15103831d35Sstevel 
15203831d35Sstevel 	gdcd = (gdcd_t *)kmem_zalloc(sizeof (gdcd_t), KM_SLEEP);
15303831d35Sstevel 
15403831d35Sstevel 	/*
15503831d35Sstevel 	 * Get the Starcat Specific Global DCD Structure from the golden
15603831d35Sstevel 	 * IOSRAM.
15703831d35Sstevel 	 */
15803831d35Sstevel 	if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
15903831d35Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: Unable To Read GDCD "
16003831d35Sstevel 		    "From IOSRAM\n");
16103831d35Sstevel 		kmem_free(gdcd, sizeof (gdcd_t));
16203831d35Sstevel 		return (NULL);
16303831d35Sstevel 	}
16403831d35Sstevel 
16503831d35Sstevel 	if (gdcd->h.dcd_magic != GDCD_MAGIC) {
16603831d35Sstevel 
16703831d35Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Magic 0x%x\n",
16803831d35Sstevel 		    gdcd->h.dcd_magic);
16903831d35Sstevel 
17003831d35Sstevel 		kmem_free(gdcd, sizeof (gdcd_t));
17103831d35Sstevel 		return (NULL);
17203831d35Sstevel 	}
17303831d35Sstevel 
17403831d35Sstevel 	if (gdcd->h.dcd_version != DCD_VERSION) {
17503831d35Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Version: "
17603831d35Sstevel 		    "GDCD Version 0x%x Expecting 0x%x\n",
17703831d35Sstevel 		    gdcd->h.dcd_version, DCD_VERSION);
17803831d35Sstevel 
17903831d35Sstevel 		kmem_free(gdcd, sizeof (gdcd_t));
18003831d35Sstevel 		return (NULL);
18103831d35Sstevel 	}
18203831d35Sstevel 
18303831d35Sstevel 	pcd = (spcd_t *)kmem_zalloc(sizeof (spcd_t), KM_SLEEP);
18403831d35Sstevel 
18503831d35Sstevel 	/*
18603831d35Sstevel 	 * Copy various information from the platform specific Port
18703831d35Sstevel 	 * Resource Descriptor (PRD) To the platform independent
18803831d35Sstevel 	 * Port Configuration Descriptor.
18903831d35Sstevel 	 */
19003831d35Sstevel 	pcd->spcd_magic = PCD_MAGIC;
19103831d35Sstevel 	pcd->spcd_version = PCD_VERSION;
19203831d35Sstevel 	pcd->spcd_ptype = gdcd->dcd_prd[expander][prd_slot].prd_ptype;
19303831d35Sstevel 	pcd->spcd_ver_reg = gdcd->dcd_prd[expander][prd_slot].prd_ver_reg;
19403831d35Sstevel 
19503831d35Sstevel 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
19603831d35Sstevel 		/*
19703831d35Sstevel 		 * This will calculate the cpu speed based on the
19803831d35Sstevel 		 * the actual frequency ratio * interconnect frequency
19903831d35Sstevel 		 * converted to Mhz.
20003831d35Sstevel 		 */
20103831d35Sstevel 		pcd->spcd_afreq = gdcd->dcd_prd[expander][prd_slot].
20203831d35Sstevel 		    prd_afreq_ratio *
20303831d35Sstevel 		    (uint16_t)((gdcd->dcd_intercon_freq + 500000) / 1000000);
20403831d35Sstevel 	} else {
20503831d35Sstevel 		/*
20603831d35Sstevel 		 * For non-cpu devices, just pass through the frequency
20703831d35Sstevel 		 * unchanged.
20803831d35Sstevel 		 */
20903831d35Sstevel 		pcd->spcd_afreq =
21003831d35Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_afreq_ratio;
21103831d35Sstevel 	}
21203831d35Sstevel 
21303831d35Sstevel 	pcd->spcd_cache = gdcd->dcd_prd[expander][prd_slot].prd_cache;
21403831d35Sstevel 
21503831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "Safari Device Status status=0x%x\n",
21603831d35Sstevel 	    gdcd->dcd_prd[expander][prd_slot].prd_prsv));
21703831d35Sstevel 
21803831d35Sstevel 	/*
21903831d35Sstevel 	 * Fill in the entire port status.
22003831d35Sstevel 	 */
22103831d35Sstevel 	if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].prd_prsv)) {
22203831d35Sstevel 		pcd->spcd_prsv = SPCD_RSV_PASS;
22303831d35Sstevel 	} else {
22403831d35Sstevel 		pcd->spcd_prsv = SPCD_RSV_FAIL;
22503831d35Sstevel 	}
22603831d35Sstevel 
22703831d35Sstevel 	/*
22803831d35Sstevel 	 * Fill in the per agent status.
22903831d35Sstevel 	 */
23003831d35Sstevel 	if (gdcd->dcd_prd[expander][prd_slot].prd_agent[1] == RSV_UNKNOWN) {
23103831d35Sstevel 		pcd->spcd_agent[0] = pcd->spcd_prsv;
23203831d35Sstevel 		pcd->spcd_agent[1] = SPCD_RSV_FAIL;
23303831d35Sstevel 	} else {
23403831d35Sstevel 		for (i = 0; i < AGENTS_PER_PORT; i++) {
23503831d35Sstevel 
23603831d35Sstevel 			if (RSV_GOOD(
23703831d35Sstevel 			    gdcd->dcd_prd[expander][prd_slot].prd_agent[i]))
23803831d35Sstevel 				pcd->spcd_agent[i] = SPCD_RSV_PASS;
23903831d35Sstevel 			else
24003831d35Sstevel 				pcd->spcd_agent[i] = SPCD_RSV_FAIL;
24103831d35Sstevel 		}
24203831d35Sstevel 	}
24303831d35Sstevel 
24403831d35Sstevel 	/*
24503831d35Sstevel 	 * If this is a CPU device calculate the cpuid for it.  For Starcat
24603831d35Sstevel 	 * the cpuid is in the following format.
24703831d35Sstevel 	 *
24803831d35Sstevel 	 * EEEEEPPAPP
24903831d35Sstevel 	 *
25003831d35Sstevel 	 * where:	EEEEE is the expander
25103831d35Sstevel 	 *		PP_PP is the portid
25203831d35Sstevel 	 *		__A__ is the sub-agent identifier.
25303831d35Sstevel 	 */
25403831d35Sstevel 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
25503831d35Sstevel 		for (i = 0; i < AGENTS_PER_PORT; i++) {
25603831d35Sstevel 			switch (prd_slot) {
25703831d35Sstevel 			case 0:
25803831d35Sstevel 			case 1:
25903831d35Sstevel 			case 2:
26003831d35Sstevel 			case 3:
26103831d35Sstevel 				portid = (expander << 5) | prd_slot;
26203831d35Sstevel 				break;
26303831d35Sstevel 			case 4: /* Maxcat */
26403831d35Sstevel 				portid = (expander << 5) | 8;
26503831d35Sstevel 				break;
26603831d35Sstevel 			case 5: /* Maxcat */
26703831d35Sstevel 				portid = (expander << 5) | 9;
26803831d35Sstevel 				break;
26903831d35Sstevel 			default:
27003831d35Sstevel 				cmn_err(CE_WARN, "sc_gptwocfg: invalid "
27103831d35Sstevel 				    "prd_slot=%d\n", prd_slot);
27203831d35Sstevel 			}
27303831d35Sstevel 			pcd->spcd_cpuid[i] = (i << 2) | portid;
27403831d35Sstevel 		}
27503831d35Sstevel 	}
27603831d35Sstevel 
27703831d35Sstevel 	/*
27803831d35Sstevel 	 * Starcat does not have ports with UPA devices so
27903831d35Sstevel 	 * spcd_upadev structure will not be filled in.
28003831d35Sstevel 	 */
28103831d35Sstevel 
28203831d35Sstevel 	/*
28303831d35Sstevel 	 * Fill in IO Bus Status
28403831d35Sstevel 	 */
28503831d35Sstevel 	for (i = 0; i < IOBUS_PER_PORT; i++) {
28603831d35Sstevel 
28703831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "   IO Bus Status "
28803831d35Sstevel 		    "bus=%d status=0x%x\n", i,
28903831d35Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i]));
29003831d35Sstevel 
29103831d35Sstevel 		if (RSV_GOOD(
29203831d35Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i])) {
29303831d35Sstevel 			pcd->spcd_iobus_rsv[i] = SPCD_RSV_PASS;
29403831d35Sstevel 		} else {
29503831d35Sstevel 			pcd->spcd_iobus_rsv[i] = SPCD_RSV_FAIL;
29603831d35Sstevel 		}
29703831d35Sstevel 
29803831d35Sstevel 		for (j = 0; j < IOCARD_PER_BUS; j++)
29903831d35Sstevel 			pcd->spcd_iocard_rsv[i][j] = SPCD_RSV_FAIL;
30003831d35Sstevel 
30103831d35Sstevel 		/*
30203831d35Sstevel 		 * Fill in IO Card Status
30303831d35Sstevel 		 */
30403831d35Sstevel 		for (j = 0; j < IOCARD_PER_BUS; j++) {
30503831d35Sstevel 
30603831d35Sstevel 			SC_DEBUG(1, (CE_WARN, "       Card Status bus=%d "
30703831d35Sstevel 			    "slot=%d status=0x%x\n", i, j,
30803831d35Sstevel 			    gdcd->dcd_prd[expander][prd_slot].
30903831d35Sstevel 			    prd_iocard_rsv[i][j]));
31003831d35Sstevel 
31103831d35Sstevel 			if (j == 1)
31203831d35Sstevel 				continue;
31303831d35Sstevel 
31403831d35Sstevel 			if (j == 0)
31503831d35Sstevel 				slot = 1;
31603831d35Sstevel 			else
31703831d35Sstevel 				slot = j;
31803831d35Sstevel 
31903831d35Sstevel 			/*
32003831d35Sstevel 			 * If POST marked the card as GOOD or if the slot
32103831d35Sstevel 			 * is empty, we want to probe for the device.
32203831d35Sstevel 			 */
32303831d35Sstevel 			if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].
32403831d35Sstevel 			    prd_iocard_rsv[i][j]) ||
32503831d35Sstevel 			    (gdcd->dcd_prd[expander][prd_slot].
32603831d35Sstevel 			    prd_iocard_rsv[i][j] == RSV_MISS) ||
32703831d35Sstevel 			    (gdcd->dcd_prd[expander][prd_slot].
32803831d35Sstevel 			    prd_iocard_rsv[i][j] == RSV_EMPTY_CASSETTE))
32903831d35Sstevel 				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_PASS;
33003831d35Sstevel 			else
33103831d35Sstevel 				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_FAIL;
33203831d35Sstevel 		}
33303831d35Sstevel 	}
33403831d35Sstevel 
33503831d35Sstevel 	/*
33603831d35Sstevel 	 * Fill in WIC Link Status
33703831d35Sstevel 	 */
33803831d35Sstevel 	for (i = 0; i < LINKS_PER_PORT; i++) {
33903831d35Sstevel 		if (RSV_GOOD(
34003831d35Sstevel 		    gdcd->dcd_prd[expander][prd_slot].prd_wic_links[i])) {
34103831d35Sstevel 			pcd->spcd_wic_links[i] = SPCD_RSV_PASS;
34203831d35Sstevel 
34303831d35Sstevel 		} else {
34403831d35Sstevel 			pcd->spcd_wic_links[i] = SPCD_RSV_FAIL;
34503831d35Sstevel 		}
34603831d35Sstevel 	}
34703831d35Sstevel 
34803831d35Sstevel 	/*
34903831d35Sstevel 	 * Get data for the "bank-status" property.
35003831d35Sstevel 	 */
35103831d35Sstevel 	pcd->sprd_bank_rsv[0] =
35203831d35Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][0]);
35303831d35Sstevel 	pcd->sprd_bank_rsv[1] =
35403831d35Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][0]);
35503831d35Sstevel 	pcd->sprd_bank_rsv[2] =
35603831d35Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][1]);
35703831d35Sstevel 	pcd->sprd_bank_rsv[3] =
35803831d35Sstevel 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][1]);
35903831d35Sstevel 
36003831d35Sstevel 	dimm = 0;
36103831d35Sstevel 	for (i = 0; i < PMBANKS_PER_PORT; i++) {
36203831d35Sstevel 		for (j = 0; j < DIMMS_PER_PMBANK; j++) {
36303831d35Sstevel 			if (dimm < MAX_DIMMS_PER_PORT) {
36403831d35Sstevel 				pcd->sprd_dimm[dimm] = rsv_string(
36503831d35Sstevel 				    gdcd->dcd_prd[expander][prd_slot].
36603831d35Sstevel 				    prd_dimm[i][j]);
36703831d35Sstevel 				dimm++;
36803831d35Sstevel 			}
36903831d35Sstevel 		}
37003831d35Sstevel 	}
37103831d35Sstevel 
37203831d35Sstevel 	/*
37303831d35Sstevel 	 * Get data for the "ecache-dimm-label" property.
37403831d35Sstevel 	 *
37503831d35Sstevel 	 * Right now it is hardcoded, but we should eventually get this
37603831d35Sstevel 	 * from the SC.
37703831d35Sstevel 	 */
37803831d35Sstevel 	label1 = NULL;
37903831d35Sstevel 	label2 = NULL;
38003831d35Sstevel 
38103831d35Sstevel 	switch (prd_slot) {
38203831d35Sstevel 	case 0:
38303831d35Sstevel 		label1 = "4400";
38403831d35Sstevel 		label2 = "4300";
38503831d35Sstevel 		break;
38603831d35Sstevel 	case 1:
38703831d35Sstevel 		label1 = "5400";
38803831d35Sstevel 		label2 = "5300";
38903831d35Sstevel 		break;
39003831d35Sstevel 	case 2:
39103831d35Sstevel 		label1 = "6400";
39203831d35Sstevel 		label2 = "6300";
39303831d35Sstevel 		break;
39403831d35Sstevel 	case 3:
39503831d35Sstevel 		label1 = "7400";
39603831d35Sstevel 		label2 = "7300";
39703831d35Sstevel 		break;
39803831d35Sstevel 
39903831d35Sstevel 	/*
40003831d35Sstevel 	 * Maxcat labels.
40103831d35Sstevel 	 */
40203831d35Sstevel 	case 4:
40303831d35Sstevel 		label1 = "6400";
40403831d35Sstevel 		label2 = "6300";
40503831d35Sstevel 		break;
40603831d35Sstevel 	case 5:
40703831d35Sstevel 		label1 = "7400";
40803831d35Sstevel 		label2 = "7300";
40903831d35Sstevel 		break;
41003831d35Sstevel 	}
41103831d35Sstevel 
41203831d35Sstevel 	i = 0;
41303831d35Sstevel 	if (label1) {
41403831d35Sstevel 		pcd->sprd_ecache_dimm_label[i] =
41503831d35Sstevel 		    kmem_alloc(strlen(label1) + 1, KM_SLEEP);
41603831d35Sstevel 
41703831d35Sstevel 		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label1);
41803831d35Sstevel 
41903831d35Sstevel 		i++;
42003831d35Sstevel 	}
42103831d35Sstevel 	if (label2) {
42203831d35Sstevel 		pcd->sprd_ecache_dimm_label[i] =
42303831d35Sstevel 		    kmem_alloc(strlen(label2) + 1, KM_SLEEP);
42403831d35Sstevel 
42503831d35Sstevel 		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label2);
42603831d35Sstevel 
42703831d35Sstevel 		i++;
42803831d35Sstevel 
42903831d35Sstevel 	}
43003831d35Sstevel 
43103831d35Sstevel 	kmem_free(gdcd, sizeof (gdcd_t));
43203831d35Sstevel 
43303831d35Sstevel #ifdef DEBUG
43403831d35Sstevel 	dump_pcd(pcd);
43503831d35Sstevel #endif
43603831d35Sstevel 
43703831d35Sstevel 	return (pcd);
43803831d35Sstevel }
43903831d35Sstevel 
44003831d35Sstevel void
44103831d35Sstevel sc_free_common_pcd(spcd_t *pcd)
44203831d35Sstevel {
44303831d35Sstevel 	int i;
44403831d35Sstevel 
445*07d06da5SSurya Prakki 	SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd pcd=%p\n", (void *)pcd));
44603831d35Sstevel 
44703831d35Sstevel 	if (pcd->memory_layout && pcd->memory_layout_size) {
44803831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd: memory_layout %p "
449*07d06da5SSurya Prakki 		    "size=%x", (void *)pcd->memory_layout,
450*07d06da5SSurya Prakki 		    pcd->memory_layout_size));
45103831d35Sstevel 		kmem_free(pcd->memory_layout, pcd->memory_layout_size);
45203831d35Sstevel 	}
45303831d35Sstevel 
45403831d35Sstevel 	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
45503831d35Sstevel 		if (pcd->sprd_bank_rsv[i]) {
45603831d35Sstevel 			kmem_free(pcd->sprd_bank_rsv[i],
45703831d35Sstevel 			    strlen(pcd->sprd_bank_rsv[i]) + 1);
45803831d35Sstevel 
45903831d35Sstevel 			pcd->sprd_bank_rsv[i] = NULL;
46003831d35Sstevel 		}
46103831d35Sstevel 	}
46203831d35Sstevel 
46303831d35Sstevel 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
46403831d35Sstevel 		if (pcd->sprd_dimm[i]) {
46503831d35Sstevel 			kmem_free(pcd->sprd_dimm[i],
46603831d35Sstevel 			    strlen(pcd->sprd_dimm[i]) + 1);
46703831d35Sstevel 
46803831d35Sstevel 			pcd->sprd_dimm[i] = NULL;
46903831d35Sstevel 		}
47003831d35Sstevel 		if (pcd->sprd_ecache_dimm_label[i]) {
47103831d35Sstevel 			kmem_free(pcd->sprd_ecache_dimm_label[i],
47203831d35Sstevel 			    strlen(pcd->sprd_ecache_dimm_label[i]) + 1);
47303831d35Sstevel 
47403831d35Sstevel 			pcd->sprd_ecache_dimm_label[i] = NULL;
47503831d35Sstevel 		}
47603831d35Sstevel 	}
47703831d35Sstevel 
47803831d35Sstevel 	kmem_free(pcd, sizeof (spcd_t));
47903831d35Sstevel }
48003831d35Sstevel 
48103831d35Sstevel sc_gptwocfg_cookie_t
48203831d35Sstevel sc_probe_board(uint_t board)
48303831d35Sstevel {
48403831d35Sstevel 	return (sc_configure(board, 1));
48503831d35Sstevel }
48603831d35Sstevel 
48703831d35Sstevel static sc_gptwocfg_cookie_t
48803831d35Sstevel sc_configure(uint_t board, int create_nodes)
48903831d35Sstevel {
49003831d35Sstevel 	spcd_t *pcd;
49103831d35Sstevel 	dev_info_t *ap, *axq_dip;
49203831d35Sstevel 	uint_t agent_id;
49303831d35Sstevel 	uint_t prd_slot, prd_slot_start, prd_slot_end;
49403831d35Sstevel 	uint_t expander, slot;
49503831d35Sstevel 	gptwo_new_nodes_t *new_nodes;
49603831d35Sstevel 	gptwocfg_config_t *port_cookie;
49703831d35Sstevel 	struct sc_gptwocfg_config *board_config, *last, *new;
49803831d35Sstevel 	int created_node = 0;
49903831d35Sstevel 	uint32_t size;
50003831d35Sstevel 
50103831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: board=%d, create_nodes=%d\n",
50203831d35Sstevel 	    board, create_nodes));
50303831d35Sstevel 
50403831d35Sstevel 	if (board > 35) {
50503831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg - probe_board - "
50603831d35Sstevel 		    "invalid board 0x%x\n", board));
50703831d35Sstevel 		return (NULL);
50803831d35Sstevel 	}
50903831d35Sstevel 
51003831d35Sstevel 	slot = board & 1;	/* Extract Slot Number */
51103831d35Sstevel 	expander = board >> 1;	/* Extract Expander Number */
51203831d35Sstevel 
51303831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: exp=0x%x slot=0x%x\n",
51403831d35Sstevel 	    expander, slot));
51503831d35Sstevel 
51603831d35Sstevel 	/*
51703831d35Sstevel 	 * Get the Attachment Point.  For Starcat the parent of all
51803831d35Sstevel 	 * Safari children is root node.
51903831d35Sstevel 	 */
52003831d35Sstevel 	ap = ddi_root_node();
52103831d35Sstevel 
52203831d35Sstevel 	/*
52303831d35Sstevel 	 * Get the agent id of the AXQ.
52403831d35Sstevel 	 */
52503831d35Sstevel 	agent_id = (expander << 5) | 0x1e | slot;
52603831d35Sstevel 
52703831d35Sstevel 	/*
52803831d35Sstevel 	 * Look to see if the board is already configured by searching for
52903831d35Sstevel 	 * its AXQ.
53003831d35Sstevel 	 */
53103831d35Sstevel 	if (create_nodes && (axq_dip = sc_find_axq_node(agent_id))) {
53203831d35Sstevel 		ddi_release_devi(axq_dip);
53303831d35Sstevel 		cmn_err(CE_WARN, "Board %d AXQ is already configured\n",
53403831d35Sstevel 		    board);
53503831d35Sstevel 		return (NULL);
53603831d35Sstevel 	}
53703831d35Sstevel 
53803831d35Sstevel 	/*
53903831d35Sstevel 	 * Probe AXQ first
54003831d35Sstevel 	 */
54103831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: Probing AXQ exp=0x%x brd=0x%x\n",
54203831d35Sstevel 	    expander, slot));
54303831d35Sstevel 
54403831d35Sstevel 	/*
54503831d35Sstevel 	 * The generic gptwocfg does not support the AXQ, so we need
54603831d35Sstevel 	 * to configure it. The AXQ branch is returned held.
54703831d35Sstevel 	 */
54803831d35Sstevel 	new_nodes = sc_gptwocfg_configure_axq(ap, agent_id, create_nodes);
54903831d35Sstevel 
55003831d35Sstevel 	if (new_nodes == NULL) {
55103831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_configure: Can not probe AXQ\n"));
55203831d35Sstevel 		return (NULL);
55303831d35Sstevel 	}
55403831d35Sstevel 
55503831d35Sstevel 	port_cookie = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP);
55603831d35Sstevel 
55703831d35Sstevel 	/*
55803831d35Sstevel 	 * Build a cookie for the AXQ.
55903831d35Sstevel 	 */
56003831d35Sstevel 	port_cookie->gptwo_ap = ap;
56103831d35Sstevel 	port_cookie->gptwo_portid = agent_id;
56203831d35Sstevel 	port_cookie->gptwo_nodes = new_nodes;
56303831d35Sstevel 
56403831d35Sstevel 	board_config = kmem_zalloc(sizeof (sc_gptwocfg_config_t), KM_SLEEP);
56503831d35Sstevel 
56603831d35Sstevel 	board_config->port_cookie = port_cookie;
56703831d35Sstevel 	board_config->board = board;
56803831d35Sstevel 	board_config->portid = agent_id;
56903831d35Sstevel 	board_config->link = NULL;
57003831d35Sstevel 	last = board_config;
57103831d35Sstevel 
57203831d35Sstevel 	mutex_enter(&sc_gptwo_config_list_lock);
57303831d35Sstevel 	board_config->next = sc_gptwo_config_list;
57403831d35Sstevel 	sc_gptwo_config_list = board_config;
57503831d35Sstevel 	mutex_exit(&sc_gptwo_config_list_lock);
57603831d35Sstevel 
57703831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: AXQ Probing Complete. "
57803831d35Sstevel 	    "%d nodes added\n", new_nodes->gptwo_number_of_nodes));
57903831d35Sstevel 
58003831d35Sstevel 	/*
58103831d35Sstevel 	 * Determine the starting ending slots of the PRD array.
58203831d35Sstevel 	 */
58303831d35Sstevel 	switch (slot) {
58403831d35Sstevel 	case 0:		/* Full Bandwidth Slot */
58503831d35Sstevel 		prd_slot_start = 0;
58603831d35Sstevel 		prd_slot_end = 3;
58703831d35Sstevel 		break;
58803831d35Sstevel 	case 1:		/* Half Bandwidth Slot */
58903831d35Sstevel 		prd_slot_start = 4;
59003831d35Sstevel 		prd_slot_end = 5;
59103831d35Sstevel 		break;
59203831d35Sstevel 	default:
59303831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "Unknown Board Address - "
59403831d35Sstevel 		    "Can not probe\n"));
59503831d35Sstevel 		return (board_config);
59603831d35Sstevel 	}
59703831d35Sstevel 
59803831d35Sstevel 	/*
59903831d35Sstevel 	 * For each valid PRD entry, determine the agent id which is based
60003831d35Sstevel 	 * on what type of device is described by the slot, and then
60103831d35Sstevel 	 * call the safari configurator.
60203831d35Sstevel 	 */
60303831d35Sstevel 	for (prd_slot = prd_slot_start; prd_slot <= prd_slot_end; prd_slot++) {
60403831d35Sstevel 
60503831d35Sstevel 		pcd = sc_get_common_pcd(expander, prd_slot);
60603831d35Sstevel 
60703831d35Sstevel 		if (pcd == NULL) {
60803831d35Sstevel 
60903831d35Sstevel 			/*
61003831d35Sstevel 			 * We can not get a PCD for this port so skip it.
61103831d35Sstevel 			 */
61203831d35Sstevel 			cmn_err(CE_WARN, "sc_gptwocfg: Can not get PCD "
61303831d35Sstevel 			    "expander 0x%x prd slot 0x%x\n",
61403831d35Sstevel 			    expander, prd_slot);
61503831d35Sstevel 
61603831d35Sstevel 			return (board_config);
61703831d35Sstevel 		}
61803831d35Sstevel 
61903831d35Sstevel 		/*
62003831d35Sstevel 		 * Only configure good devices.
62103831d35Sstevel 		 */
62203831d35Sstevel 		if (pcd->spcd_prsv == SPCD_RSV_PASS) {
62303831d35Sstevel 			/*
62403831d35Sstevel 			 * Determine the agent id.
62503831d35Sstevel 			 */
62603831d35Sstevel 			agent_id = sc_get_agent_id(
62703831d35Sstevel 			    pcd, expander, slot, prd_slot);
62803831d35Sstevel 
62903831d35Sstevel 			pcd->memory_layout = get_memlayout(agent_id, &size);
63003831d35Sstevel 			pcd->memory_layout_size = size;
63103831d35Sstevel 
63203831d35Sstevel 			/*
63303831d35Sstevel 			 * Call Platform Independent gptwo configurator to
63403831d35Sstevel 			 * create node and properties.
63503831d35Sstevel 			 */
63603831d35Sstevel 			if (create_nodes) {
63703831d35Sstevel 				port_cookie =
63803831d35Sstevel 				    gptwocfg_configure(ap, pcd, agent_id);
63903831d35Sstevel 				if (port_cookie)
64003831d35Sstevel 					created_node++;
64103831d35Sstevel 			}
64203831d35Sstevel 
64303831d35Sstevel 			new = kmem_zalloc
64403831d35Sstevel 			    (sizeof (sc_gptwocfg_config_t), KM_SLEEP);
64503831d35Sstevel 
64603831d35Sstevel 			/*
64703831d35Sstevel 			 * XXX Shouldn't port_cookie be NULL if
64803831d35Sstevel 			 * !create_nodes ?
64903831d35Sstevel 			 */
65003831d35Sstevel 			new->port_cookie = port_cookie;
65103831d35Sstevel 			new->portid = agent_id;
65203831d35Sstevel 			new->link = NULL;
65303831d35Sstevel 			last->link = new;
65403831d35Sstevel 			last = new;
65503831d35Sstevel 		} else {
65603831d35Sstevel 			SC_DEBUG(1, (CE_WARN, "sc_configure: Bad Agent "
65703831d35Sstevel 			    "Exp=0x%x PRD Slot=0x%x  prsv Status=0x%x\n",
65803831d35Sstevel 			    expander, prd_slot, pcd->spcd_prsv));
65903831d35Sstevel 		}
66003831d35Sstevel 
66103831d35Sstevel 		sc_free_common_pcd(pcd);
66203831d35Sstevel 
66303831d35Sstevel 	} /* for loop */
66403831d35Sstevel 
66503831d35Sstevel 	dump_config(board_config);
66603831d35Sstevel 
66703831d35Sstevel 	if (create_nodes && !created_node) {
66803831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_configure: GPTWO Devices failed "
66903831d35Sstevel 		    "to configure - unprobing board %d\n", board));
67003831d35Sstevel 		board_config = sc_unprobe_board(board);
67103831d35Sstevel 	}
67203831d35Sstevel 
67303831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_configure: Returning 0x%p\n",
674*07d06da5SSurya Prakki 	    (void *)board_config));
67503831d35Sstevel 
67603831d35Sstevel 	return (board_config);
67703831d35Sstevel }
67803831d35Sstevel 
67903831d35Sstevel sc_gptwocfg_cookie_t
68003831d35Sstevel sc_unprobe_board(uint_t board)
68103831d35Sstevel {
68203831d35Sstevel 	sc_gptwocfg_config_t *board_config, *axq_config, *prior_config;
68303831d35Sstevel 	gptwocfg_cookie_t port_cookie;
68403831d35Sstevel 
68503831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: board=%d\n", board));
68603831d35Sstevel 
68703831d35Sstevel 	if (board > 35) {
68803831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
68903831d35Sstevel 		    "invalid board 0x%x\n", board));
69003831d35Sstevel 		return (NULL);
69103831d35Sstevel 	}
69203831d35Sstevel 	mutex_enter(&sc_gptwo_config_list_lock);
69303831d35Sstevel 	board_config = sc_gptwo_config_list;
69403831d35Sstevel 	while (board_config != NULL) {
69503831d35Sstevel 		if (board_config->board == board) {
69603831d35Sstevel 			break;
69703831d35Sstevel 		}
69803831d35Sstevel 		board_config = board_config->next;
69903831d35Sstevel 	}
70003831d35Sstevel 	mutex_exit(&sc_gptwo_config_list_lock);
70103831d35Sstevel 
70203831d35Sstevel 	if (board_config == NULL) {
70303831d35Sstevel 
70403831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: No "
70503831d35Sstevel 		    "config structure board=0x%x\n", board));
70603831d35Sstevel 
70703831d35Sstevel 		/*
70803831d35Sstevel 		 * Configure the board without creating nodes.
70903831d35Sstevel 		 */
71003831d35Sstevel 		board_config = sc_configure(board, 0);
71103831d35Sstevel 
71203831d35Sstevel 		if (board_config == NULL) {
71303831d35Sstevel 
71403831d35Sstevel 			cmn_err(CE_WARN, "sc_gptwocfg: sc_unprobe_board: "
71503831d35Sstevel 			    "Unable to unconfigure board %d - board is not "
71603831d35Sstevel 			    "configured\n", board);
71703831d35Sstevel 
71803831d35Sstevel 			return (NULL);
71903831d35Sstevel 		}
72003831d35Sstevel 	}
72103831d35Sstevel 
72203831d35Sstevel 	axq_config = board_config;
72303831d35Sstevel 
72403831d35Sstevel 	/*
72503831d35Sstevel 	 * Walk the link of ports on this board and unconfigure them.
72603831d35Sstevel 	 * Save the AXQ for last.
72703831d35Sstevel 	 */
72803831d35Sstevel 	while (board_config->link != NULL) {
72903831d35Sstevel 		prior_config = board_config;
73003831d35Sstevel 		board_config = board_config->link;
73103831d35Sstevel 
73203831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
73303831d35Sstevel 		    "calling gptwocfg_unconfigure(ap=0x%p portid=0x%x)\n",
734*07d06da5SSurya Prakki 		    (void *)ddi_root_node(), board_config->portid));
73503831d35Sstevel 
73603831d35Sstevel 		port_cookie = gptwocfg_unconfigure(ddi_root_node(),
73703831d35Sstevel 		    board_config->portid);
73803831d35Sstevel 
73903831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
74003831d35Sstevel 		    "gptwocfg_unconfigure returned cookie=0x%p\n",
74103831d35Sstevel 		    port_cookie));
74203831d35Sstevel 
74303831d35Sstevel 		if (port_cookie == NULL) {
74403831d35Sstevel 			/*
74503831d35Sstevel 			 * Can be removed from list.
74603831d35Sstevel 			 */
74703831d35Sstevel 			prior_config->link = board_config->link;
74803831d35Sstevel 			kmem_free(board_config, sizeof (sc_gptwocfg_config_t));
74903831d35Sstevel 			board_config = prior_config;
75003831d35Sstevel 		} else {
75103831d35Sstevel 			board_config->port_cookie = port_cookie;
75203831d35Sstevel 		}
75303831d35Sstevel 	}
75403831d35Sstevel 
75503831d35Sstevel 	if (axq_config->link == NULL) {
75603831d35Sstevel 
75703831d35Sstevel 		/*
75803831d35Sstevel 		 * If all the other Safari devices have been successfully
75903831d35Sstevel 		 * unconfigured, then the AXQ can be unconfigured.
76003831d35Sstevel 		 */
76103831d35Sstevel 		axq_config->port_cookie =
76203831d35Sstevel 		    sc_gptwocfg_unconfigure_axq(axq_config->port_cookie);
76303831d35Sstevel 
76403831d35Sstevel 		if (axq_config->port_cookie == NULL) {
76503831d35Sstevel 
76603831d35Sstevel 			/*
76703831d35Sstevel 			 * If the AXQ was successfully unconfigured, then
76803831d35Sstevel 			 * the board is removed from the configured list.
76903831d35Sstevel 			 */
77003831d35Sstevel 			mutex_enter(&sc_gptwo_config_list_lock);
77103831d35Sstevel 			if (sc_gptwo_config_list == axq_config) {
77203831d35Sstevel 				sc_gptwo_config_list = axq_config->next;
77303831d35Sstevel 			} else {
77403831d35Sstevel 				board_config = sc_gptwo_config_list;
77503831d35Sstevel 				while (board_config->next != axq_config) {
77603831d35Sstevel 					board_config = board_config->next;
77703831d35Sstevel 				}
77803831d35Sstevel 				board_config->next = axq_config->next;
77903831d35Sstevel 			}
78003831d35Sstevel 			mutex_exit(&sc_gptwo_config_list_lock);
78103831d35Sstevel 			kmem_free(axq_config, sizeof (sc_gptwocfg_config_t));
78203831d35Sstevel 			axq_config = NULL;
78303831d35Sstevel 		}
78403831d35Sstevel 	}
78503831d35Sstevel 	dump_config(axq_config);
78603831d35Sstevel 	return (axq_config);
78703831d35Sstevel }
78803831d35Sstevel 
78903831d35Sstevel int
79003831d35Sstevel sc_next_node(sc_gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next)
79103831d35Sstevel {
79203831d35Sstevel 	dev_info_t *dip;
79303831d35Sstevel 	sc_gptwocfg_config_t *cookie;
79403831d35Sstevel 
79503831d35Sstevel 	SC_DEBUG(1, (CE_WARN, "sccfg: sccfg_next_node"
796*07d06da5SSurya Prakki 	    "(c=0x%p, previous=0x%p, next=0x%p)\n", (void *)c,
797*07d06da5SSurya Prakki 	    (void *)previous, (void *)next));
79803831d35Sstevel 
79903831d35Sstevel 	cookie = (sc_gptwocfg_config_t *)c;
80003831d35Sstevel 
80103831d35Sstevel 	if (cookie == NULL) {
80203831d35Sstevel 		cmn_err(CE_WARN, "sccfg: sccfg_next_node - "
80303831d35Sstevel 		    "Invalid Cookie\n");
80403831d35Sstevel 		return (0);
80503831d35Sstevel 	}
80603831d35Sstevel 	if (previous == NULL) {
80703831d35Sstevel 		/*
80803831d35Sstevel 		 * Start with the AXQ node.
80903831d35Sstevel 		 */
81003831d35Sstevel 		if (gptwocfg_next_node(cookie->port_cookie, NULL, &dip)) {
81103831d35Sstevel 			*next = dip;
81203831d35Sstevel 			return (1);
81303831d35Sstevel 		} else {
81403831d35Sstevel 			return (0);
81503831d35Sstevel 		}
81603831d35Sstevel 	}
81703831d35Sstevel 
81803831d35Sstevel 	while (cookie != NULL) {
81903831d35Sstevel 		if (gptwocfg_next_node(cookie->port_cookie, previous, &dip)) {
82003831d35Sstevel 			if ((dip == NULL) && (cookie->link == NULL)) {
82103831d35Sstevel 				*next = NULL;
82203831d35Sstevel 				return (1);
82303831d35Sstevel 			}
82403831d35Sstevel 			if (dip != NULL) {
82503831d35Sstevel 				*next = dip;
82603831d35Sstevel 				return (1);
82703831d35Sstevel 			}
82803831d35Sstevel 
82903831d35Sstevel 			/* dip == NULL */
83003831d35Sstevel 
83103831d35Sstevel 			previous = NULL;
83203831d35Sstevel 		}
83303831d35Sstevel 		cookie = cookie->link;
83403831d35Sstevel 	}
83503831d35Sstevel 
83603831d35Sstevel 	return (0);
83703831d35Sstevel }
83803831d35Sstevel 
83903831d35Sstevel static dev_info_t *
84003831d35Sstevel sc_find_axq_node(uint_t axq_id)
84103831d35Sstevel {
84203831d35Sstevel 	char *name;
84303831d35Sstevel 	int size;
84403831d35Sstevel 	gptwo_regspec_t *reg;
84503831d35Sstevel 	dev_info_t *dip;
84603831d35Sstevel 	uint_t id;
84703831d35Sstevel 	int circ;
84803831d35Sstevel 
84903831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: id=0x%x\n", axq_id));
85003831d35Sstevel 
85103831d35Sstevel 	/*
85203831d35Sstevel 	 * Hold root node busy to walk its child list
85303831d35Sstevel 	 */
85403831d35Sstevel 	ndi_devi_enter(ddi_root_node(), &circ);
85503831d35Sstevel 
85603831d35Sstevel 	dip = ddi_get_child(ddi_root_node());
85703831d35Sstevel 
85803831d35Sstevel 	while (dip != NULL) {
85903831d35Sstevel 
86003831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "Searching dip=0x%p for our AXQ\n",
861*07d06da5SSurya Prakki 		    (void *)dip));
86203831d35Sstevel 
86303831d35Sstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
86403831d35Sstevel 		    DDI_PROP_DONTPASS, "name", (caddr_t)&name, &size)
86503831d35Sstevel 		    != DDI_PROP_SUCCESS) {
86603831d35Sstevel 
86703831d35Sstevel 			/*
86803831d35Sstevel 			 * This node does not have a name property.
86903831d35Sstevel 			 */
87003831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p does not have a "
871*07d06da5SSurya Prakki 			    "'name' property\n", (void *)dip));
87203831d35Sstevel 
87303831d35Sstevel 			dip = ddi_get_next_sibling(dip);
87403831d35Sstevel 			continue;
87503831d35Sstevel 		}
87603831d35Sstevel 
877*07d06da5SSurya Prakki 		SC_DEBUG(1, (CE_CONT, "dip=0x%p name=%s\n", (void *)dip, name));
87803831d35Sstevel 
87903831d35Sstevel 		if (strcmp(name, "address-extender-queue")) {
88003831d35Sstevel 
88103831d35Sstevel 			/*
88203831d35Sstevel 			 * This node is not a AXQ node.
88303831d35Sstevel 			 */
88403831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p is not an AXQ "
885*07d06da5SSurya Prakki 			    "node\n", (void *)dip));
88603831d35Sstevel 			kmem_free(name, size);
88703831d35Sstevel 			dip = ddi_get_next_sibling(dip);
88803831d35Sstevel 			continue;
88903831d35Sstevel 		}
89003831d35Sstevel 		kmem_free(name, size);
89103831d35Sstevel 
89203831d35Sstevel 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
89303831d35Sstevel 		    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &size)
89403831d35Sstevel 		    != DDI_PROP_SUCCESS) {
89503831d35Sstevel 
89603831d35Sstevel 			/*
89703831d35Sstevel 			 * This AXQ node does not have a reg property.
89803831d35Sstevel 			 */
89903831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p (AXQ Node) does "
900*07d06da5SSurya Prakki 			    "have a 'reg' property\n", (void *)dip));
90103831d35Sstevel 			dip = ddi_get_next_sibling(dip);
90203831d35Sstevel 			continue;
90303831d35Sstevel 		}
90403831d35Sstevel 
90503831d35Sstevel 		id = ((reg[0].gptwo_phys_hi & 1) << 9) |
90603831d35Sstevel 		    ((reg[0].gptwo_phys_low & 0xff800000) >> 23);
90703831d35Sstevel 
90803831d35Sstevel 		kmem_free(reg, size);
90903831d35Sstevel 
91003831d35Sstevel 		if (axq_id != id) {
91103831d35Sstevel 
91203831d35Sstevel 			/*
91303831d35Sstevel 			 * This is the wrong AXQ node.
91403831d35Sstevel 			 */
91503831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "dip=0x%p Wrong node id=0x%x\n",
916*07d06da5SSurya Prakki 			    (void *)dip, id));
91703831d35Sstevel 
91803831d35Sstevel 			dip = ddi_get_next_sibling(dip);
91903831d35Sstevel 			continue;
92003831d35Sstevel 
92103831d35Sstevel 		}
92203831d35Sstevel 
92303831d35Sstevel 		/*
92403831d35Sstevel 		 * The correct AXQ node was found.
92503831d35Sstevel 		 */
926*07d06da5SSurya Prakki 		SC_DEBUG(1, (CE_CONT, "dip=0x%p Found AXQ Node\n",
927*07d06da5SSurya Prakki 		    (void *)dip));
92803831d35Sstevel 		ndi_hold_devi(dip);
92903831d35Sstevel 		break;
93003831d35Sstevel 	}
93103831d35Sstevel 	ndi_devi_exit(ddi_root_node(), circ);
93203831d35Sstevel 
933*07d06da5SSurya Prakki 	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: Returning 0x%p\n",
934*07d06da5SSurya Prakki 	    (void *)dip));
93503831d35Sstevel 
93603831d35Sstevel 	return (dip);
93703831d35Sstevel }
93803831d35Sstevel 
93903831d35Sstevel struct axq_arg {
94003831d35Sstevel 	uint_t id;
94103831d35Sstevel 	dev_info_t *axq_dip;
94203831d35Sstevel };
94303831d35Sstevel 
94403831d35Sstevel /*ARGSUSED*/
94503831d35Sstevel static int
94603831d35Sstevel axq_set_prop(dev_info_t *axq_dip, void *arg, uint_t flags)
94703831d35Sstevel {
94803831d35Sstevel 	struct axq_arg *aqp = (struct axq_arg *)arg;
94903831d35Sstevel 	gptwo_regspec_t	reg[2];
95003831d35Sstevel 	uint_t		id;
95103831d35Sstevel 
95203831d35Sstevel 	ASSERT(aqp);
95303831d35Sstevel 
95403831d35Sstevel 	id = aqp->id;
95503831d35Sstevel 
95603831d35Sstevel 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
95703831d35Sstevel 	    "name", "address-extender-queue") != DDI_SUCCESS) {
95803831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
95903831d35Sstevel 		    "to create name property\n"));
96003831d35Sstevel 		return (DDI_WALK_ERROR);
96103831d35Sstevel 	}
96203831d35Sstevel 
96303831d35Sstevel 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
96403831d35Sstevel 	    "device_type", "address-extender-queue") != DDI_SUCCESS) {
96503831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
96603831d35Sstevel 		    "to create device_type property\n"));
96703831d35Sstevel 		return (DDI_WALK_ERROR);
96803831d35Sstevel 	}
96903831d35Sstevel 
97003831d35Sstevel 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
97103831d35Sstevel 	    "compatible", "SUNW,axq") != DDI_SUCCESS) {
97203831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "sc_gptwocfg: failed "
97303831d35Sstevel 		    "to create compatible property\n"));
97403831d35Sstevel 		return (DDI_WALK_ERROR);
97503831d35Sstevel 	}
97603831d35Sstevel 
97703831d35Sstevel 	if (ndi_prop_update_int(DDI_DEV_T_NONE, axq_dip,
97803831d35Sstevel 	    "portid", id) != DDI_SUCCESS) {
97903831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
98003831d35Sstevel 		    "to create portid property\n"));
98103831d35Sstevel 		return (DDI_WALK_ERROR);
98203831d35Sstevel 	}
98303831d35Sstevel 
98403831d35Sstevel 	reg[0].gptwo_phys_hi = 0x400 | (id >> 9);
98503831d35Sstevel 	reg[0].gptwo_phys_low = (id << 23);
98603831d35Sstevel 	reg[0].gptwo_size_hi = 0;
98703831d35Sstevel 	reg[0].gptwo_size_low = 0x520;
98803831d35Sstevel 
98903831d35Sstevel 	reg[1].gptwo_phys_hi = 0x401;
99003831d35Sstevel 	reg[1].gptwo_phys_low = 0xf0000000;
99103831d35Sstevel 	reg[1].gptwo_size_hi = 0;
99203831d35Sstevel 	reg[1].gptwo_size_low = 0x520;
99303831d35Sstevel 
99403831d35Sstevel 	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
99503831d35Sstevel 	    axq_dip, "reg", (int *)&reg,
99603831d35Sstevel 	    (sizeof (gptwo_regspec_t) * 2)/sizeof (int)) != DDI_SUCCESS) {
99703831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
99803831d35Sstevel 		    "to create reg property\n"));
99903831d35Sstevel 		return (DDI_WALK_ERROR);
100003831d35Sstevel 	}
100103831d35Sstevel 
100203831d35Sstevel 	return (DDI_WALK_TERMINATE);
100303831d35Sstevel }
100403831d35Sstevel 
100503831d35Sstevel /*ARGSUSED*/
100603831d35Sstevel static void
100703831d35Sstevel get_axq_dip(dev_info_t *rdip, void *arg, uint_t flags)
100803831d35Sstevel {
100903831d35Sstevel 	struct axq_arg *aqp = (struct axq_arg *)arg;
101003831d35Sstevel 
101103831d35Sstevel 	ASSERT(aqp);
101203831d35Sstevel 
101303831d35Sstevel 	aqp->axq_dip = rdip;
101403831d35Sstevel }
101503831d35Sstevel 
101603831d35Sstevel static gptwo_new_nodes_t *
101703831d35Sstevel sc_gptwocfg_configure_axq(dev_info_t *ap, uint_t id, int create_nodes)
101803831d35Sstevel {
101903831d35Sstevel 	struct axq_arg arg = {0};
102003831d35Sstevel 	devi_branch_t b = {0};
102103831d35Sstevel 	dev_info_t *axq_dip, *fdip = NULL;
102203831d35Sstevel 	gptwo_new_nodes_t *new_nodes = NULL;
102303831d35Sstevel 	int rv;
102403831d35Sstevel 
102503831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: id=0x%x "
102603831d35Sstevel 	    "create_nodes=%d\n", id, create_nodes));
102703831d35Sstevel 
102803831d35Sstevel 	if (!create_nodes) {
102903831d35Sstevel 		axq_dip = sc_find_axq_node(id);
103003831d35Sstevel 
103103831d35Sstevel 		if (axq_dip) {
103203831d35Sstevel 			new_nodes = gptwocfg_allocate_node_list(1);
103303831d35Sstevel 			new_nodes->gptwo_nodes[0] = axq_dip;
103403831d35Sstevel 			ASSERT(!e_ddi_branch_held(axq_dip));
103503831d35Sstevel 			e_ddi_branch_hold(axq_dip);
103603831d35Sstevel 			/*
103703831d35Sstevel 			 * Release hold from sc_find_axq_node()
103803831d35Sstevel 			 */
103903831d35Sstevel 			ddi_release_devi(axq_dip);
104003831d35Sstevel 		}
104103831d35Sstevel 
104203831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: "
1043*07d06da5SSurya Prakki 		    "Returning 0x%p\n", (void *)new_nodes));
104403831d35Sstevel 
104503831d35Sstevel 		return (new_nodes);
104603831d35Sstevel 	}
104703831d35Sstevel 
104803831d35Sstevel 	arg.id = id;
104903831d35Sstevel 	arg.axq_dip = NULL;
105003831d35Sstevel 
105103831d35Sstevel 	b.arg = &arg;
105203831d35Sstevel 	b.type = DEVI_BRANCH_SID;
105303831d35Sstevel 	b.create.sid_branch_create = axq_set_prop;
105403831d35Sstevel 	b.devi_branch_callback = get_axq_dip;
105503831d35Sstevel 
105603831d35Sstevel 	rv = e_ddi_branch_create(ap, &b, &fdip, DEVI_BRANCH_CONFIGURE);
105703831d35Sstevel 	if (rv != 0) {
105803831d35Sstevel 		char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
105903831d35Sstevel 
106003831d35Sstevel 		/*
106103831d35Sstevel 		 * If non-NULL, fdip is held and must be released.
106203831d35Sstevel 		 */
106303831d35Sstevel 		if (fdip != NULL) {
106403831d35Sstevel 			(void) ddi_pathname(fdip, path);
106503831d35Sstevel 			ddi_release_devi(fdip);
106603831d35Sstevel 		} else {
106703831d35Sstevel 			(void) ddi_pathname(ap, path);
106803831d35Sstevel 		}
106903831d35Sstevel 
107003831d35Sstevel 		SC_DEBUG(1, (CE_WARN, "e_ddi_branch_create failed: "
107103831d35Sstevel 		    "path=%s, dip=%p, rv=%d", path, fdip ? (void *)fdip :
107203831d35Sstevel 		    (void *)ap, rv));
107303831d35Sstevel 
107403831d35Sstevel 		kmem_free(path, MAXPATHLEN);
107503831d35Sstevel 
107603831d35Sstevel 		return (NULL);
107703831d35Sstevel 	}
107803831d35Sstevel 
107903831d35Sstevel 	axq_dip = arg.axq_dip;
108003831d35Sstevel 
108103831d35Sstevel 	new_nodes = gptwocfg_allocate_node_list(1);
108203831d35Sstevel 	new_nodes->gptwo_nodes[0] = axq_dip;
108303831d35Sstevel 
108403831d35Sstevel 	return (new_nodes);
108503831d35Sstevel }
108603831d35Sstevel 
108703831d35Sstevel static gptwocfg_config_t *
108803831d35Sstevel sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *config)
108903831d35Sstevel {
109003831d35Sstevel 	int i;
109103831d35Sstevel 	int failure = 0;
109203831d35Sstevel 	dev_info_t *saf_dip;
109303831d35Sstevel 
109403831d35Sstevel 	if (config == NULL) {
109503831d35Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: sc_gptwocfg_unconfigure_axq: "
109603831d35Sstevel 		    "Invalid AXQ\n");
109703831d35Sstevel 		return (NULL);
109803831d35Sstevel 	}
109903831d35Sstevel 	for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) {
110003831d35Sstevel 		int rv;
110103831d35Sstevel 		dev_info_t *fdip = NULL;
110203831d35Sstevel 
110303831d35Sstevel 		saf_dip = config->gptwo_nodes->gptwo_nodes[i];
110403831d35Sstevel 		ASSERT(e_ddi_branch_held(saf_dip));
110503831d35Sstevel 		rv = e_ddi_branch_destroy(saf_dip, &fdip, 0);
110603831d35Sstevel 		if (rv != 0) {
110703831d35Sstevel 			char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
110803831d35Sstevel 
110903831d35Sstevel 			/*
111003831d35Sstevel 			 * If non-NULL, fdip is held and must be released.
111103831d35Sstevel 			 */
111203831d35Sstevel 			if (fdip != NULL) {
111303831d35Sstevel 				(void) ddi_pathname(fdip, path);
111403831d35Sstevel 				ddi_release_devi(fdip);
111503831d35Sstevel 			} else {
111603831d35Sstevel 				(void) ddi_pathname(saf_dip, path);
111703831d35Sstevel 			}
111803831d35Sstevel 
111903831d35Sstevel 			cmn_err(CE_CONT, "AXQ node removal failed: "
112003831d35Sstevel 			    "path=%s, dip=%p, rv=%d\n", path,
112103831d35Sstevel 			    fdip ? (void *)fdip : (void *)saf_dip, rv);
112203831d35Sstevel 
112303831d35Sstevel 			kmem_free(path, MAXPATHLEN);
112403831d35Sstevel 			failure = 1;
112503831d35Sstevel 		} else {
112603831d35Sstevel 			config->gptwo_nodes->gptwo_nodes[i] = NULL;
112703831d35Sstevel 		}
112803831d35Sstevel 	}
112903831d35Sstevel 	if (!failure) {
113003831d35Sstevel 		gptwocfg_free_node_list(config->gptwo_nodes);
113103831d35Sstevel 
113203831d35Sstevel 		kmem_free(config, sizeof (gptwocfg_config_t));
113303831d35Sstevel 		config = NULL;
113403831d35Sstevel 	}
113503831d35Sstevel 	return (config);
113603831d35Sstevel }
113703831d35Sstevel 
113803831d35Sstevel static uint_t
113903831d35Sstevel sc_get_agent_id(spcd_t *pcd, uint_t expander, uint_t slot, uint_t prd_slot)
114003831d35Sstevel {
114103831d35Sstevel 	uint_t agent_id;
114203831d35Sstevel 
114303831d35Sstevel 	switch (pcd->spcd_ptype) {
114403831d35Sstevel 	case SAFPTYPE_CPU:
114503831d35Sstevel 		if (slot == 0) {
114603831d35Sstevel 			agent_id = prd_slot;
114703831d35Sstevel 		} else {
114803831d35Sstevel 			if (prd_slot == 4) {
114903831d35Sstevel 				agent_id = 8;
115003831d35Sstevel 			} else {
115103831d35Sstevel 				agent_id = 9;
115203831d35Sstevel 			}
115303831d35Sstevel 		}
115403831d35Sstevel 		break;
115503831d35Sstevel 
115603831d35Sstevel 	case SAFPTYPE_sPCI:
115703831d35Sstevel 	case SAFPTYPE_cPCI:
115803831d35Sstevel 	case SAFPTYPE_PCIX:
115903831d35Sstevel 		if (prd_slot == 4) {
116003831d35Sstevel 			agent_id = 0x1c;
116103831d35Sstevel 		} else {
116203831d35Sstevel 			agent_id = 0x1d;
116303831d35Sstevel 		}
116403831d35Sstevel 		break;
116503831d35Sstevel 	case SAFPTYPE_WCI:
116603831d35Sstevel 		agent_id = 0x1d;
116703831d35Sstevel 		break;
116803831d35Sstevel 	default:
116903831d35Sstevel 		cmn_err(CE_WARN, "sc_gptwocfg: Invalid Safari Port "
117003831d35Sstevel 		    "Type 0x%x Slot 0x%x\n",
117103831d35Sstevel 		    pcd->spcd_ptype, prd_slot);
117203831d35Sstevel 	} /* switch */
117303831d35Sstevel 
117403831d35Sstevel 	agent_id |= (expander << 5);
117503831d35Sstevel 
117603831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "sc_get_agent_id(pcd=0x%p, expander=0x%x, "
1177*07d06da5SSurya Prakki 	    "prd_slot=0x%x) Returning agent_id=0x%x\n", (void *)pcd, expander,
117803831d35Sstevel 	    prd_slot, agent_id));
117903831d35Sstevel 
118003831d35Sstevel 	return (agent_id);
118103831d35Sstevel }
118203831d35Sstevel 
118303831d35Sstevel static void
118403831d35Sstevel dump_config(sc_gptwocfg_config_t *board_config)
118503831d35Sstevel {
118603831d35Sstevel 	gptwocfg_config_t *port;
118703831d35Sstevel 
1188*07d06da5SSurya Prakki 	SC_DEBUG(1, (CE_CONT, "dump_config 0x%p", (void *)board_config));
118903831d35Sstevel 	while (board_config != NULL) {
119003831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "************* 0x%p ************\n",
1191*07d06da5SSurya Prakki 		    (void *)board_config));
119203831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "port_cookie - 0x%p\n",
1193*07d06da5SSurya Prakki 		    (void *)board_config->port_cookie));
119403831d35Sstevel 
119503831d35Sstevel 		port = board_config->port_cookie;
119603831d35Sstevel 		if (port) {
119703831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "     ap     - 0x%p\n",
1198*07d06da5SSurya Prakki 			    (void *)port->gptwo_ap));
119903831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "     portid - 0x%x\n",
120003831d35Sstevel 			    port->gptwo_portid));
120103831d35Sstevel 		}
120203831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "portid      - 0x%x\n",
120303831d35Sstevel 		    board_config->portid));
120403831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "board      - 0x%x\n",
120503831d35Sstevel 		    board_config->board));
120603831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "link        - 0x%p\n",
1207*07d06da5SSurya Prakki 		    (void *)board_config->link));
120803831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "next        - 0x%p\n",
1209*07d06da5SSurya Prakki 		    (void *)board_config->next));
121003831d35Sstevel 		board_config = board_config->link;
121103831d35Sstevel 	}
121203831d35Sstevel }
121303831d35Sstevel 
121403831d35Sstevel static void
121503831d35Sstevel dump_pcd(spcd_t *pcd)
121603831d35Sstevel {
121703831d35Sstevel 	int i;
121803831d35Sstevel 
1219*07d06da5SSurya Prakki 	SC_DEBUG(1, (CE_CONT, "dump_pcd 0x%p", (void *)pcd));
122003831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     magic   - 0x%x\n", pcd->spcd_magic));
122103831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     version - 0x%x\n", pcd->spcd_version));
122203831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     ver.reg - 0x%lx\n", pcd->spcd_ver_reg));
122303831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     afreq   - %d\n", pcd->spcd_afreq));
122403831d35Sstevel 	switch (pcd->spcd_ptype) {
122503831d35Sstevel 	case SAFPTYPE_CPU:
122603831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - CPU\n"));
122703831d35Sstevel 		break;
122803831d35Sstevel 	case SAFPTYPE_sPCI:
122903831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI\n"));
123003831d35Sstevel 		break;
123103831d35Sstevel 	case SAFPTYPE_cPCI:
123203831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - cPCI\n"));
123303831d35Sstevel 		break;
123403831d35Sstevel 	case SAFPTYPE_PCIX:
123503831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI+\n"));
123603831d35Sstevel 		break;
123703831d35Sstevel 	case SAFPTYPE_WCI:
123803831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - WIC\n"));
123903831d35Sstevel 		break;
124003831d35Sstevel 	default:
124103831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     ptype   - 0x%x\n",
124203831d35Sstevel 		    pcd->spcd_ptype));
124303831d35Sstevel 		break;
124403831d35Sstevel 	}
124503831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     cache   - %d\n", pcd->spcd_cache));
124603831d35Sstevel 
124703831d35Sstevel 	if (pcd->spcd_prsv == SPCD_RSV_PASS) {
124803831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     prsv    - SPCD_RSV_PASS\n"));
124903831d35Sstevel 	} else {
125003831d35Sstevel 		SC_DEBUG(1, (CE_CONT, "     prsv    - 0x%x (FAIL)\n",
125103831d35Sstevel 		    pcd->spcd_prsv));
125203831d35Sstevel 	}
125303831d35Sstevel 
125403831d35Sstevel 	for (i = 0; i < AGENTS_PER_PORT; i++) {
125503831d35Sstevel 		if (pcd->spcd_agent[i] == SPCD_RSV_PASS) {
125603831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
125703831d35Sstevel 			    "- SPCD_RSV_PASS\n", i));
125803831d35Sstevel 		} else {
125903831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
126003831d35Sstevel 			    "- 0x%x (FAIL)\n", i, pcd->spcd_agent[i]));
126103831d35Sstevel 		}
126203831d35Sstevel 	}
126303831d35Sstevel 
126403831d35Sstevel 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
126503831d35Sstevel 		for (i = 0; i < AGENTS_PER_PORT; i++) {
126603831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "     cpuid[%d] - 0x%x\n",
126703831d35Sstevel 			    i, pcd->spcd_cpuid[i]));
126803831d35Sstevel 		}
126903831d35Sstevel 	}
127003831d35Sstevel 
127103831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     Banks\n"));
127203831d35Sstevel 	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
127303831d35Sstevel 		if (pcd->sprd_bank_rsv[i]) {
127403831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
127503831d35Sstevel 			    pcd->sprd_bank_rsv[i]));
127603831d35Sstevel 		}
127703831d35Sstevel 	}
127803831d35Sstevel 
127903831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     Dimms\n"));
128003831d35Sstevel 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
128103831d35Sstevel 		if (pcd->sprd_dimm[i]) {
128203831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
128303831d35Sstevel 			    pcd->sprd_dimm[i]));
128403831d35Sstevel 		}
128503831d35Sstevel 	}
128603831d35Sstevel 	SC_DEBUG(1, (CE_CONT, "     Ecache Dimm Labels\n"));
128703831d35Sstevel 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
128803831d35Sstevel 		if (pcd->sprd_ecache_dimm_label[i]) {
128903831d35Sstevel 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
129003831d35Sstevel 			    pcd->sprd_ecache_dimm_label[i]));
129103831d35Sstevel 		}
129203831d35Sstevel 	}
129303831d35Sstevel }
129403831d35Sstevel 
129503831d35Sstevel 
129603831d35Sstevel typedef struct {
129703831d35Sstevel 	char Jnumber[8][8];
129803831d35Sstevel 	uint8_t sym_flag;
129903831d35Sstevel 	uint8_t d_dimmtable[144];
130003831d35Sstevel 	uint8_t d_pintable[576];
130103831d35Sstevel }m_layout;
130203831d35Sstevel 
130303831d35Sstevel /*
130403831d35Sstevel  * Use 2 bits to represent each bit at a cache line. The table
130503831d35Sstevel  * is in big endian order, i.e.
130603831d35Sstevel  *      dimmtable[0], ... , dimmtable[143]
130703831d35Sstevel  * Q0:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
130803831d35Sstevel  *                      .
130903831d35Sstevel  *                      .
131003831d35Sstevel  * Q3:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
131103831d35Sstevel  */
131203831d35Sstevel uint8_t J_dimm_pinTable[] = {
131303831d35Sstevel /* Jnumber */
131403831d35Sstevel /*  0 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x30, 0x00, 0x00,
131503831d35Sstevel /*  1 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x30, 0x00, 0x00,
131603831d35Sstevel /*  2 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x30, 0x00, 0x00,
131703831d35Sstevel /*  3 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x30, 0x00, 0x00,
131803831d35Sstevel /*  4 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x31, 0x00, 0x00,
131903831d35Sstevel /*  5 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x31, 0x00, 0x00,
132003831d35Sstevel /*  6 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x31, 0x00, 0x00,
132103831d35Sstevel /*  7 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x31, 0x00, 0x00,
132203831d35Sstevel /* flag */	0x01,
132303831d35Sstevel /*  -- Q0 --  */
132403831d35Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
132503831d35Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
132603831d35Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
132703831d35Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
132803831d35Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
132903831d35Sstevel /*  -- Q1 --  */
133003831d35Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
133103831d35Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
133203831d35Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
133303831d35Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
133403831d35Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
133503831d35Sstevel /*  -- Q2 --  */
133603831d35Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
133703831d35Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
133803831d35Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
133903831d35Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
134003831d35Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
134103831d35Sstevel /*  -- Q3 --  */
134203831d35Sstevel /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
134303831d35Sstevel /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
134403831d35Sstevel /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
134503831d35Sstevel /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
134603831d35Sstevel /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
134703831d35Sstevel /*
134803831d35Sstevel  * In the following order
134903831d35Sstevel  *      pintable[0], ..., pintable[575]
135003831d35Sstevel  * Quadword3, Quadword2, Quadword1, Quadword0
135103831d35Sstevel  *      MtagEcc, Mtag, Ecc, Data
135203831d35Sstevel  */
135303831d35Sstevel /* -- Q3 -- */
135403831d35Sstevel /*  0  */	227, 227, 227, 227, 111, 111, 111,  22,
135503831d35Sstevel /*  1  */	22,  32, 138, 222,  81, 117, 117, 117,
135603831d35Sstevel /*  2  */	111, 222, 106, 222, 222, 106, 106, 106,
135703831d35Sstevel /*  3  */	217, 101, 212,  96, 217, 101, 212,  96,
135803831d35Sstevel /*  4  */	217, 101, 212,  96, 217, 101, 212,  96,
135903831d35Sstevel /*  5  */	207,  91, 202,  86, 187,  71, 158,  42,
136003831d35Sstevel /*  6  */	187,  71, 158,  42, 153,  37, 148,  32,
136103831d35Sstevel /*  7  */	153,  37, 148,  32, 153,  37, 148,  32,
136203831d35Sstevel /*  8  */	153,  37, 148, 143,  27, 138, 143,  27,
136303831d35Sstevel /*  9  */	143,  27, 138,  22, 207,  91, 202,  86,
136403831d35Sstevel /*  10 */	207,  91, 202,  86, 207,  91, 202,  86,
136503831d35Sstevel /*  11 */	192,  76,  81, 192,  76,  81, 192,  76,
136603831d35Sstevel /*  12 */	197,  81, 192,  76, 187,  71, 158,  42,
136703831d35Sstevel /*  13 */	187,  71, 158,  42, 143,  27, 138,  22,
136803831d35Sstevel /*  14 */	133,  17, 128,  12, 133,  17, 128,  12,
136903831d35Sstevel /*  15 */	133,  17, 128,  12, 133,  17, 128,  12,
137003831d35Sstevel /*  16 */	123,  07, 118,   2, 123,  07, 118,   2,
137103831d35Sstevel /*  17 */	123,  07, 118,   2, 123,  07, 118,   2,
137203831d35Sstevel /* -- Q2 -- */
137303831d35Sstevel /*  0  */	228, 228, 228, 228, 112, 112, 112,  23,
137403831d35Sstevel /*  1  */	23,  33, 139, 223,  82, 118, 118, 118,
137503831d35Sstevel /*  2  */	112, 223, 107, 223, 223, 107, 107, 107,
137603831d35Sstevel /*  3  */	218, 102, 213,  97, 218, 102, 213,  97,
137703831d35Sstevel /*  4  */	218, 102, 213,  97, 218, 102, 213,  97,
137803831d35Sstevel /*  5  */	208,  92, 203,  87, 188,  72, 159,  43,
137903831d35Sstevel /*  6  */	188,  72, 159,  43, 154,  38, 149,  33,
138003831d35Sstevel /*  7  */	154,  38, 149,  33, 154,  38, 149,  33,
138103831d35Sstevel /*  8  */	154,  38, 149, 144,  28, 139, 144,  28,
138203831d35Sstevel /*  9  */	144,  28, 139,  23, 208,  92, 203,  87,
138303831d35Sstevel /*  10 */	208,  92, 203,  87, 208,  92, 203,  87,
138403831d35Sstevel /*  11 */	193,  77,  82, 193,  77,  82, 193,  77,
138503831d35Sstevel /*  12 */	198,  82, 193,  77, 188,  72, 159,  43,
138603831d35Sstevel /*  13 */	188,  72, 159,  43, 144,  28, 139,  23,
138703831d35Sstevel /*  14 */	134,  18, 129,  13, 134,  18, 129,  13,
138803831d35Sstevel /*  15 */	134,  18, 129,  13, 134,  18, 129,  13,
138903831d35Sstevel /*  16 */	124,   8, 119,   3, 124,   8, 119,   3,
139003831d35Sstevel /*  17 */	124,   8, 119,   3, 124,   8, 119,   3,
139103831d35Sstevel /* -- Q1 -- */
139203831d35Sstevel /*  0  */	229, 229, 229, 229, 113, 113, 113,  24,
139303831d35Sstevel /*  1  */	24,  34, 140, 224,  83, 119, 119, 119,
139403831d35Sstevel /*  2  */	113, 224, 108, 224, 224, 108, 108, 108,
139503831d35Sstevel /*  3  */	219, 103, 214,  98, 219, 103, 214,  98,
139603831d35Sstevel /*  4  */	219, 103, 214,  98, 219, 103, 214,  98,
139703831d35Sstevel /*  5  */	209,  93, 204,  88, 189,  73, 160,  44,
139803831d35Sstevel /*  6  */	189,  73, 160,  44, 155,  39, 150,  34,
139903831d35Sstevel /*  7  */	155,  39, 150,  34, 155,  39, 150,  34,
140003831d35Sstevel /*  8  */	155,  39, 150, 145,  29, 140, 145,  29,
140103831d35Sstevel /*  9  */	145,  29, 140,  24, 209,  93, 204,  88,
140203831d35Sstevel /*  10 */	209,  93, 204,  88, 209,  93, 204,  88,
140303831d35Sstevel /*  11 */	194,  78,  83, 194,  78,  83, 194,  78,
140403831d35Sstevel /*  12 */	199,  83, 194,  78, 189,  73, 160,  44,
140503831d35Sstevel /*  13 */	189,  73, 160,  44, 145,  29, 140,  24,
140603831d35Sstevel /*  14 */	135,  19, 130,  14, 135,  19, 130,  14,
140703831d35Sstevel /*  15 */	135,  19, 130,  14, 135,  19, 130,  14,
140803831d35Sstevel /*  16 */	125,   9, 120,   4, 125,   9, 120,   4,
140903831d35Sstevel /*  17 */	125,   9, 120,   4, 125,   9, 120,   4,
141003831d35Sstevel /* -- Q0 -- */
141103831d35Sstevel /*  0  */	230, 230, 230, 230, 114, 114, 114,  25,
141203831d35Sstevel /*  1  */	25,  35, 141, 225,  84, 200, 200, 200,
141303831d35Sstevel /*  2  */	114, 225, 109, 225, 225, 109, 109, 109,
141403831d35Sstevel /*  3  */	220, 104, 215,  99, 220, 104, 215,  99,
141503831d35Sstevel /*  4  */	220, 104, 215,  99, 220, 104, 215,  99,
141603831d35Sstevel /*  5  */	210,  94, 205,  89, 190,  74, 161,  45,
141703831d35Sstevel /*  6  */	190,  74, 161,  45, 156,  40, 151,  35,
141803831d35Sstevel /*  7  */	156,  40, 151,  35, 156,  40, 151,  35,
141903831d35Sstevel /*  8  */	156,  40, 151, 146,  30, 141, 146,  30,
142003831d35Sstevel /*  9  */	146,  30, 141,  25, 210,  94, 205,  89,
142103831d35Sstevel /*  10 */	210,  94, 205,  89, 210,  94, 205,  89,
142203831d35Sstevel /*  11 */	195,  79,  84, 195,  79,  84, 195,  79,
142303831d35Sstevel /*  12 */	200,  84, 195,  79, 190,  74, 161,  45,
142403831d35Sstevel /*  13 */	190,  74, 161,  45, 146,  30, 141,  25,
142503831d35Sstevel /*  14 */	136,  20, 131,  15, 136,  20, 131,  15,
142603831d35Sstevel /*  15 */	136,  20, 131,  15, 136,  20, 131,  15,
142703831d35Sstevel /*  16 */	126,  10, 121,   5, 126,  10, 121,   5,
142803831d35Sstevel /*  17 */	126,  10, 121,   5, 126,  10, 121,   5
142903831d35Sstevel };
143003831d35Sstevel 
143103831d35Sstevel /*
143203831d35Sstevel  *  This table is for internal reference
143303831d35Sstevel  *
143403831d35Sstevel  * pintable_internal[]= {
143503831d35Sstevel  * -- Q0 --
143603831d35Sstevel  * 0  143,143,143,143,139,139,139,35
143703831d35Sstevel  * 1  35,51,39,135,91,95,95,95
143803831d35Sstevel  * 2  139,135,131,135,135,131,131,131
143903831d35Sstevel  * 3  127,123,119,115,127,123,119,115
144003831d35Sstevel  * 4  127,123,119,115,127,123,119,115
144103831d35Sstevel  * 5  111,107,103,99,79,75,71,67
144203831d35Sstevel  * 6  79,75,71,67,63,59,55,51
144303831d35Sstevel  * 7  63,59,55,51,63,59,55,51
144403831d35Sstevel  * 8  63,59,55,47,43,39,47,43
144503831d35Sstevel  * 9  47,43,39,35,111,107,103,99
144603831d35Sstevel  * 10  111,107,103,99,111,107,103,99
144703831d35Sstevel  * 11  87,83,91,87,83,91,87,83
144803831d35Sstevel  * 12  95,91,87,83,79,75,71,67
144903831d35Sstevel  * 13  79,75,71,67,47,43,39,35
145003831d35Sstevel  * 14  31,27,23,19,31,27,23,19
145103831d35Sstevel  * 15  31,27,23,19,31,27,23,19
145203831d35Sstevel  * 16  15,11,7,3,15,11,7,3
145303831d35Sstevel  * 17  15,11,7,3,15,11,7,3
145403831d35Sstevel  * }
145503831d35Sstevel  */
145603831d35Sstevel 
145703831d35Sstevel char *dimm_Jno[] = {
145803831d35Sstevel /* P0 */	"J13300", "J13400", "J13500", "J13600",
145903831d35Sstevel 		"J13301", "J13401", "J13501", "J13601",
146003831d35Sstevel /* P1 */	"J14300", "J14400", "J14500", "J14600",
146103831d35Sstevel 		"J14301", "J14401", "J14501", "J14601",
146203831d35Sstevel /* P2 */	"J15300", "J15400", "J15500", "J15600",
146303831d35Sstevel 		"J15301", "J15401", "J15501", "J15601",
146403831d35Sstevel /* P3 */	"J16300", "J16400", "J16500", "J16600",
146503831d35Sstevel 		"J16301", "J16401", "J16501", "J16601",
146603831d35Sstevel 		NULL
146703831d35Sstevel 	};
146803831d35Sstevel 
146903831d35Sstevel 
147003831d35Sstevel static uint8_t *
147103831d35Sstevel get_memlayout(uint32_t cpuid, uint32_t *len)
147203831d35Sstevel {
147303831d35Sstevel 	m_layout *LayoutBuf;
147403831d35Sstevel 
147503831d35Sstevel 	if ((LayoutBuf = (m_layout *)kmem_zalloc(sizeof (m_layout),
147603831d35Sstevel 	    KM_SLEEP)) == NULL) {
147703831d35Sstevel 		*len = 0;
147803831d35Sstevel 		return (NULL);
147903831d35Sstevel 	}
148003831d35Sstevel 
148103831d35Sstevel 	bcopy(J_dimm_pinTable, LayoutBuf, sizeof (m_layout));
148203831d35Sstevel 
148303831d35Sstevel 	*len = sizeof (m_layout);
148403831d35Sstevel 	cpuid &= 0x03;	/* last 2 bits of a 10 bit number */
148503831d35Sstevel 
148603831d35Sstevel 	bcopy(dimm_Jno[cpuid << 3], LayoutBuf->Jnumber[0], 64);
148703831d35Sstevel 
148803831d35Sstevel 	return ((uint8_t *)LayoutBuf);
148903831d35Sstevel }
149003831d35Sstevel 
149103831d35Sstevel static char *
149203831d35Sstevel rsv_string(prdrsv_t rsv)
149303831d35Sstevel {
149403831d35Sstevel 	char *buffer;
149503831d35Sstevel 	char *status;
149603831d35Sstevel 
149703831d35Sstevel 	switch (rsv) {
149803831d35Sstevel 	case RSV_UNKNOWN:
149903831d35Sstevel 		buffer = "unknown";
150003831d35Sstevel 		break;
150103831d35Sstevel 	case RSV_PRESENT:
150203831d35Sstevel 		buffer = "okay";
150303831d35Sstevel 		break;
150403831d35Sstevel 	case RSV_CRUNCH:
150503831d35Sstevel 		buffer = "disabled";
150603831d35Sstevel 		break;
150703831d35Sstevel 	case RSV_UNDEFINED:
150803831d35Sstevel 		buffer = "undefined";
150903831d35Sstevel 		break;
151003831d35Sstevel 	case RSV_MISS:
151103831d35Sstevel 		buffer = "missing";
151203831d35Sstevel 		break;
151303831d35Sstevel 	case RSV_EMPTY_CASSETTE:
151403831d35Sstevel 		buffer = "disabled";
151503831d35Sstevel 		break;
151603831d35Sstevel 	case RSV_MISCONFIG:
151703831d35Sstevel 		buffer = "misconfigured";
151803831d35Sstevel 		break;
151903831d35Sstevel 	case RSV_FAIL_OBP:
152003831d35Sstevel 		buffer = "fail-obp";
152103831d35Sstevel 		break;
152203831d35Sstevel 	case RSV_BLACK:
152303831d35Sstevel 		buffer = "blacklisted";
152403831d35Sstevel 		break;
152503831d35Sstevel 	case RSV_RED:
152603831d35Sstevel 		buffer = "redlisted";
152703831d35Sstevel 		break;
152803831d35Sstevel 	case RSV_EXCLUDED:
152903831d35Sstevel 		buffer = "disabled";
153003831d35Sstevel 		break;
153103831d35Sstevel 	case RSV_UNCONFIG:
153203831d35Sstevel 		buffer = "disabled";
153303831d35Sstevel 		break;
153403831d35Sstevel 	case RSV_PASS:
153503831d35Sstevel 		buffer = "okay";
153603831d35Sstevel 		break;
153703831d35Sstevel 	case RSV_FAIL:
153803831d35Sstevel 	default:
153903831d35Sstevel 		buffer = "fail";
154003831d35Sstevel 		break;
154103831d35Sstevel 	}
154203831d35Sstevel 
154303831d35Sstevel 	status = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
154403831d35Sstevel 	(void) strcpy(status, buffer);
154503831d35Sstevel 
154603831d35Sstevel 	return (status);
154703831d35Sstevel }
1548