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