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