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
51int sc_gptwocfg_debug = 0;
52
53#define	SC_DEBUG(level, args) if (sc_gptwocfg_debug >= level) cmn_err args
54
55typedef 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
63static kmutex_t sc_gptwo_config_list_lock;
64static sc_gptwocfg_config_t *sc_gptwo_config_list;
65static dev_info_t *sc_find_axq_node(uint_t);
66static sc_gptwocfg_cookie_t sc_configure(uint_t, int);
67static spcd_t *sc_get_common_pcd(uint_t, uint_t);
68static void sc_free_common_pcd(spcd_t *);
69static gptwo_new_nodes_t *sc_gptwocfg_configure_axq(dev_info_t *, uint_t, int);
70static gptwocfg_config_t *sc_gptwocfg_unconfigure_axq(gptwocfg_config_t *);
71static void dump_config(sc_gptwocfg_config_t *);
72static void dump_pcd(spcd_t *);
73static uint_t sc_get_agent_id(spcd_t *, uint_t, uint_t, uint_t);
74static char *rsv_string(prdrsv_t);
75
76extern gptwo_new_nodes_t *gptwocfg_allocate_node_list(int);
77extern void gptwocfg_free_node_list(gptwo_new_nodes_t *);
78
79static uint8_t *get_memlayout(uint32_t, uint32_t *);
80
81#ifdef NO_IOSRAM
82int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
83#else
84extern int iosram_rd(uint32_t, uint32_t, uint32_t, caddr_t);
85#endif
86extern void gptwocfg_devi_attach_to_parent(dev_info_t *);
87
88/*
89 * Module control operations
90 */
91
92extern struct mod_ops mod_miscops;
93
94static struct modlmisc modlmisc = {
95	&mod_miscops, /* Type of module */
96	"Sun Fire 15000 gptwocfg"
97};
98
99static struct modlinkage modlinkage = {
100	MODREV_1, (void *)&modlmisc, NULL
101};
102
103int
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
125int
126_fini(void)
127{
128	mutex_destroy(&sc_gptwo_config_list_lock);
129	return (mod_remove(&modlinkage));
130}
131
132int
133_info(modinfop)
134struct modinfo *modinfop;
135{
136	return (mod_info(&modlinkage, modinfop));
137}
138
139static spcd_t *
140sc_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
440void
441sc_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
481sc_gptwocfg_cookie_t
482sc_probe_board(uint_t board)
483{
484	return (sc_configure(board, 1));
485}
486
487static sc_gptwocfg_cookie_t
488sc_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
679sc_gptwocfg_cookie_t
680sc_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
789int
790sc_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
839static dev_info_t *
840sc_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
939struct axq_arg {
940	uint_t id;
941	dev_info_t *axq_dip;
942};
943
944/*ARGSUSED*/
945static int
946axq_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*/
1006static void
1007get_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
1016static gptwo_new_nodes_t *
1017sc_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
1087static gptwocfg_config_t *
1088sc_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
1138static uint_t
1139sc_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
1183static void
1184dump_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
1214static void
1215dump_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
1296typedef 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 */
1312uint8_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
1457char *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
1470static uint8_t *
1471get_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
1491static char *
1492rsv_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