xref: /titanic_44/usr/src/uts/sun4u/starcat/io/sc_gptwocfg.c (revision 40e5e17b3361b3eea56a9723071c406894a20b78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *     Starcat Specific Glue for Safari Configurator
31  */
32 
33 #include <sys/isa_defs.h>
34 #include <sys/conf.h>
35 #include <sys/kmem.h>
36 #include <sys/debug.h>
37 #include <sys/modctl.h>
38 #include <sys/autoconf.h>
39 #include <sys/hwconf.h>
40 #include <sys/ddi_impldefs.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/sunndi.h>
44 #include <sys/ndi_impldefs.h>
45 #include <sys/safari_pcd.h>
46 #include <sys/gp2cfg.h>
47 #include <sys/gptwo_cpu.h>
48 #include <sys/gptwo_pci.h>
49 #include <sys/gptwo_wci.h>
50 #include <sys/sc_gptwocfg.h>
51 #include <post/scat_dcd.h>
52 #include <sys/machsystm.h>
53 
54 int sc_gptwocfg_debug = 0;
55 
56 #define	SC_DEBUG(level, args) if (sc_gptwocfg_debug >= level) cmn_err args
57 
58 typedef struct sc_gptwocfg_config {
59 	int				board;
60 	struct gptwocfg_config		*port_cookie;
61 	gptwo_aid_t			portid;
62 	struct sc_gptwocfg_config	*link;
63 	struct sc_gptwocfg_config	*next;
64 } sc_gptwocfg_config_t;
65 
66 static kmutex_t sc_gptwo_config_list_lock;
67 static sc_gptwocfg_config_t *sc_gptwo_config_list;
68 static dev_info_t *sc_find_axq_node(uint_t);
69 static sc_gptwocfg_cookie_t sc_configure(uint_t, int);
70 static spcd_t *sc_get_common_pcd(uint_t, uint_t);
71 static void sc_free_common_pcd(spcd_t *);
72 static gptwo_new_nodes_t *sc_gptwocfg_configure_axq(dev_info_t *, uint_t, int);
73 static gptwocfg_config_t *sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *);
74 static void dump_config(sc_gptwocfg_config_t *);
75 static void dump_pcd(spcd_t *);
76 static uint_t sc_get_agent_id(spcd_t *, uint_t, uint_t, uint_t);
77 static char *rsv_string(prdrsv_t);
78 
79 extern gptwo_new_nodes_t *gptwocfg_allocate_node_list(int);
80 extern void gptwocfg_free_node_list(gptwo_new_nodes_t *);
81 
82 static uint8_t *get_memlayout(uint32_t, uint32_t *);
83 
84 #ifdef NO_IOSRAM
85 int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
86 #else
87 extern int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
88 #endif
89 extern void gptwocfg_devi_attach_to_parent(dev_info_t *);
90 
91 /*
92  * Module control operations
93  */
94 
95 extern struct mod_ops mod_miscops;
96 
97 static struct modlmisc modlmisc = {
98 	&mod_miscops, /* Type of module */
99 	"Sun Fire 15000 gptwocfg %I%"
100 };
101 
102 static struct modlinkage modlinkage = {
103 	MODREV_1, (void *)&modlmisc, NULL
104 };
105 
106 int
107 _init()
108 {
109 	int err = 0;
110 
111 	mutex_init(&sc_gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL);
112 	sc_gptwo_config_list = NULL;
113 
114 	/*
115 	 * CPU/PCI devices are already registered by their respective modules,
116 	 * so all we need to do now is install.
117 	 */
118 	if ((err = mod_install(&modlinkage)) != 0) {
119 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg failed to load, error=%d\n",
120 			err));
121 		mutex_destroy(&sc_gptwo_config_list_lock);
122 	} else {
123 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg has been loaded.\n"));
124 	}
125 	return (err);
126 }
127 
128 int
129 _fini(void)
130 {
131 	mutex_destroy(&sc_gptwo_config_list_lock);
132 	return (mod_remove(&modlinkage));
133 }
134 
135 int
136 _info(modinfop)
137 struct modinfo *modinfop;
138 {
139 	return (mod_info(&modlinkage, modinfop));
140 }
141 
142 static spcd_t *
143 sc_get_common_pcd(uint_t expander, uint_t prd_slot)
144 {
145 	spcd_t *pcd;
146 	gdcd_t *gdcd;
147 	int portid;
148 	int i, j, slot;
149 	int dimm;
150 	char *label1, *label2;
151 
152 	SC_DEBUG(1, (CE_WARN, "sc_get_common_pcd() expander=%d prd_slot=%d\n",
153 	    expander, prd_slot));
154 
155 	gdcd = (gdcd_t *)kmem_zalloc(sizeof (gdcd_t), KM_SLEEP);
156 
157 	/*
158 	 * Get the Starcat Specific Global DCD Structure from the golden
159 	 * IOSRAM.
160 	 */
161 	if (iosram_rd(GDCD_MAGIC, 0, sizeof (gdcd_t), (caddr_t)gdcd)) {
162 		cmn_err(CE_WARN, "sc_gptwocfg: Unable To Read GDCD "
163 		    "From IOSRAM\n");
164 		kmem_free(gdcd, sizeof (gdcd_t));
165 		return (NULL);
166 	}
167 
168 	if (gdcd->h.dcd_magic != GDCD_MAGIC) {
169 
170 		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Magic 0x%x\n",
171 		    gdcd->h.dcd_magic);
172 
173 		kmem_free(gdcd, sizeof (gdcd_t));
174 		return (NULL);
175 	}
176 
177 	if (gdcd->h.dcd_version != DCD_VERSION) {
178 		cmn_err(CE_WARN, "sc_gptwocfg: GDCD Bad Version: "
179 		    "GDCD Version 0x%x Expecting 0x%x\n",
180 		    gdcd->h.dcd_version, DCD_VERSION);
181 
182 		kmem_free(gdcd, sizeof (gdcd_t));
183 		return (NULL);
184 	}
185 
186 	pcd = (spcd_t *)kmem_zalloc(sizeof (spcd_t), KM_SLEEP);
187 
188 	/*
189 	 * Copy various information from the platform specific Port
190 	 * Resource Descriptor (PRD) To the platform independent
191 	 * Port Configuration Descriptor.
192 	 */
193 	pcd->spcd_magic = PCD_MAGIC;
194 	pcd->spcd_version = PCD_VERSION;
195 	pcd->spcd_ptype = gdcd->dcd_prd[expander][prd_slot].prd_ptype;
196 	pcd->spcd_ver_reg = gdcd->dcd_prd[expander][prd_slot].prd_ver_reg;
197 
198 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
199 		/*
200 		 * This will calculate the cpu speed based on the
201 		 * the actual frequency ratio * interconnect frequency
202 		 * converted to Mhz.
203 		 */
204 		pcd->spcd_afreq = gdcd->dcd_prd[expander][prd_slot].
205 		    prd_afreq_ratio *
206 		    (uint16_t)((gdcd->dcd_intercon_freq + 500000) / 1000000);
207 	} else {
208 		/*
209 		 * For non-cpu devices, just pass through the frequency
210 		 * unchanged.
211 		 */
212 		pcd->spcd_afreq =
213 		    gdcd->dcd_prd[expander][prd_slot].prd_afreq_ratio;
214 	}
215 
216 	pcd->spcd_cache = gdcd->dcd_prd[expander][prd_slot].prd_cache;
217 
218 	SC_DEBUG(1, (CE_WARN, "Safari Device Status status=0x%x\n",
219 	    gdcd->dcd_prd[expander][prd_slot].prd_prsv));
220 
221 	/*
222 	 * Fill in the entire port status.
223 	 */
224 	if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].prd_prsv)) {
225 		pcd->spcd_prsv = SPCD_RSV_PASS;
226 	} else {
227 		pcd->spcd_prsv = SPCD_RSV_FAIL;
228 	}
229 
230 	/*
231 	 * Fill in the per agent status.
232 	 */
233 	if (gdcd->dcd_prd[expander][prd_slot].prd_agent[1] == RSV_UNKNOWN) {
234 		pcd->spcd_agent[0] = pcd->spcd_prsv;
235 		pcd->spcd_agent[1] = SPCD_RSV_FAIL;
236 	} else {
237 		for (i = 0; i < AGENTS_PER_PORT; i++) {
238 
239 			if (RSV_GOOD(
240 			    gdcd->dcd_prd[expander][prd_slot].prd_agent[i]))
241 				pcd->spcd_agent[i] = SPCD_RSV_PASS;
242 			else
243 				pcd->spcd_agent[i] = SPCD_RSV_FAIL;
244 		}
245 	}
246 
247 	/*
248 	 * If this is a CPU device calculate the cpuid for it.  For Starcat
249 	 * the cpuid is in the following format.
250 	 *
251 	 * EEEEEPPAPP
252 	 *
253 	 * where:	EEEEE is the expander
254 	 *		PP_PP is the portid
255 	 *		__A__ is the sub-agent identifier.
256 	 */
257 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
258 		for (i = 0; i < AGENTS_PER_PORT; i++) {
259 			switch (prd_slot) {
260 			case 0:
261 			case 1:
262 			case 2:
263 			case 3:
264 				portid = (expander << 5) | prd_slot;
265 				break;
266 			case 4: /* Maxcat */
267 				portid = (expander << 5) | 8;
268 				break;
269 			case 5: /* Maxcat */
270 				portid = (expander << 5) | 9;
271 				break;
272 			default:
273 				cmn_err(CE_WARN, "sc_gptwocfg: invalid "
274 				    "prd_slot=%d\n", prd_slot);
275 			}
276 			pcd->spcd_cpuid[i] = (i << 2) | portid;
277 		}
278 	}
279 
280 	/*
281 	 * Starcat does not have ports with UPA devices so
282 	 * spcd_upadev structure will not be filled in.
283 	 */
284 
285 	/*
286 	 * Fill in IO Bus Status
287 	 */
288 	for (i = 0; i < IOBUS_PER_PORT; i++) {
289 
290 		SC_DEBUG(1, (CE_WARN, "   IO Bus Status "
291 		    "bus=%d status=0x%x\n", i,
292 		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i]));
293 
294 		if (RSV_GOOD(
295 		    gdcd->dcd_prd[expander][prd_slot].prd_iobus_rsv[i])) {
296 			pcd->spcd_iobus_rsv[i] = SPCD_RSV_PASS;
297 		} else {
298 			pcd->spcd_iobus_rsv[i] = SPCD_RSV_FAIL;
299 		}
300 
301 		for (j = 0; j < IOCARD_PER_BUS; j++)
302 			pcd->spcd_iocard_rsv[i][j] = SPCD_RSV_FAIL;
303 
304 		/*
305 		 * Fill in IO Card Status
306 		 */
307 		for (j = 0; j < IOCARD_PER_BUS; j++) {
308 
309 			SC_DEBUG(1, (CE_WARN, "       Card Status bus=%d "
310 			    "slot=%d status=0x%x\n", i, j,
311 			    gdcd->dcd_prd[expander][prd_slot].
312 			    prd_iocard_rsv[i][j]));
313 
314 			if (j == 1)
315 				continue;
316 
317 			if (j == 0)
318 				slot = 1;
319 			else
320 				slot = j;
321 
322 			/*
323 			 * If POST marked the card as GOOD or if the slot
324 			 * is empty, we want to probe for the device.
325 			 */
326 			if (RSV_GOOD(gdcd->dcd_prd[expander][prd_slot].
327 			    prd_iocard_rsv[i][j]) ||
328 			    (gdcd->dcd_prd[expander][prd_slot].
329 			    prd_iocard_rsv[i][j] == RSV_MISS) ||
330 			    (gdcd->dcd_prd[expander][prd_slot].
331 			    prd_iocard_rsv[i][j] == RSV_EMPTY_CASSETTE))
332 				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_PASS;
333 			else
334 				pcd->spcd_iocard_rsv[i][slot] = SPCD_RSV_FAIL;
335 		}
336 	}
337 
338 	/*
339 	 * Fill in WIC Link Status
340 	 */
341 	for (i = 0; i < LINKS_PER_PORT; i++) {
342 		if (RSV_GOOD(
343 		    gdcd->dcd_prd[expander][prd_slot].prd_wic_links[i])) {
344 			pcd->spcd_wic_links[i] = SPCD_RSV_PASS;
345 
346 		} else {
347 			pcd->spcd_wic_links[i] = SPCD_RSV_FAIL;
348 		}
349 	}
350 
351 	/*
352 	 * Get data for the "bank-status" property.
353 	 */
354 	pcd->sprd_bank_rsv[0] =
355 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][0]);
356 	pcd->sprd_bank_rsv[1] =
357 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][0]);
358 	pcd->sprd_bank_rsv[2] =
359 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[0][1]);
360 	pcd->sprd_bank_rsv[3] =
361 	    rsv_string(gdcd->dcd_prd[expander][prd_slot].prd_bank_rsv[1][1]);
362 
363 	dimm = 0;
364 	for (i = 0; i < PMBANKS_PER_PORT; i++) {
365 		for (j = 0; j < DIMMS_PER_PMBANK; j++) {
366 			if (dimm < MAX_DIMMS_PER_PORT) {
367 				pcd->sprd_dimm[dimm] = rsv_string(
368 				    gdcd->dcd_prd[expander][prd_slot].
369 				    prd_dimm[i][j]);
370 				dimm++;
371 			}
372 		}
373 	}
374 
375 	/*
376 	 * Get data for the "ecache-dimm-label" property.
377 	 *
378 	 * Right now it is hardcoded, but we should eventually get this
379 	 * from the SC.
380 	 */
381 	label1 = NULL;
382 	label2 = NULL;
383 
384 	switch (prd_slot) {
385 	case 0:
386 		label1 = "4400";
387 		label2 = "4300";
388 		break;
389 	case 1:
390 		label1 = "5400";
391 		label2 = "5300";
392 		break;
393 	case 2:
394 		label1 = "6400";
395 		label2 = "6300";
396 		break;
397 	case 3:
398 		label1 = "7400";
399 		label2 = "7300";
400 		break;
401 
402 	/*
403 	 * Maxcat labels.
404 	 */
405 	case 4:
406 		label1 = "6400";
407 		label2 = "6300";
408 		break;
409 	case 5:
410 		label1 = "7400";
411 		label2 = "7300";
412 		break;
413 	}
414 
415 	i = 0;
416 	if (label1) {
417 		pcd->sprd_ecache_dimm_label[i] =
418 		    kmem_alloc(strlen(label1) + 1, KM_SLEEP);
419 
420 		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label1);
421 
422 		i++;
423 	}
424 	if (label2) {
425 		pcd->sprd_ecache_dimm_label[i] =
426 		    kmem_alloc(strlen(label2) + 1, KM_SLEEP);
427 
428 		(void) strcpy(pcd->sprd_ecache_dimm_label[i], label2);
429 
430 		i++;
431 
432 	}
433 
434 	kmem_free(gdcd, sizeof (gdcd_t));
435 
436 #ifdef DEBUG
437 	dump_pcd(pcd);
438 #endif
439 
440 	return (pcd);
441 }
442 
443 void
444 sc_free_common_pcd(spcd_t *pcd)
445 {
446 	int i;
447 
448 	SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd pcd=%p\n", pcd));
449 
450 	if (pcd->memory_layout && pcd->memory_layout_size) {
451 		SC_DEBUG(1, (CE_WARN, "sc_free_common_pcd: memory_layout %p "
452 		    "size=%x", pcd->memory_layout, pcd->memory_layout_size));
453 		kmem_free(pcd->memory_layout, pcd->memory_layout_size);
454 	}
455 
456 	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
457 		if (pcd->sprd_bank_rsv[i]) {
458 			kmem_free(pcd->sprd_bank_rsv[i],
459 			    strlen(pcd->sprd_bank_rsv[i]) + 1);
460 
461 			pcd->sprd_bank_rsv[i] = NULL;
462 		}
463 	}
464 
465 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
466 		if (pcd->sprd_dimm[i]) {
467 			kmem_free(pcd->sprd_dimm[i],
468 			    strlen(pcd->sprd_dimm[i]) + 1);
469 
470 			pcd->sprd_dimm[i] = NULL;
471 		}
472 		if (pcd->sprd_ecache_dimm_label[i]) {
473 			kmem_free(pcd->sprd_ecache_dimm_label[i],
474 			    strlen(pcd->sprd_ecache_dimm_label[i]) + 1);
475 
476 			pcd->sprd_ecache_dimm_label[i] = NULL;
477 		}
478 	}
479 
480 	kmem_free(pcd, sizeof (spcd_t));
481 }
482 
483 sc_gptwocfg_cookie_t
484 sc_probe_board(uint_t board)
485 {
486 	return (sc_configure(board, 1));
487 }
488 
489 static sc_gptwocfg_cookie_t
490 sc_configure(uint_t board, int create_nodes)
491 {
492 	spcd_t *pcd;
493 	dev_info_t *ap, *axq_dip;
494 	uint_t agent_id;
495 	uint_t prd_slot, prd_slot_start, prd_slot_end;
496 	uint_t expander, slot;
497 	gptwo_new_nodes_t *new_nodes;
498 	gptwocfg_config_t *port_cookie;
499 	struct sc_gptwocfg_config *board_config, *last, *new;
500 	int created_node = 0;
501 	uint32_t size;
502 
503 	SC_DEBUG(1, (CE_WARN, "sc_configure: board=%d, create_nodes=%d\n",
504 		board, create_nodes));
505 
506 	if (board > 35) {
507 		SC_DEBUG(1, (CE_WARN, "sc_gptwocfg - probe_board - "
508 		    "invalid board 0x%x\n", board));
509 		return (NULL);
510 	}
511 
512 	slot = board & 1;	/* Extract Slot Number */
513 	expander = board >> 1;	/* Extract Expander Number */
514 
515 	SC_DEBUG(1, (CE_WARN, "sc_configure: exp=0x%x slot=0x%x\n",
516 	    expander, slot));
517 
518 	/*
519 	 * Get the Attachment Point.  For Starcat the parent of all
520 	 * Safari children is root node.
521 	 */
522 	ap = ddi_root_node();
523 
524 	/*
525 	 * Get the agent id of the AXQ.
526 	 */
527 	agent_id = (expander << 5) | 0x1e | slot;
528 
529 	/*
530 	 * Look to see if the board is already configured by searching for
531 	 * its AXQ.
532 	 */
533 	if (create_nodes && (axq_dip = sc_find_axq_node(agent_id))) {
534 		ddi_release_devi(axq_dip);
535 		cmn_err(CE_WARN, "Board %d AXQ is already configured\n",
536 		    board);
537 		return (NULL);
538 	}
539 
540 	/*
541 	 * Probe AXQ first
542 	 */
543 	SC_DEBUG(1, (CE_WARN, "sc_configure: Probing AXQ exp=0x%x brd=0x%x\n",
544 	    expander, slot));
545 
546 	/*
547 	 * The generic gptwocfg does not support the AXQ, so we need
548 	 * to configure it. The AXQ branch is returned held.
549 	 */
550 	new_nodes = sc_gptwocfg_configure_axq(ap, agent_id, create_nodes);
551 
552 	if (new_nodes == NULL) {
553 		SC_DEBUG(1, (CE_WARN, "sc_configure: Can not probe AXQ\n"));
554 		return (NULL);
555 	}
556 
557 	port_cookie = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP);
558 
559 	/*
560 	 * Build a cookie for the AXQ.
561 	 */
562 	port_cookie->gptwo_ap = ap;
563 	port_cookie->gptwo_portid = agent_id;
564 	port_cookie->gptwo_nodes = new_nodes;
565 
566 	board_config = kmem_zalloc(sizeof (sc_gptwocfg_config_t), KM_SLEEP);
567 
568 	board_config->port_cookie = port_cookie;
569 	board_config->board = board;
570 	board_config->portid = agent_id;
571 	board_config->link = NULL;
572 	last = board_config;
573 
574 	mutex_enter(&sc_gptwo_config_list_lock);
575 	board_config->next = sc_gptwo_config_list;
576 	sc_gptwo_config_list = board_config;
577 	mutex_exit(&sc_gptwo_config_list_lock);
578 
579 	SC_DEBUG(1, (CE_WARN, "sc_configure: AXQ Probing Complete. "
580 	    "%d nodes added\n", new_nodes->gptwo_number_of_nodes));
581 
582 	/*
583 	 * Determine the starting ending slots of the PRD array.
584 	 */
585 	switch (slot) {
586 	case 0:		/* Full Bandwidth Slot */
587 		prd_slot_start = 0;
588 		prd_slot_end = 3;
589 		break;
590 	case 1:		/* Half Bandwidth Slot */
591 		prd_slot_start = 4;
592 		prd_slot_end = 5;
593 		break;
594 	default:
595 		SC_DEBUG(1, (CE_WARN, "Unknown Board Address - "
596 		    "Can not probe\n"));
597 		return (board_config);
598 	}
599 
600 	/*
601 	 * For each valid PRD entry, determine the agent id which is based
602 	 * on what type of device is described by the slot, and then
603 	 * call the safari configurator.
604 	 */
605 	for (prd_slot = prd_slot_start; prd_slot <= prd_slot_end; prd_slot++) {
606 
607 		pcd = sc_get_common_pcd(expander, prd_slot);
608 
609 		if (pcd == NULL) {
610 
611 			/*
612 			 * We can not get a PCD for this port so skip it.
613 			 */
614 			cmn_err(CE_WARN, "sc_gptwocfg: Can not get PCD "
615 			    "expander 0x%x prd slot 0x%x\n",
616 			    expander, prd_slot);
617 
618 			return (board_config);
619 		}
620 
621 		/*
622 		 * Only configure good devices.
623 		 */
624 		if (pcd->spcd_prsv == SPCD_RSV_PASS) {
625 			/*
626 			 * Determine the agent id.
627 			 */
628 			agent_id = sc_get_agent_id(
629 			    pcd, expander, slot, prd_slot);
630 
631 			pcd->memory_layout = get_memlayout(agent_id, &size);
632 			pcd->memory_layout_size = size;
633 
634 			/*
635 			 * Call Platform Independent gptwo configurator to
636 			 * create node and properties.
637 			 */
638 			if (create_nodes) {
639 				port_cookie =
640 				    gptwocfg_configure(ap, pcd, agent_id);
641 				if (port_cookie)
642 					created_node++;
643 			}
644 
645 			new = kmem_zalloc
646 			    (sizeof (sc_gptwocfg_config_t), KM_SLEEP);
647 
648 			/*
649 			 * XXX Shouldn't port_cookie be NULL if
650 			 * !create_nodes ?
651 			 */
652 			new->port_cookie = port_cookie;
653 			new->portid = agent_id;
654 			new->link = NULL;
655 			last->link = new;
656 			last = new;
657 		} else {
658 			SC_DEBUG(1, (CE_WARN, "sc_configure: Bad Agent "
659 			    "Exp=0x%x PRD Slot=0x%x  prsv Status=0x%x\n",
660 			    expander, prd_slot, pcd->spcd_prsv));
661 		}
662 
663 		sc_free_common_pcd(pcd);
664 
665 	} /* for loop */
666 
667 	dump_config(board_config);
668 
669 	if (create_nodes && !created_node) {
670 		SC_DEBUG(1, (CE_WARN, "sc_configure: GPTWO Devices failed "
671 		    "to configure - unprobing board %d\n", board));
672 		board_config = sc_unprobe_board(board);
673 	}
674 
675 	SC_DEBUG(1, (CE_WARN, "sc_configure: Returning 0x%p\n",
676 	    board_config));
677 
678 	return (board_config);
679 }
680 
681 sc_gptwocfg_cookie_t
682 sc_unprobe_board(uint_t board)
683 {
684 	sc_gptwocfg_config_t *board_config, *axq_config, *prior_config;
685 	gptwocfg_cookie_t port_cookie;
686 
687 	SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: board=%d\n", board));
688 
689 	if (board > 35) {
690 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
691 		    "invalid board 0x%x\n", board));
692 		return (NULL);
693 	}
694 	mutex_enter(&sc_gptwo_config_list_lock);
695 	board_config = sc_gptwo_config_list;
696 	while (board_config != NULL) {
697 		if (board_config->board == board) {
698 			break;
699 		}
700 		board_config = board_config->next;
701 	}
702 	mutex_exit(&sc_gptwo_config_list_lock);
703 
704 	if (board_config == NULL) {
705 
706 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: No "
707 		    "config structure board=0x%x\n", board));
708 
709 		/*
710 		 * Configure the board without creating nodes.
711 		 */
712 		board_config = sc_configure(board, 0);
713 
714 		if (board_config == NULL) {
715 
716 			cmn_err(CE_WARN, "sc_gptwocfg: sc_unprobe_board: "
717 			    "Unable to unconfigure board %d - board is not "
718 			    "configured\n", board);
719 
720 			return (NULL);
721 		}
722 	}
723 
724 	axq_config = board_config;
725 
726 	/*
727 	 * Walk the link of ports on this board and unconfigure them.
728 	 * Save the AXQ for last.
729 	 */
730 	while (board_config->link != NULL) {
731 		prior_config = board_config;
732 		board_config = board_config->link;
733 
734 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
735 		    "calling gptwocfg_unconfigure(ap=0x%p portid=0x%x)\n",
736 		    ddi_root_node(), board_config->portid));
737 
738 		port_cookie = gptwocfg_unconfigure(ddi_root_node(),
739 		    board_config->portid);
740 
741 		SC_DEBUG(1, (CE_WARN, "sc_unprobe_board: "
742 		    "gptwocfg_unconfigure returned cookie=0x%p\n",
743 		    port_cookie));
744 
745 		if (port_cookie == NULL) {
746 			/*
747 			 * Can be removed from list.
748 			 */
749 			prior_config->link = board_config->link;
750 			kmem_free(board_config, sizeof (sc_gptwocfg_config_t));
751 			board_config = prior_config;
752 		} else {
753 			board_config->port_cookie = port_cookie;
754 		}
755 	}
756 
757 	if (axq_config->link == NULL) {
758 
759 		/*
760 		 * If all the other Safari devices have been successfully
761 		 * unconfigured, then the AXQ can be unconfigured.
762 		 */
763 		axq_config->port_cookie =
764 		    sc_gptwocfg_unconfigure_axq(axq_config->port_cookie);
765 
766 		if (axq_config->port_cookie == NULL) {
767 
768 			/*
769 			 * If the AXQ was successfully unconfigured, then
770 			 * the board is removed from the configured list.
771 			 */
772 			mutex_enter(&sc_gptwo_config_list_lock);
773 			if (sc_gptwo_config_list == axq_config) {
774 				sc_gptwo_config_list = axq_config->next;
775 			} else {
776 				board_config = sc_gptwo_config_list;
777 				while (board_config->next != axq_config) {
778 					board_config = board_config->next;
779 				}
780 				board_config->next = axq_config->next;
781 			}
782 			mutex_exit(&sc_gptwo_config_list_lock);
783 			kmem_free(axq_config, sizeof (sc_gptwocfg_config_t));
784 			axq_config = NULL;
785 		}
786 	}
787 	dump_config(axq_config);
788 	return (axq_config);
789 }
790 
791 int
792 sc_next_node(sc_gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next)
793 {
794 	dev_info_t *dip;
795 	sc_gptwocfg_config_t *cookie;
796 
797 	SC_DEBUG(1, (CE_WARN, "sccfg: sccfg_next_node"
798 	    "(c=0x%p, previous=0x%p, next=0x%p)\n", c, previous, next));
799 
800 	cookie = (sc_gptwocfg_config_t *)c;
801 
802 	if (cookie == NULL) {
803 		cmn_err(CE_WARN, "sccfg: sccfg_next_node - "
804 		    "Invalid Cookie\n");
805 		return (0);
806 	}
807 	if (previous == NULL) {
808 		/*
809 		 * Start with the AXQ node.
810 		 */
811 		if (gptwocfg_next_node(cookie->port_cookie, NULL, &dip)) {
812 			*next = dip;
813 			return (1);
814 		} else {
815 			return (0);
816 		}
817 	}
818 
819 	while (cookie != NULL) {
820 		if (gptwocfg_next_node(cookie->port_cookie, previous, &dip)) {
821 			if ((dip == NULL) && (cookie->link == NULL)) {
822 				*next = NULL;
823 				return (1);
824 			}
825 			if (dip != NULL) {
826 				*next = dip;
827 				return (1);
828 			}
829 
830 			/* dip == NULL */
831 
832 			previous = NULL;
833 		}
834 		cookie = cookie->link;
835 	}
836 
837 	return (0);
838 }
839 
840 static dev_info_t *
841 sc_find_axq_node(uint_t axq_id)
842 {
843 	char *name;
844 	int size;
845 	gptwo_regspec_t *reg;
846 	dev_info_t *dip;
847 	uint_t id;
848 	int circ;
849 
850 	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: id=0x%x\n", axq_id));
851 
852 	/*
853 	 * Hold root node busy to walk its child list
854 	 */
855 	ndi_devi_enter(ddi_root_node(), &circ);
856 
857 	dip = ddi_get_child(ddi_root_node());
858 
859 	while (dip != NULL) {
860 
861 		SC_DEBUG(1, (CE_CONT, "Searching dip=0x%p for our AXQ\n",
862 		    dip));
863 
864 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
865 		    DDI_PROP_DONTPASS, "name", (caddr_t)&name, &size)
866 		    != DDI_PROP_SUCCESS) {
867 
868 			/*
869 			 * This node does not have a name property.
870 			 */
871 			SC_DEBUG(1, (CE_CONT, "dip=0x%p does not have a "
872 			    "'name' property\n", dip));
873 
874 			dip = ddi_get_next_sibling(dip);
875 			continue;
876 		}
877 
878 		SC_DEBUG(1, (CE_CONT, "dip=0x%p name=%s\n", dip, name));
879 
880 		if (strcmp(name, "address-extender-queue")) {
881 
882 			/*
883 			 * This node is not a AXQ node.
884 			 */
885 			SC_DEBUG(1, (CE_CONT, "dip=0x%p is not an AXQ "
886 			    "node\n", dip));
887 			kmem_free(name, size);
888 			dip = ddi_get_next_sibling(dip);
889 			continue;
890 		}
891 		kmem_free(name, size);
892 
893 		if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
894 		    DDI_PROP_DONTPASS, "reg", (caddr_t)&reg, &size)
895 		    != DDI_PROP_SUCCESS) {
896 
897 			/*
898 			 * This AXQ node does not have a reg property.
899 			 */
900 			SC_DEBUG(1, (CE_CONT, "dip=0x%p (AXQ Node) does "
901 			    "have a 'reg' property\n", dip));
902 			dip = ddi_get_next_sibling(dip);
903 			continue;
904 		}
905 
906 		id = ((reg[0].gptwo_phys_hi & 1) << 9) |
907 		    ((reg[0].gptwo_phys_low & 0xff800000) >> 23);
908 
909 		kmem_free(reg, size);
910 
911 		if (axq_id != id) {
912 
913 			/*
914 			 * This is the wrong AXQ node.
915 			 */
916 			SC_DEBUG(1, (CE_CONT, "dip=0x%p Wrong node id=0x%x\n",
917 			    dip, id));
918 
919 			dip = ddi_get_next_sibling(dip);
920 			continue;
921 
922 		}
923 
924 		/*
925 		 * The correct AXQ node was found.
926 		 */
927 		SC_DEBUG(1, (CE_CONT, "dip=0x%p Found AXQ Node\n", dip));
928 		ndi_hold_devi(dip);
929 		break;
930 	}
931 	ndi_devi_exit(ddi_root_node(), circ);
932 
933 	SC_DEBUG(1, (CE_CONT, "sc_find_axq_node: Returning 0x%p\n", dip));
934 
935 	return (dip);
936 }
937 
938 struct axq_arg {
939 	uint_t id;
940 	dev_info_t *axq_dip;
941 };
942 
943 /*ARGSUSED*/
944 static int
945 axq_set_prop(dev_info_t *axq_dip, void *arg, uint_t flags)
946 {
947 	struct axq_arg *aqp = (struct axq_arg *)arg;
948 	gptwo_regspec_t	reg[2];
949 	uint_t		id;
950 
951 	ASSERT(aqp);
952 
953 	id = aqp->id;
954 
955 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
956 	    "name", "address-extender-queue") != DDI_SUCCESS) {
957 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
958 		    "to create name property\n"));
959 		return (DDI_WALK_ERROR);
960 	}
961 
962 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
963 	    "device_type", "address-extender-queue") != DDI_SUCCESS) {
964 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
965 		    "to create device_type property\n"));
966 		return (DDI_WALK_ERROR);
967 	}
968 
969 	if (ndi_prop_update_string(DDI_DEV_T_NONE, axq_dip,
970 	    "compatible", "SUNW,axq") != DDI_SUCCESS) {
971 		SC_DEBUG(1, (CE_CONT, "sc_gptwocfg: failed "
972 		    "to create compatible property\n"));
973 		return (DDI_WALK_ERROR);
974 	}
975 
976 	if (ndi_prop_update_int(DDI_DEV_T_NONE, axq_dip,
977 	    "portid", id) != DDI_SUCCESS) {
978 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
979 		    "to create portid property\n"));
980 		return (DDI_WALK_ERROR);
981 	}
982 
983 	reg[0].gptwo_phys_hi = 0x400 | (id >> 9);
984 	reg[0].gptwo_phys_low = (id << 23);
985 	reg[0].gptwo_size_hi = 0;
986 	reg[0].gptwo_size_low = 0x520;
987 
988 	reg[1].gptwo_phys_hi = 0x401;
989 	reg[1].gptwo_phys_low = 0xf0000000;
990 	reg[1].gptwo_size_hi = 0;
991 	reg[1].gptwo_size_low = 0x520;
992 
993 	if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
994 	    axq_dip, "reg", (int *)&reg,
995 	    (sizeof (gptwo_regspec_t) * 2)/sizeof (int)) != DDI_SUCCESS) {
996 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_pci: failed "
997 		    "to create reg property\n"));
998 		return (DDI_WALK_ERROR);
999 	}
1000 
1001 	return (DDI_WALK_TERMINATE);
1002 }
1003 
1004 /*ARGSUSED*/
1005 static void
1006 get_axq_dip(dev_info_t *rdip, void *arg, uint_t flags)
1007 {
1008 	struct axq_arg *aqp = (struct axq_arg *)arg;
1009 
1010 	ASSERT(aqp);
1011 
1012 	aqp->axq_dip = rdip;
1013 }
1014 
1015 static gptwo_new_nodes_t *
1016 sc_gptwocfg_configure_axq(dev_info_t *ap, uint_t id, int create_nodes)
1017 {
1018 	struct axq_arg arg = {0};
1019 	devi_branch_t b = {0};
1020 	dev_info_t *axq_dip, *fdip = NULL;
1021 	gptwo_new_nodes_t *new_nodes = NULL;
1022 	int rv;
1023 
1024 	SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: id=0x%x "
1025 	    "create_nodes=%d\n", id, create_nodes));
1026 
1027 	if (!create_nodes) {
1028 		axq_dip = sc_find_axq_node(id);
1029 
1030 		if (axq_dip) {
1031 			new_nodes = gptwocfg_allocate_node_list(1);
1032 			new_nodes->gptwo_nodes[0] = axq_dip;
1033 			ASSERT(!e_ddi_branch_held(axq_dip));
1034 			e_ddi_branch_hold(axq_dip);
1035 			/*
1036 			 * Release hold from sc_find_axq_node()
1037 			 */
1038 			ddi_release_devi(axq_dip);
1039 		}
1040 
1041 		SC_DEBUG(1, (CE_CONT, "gptwocfg_configure_axq: "
1042 		    "Returning 0x%p\n", new_nodes));
1043 
1044 		return (new_nodes);
1045 	}
1046 
1047 	arg.id = id;
1048 	arg.axq_dip = NULL;
1049 
1050 	b.arg = &arg;
1051 	b.type = DEVI_BRANCH_SID;
1052 	b.create.sid_branch_create = axq_set_prop;
1053 	b.devi_branch_callback = get_axq_dip;
1054 
1055 	rv = e_ddi_branch_create(ap, &b, &fdip, DEVI_BRANCH_CONFIGURE);
1056 	if (rv != 0) {
1057 		char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1058 
1059 		/*
1060 		 * If non-NULL, fdip is held and must be released.
1061 		 */
1062 		if (fdip != NULL) {
1063 			(void) ddi_pathname(fdip, path);
1064 			ddi_release_devi(fdip);
1065 		} else {
1066 			(void) ddi_pathname(ap, path);
1067 		}
1068 
1069 		SC_DEBUG(1, (CE_WARN, "e_ddi_branch_create failed: "
1070 		    "path=%s, dip=%p, rv=%d", path, fdip ? (void *)fdip :
1071 		    (void *)ap, rv));
1072 
1073 		kmem_free(path, MAXPATHLEN);
1074 
1075 		return (NULL);
1076 	}
1077 
1078 	axq_dip = arg.axq_dip;
1079 
1080 	new_nodes = gptwocfg_allocate_node_list(1);
1081 	new_nodes->gptwo_nodes[0] = axq_dip;
1082 
1083 	return (new_nodes);
1084 }
1085 
1086 static gptwocfg_config_t *
1087 sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *config)
1088 {
1089 	int i;
1090 	int failure = 0;
1091 	dev_info_t *saf_dip;
1092 
1093 	if (config == NULL) {
1094 		cmn_err(CE_WARN, "sc_gptwocfg: sc_gptwocfg_unconfigure_axq: "
1095 		    "Invalid AXQ\n");
1096 		return (NULL);
1097 	}
1098 	for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) {
1099 		int rv;
1100 		dev_info_t *fdip = NULL;
1101 
1102 		saf_dip = config->gptwo_nodes->gptwo_nodes[i];
1103 		ASSERT(e_ddi_branch_held(saf_dip));
1104 		rv = e_ddi_branch_destroy(saf_dip, &fdip, 0);
1105 		if (rv != 0) {
1106 			char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1107 
1108 			/*
1109 			 * If non-NULL, fdip is held and must be released.
1110 			 */
1111 			if (fdip != NULL) {
1112 				(void) ddi_pathname(fdip, path);
1113 				ddi_release_devi(fdip);
1114 			} else {
1115 				(void) ddi_pathname(saf_dip, path);
1116 			}
1117 
1118 			cmn_err(CE_CONT, "AXQ node removal failed: "
1119 			    "path=%s, dip=%p, rv=%d\n", path,
1120 			    fdip ? (void *)fdip : (void *)saf_dip, rv);
1121 
1122 			kmem_free(path, MAXPATHLEN);
1123 			failure = 1;
1124 		} else {
1125 			config->gptwo_nodes->gptwo_nodes[i] = NULL;
1126 		}
1127 	}
1128 	if (!failure) {
1129 		gptwocfg_free_node_list(config->gptwo_nodes);
1130 
1131 		kmem_free(config, sizeof (gptwocfg_config_t));
1132 		config = NULL;
1133 	}
1134 	return (config);
1135 }
1136 
1137 static uint_t
1138 sc_get_agent_id(spcd_t *pcd, uint_t expander, uint_t slot, uint_t prd_slot)
1139 {
1140 	uint_t agent_id;
1141 
1142 	switch (pcd->spcd_ptype) {
1143 	case SAFPTYPE_CPU:
1144 		if (slot == 0) {
1145 			agent_id = prd_slot;
1146 		} else {
1147 			if (prd_slot == 4) {
1148 				agent_id = 8;
1149 			} else {
1150 				agent_id = 9;
1151 			}
1152 		}
1153 		break;
1154 
1155 	case SAFPTYPE_sPCI:
1156 	case SAFPTYPE_cPCI:
1157 	case SAFPTYPE_PCIX:
1158 		if (prd_slot == 4) {
1159 			agent_id = 0x1c;
1160 		} else {
1161 			agent_id = 0x1d;
1162 		}
1163 		break;
1164 	case SAFPTYPE_WCI:
1165 		agent_id = 0x1d;
1166 		break;
1167 	default:
1168 		cmn_err(CE_WARN, "sc_gptwocfg: Invalid Safari Port "
1169 		    "Type 0x%x Slot 0x%x\n",
1170 		    pcd->spcd_ptype, prd_slot);
1171 	} /* switch */
1172 
1173 	agent_id |= (expander << 5);
1174 
1175 	SC_DEBUG(1, (CE_CONT, "sc_get_agent_id(pcd=0x%p, expander=0x%x, "
1176 	    "prd_slot=0x%x) Returning agent_id=0x%x\n", pcd, expander,
1177 	    prd_slot, agent_id));
1178 
1179 	return (agent_id);
1180 }
1181 
1182 static void
1183 dump_config(sc_gptwocfg_config_t *board_config)
1184 {
1185 	gptwocfg_config_t *port;
1186 
1187 	SC_DEBUG(1, (CE_CONT, "dump_config 0x%p", board_config));
1188 	while (board_config != NULL) {
1189 		SC_DEBUG(1, (CE_CONT, "************* 0x%p ************\n",
1190 		    board_config));
1191 		SC_DEBUG(1, (CE_CONT, "port_cookie - 0x%p\n",
1192 		    board_config->port_cookie));
1193 
1194 		port = board_config->port_cookie;
1195 		if (port) {
1196 			SC_DEBUG(1, (CE_CONT, "     ap     - 0x%p\n",
1197 			    port->gptwo_ap));
1198 			SC_DEBUG(1, (CE_CONT, "     portid - 0x%x\n",
1199 			    port->gptwo_portid));
1200 		}
1201 		SC_DEBUG(1, (CE_CONT, "portid      - 0x%x\n",
1202 		    board_config->portid));
1203 		SC_DEBUG(1, (CE_CONT, "board      - 0x%x\n",
1204 		    board_config->board));
1205 		SC_DEBUG(1, (CE_CONT, "link        - 0x%p\n",
1206 		    board_config->link));
1207 		SC_DEBUG(1, (CE_CONT, "next        - 0x%p\n",
1208 		    board_config->next));
1209 		board_config = board_config->link;
1210 	}
1211 }
1212 
1213 static void
1214 dump_pcd(spcd_t *pcd)
1215 {
1216 	int i;
1217 
1218 	SC_DEBUG(1, (CE_CONT, "dump_pcd 0x%p", pcd));
1219 	SC_DEBUG(1, (CE_CONT, "     magic   - 0x%x\n", pcd->spcd_magic));
1220 	SC_DEBUG(1, (CE_CONT, "     version - 0x%x\n", pcd->spcd_version));
1221 	SC_DEBUG(1, (CE_CONT, "     ver.reg - 0x%lx\n", pcd->spcd_ver_reg));
1222 	SC_DEBUG(1, (CE_CONT, "     afreq   - %d\n", pcd->spcd_afreq));
1223 	switch (pcd->spcd_ptype) {
1224 	case SAFPTYPE_CPU:
1225 		SC_DEBUG(1, (CE_CONT, "     ptype   - CPU\n"));
1226 		break;
1227 	case SAFPTYPE_sPCI:
1228 		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI\n"));
1229 		break;
1230 	case SAFPTYPE_cPCI:
1231 		SC_DEBUG(1, (CE_CONT, "     ptype   - cPCI\n"));
1232 		break;
1233 	case SAFPTYPE_PCIX:
1234 		SC_DEBUG(1, (CE_CONT, "     ptype   - sPCI+\n"));
1235 		break;
1236 	case SAFPTYPE_WCI:
1237 		SC_DEBUG(1, (CE_CONT, "     ptype   - WIC\n"));
1238 		break;
1239 	default:
1240 		SC_DEBUG(1, (CE_CONT, "     ptype   - 0x%x\n",
1241 		    pcd->spcd_ptype));
1242 		break;
1243 	}
1244 	SC_DEBUG(1, (CE_CONT, "     cache   - %d\n", pcd->spcd_cache));
1245 
1246 	if (pcd->spcd_prsv == SPCD_RSV_PASS) {
1247 		SC_DEBUG(1, (CE_CONT, "     prsv    - SPCD_RSV_PASS\n"));
1248 	} else {
1249 		SC_DEBUG(1, (CE_CONT, "     prsv    - 0x%x (FAIL)\n",
1250 		    pcd->spcd_prsv));
1251 	}
1252 
1253 	for (i = 0; i < AGENTS_PER_PORT; i++) {
1254 		if (pcd->spcd_agent[i] == SPCD_RSV_PASS) {
1255 			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
1256 			    "- SPCD_RSV_PASS\n", i));
1257 		} else {
1258 			SC_DEBUG(1, (CE_CONT, "     agent[%d]    "
1259 			    "- 0x%x (FAIL)\n", i, pcd->spcd_agent[i]));
1260 		}
1261 	}
1262 
1263 	if (pcd->spcd_ptype == SAFPTYPE_CPU) {
1264 		for (i = 0; i < AGENTS_PER_PORT; i++) {
1265 			SC_DEBUG(1, (CE_CONT, "     cpuid[%d] - 0x%x\n",
1266 			    i, pcd->spcd_cpuid[i]));
1267 		}
1268 	}
1269 
1270 	SC_DEBUG(1, (CE_CONT, "     Banks\n"));
1271 	for (i = 0; i < MAX_BANKS_PER_PORT; i++) {
1272 		if (pcd->sprd_bank_rsv[i]) {
1273 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
1274 			    pcd->sprd_bank_rsv[i]));
1275 		}
1276 	}
1277 
1278 	SC_DEBUG(1, (CE_CONT, "     Dimms\n"));
1279 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
1280 		if (pcd->sprd_dimm[i]) {
1281 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
1282 			    pcd->sprd_dimm[i]));
1283 		}
1284 	}
1285 	SC_DEBUG(1, (CE_CONT, "     Ecache Dimm Labels\n"));
1286 	for (i = 0; i < MAX_DIMMS_PER_PORT; i++) {
1287 		if (pcd->sprd_ecache_dimm_label[i]) {
1288 			SC_DEBUG(1, (CE_CONT, "       %d %s\n", i,
1289 			    pcd->sprd_ecache_dimm_label[i]));
1290 		}
1291 	}
1292 }
1293 
1294 
1295 typedef struct {
1296 	char Jnumber[8][8];
1297 	uint8_t sym_flag;
1298 	uint8_t d_dimmtable[144];
1299 	uint8_t d_pintable[576];
1300 }m_layout;
1301 
1302 /*
1303  * Use 2 bits to represent each bit at a cache line. The table
1304  * is in big endian order, i.e.
1305  *      dimmtable[0], ... , dimmtable[143]
1306  * Q0:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
1307  *                      .
1308  *                      .
1309  * Q3:data-bits[127 126 125 124], ... , MtagEcc[3 2 1 0]
1310  */
1311 uint8_t J_dimm_pinTable[] = {
1312 /* Jnumber */
1313 /*  0 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x30, 0x00, 0x00,
1314 /*  1 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x30, 0x00, 0x00,
1315 /*  2 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x30, 0x00, 0x00,
1316 /*  3 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x30, 0x00, 0x00,
1317 /*  4 */	0x4a, 0x31, 0x33, 0x33, 0x30, 0x31, 0x00, 0x00,
1318 /*  5 */	0x4a, 0x31, 0x33, 0x34, 0x30, 0x31, 0x00, 0x00,
1319 /*  6 */	0x4a, 0x31, 0x33, 0x35, 0x30, 0x31, 0x00, 0x00,
1320 /*  7 */	0x4a, 0x31, 0x33, 0x36, 0x30, 0x31, 0x00, 0x00,
1321 /* flag */	0x01,
1322 /*  -- Q0 --  */
1323 /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
1324 /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
1325 /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
1326 /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
1327 /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
1328 /*  -- Q1 --  */
1329 /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
1330 /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
1331 /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
1332 /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
1333 /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
1334 /*  -- Q2 --  */
1335 /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
1336 /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
1337 /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
1338 /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
1339 /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
1340 /*  -- Q3 --  */
1341 /*  0 */	0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa, 0xff,
1342 /*  1 */	0x00, 0xaa, 0xff, 0x00, 0x56, 0xaf, 0x00, 0x55,
1343 /*  2 */	0xaa, 0x55, 0xaf, 0xc0, 0x55, 0xaa, 0xff, 0x00,
1344 /*  3 */	0x55, 0xff, 0x00, 0x55, 0xaa, 0xff, 0x6d, 0x80,
1345 /*  4 */	0xe7, 0xe3, 0x9b, 0x1b,
1346 /*
1347  * In the following order
1348  *      pintable[0], ..., pintable[575]
1349  * Quadword3, Quadword2, Quadword1, Quadword0
1350  *      MtagEcc, Mtag, Ecc, Data
1351  */
1352 /* -- Q3 -- */
1353 /*  0  */	227, 227, 227, 227, 111, 111, 111,  22,
1354 /*  1  */	22,  32, 138, 222,  81, 117, 117, 117,
1355 /*  2  */	111, 222, 106, 222, 222, 106, 106, 106,
1356 /*  3  */	217, 101, 212,  96, 217, 101, 212,  96,
1357 /*  4  */	217, 101, 212,  96, 217, 101, 212,  96,
1358 /*  5  */	207,  91, 202,  86, 187,  71, 158,  42,
1359 /*  6  */	187,  71, 158,  42, 153,  37, 148,  32,
1360 /*  7  */	153,  37, 148,  32, 153,  37, 148,  32,
1361 /*  8  */	153,  37, 148, 143,  27, 138, 143,  27,
1362 /*  9  */	143,  27, 138,  22, 207,  91, 202,  86,
1363 /*  10 */	207,  91, 202,  86, 207,  91, 202,  86,
1364 /*  11 */	192,  76,  81, 192,  76,  81, 192,  76,
1365 /*  12 */	197,  81, 192,  76, 187,  71, 158,  42,
1366 /*  13 */	187,  71, 158,  42, 143,  27, 138,  22,
1367 /*  14 */	133,  17, 128,  12, 133,  17, 128,  12,
1368 /*  15 */	133,  17, 128,  12, 133,  17, 128,  12,
1369 /*  16 */	123,  07, 118,   2, 123,  07, 118,   2,
1370 /*  17 */	123,  07, 118,   2, 123,  07, 118,   2,
1371 /* -- Q2 -- */
1372 /*  0  */	228, 228, 228, 228, 112, 112, 112,  23,
1373 /*  1  */	23,  33, 139, 223,  82, 118, 118, 118,
1374 /*  2  */	112, 223, 107, 223, 223, 107, 107, 107,
1375 /*  3  */	218, 102, 213,  97, 218, 102, 213,  97,
1376 /*  4  */	218, 102, 213,  97, 218, 102, 213,  97,
1377 /*  5  */	208,  92, 203,  87, 188,  72, 159,  43,
1378 /*  6  */	188,  72, 159,  43, 154,  38, 149,  33,
1379 /*  7  */	154,  38, 149,  33, 154,  38, 149,  33,
1380 /*  8  */	154,  38, 149, 144,  28, 139, 144,  28,
1381 /*  9  */	144,  28, 139,  23, 208,  92, 203,  87,
1382 /*  10 */	208,  92, 203,  87, 208,  92, 203,  87,
1383 /*  11 */	193,  77,  82, 193,  77,  82, 193,  77,
1384 /*  12 */	198,  82, 193,  77, 188,  72, 159,  43,
1385 /*  13 */	188,  72, 159,  43, 144,  28, 139,  23,
1386 /*  14 */	134,  18, 129,  13, 134,  18, 129,  13,
1387 /*  15 */	134,  18, 129,  13, 134,  18, 129,  13,
1388 /*  16 */	124,   8, 119,   3, 124,   8, 119,   3,
1389 /*  17 */	124,   8, 119,   3, 124,   8, 119,   3,
1390 /* -- Q1 -- */
1391 /*  0  */	229, 229, 229, 229, 113, 113, 113,  24,
1392 /*  1  */	24,  34, 140, 224,  83, 119, 119, 119,
1393 /*  2  */	113, 224, 108, 224, 224, 108, 108, 108,
1394 /*  3  */	219, 103, 214,  98, 219, 103, 214,  98,
1395 /*  4  */	219, 103, 214,  98, 219, 103, 214,  98,
1396 /*  5  */	209,  93, 204,  88, 189,  73, 160,  44,
1397 /*  6  */	189,  73, 160,  44, 155,  39, 150,  34,
1398 /*  7  */	155,  39, 150,  34, 155,  39, 150,  34,
1399 /*  8  */	155,  39, 150, 145,  29, 140, 145,  29,
1400 /*  9  */	145,  29, 140,  24, 209,  93, 204,  88,
1401 /*  10 */	209,  93, 204,  88, 209,  93, 204,  88,
1402 /*  11 */	194,  78,  83, 194,  78,  83, 194,  78,
1403 /*  12 */	199,  83, 194,  78, 189,  73, 160,  44,
1404 /*  13 */	189,  73, 160,  44, 145,  29, 140,  24,
1405 /*  14 */	135,  19, 130,  14, 135,  19, 130,  14,
1406 /*  15 */	135,  19, 130,  14, 135,  19, 130,  14,
1407 /*  16 */	125,   9, 120,   4, 125,   9, 120,   4,
1408 /*  17 */	125,   9, 120,   4, 125,   9, 120,   4,
1409 /* -- Q0 -- */
1410 /*  0  */	230, 230, 230, 230, 114, 114, 114,  25,
1411 /*  1  */	25,  35, 141, 225,  84, 200, 200, 200,
1412 /*  2  */	114, 225, 109, 225, 225, 109, 109, 109,
1413 /*  3  */	220, 104, 215,  99, 220, 104, 215,  99,
1414 /*  4  */	220, 104, 215,  99, 220, 104, 215,  99,
1415 /*  5  */	210,  94, 205,  89, 190,  74, 161,  45,
1416 /*  6  */	190,  74, 161,  45, 156,  40, 151,  35,
1417 /*  7  */	156,  40, 151,  35, 156,  40, 151,  35,
1418 /*  8  */	156,  40, 151, 146,  30, 141, 146,  30,
1419 /*  9  */	146,  30, 141,  25, 210,  94, 205,  89,
1420 /*  10 */	210,  94, 205,  89, 210,  94, 205,  89,
1421 /*  11 */	195,  79,  84, 195,  79,  84, 195,  79,
1422 /*  12 */	200,  84, 195,  79, 190,  74, 161,  45,
1423 /*  13 */	190,  74, 161,  45, 146,  30, 141,  25,
1424 /*  14 */	136,  20, 131,  15, 136,  20, 131,  15,
1425 /*  15 */	136,  20, 131,  15, 136,  20, 131,  15,
1426 /*  16 */	126,  10, 121,   5, 126,  10, 121,   5,
1427 /*  17 */	126,  10, 121,   5, 126,  10, 121,   5
1428 };
1429 
1430 /*
1431  *  This table is for internal reference
1432  *
1433  * pintable_internal[]= {
1434  * -- Q0 --
1435  * 0  143,143,143,143,139,139,139,35
1436  * 1  35,51,39,135,91,95,95,95
1437  * 2  139,135,131,135,135,131,131,131
1438  * 3  127,123,119,115,127,123,119,115
1439  * 4  127,123,119,115,127,123,119,115
1440  * 5  111,107,103,99,79,75,71,67
1441  * 6  79,75,71,67,63,59,55,51
1442  * 7  63,59,55,51,63,59,55,51
1443  * 8  63,59,55,47,43,39,47,43
1444  * 9  47,43,39,35,111,107,103,99
1445  * 10  111,107,103,99,111,107,103,99
1446  * 11  87,83,91,87,83,91,87,83
1447  * 12  95,91,87,83,79,75,71,67
1448  * 13  79,75,71,67,47,43,39,35
1449  * 14  31,27,23,19,31,27,23,19
1450  * 15  31,27,23,19,31,27,23,19
1451  * 16  15,11,7,3,15,11,7,3
1452  * 17  15,11,7,3,15,11,7,3
1453  * }
1454  */
1455 
1456 char *dimm_Jno[] = {
1457 /* P0 */	"J13300", "J13400", "J13500", "J13600",
1458 		"J13301", "J13401", "J13501", "J13601",
1459 /* P1 */	"J14300", "J14400", "J14500", "J14600",
1460 		"J14301", "J14401", "J14501", "J14601",
1461 /* P2 */	"J15300", "J15400", "J15500", "J15600",
1462 		"J15301", "J15401", "J15501", "J15601",
1463 /* P3 */	"J16300", "J16400", "J16500", "J16600",
1464 		"J16301", "J16401", "J16501", "J16601",
1465 		NULL
1466 	};
1467 
1468 
1469 static uint8_t *
1470 get_memlayout(uint32_t cpuid, uint32_t *len)
1471 {
1472 	m_layout *LayoutBuf;
1473 
1474 	if ((LayoutBuf = (m_layout *)kmem_zalloc(sizeof (m_layout),
1475 	    KM_SLEEP)) == NULL) {
1476 		*len = 0;
1477 		return (NULL);
1478 	}
1479 
1480 	bcopy(J_dimm_pinTable, LayoutBuf, sizeof (m_layout));
1481 
1482 	*len = sizeof (m_layout);
1483 	cpuid &= 0x03;	/* last 2 bits of a 10 bit number */
1484 
1485 	bcopy(dimm_Jno[cpuid << 3], LayoutBuf->Jnumber[0], 64);
1486 
1487 	return ((uint8_t *)LayoutBuf);
1488 }
1489 
1490 static char *
1491 rsv_string(prdrsv_t rsv)
1492 {
1493 	char *buffer;
1494 	char *status;
1495 
1496 	switch (rsv) {
1497 	case RSV_UNKNOWN:
1498 		buffer = "unknown";
1499 		break;
1500 	case RSV_PRESENT:
1501 		buffer = "okay";
1502 		break;
1503 	case RSV_CRUNCH:
1504 		buffer = "disabled";
1505 		break;
1506 	case RSV_UNDEFINED:
1507 		buffer = "undefined";
1508 		break;
1509 	case RSV_MISS:
1510 		buffer = "missing";
1511 		break;
1512 	case RSV_EMPTY_CASSETTE:
1513 		buffer = "disabled";
1514 		break;
1515 	case RSV_MISCONFIG:
1516 		buffer = "misconfigured";
1517 		break;
1518 	case RSV_FAIL_OBP:
1519 		buffer = "fail-obp";
1520 		break;
1521 	case RSV_BLACK:
1522 		buffer = "blacklisted";
1523 		break;
1524 	case RSV_RED:
1525 		buffer = "redlisted";
1526 		break;
1527 	case RSV_EXCLUDED:
1528 		buffer = "disabled";
1529 		break;
1530 	case RSV_UNCONFIG:
1531 		buffer = "disabled";
1532 		break;
1533 	case RSV_PASS:
1534 		buffer = "okay";
1535 		break;
1536 	case RSV_FAIL:
1537 	default:
1538 		buffer = "fail";
1539 		break;
1540 	}
1541 
1542 	status = kmem_alloc(strlen(buffer) + 1, KM_SLEEP);
1543 	(void) strcpy(status, buffer);
1544 
1545 	return (status);
1546 }
1547