xref: /titanic_50/usr/src/uts/sun4u/opl/io/mc-opl.c (revision 2df1fe9ca32bb227b9158c67f5c00b54c20b10fd)
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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*
26  * All Rights Reserved, Copyright (c) FUJITSU LIMITED 2006
27  */
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/conf.h>
34 #include <sys/modctl.h>
35 #include <sys/stat.h>
36 #include <sys/async.h>
37 #include <sys/machcpuvar.h>
38 #include <sys/machsystm.h>
39 #include <sys/promif.h>
40 #include <sys/ksynch.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/sunndi.h>
44 #include <sys/ddifm.h>
45 #include <sys/fm/protocol.h>
46 #include <sys/fm/util.h>
47 #include <sys/kmem.h>
48 #include <sys/fm/io/opl_mc_fm.h>
49 #include <sys/memlist.h>
50 #include <sys/param.h>
51 #include <sys/disp.h>
52 #include <vm/page.h>
53 #include <sys/mc-opl.h>
54 #include <sys/opl.h>
55 #include <sys/opl_dimm.h>
56 #include <sys/scfd/scfostoescf.h>
57 #include <sys/cpu_module.h>
58 #include <vm/seg_kmem.h>
59 #include <sys/vmem.h>
60 #include <vm/hat_sfmmu.h>
61 #include <sys/vmsystm.h>
62 #include <sys/membar.h>
63 
64 /*
65  * Function prototypes
66  */
67 static int mc_open(dev_t *, int, int, cred_t *);
68 static int mc_close(dev_t, int, int, cred_t *);
69 static int mc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
70 static int mc_attach(dev_info_t *, ddi_attach_cmd_t);
71 static int mc_detach(dev_info_t *, ddi_detach_cmd_t);
72 
73 static int mc_poll_init(void);
74 static void mc_poll_fini(void);
75 static int mc_board_add(mc_opl_t *mcp);
76 static int mc_board_del(mc_opl_t *mcp);
77 static int mc_suspend(mc_opl_t *mcp, uint32_t flag);
78 static int mc_resume(mc_opl_t *mcp, uint32_t flag);
79 int opl_mc_suspend(void);
80 int opl_mc_resume(void);
81 
82 static void insert_mcp(mc_opl_t *mcp);
83 static void delete_mcp(mc_opl_t *mcp);
84 
85 static int pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr);
86 
87 static int mc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa);
88 
89 int mc_get_mem_unum(int, uint64_t, char *, int, int *);
90 int mc_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *paddr);
91 int mc_get_mem_offset(uint64_t paddr, uint64_t *offp);
92 int mc_get_mem_sid(char *unum, char *buf, int buflen, int *lenp);
93 int mc_get_mem_sid_dimm(mc_opl_t *mcp, char *dname, char *buf,
94     int buflen, int *lenp);
95 mc_dimm_info_t *mc_get_dimm_list(mc_opl_t *mcp);
96 mc_dimm_info_t *mc_prepare_dimmlist(board_dimm_info_t *bd_dimmp);
97 int mc_set_mem_sid(mc_opl_t *mcp, char *buf, int buflen, int lsb, int bank,
98     uint32_t mf_type, uint32_t d_slot);
99 static void mc_free_dimm_list(mc_dimm_info_t *d);
100 static void mc_get_mlist(mc_opl_t *);
101 static void mc_polling(void);
102 static int mc_opl_get_physical_board(int);
103 
104 #ifdef	DEBUG
105 static int mc_ioctl_debug(dev_t, int, intptr_t, int, cred_t *, int *);
106 void mc_dump_dimm(char *buf, int dnamesz, int serialsz, int partnumsz);
107 void mc_dump_dimm_info(board_dimm_info_t *bd_dimmp);
108 #endif
109 
110 #pragma weak opl_get_physical_board
111 extern int opl_get_physical_board(int);
112 extern int plat_max_boards(void);
113 
114 /*
115  * Configuration data structures
116  */
117 static struct cb_ops mc_cb_ops = {
118 	mc_open,			/* open */
119 	mc_close,			/* close */
120 	nulldev,			/* strategy */
121 	nulldev,			/* print */
122 	nodev,				/* dump */
123 	nulldev,			/* read */
124 	nulldev,			/* write */
125 	mc_ioctl,			/* ioctl */
126 	nodev,				/* devmap */
127 	nodev,				/* mmap */
128 	nodev,				/* segmap */
129 	nochpoll,			/* poll */
130 	ddi_prop_op,			/* cb_prop_op */
131 	0,				/* streamtab */
132 	D_MP | D_NEW | D_HOTPLUG,	/* Driver compatibility flag */
133 	CB_REV,				/* rev */
134 	nodev,				/* cb_aread */
135 	nodev				/* cb_awrite */
136 };
137 
138 static struct dev_ops mc_ops = {
139 	DEVO_REV,			/* rev */
140 	0,				/* refcnt  */
141 	ddi_getinfo_1to1,		/* getinfo */
142 	nulldev,			/* identify */
143 	nulldev,			/* probe */
144 	mc_attach,			/* attach */
145 	mc_detach,			/* detach */
146 	nulldev,			/* reset */
147 	&mc_cb_ops,			/* cb_ops */
148 	(struct bus_ops *)0,		/* bus_ops */
149 	nulldev				/* power */
150 };
151 
152 /*
153  * Driver globals
154  */
155 
156 static enum {
157 	MODEL_FF1 = 0,
158 	MODEL_FF2 = 1,
159 	MODEL_DC = 2
160 } plat_model = MODEL_DC;	/* The default behaviour is DC */
161 
162 static struct plat_model_names {
163 	const char *unit_name;
164 	const char *mem_name;
165 } model_names[] = {
166 	{ "MBU_A", "MEMB" },
167 	{ "MBU_B", "MEMB" },
168 	{ "CMU", "" }
169 };
170 
171 /*
172  * The DIMM Names for DC platform.
173  * The index into this table is made up of (bank, dslot),
174  * Where dslot occupies bits 0-1 and bank occupies 2-4.
175  */
176 static char *mc_dc_dimm_unum_table[OPL_MAX_DIMMS] = {
177 	/* --------CMUnn----------- */
178 	/* --CS0-----|--CS1------ */
179 	/* -H-|--L-- | -H- | -L-- */
180 	"03A", "02A", "03B", "02B", /* Bank 0 (MAC 0 bank 0) */
181 	"13A", "12A", "13B", "12B", /* Bank 1 (MAC 0 bank 1) */
182 	"23A", "22A", "23B", "22B", /* Bank 2 (MAC 1 bank 0) */
183 	"33A", "32A", "33B", "32B", /* Bank 3 (MAC 1 bank 1) */
184 	"01A", "00A", "01B", "00B", /* Bank 4 (MAC 2 bank 0) */
185 	"11A", "10A", "11B", "10B", /* Bank 5 (MAC 2 bank 1) */
186 	"21A", "20A", "21B", "20B", /* Bank 6 (MAC 3 bank 0) */
187 	"31A", "30A", "31B", "30B"  /* Bank 7 (MAC 3 bank 1) */
188 };
189 
190 /*
191  * The DIMM Names for FF1/FF2 platforms.
192  * The index into this table is made up of (board, bank, dslot),
193  * Where dslot occupies bits 0-1, bank occupies 2-4 and
194  * board occupies the bit 5.
195  */
196 static char *mc_ff_dimm_unum_table[2 * OPL_MAX_DIMMS] = {
197 	/* --------CMU0---------- */
198 	/* --CS0-----|--CS1------ */
199 	/* -H-|--L-- | -H- | -L-- */
200 	"03A", "02A", "03B", "02B", /* Bank 0 (MAC 0 bank 0) */
201 	"01A", "00A", "01B", "00B", /* Bank 1 (MAC 0 bank 1) */
202 	"13A", "12A", "13B", "12B", /* Bank 2 (MAC 1 bank 0) */
203 	"11A", "10A", "11B", "10B", /* Bank 3 (MAC 1 bank 1) */
204 	"23A", "22A", "23B", "22B", /* Bank 4 (MAC 2 bank 0) */
205 	"21A", "20A", "21B", "20B", /* Bank 5 (MAC 2 bank 1) */
206 	"33A", "32A", "33B", "32B", /* Bank 6 (MAC 3 bank 0) */
207 	"31A", "30A", "31B", "30B", /* Bank 7 (MAC 3 bank 1) */
208 	/* --------CMU1---------- */
209 	/* --CS0-----|--CS1------ */
210 	/* -H-|--L-- | -H- | -L-- */
211 	"43A", "42A", "43B", "42B", /* Bank 0 (MAC 0 bank 0) */
212 	"41A", "40A", "41B", "40B", /* Bank 1 (MAC 0 bank 1) */
213 	"53A", "52A", "53B", "52B", /* Bank 2 (MAC 1 bank 0) */
214 	"51A", "50A", "51B", "50B", /* Bank 3 (MAC 1 bank 1) */
215 	"63A", "62A", "63B", "62B", /* Bank 4 (MAC 2 bank 0) */
216 	"61A", "60A", "61B", "60B", /* Bank 5 (MAC 2 bank 1) */
217 	"73A", "72A", "73B", "72B", /* Bank 6 (MAC 3 bank 0) */
218 	"71A", "70A", "71B", "70B"  /* Bank 7 (MAC 3 bank 1) */
219 };
220 
221 #define	BD_BK_SLOT_TO_INDEX(bd, bk, s)			\
222 	(((bd & 0x01) << 5) | ((bk & 0x07) << 2) | (s & 0x03))
223 
224 #define	INDEX_TO_BANK(i)			(((i) & 0x1C) >> 2)
225 #define	INDEX_TO_SLOT(i)			((i) & 0x03)
226 
227 #define	SLOT_TO_CS(slot)	((slot & 0x3) >> 1)
228 
229 /* Isolation unit size is 64 MB */
230 #define	MC_ISOLATION_BSIZE	(64 * 1024 * 1024)
231 
232 #define	MC_MAX_SPEEDS 7
233 
234 typedef struct {
235 	uint32_t mc_speeds;
236 	uint32_t mc_period;
237 } mc_scan_speed_t;
238 
239 #define	MC_CNTL_SPEED_SHIFT 26
240 
241 /*
242  * In mirror mode, we normalized the bank idx to "even" since
243  * the HW treats them as one unit w.r.t programming.
244  * This bank index will be the "effective" bank index.
245  * All mirrored bank state info on mc_period, mc_speedup_period
246  * will be stored in the even bank structure to avoid code duplication.
247  */
248 #define	MIRROR_IDX(bankidx)	(bankidx & ~1)
249 
250 static mc_scan_speed_t	mc_scan_speeds[MC_MAX_SPEEDS] = {
251 	{0x6 << MC_CNTL_SPEED_SHIFT, 0},
252 	{0x5 << MC_CNTL_SPEED_SHIFT, 32},
253 	{0x4 << MC_CNTL_SPEED_SHIFT, 64},
254 	{0x3 << MC_CNTL_SPEED_SHIFT, 128},
255 	{0x2 << MC_CNTL_SPEED_SHIFT, 256},
256 	{0x1 << MC_CNTL_SPEED_SHIFT, 512},
257 	{0x0 << MC_CNTL_SPEED_SHIFT, 1024}
258 };
259 
260 static uint32_t	mc_max_speed = (0x6 << 26);
261 
262 int mc_isolation_bsize = MC_ISOLATION_BSIZE;
263 int mc_patrol_interval_sec = MC_PATROL_INTERVAL_SEC;
264 int mc_max_scf_retry = 16;
265 int mc_max_scf_logs = 64;
266 int mc_max_errlog_processed = BANKNUM_PER_SB*2;
267 int mc_scan_period = 12 * 60 * 60;	/* 12 hours period */
268 int mc_max_rewrite_loop = 100;
269 int mc_rewrite_delay = 10;
270 /*
271  * it takes SCF about 300 m.s. to process a requst.  We can bail out
272  * if it is busy.  It does not pay to wait for it too long.
273  */
274 int mc_max_scf_loop = 2;
275 int mc_scf_delay = 100;
276 int mc_pce_dropped = 0;
277 int mc_poll_priority = MINCLSYSPRI;
278 
279 
280 /*
281  * Mutex hierarchy in mc-opl
282  * If both mcmutex and mc_lock must be held,
283  * mcmutex must be acquired first, and then mc_lock.
284  */
285 
286 static kmutex_t mcmutex;
287 mc_opl_t *mc_instances[OPL_MAX_BOARDS];
288 
289 static kmutex_t mc_polling_lock;
290 static kcondvar_t mc_polling_cv;
291 static kcondvar_t mc_poll_exit_cv;
292 static int mc_poll_cmd = 0;
293 static int mc_pollthr_running = 0;
294 int mc_timeout_period = 0; /* this is in m.s. */
295 void *mc_statep;
296 
297 #ifdef	DEBUG
298 int oplmc_debug = 0;
299 #endif
300 
301 static int mc_debug_show_all = 0;
302 
303 extern struct mod_ops mod_driverops;
304 
305 static struct modldrv modldrv = {
306 	&mod_driverops,			/* module type, this one is a driver */
307 	"OPL Memory-controller %I%",	/* module name */
308 	&mc_ops,			/* driver ops */
309 };
310 
311 static struct modlinkage modlinkage = {
312 	MODREV_1,		/* rev */
313 	(void *)&modldrv,
314 	NULL
315 };
316 
317 #pragma weak opl_get_mem_unum
318 #pragma weak opl_get_mem_sid
319 #pragma weak opl_get_mem_offset
320 #pragma weak opl_get_mem_addr
321 
322 extern int (*opl_get_mem_unum)(int, uint64_t, char *, int, int *);
323 extern int (*opl_get_mem_sid)(char *unum, char *buf, int buflen, int *lenp);
324 extern int (*opl_get_mem_offset)(uint64_t paddr, uint64_t *offp);
325 extern int (*opl_get_mem_addr)(char *unum, char *sid, uint64_t offset,
326     uint64_t *paddr);
327 
328 
329 /*
330  * pseudo-mc node portid format
331  *
332  *		[10]   = 0
333  *		[9]    = 1
334  *		[8]    = LSB_ID[4] = 0
335  *		[7:4]  = LSB_ID[3:0]
336  *		[3:0]  = 0
337  *
338  */
339 
340 /*
341  * These are the module initialization routines.
342  */
343 int
344 _init(void)
345 {
346 	int	error;
347 	int	plen;
348 	char	model[20];
349 	pnode_t	node;
350 
351 
352 	if ((error = ddi_soft_state_init(&mc_statep,
353 	    sizeof (mc_opl_t), 1)) != 0)
354 		return (error);
355 
356 	if ((error = mc_poll_init()) != 0) {
357 		ddi_soft_state_fini(&mc_statep);
358 		return (error);
359 	}
360 
361 	mutex_init(&mcmutex, NULL, MUTEX_DRIVER, NULL);
362 	if (&opl_get_mem_unum)
363 		opl_get_mem_unum = mc_get_mem_unum;
364 	if (&opl_get_mem_sid)
365 		opl_get_mem_sid = mc_get_mem_sid;
366 	if (&opl_get_mem_offset)
367 		opl_get_mem_offset = mc_get_mem_offset;
368 	if (&opl_get_mem_addr)
369 		opl_get_mem_addr = mc_get_mem_addr;
370 
371 	node = prom_rootnode();
372 	plen = prom_getproplen(node, "model");
373 
374 	if (plen > 0 && plen < sizeof (model)) {
375 		(void) prom_getprop(node, "model", model);
376 		model[plen] = '\0';
377 		if (strcmp(model, "FF1") == 0)
378 			plat_model = MODEL_FF1;
379 		else if (strcmp(model, "FF2") == 0)
380 			plat_model = MODEL_FF2;
381 		else if (strncmp(model, "DC", 2) == 0)
382 			plat_model = MODEL_DC;
383 	}
384 
385 	error =  mod_install(&modlinkage);
386 	if (error != 0) {
387 		if (&opl_get_mem_unum)
388 			opl_get_mem_unum = NULL;
389 		if (&opl_get_mem_sid)
390 			opl_get_mem_sid = NULL;
391 		if (&opl_get_mem_offset)
392 			opl_get_mem_offset = NULL;
393 		if (&opl_get_mem_addr)
394 			opl_get_mem_addr = NULL;
395 		mutex_destroy(&mcmutex);
396 		mc_poll_fini();
397 		ddi_soft_state_fini(&mc_statep);
398 	}
399 	return (error);
400 }
401 
402 int
403 _fini(void)
404 {
405 	int error;
406 
407 	if ((error = mod_remove(&modlinkage)) != 0)
408 		return (error);
409 
410 	if (&opl_get_mem_unum)
411 		opl_get_mem_unum = NULL;
412 	if (&opl_get_mem_sid)
413 		opl_get_mem_sid = NULL;
414 	if (&opl_get_mem_offset)
415 		opl_get_mem_offset = NULL;
416 	if (&opl_get_mem_addr)
417 		opl_get_mem_addr = NULL;
418 
419 	mutex_destroy(&mcmutex);
420 	mc_poll_fini();
421 	ddi_soft_state_fini(&mc_statep);
422 
423 	return (0);
424 }
425 
426 int
427 _info(struct modinfo *modinfop)
428 {
429 	return (mod_info(&modlinkage, modinfop));
430 }
431 
432 static void
433 mc_polling_thread()
434 {
435 	mutex_enter(&mc_polling_lock);
436 	mc_pollthr_running = 1;
437 	while (!(mc_poll_cmd & MC_POLL_EXIT)) {
438 		mc_polling();
439 		cv_timedwait(&mc_polling_cv, &mc_polling_lock,
440 		    ddi_get_lbolt() + mc_timeout_period);
441 	}
442 	mc_pollthr_running = 0;
443 
444 	/*
445 	 * signal if any one is waiting for this thread to exit.
446 	 */
447 	cv_signal(&mc_poll_exit_cv);
448 	mutex_exit(&mc_polling_lock);
449 	thread_exit();
450 	/* NOTREACHED */
451 }
452 
453 static int
454 mc_poll_init()
455 {
456 	mutex_init(&mc_polling_lock, NULL, MUTEX_DRIVER, NULL);
457 	cv_init(&mc_polling_cv, NULL, CV_DRIVER, NULL);
458 	cv_init(&mc_poll_exit_cv, NULL, CV_DRIVER, NULL);
459 	return (0);
460 }
461 
462 static void
463 mc_poll_fini()
464 {
465 	mutex_enter(&mc_polling_lock);
466 	if (mc_pollthr_running) {
467 		mc_poll_cmd = MC_POLL_EXIT;
468 		cv_signal(&mc_polling_cv);
469 		while (mc_pollthr_running) {
470 			cv_wait(&mc_poll_exit_cv, &mc_polling_lock);
471 		}
472 	}
473 	mutex_exit(&mc_polling_lock);
474 	mutex_destroy(&mc_polling_lock);
475 	cv_destroy(&mc_polling_cv);
476 	cv_destroy(&mc_poll_exit_cv);
477 }
478 
479 static int
480 mc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
481 {
482 	mc_opl_t *mcp;
483 	int instance;
484 	int rv;
485 
486 	/* get the instance of this devi */
487 	instance = ddi_get_instance(devi);
488 
489 	switch (cmd) {
490 	case DDI_ATTACH:
491 		break;
492 	case DDI_RESUME:
493 		mcp = ddi_get_soft_state(mc_statep, instance);
494 		rv = mc_resume(mcp, MC_DRIVER_SUSPENDED);
495 		return (rv);
496 	default:
497 		return (DDI_FAILURE);
498 	}
499 
500 	if (ddi_soft_state_zalloc(mc_statep, instance) != DDI_SUCCESS)
501 		return (DDI_FAILURE);
502 
503 	if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
504 		goto bad;
505 	}
506 
507 	if (mc_timeout_period == 0) {
508 		mc_patrol_interval_sec = (int)ddi_getprop(DDI_DEV_T_ANY, devi,
509 		    DDI_PROP_DONTPASS, "mc-timeout-interval-sec",
510 		    mc_patrol_interval_sec);
511 		mc_timeout_period = drv_usectohz(1000000 *
512 		    mc_patrol_interval_sec / OPL_MAX_BOARDS);
513 	}
514 
515 	/* set informations in mc state */
516 	mcp->mc_dip = devi;
517 
518 	if (mc_board_add(mcp))
519 		goto bad;
520 
521 	insert_mcp(mcp);
522 
523 	/*
524 	 * Start the polling thread if it is not running already.
525 	 */
526 	mutex_enter(&mc_polling_lock);
527 	if (!mc_pollthr_running) {
528 		(void) thread_create(NULL, 0, (void (*)())mc_polling_thread,
529 		    NULL, 0, &p0, TS_RUN, mc_poll_priority);
530 	}
531 	mutex_exit(&mc_polling_lock);
532 	ddi_report_dev(devi);
533 
534 	return (DDI_SUCCESS);
535 
536 bad:
537 	ddi_soft_state_free(mc_statep, instance);
538 	return (DDI_FAILURE);
539 }
540 
541 /* ARGSUSED */
542 static int
543 mc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
544 {
545 	int rv;
546 	int instance;
547 	mc_opl_t *mcp;
548 
549 	/* get the instance of this devi */
550 	instance = ddi_get_instance(devi);
551 	if ((mcp = ddi_get_soft_state(mc_statep, instance)) == NULL) {
552 		return (DDI_FAILURE);
553 	}
554 
555 	switch (cmd) {
556 	case DDI_SUSPEND:
557 		rv = mc_suspend(mcp, MC_DRIVER_SUSPENDED);
558 		return (rv);
559 	case DDI_DETACH:
560 		break;
561 	default:
562 		return (DDI_FAILURE);
563 	}
564 
565 	delete_mcp(mcp);
566 	if (mc_board_del(mcp) != DDI_SUCCESS) {
567 		return (DDI_FAILURE);
568 	}
569 
570 	/* free up the soft state */
571 	ddi_soft_state_free(mc_statep, instance);
572 
573 	return (DDI_SUCCESS);
574 }
575 
576 /* ARGSUSED */
577 static int
578 mc_open(dev_t *devp, int flag, int otyp, cred_t *credp)
579 {
580 	return (0);
581 }
582 
583 /* ARGSUSED */
584 static int
585 mc_close(dev_t devp, int flag, int otyp, cred_t *credp)
586 {
587 	return (0);
588 }
589 
590 /* ARGSUSED */
591 static int
592 mc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
593 	int *rvalp)
594 {
595 #ifdef DEBUG
596 	return (mc_ioctl_debug(dev, cmd, arg, mode, credp, rvalp));
597 #else
598 	return (ENXIO);
599 #endif
600 }
601 
602 /*
603  * PA validity check:
604  * This function return 1 if the PA is a valid PA
605  * in the running Solaris instance i.e. in physinstall
606  * Otherwise, return 0.
607  */
608 
609 /* ARGSUSED */
610 static int
611 pa_is_valid(mc_opl_t *mcp, uint64_t addr)
612 {
613 	if (mcp->mlist == NULL)
614 		mc_get_mlist(mcp);
615 
616 	if (mcp->mlist && address_in_memlist(mcp->mlist, addr, 0)) {
617 		return (1);
618 	}
619 	return (0);
620 }
621 
622 /*
623  * mac-pa translation routines.
624  *
625  *    Input: mc driver state, (LSB#, Bank#, DIMM address)
626  *    Output: physical address
627  *
628  *    Valid   - return value:  0
629  *    Invalid - return value: -1
630  */
631 static int
632 mcaddr_to_pa(mc_opl_t *mcp, mc_addr_t *maddr, uint64_t *pa)
633 {
634 	int i;
635 	uint64_t pa_offset = 0;
636 	int cs = (maddr->ma_dimm_addr >> CS_SHIFT) & 1;
637 	int bank = maddr->ma_bank;
638 	mc_addr_t maddr1;
639 	int bank0, bank1;
640 
641 	MC_LOG("mcaddr /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
642 	    maddr->ma_dimm_addr);
643 
644 	/* loc validity check */
645 	ASSERT(maddr->ma_bd >= 0 && OPL_BOARD_MAX > maddr->ma_bd);
646 	ASSERT(bank >= 0 && OPL_BANK_MAX > bank);
647 
648 	/* Do translation */
649 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
650 		int pa_bit = 0;
651 		int mc_bit = mcp->mc_trans_table[cs][i];
652 		if (mc_bit < MC_ADDRESS_BITS) {
653 			pa_bit = (maddr->ma_dimm_addr >> mc_bit) & 1;
654 		} else if (mc_bit == MP_NONE) {
655 			pa_bit = 0;
656 		} else if (mc_bit == MP_BANK_0) {
657 			pa_bit = bank & 1;
658 		} else if (mc_bit == MP_BANK_1) {
659 			pa_bit = (bank >> 1) & 1;
660 		} else if (mc_bit == MP_BANK_2) {
661 			pa_bit = (bank >> 2) & 1;
662 		}
663 		pa_offset |= ((uint64_t)pa_bit) << i;
664 	}
665 	*pa = mcp->mc_start_address + pa_offset;
666 	MC_LOG("pa = %lx\n", *pa);
667 
668 	if (pa_to_maddr(mcp, *pa, &maddr1) == -1) {
669 		cmn_err(CE_WARN, "mcaddr_to_pa: /LSB%d/B%d/%x failed to "
670 		    "convert PA %lx\n", maddr->ma_bd, bank,
671 		    maddr->ma_dimm_addr, *pa);
672 		return (-1);
673 	}
674 
675 	/*
676 	 * In mirror mode, PA is always translated to the even bank.
677 	 */
678 	if (IS_MIRROR(mcp, maddr->ma_bank)) {
679 		bank0 = maddr->ma_bank & ~(1);
680 		bank1 = maddr1.ma_bank & ~(1);
681 	} else {
682 		bank0 = maddr->ma_bank;
683 		bank1 = maddr1.ma_bank;
684 	}
685 	/*
686 	 * there is no need to check ma_bd because it is generated from
687 	 * mcp.  They are the same.
688 	 */
689 	if ((bank0 == bank1) && (maddr->ma_dimm_addr ==
690 	    maddr1.ma_dimm_addr)) {
691 		return (0);
692 	} else {
693 		cmn_err(CE_WARN, "Translation error source /LSB%d/B%d/%x, "
694 		    "PA %lx, target /LSB%d/B%d/%x\n", maddr->ma_bd, bank,
695 		    maddr->ma_dimm_addr, *pa, maddr1.ma_bd, maddr1.ma_bank,
696 		    maddr1.ma_dimm_addr);
697 		return (-1);
698 	}
699 }
700 
701 /*
702  * PA to CS (used by pa_to_maddr).
703  */
704 static int
705 pa_to_cs(mc_opl_t *mcp, uint64_t pa_offset)
706 {
707 	int i;
708 	int cs = 1;
709 
710 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
711 		/* MAC address bit<29> is arranged on the same PA bit */
712 		/* on both table. So we may use any table. */
713 		if (mcp->mc_trans_table[0][i] == CS_SHIFT) {
714 			cs = (pa_offset >> i) & 1;
715 			break;
716 		}
717 	}
718 	return (cs);
719 }
720 
721 /*
722  * PA to DIMM (used by pa_to_maddr).
723  */
724 /* ARGSUSED */
725 static uint32_t
726 pa_to_dimm(mc_opl_t *mcp, uint64_t pa_offset)
727 {
728 	int i;
729 	int cs = pa_to_cs(mcp, pa_offset);
730 	uint32_t dimm_addr = 0;
731 
732 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
733 		int pa_bit_value = (pa_offset >> i) & 1;
734 		int mc_bit = mcp->mc_trans_table[cs][i];
735 		if (mc_bit < MC_ADDRESS_BITS) {
736 			dimm_addr |= pa_bit_value << mc_bit;
737 		}
738 	}
739 	dimm_addr |= cs << CS_SHIFT;
740 	return (dimm_addr);
741 }
742 
743 /*
744  * PA to Bank (used by pa_to_maddr).
745  */
746 static int
747 pa_to_bank(mc_opl_t *mcp, uint64_t pa_offset)
748 {
749 	int i;
750 	int cs = pa_to_cs(mcp, pa_offset);
751 	int bankno = mcp->mc_trans_table[cs][INDEX_OF_BANK_SUPPLEMENT_BIT];
752 
753 
754 	for (i = 0; i < PA_BITS_FOR_MAC; i++) {
755 		int pa_bit_value = (pa_offset >> i) & 1;
756 		int mc_bit = mcp->mc_trans_table[cs][i];
757 		switch (mc_bit) {
758 		case MP_BANK_0:
759 			bankno |= pa_bit_value;
760 			break;
761 		case MP_BANK_1:
762 			bankno |= pa_bit_value << 1;
763 			break;
764 		case MP_BANK_2:
765 			bankno |= pa_bit_value << 2;
766 			break;
767 		}
768 	}
769 
770 	return (bankno);
771 }
772 
773 /*
774  * PA to MAC address translation
775  *
776  *   Input: MAC driver state, physicall adress
777  *   Output: LSB#, Bank id, mac address
778  *
779  *    Valid   - return value:  0
780  *    Invalid - return value: -1
781  */
782 
783 int
784 pa_to_maddr(mc_opl_t *mcp, uint64_t pa, mc_addr_t *maddr)
785 {
786 	uint64_t pa_offset;
787 
788 	if (!mc_rangecheck_pa(mcp, pa))
789 		return (-1);
790 
791 	/* Do translation */
792 	pa_offset = pa - mcp->mc_start_address;
793 
794 	maddr->ma_bd = mcp->mc_board_num;
795 	maddr->ma_phys_bd = mcp->mc_phys_board_num;
796 	maddr->ma_bank = pa_to_bank(mcp, pa_offset);
797 	maddr->ma_dimm_addr = pa_to_dimm(mcp, pa_offset);
798 	MC_LOG("pa %lx -> mcaddr /LSB%d/B%d/%x\n", pa_offset, maddr->ma_bd,
799 	    maddr->ma_bank, maddr->ma_dimm_addr);
800 	return (0);
801 }
802 
803 /*
804  * UNUM format for DC is "/CMUnn/MEMxyZ", where
805  *	nn = 00..03 for DC1 and 00..07 for DC2 and 00..15 for DC3.
806  *	x = MAC 0..3
807  *	y = 0..3 (slot info).
808  *	Z = 'A' or 'B'
809  *
810  * UNUM format for FF1 is "/MBU_A/MEMBx/MEMyZ", where
811  *	x = 0..3 (MEMB number)
812  *	y = 0..3 (slot info).
813  *	Z = 'A' or 'B'
814  *
815  * UNUM format for FF2 is "/MBU_B/MEMBx/MEMyZ"
816  *	x = 0..7 (MEMB number)
817  *	y = 0..3 (slot info).
818  *	Z = 'A' or 'B'
819  */
820 int
821 mc_set_mem_unum(char *buf, int buflen, int sb, int bank,
822     uint32_t mf_type, uint32_t d_slot)
823 {
824 	char *dimmnm;
825 	char memb_num;
826 	int cs;
827 	int i;
828 	int j;
829 
830 	cs = SLOT_TO_CS(d_slot);
831 
832 	if (plat_model == MODEL_DC) {
833 		if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
834 		    mf_type == FLT_TYPE_PERMANENT_CE) {
835 			i = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
836 			dimmnm = mc_dc_dimm_unum_table[i];
837 			snprintf(buf, buflen, "/%s%02d/MEM%s",
838 			    model_names[plat_model].unit_name, sb, dimmnm);
839 		} else {
840 			i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
841 			j = (cs == 0) ?  i : i + 2;
842 			snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
843 			    model_names[plat_model].unit_name, sb,
844 			    mc_dc_dimm_unum_table[j],
845 			    mc_dc_dimm_unum_table[j + 1]);
846 		}
847 	} else {
848 		if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
849 		    mf_type == FLT_TYPE_PERMANENT_CE) {
850 			i = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
851 			dimmnm = mc_ff_dimm_unum_table[i];
852 			memb_num = dimmnm[0];
853 			snprintf(buf, buflen, "/%s/%s%c/MEM%s",
854 			    model_names[plat_model].unit_name,
855 			    model_names[plat_model].mem_name,
856 			    memb_num, &dimmnm[1]);
857 		} else {
858 			i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
859 			j = (cs == 0) ?  i : i + 2;
860 			memb_num = mc_ff_dimm_unum_table[i][0],
861 			    snprintf(buf, buflen, "/%s/%s%c/MEM%s MEM%s",
862 			    model_names[plat_model].unit_name,
863 			    model_names[plat_model].mem_name, memb_num,
864 			    &mc_ff_dimm_unum_table[j][1],
865 			    &mc_ff_dimm_unum_table[j + 1][1]);
866 		}
867 	}
868 	return (0);
869 }
870 
871 static void
872 mc_ereport_post(mc_aflt_t *mc_aflt)
873 {
874 	char buf[FM_MAX_CLASS];
875 	char device_path[MAXPATHLEN];
876 	char sid[MAXPATHLEN];
877 	nv_alloc_t *nva = NULL;
878 	nvlist_t *ereport, *detector, *resource;
879 	errorq_elem_t *eqep;
880 	int nflts;
881 	mc_flt_stat_t *flt_stat;
882 	int i, n;
883 	int blen = MAXPATHLEN;
884 	char *p, *s = NULL;
885 	uint32_t values[2], synd[2], dslot[2];
886 	uint64_t offset = (uint64_t)-1;
887 	int ret = -1;
888 
889 	if (panicstr) {
890 		eqep = errorq_reserve(ereport_errorq);
891 		if (eqep == NULL)
892 			return;
893 		ereport = errorq_elem_nvl(ereport_errorq, eqep);
894 		nva = errorq_elem_nva(ereport_errorq, eqep);
895 	} else {
896 		ereport = fm_nvlist_create(nva);
897 	}
898 
899 	/*
900 	 * Create the scheme "dev" FMRI.
901 	 */
902 	detector = fm_nvlist_create(nva);
903 	resource = fm_nvlist_create(nva);
904 
905 	nflts = mc_aflt->mflt_nflts;
906 
907 	ASSERT(nflts >= 1 && nflts <= 2);
908 
909 	flt_stat = mc_aflt->mflt_stat[0];
910 	(void) ddi_pathname(mc_aflt->mflt_mcp->mc_dip, device_path);
911 	(void) fm_fmri_dev_set(detector, FM_DEV_SCHEME_VERSION, NULL,
912 	    device_path, NULL);
913 
914 	/*
915 	 * Encode all the common data into the ereport.
916 	 */
917 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s-%s", MC_OPL_ERROR_CLASS,
918 	    mc_aflt->mflt_is_ptrl ? MC_OPL_PTRL_SUBCLASS : MC_OPL_MI_SUBCLASS,
919 	    mc_aflt->mflt_erpt_class);
920 
921 	MC_LOG("mc_ereport_post: ereport %s\n", buf);
922 
923 
924 	fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
925 	    fm_ena_generate(mc_aflt->mflt_id, FM_ENA_FMT1), detector, NULL);
926 
927 	/*
928 	 * Set payload.
929 	 */
930 	fm_payload_set(ereport, MC_OPL_BOARD, DATA_TYPE_UINT32,
931 	    flt_stat->mf_flt_maddr.ma_bd, NULL);
932 
933 	fm_payload_set(ereport, MC_OPL_PA, DATA_TYPE_UINT64,
934 	    flt_stat->mf_flt_paddr, NULL);
935 
936 	if (flt_stat->mf_type == FLT_TYPE_INTERMITTENT_CE ||
937 	    flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
938 		fm_payload_set(ereport, MC_OPL_FLT_TYPE, DATA_TYPE_UINT8,
939 		    ECC_STICKY, NULL);
940 	}
941 
942 	for (i = 0; i < nflts; i++)
943 		values[i] = mc_aflt->mflt_stat[i]->mf_flt_maddr.ma_bank;
944 
945 	fm_payload_set(ereport, MC_OPL_BANK, DATA_TYPE_UINT32_ARRAY, nflts,
946 	    values, NULL);
947 
948 	for (i = 0; i < nflts; i++)
949 		values[i] = mc_aflt->mflt_stat[i]->mf_cntl;
950 
951 	fm_payload_set(ereport, MC_OPL_STATUS, DATA_TYPE_UINT32_ARRAY, nflts,
952 	    values, NULL);
953 
954 	for (i = 0; i < nflts; i++)
955 		values[i] = mc_aflt->mflt_stat[i]->mf_err_add;
956 
957 	/* offset is set only for PCE and ICE */
958 	if (mc_aflt->mflt_stat[0]->mf_type == FLT_TYPE_INTERMITTENT_CE ||
959 	    mc_aflt->mflt_stat[0]->mf_type == FLT_TYPE_PERMANENT_CE) {
960 		offset = values[0];
961 
962 	}
963 	fm_payload_set(ereport, MC_OPL_ERR_ADD, DATA_TYPE_UINT32_ARRAY, nflts,
964 	    values, NULL);
965 
966 	for (i = 0; i < nflts; i++)
967 		values[i] = mc_aflt->mflt_stat[i]->mf_err_log;
968 
969 	fm_payload_set(ereport, MC_OPL_ERR_LOG, DATA_TYPE_UINT32_ARRAY, nflts,
970 	    values, NULL);
971 
972 	for (i = 0; i < nflts; i++) {
973 		flt_stat = mc_aflt->mflt_stat[i];
974 		if (flt_stat->mf_errlog_valid) {
975 			synd[i] = flt_stat->mf_synd;
976 			dslot[i] = flt_stat->mf_dimm_slot;
977 			values[i] = flt_stat->mf_dram_place;
978 		} else {
979 			synd[i] = 0;
980 			dslot[i] = 0;
981 			values[i] = 0;
982 		}
983 	}
984 
985 	fm_payload_set(ereport, MC_OPL_ERR_SYND, DATA_TYPE_UINT32_ARRAY, nflts,
986 	    synd, NULL);
987 
988 	fm_payload_set(ereport, MC_OPL_ERR_DIMMSLOT, DATA_TYPE_UINT32_ARRAY,
989 	    nflts, dslot, NULL);
990 
991 	fm_payload_set(ereport, MC_OPL_ERR_DRAM, DATA_TYPE_UINT32_ARRAY, nflts,
992 	    values, NULL);
993 
994 	device_path[0] = 0;
995 	p = &device_path[0];
996 	sid[0] = 0;
997 	s = &sid[0];
998 	ret = 0;
999 
1000 	for (i = 0; i < nflts; i++) {
1001 		int bank;
1002 
1003 		flt_stat = mc_aflt->mflt_stat[i];
1004 		bank = flt_stat->mf_flt_maddr.ma_bank;
1005 		ret = mc_set_mem_unum(p + strlen(p), blen,
1006 		    flt_stat->mf_flt_maddr.ma_phys_bd, bank, flt_stat->mf_type,
1007 		    flt_stat->mf_dimm_slot);
1008 
1009 		if (ret != 0) {
1010 			cmn_err(CE_WARN,
1011 			    "mc_ereport_post: Failed to determine the unum "
1012 			    "for board=%d bank=%d type=0x%x slot=0x%x",
1013 			    flt_stat->mf_flt_maddr.ma_bd, bank,
1014 			    flt_stat->mf_type, flt_stat->mf_dimm_slot);
1015 			continue;
1016 		}
1017 		n = strlen(device_path);
1018 		blen = MAXPATHLEN - n;
1019 		p = &device_path[n];
1020 		if (i < (nflts - 1)) {
1021 			snprintf(p, blen, " ");
1022 			blen--;
1023 			p++;
1024 		}
1025 
1026 		if (ret == 0) {
1027 			ret = mc_set_mem_sid(mc_aflt->mflt_mcp, s + strlen(s),
1028 			    blen, flt_stat->mf_flt_maddr.ma_phys_bd, bank,
1029 			    flt_stat->mf_type, flt_stat->mf_dimm_slot);
1030 
1031 		}
1032 	}
1033 
1034 	(void) fm_fmri_mem_set(resource, FM_MEM_SCHEME_VERSION, NULL,
1035 	    device_path, (ret == 0) ? sid : NULL, (ret == 0) ? offset :
1036 	    (uint64_t)-1);
1037 
1038 	fm_payload_set(ereport, MC_OPL_RESOURCE, DATA_TYPE_NVLIST, resource,
1039 	    NULL);
1040 
1041 	if (panicstr) {
1042 		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
1043 	} else {
1044 		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
1045 		fm_nvlist_destroy(ereport, FM_NVA_FREE);
1046 		fm_nvlist_destroy(detector, FM_NVA_FREE);
1047 		fm_nvlist_destroy(resource, FM_NVA_FREE);
1048 	}
1049 }
1050 
1051 
1052 static void
1053 mc_err_drain(mc_aflt_t *mc_aflt)
1054 {
1055 	int rv;
1056 	uint64_t pa = (uint64_t)(-1);
1057 	int i;
1058 
1059 	MC_LOG("mc_err_drain: %s\n", mc_aflt->mflt_erpt_class);
1060 	/*
1061 	 * we come here only when we have:
1062 	 * In mirror mode: MUE, SUE
1063 	 * In normal mode: UE, Permanent CE, Intermittent CE
1064 	 */
1065 	for (i = 0; i < mc_aflt->mflt_nflts; i++) {
1066 		rv = mcaddr_to_pa(mc_aflt->mflt_mcp,
1067 		    &(mc_aflt->mflt_stat[i]->mf_flt_maddr), &pa);
1068 
1069 		/* Ensure the pa is valid (not in isolated memory block) */
1070 		if (rv == 0 && pa_is_valid(mc_aflt->mflt_mcp, pa))
1071 			mc_aflt->mflt_stat[i]->mf_flt_paddr = pa;
1072 		else
1073 			mc_aflt->mflt_stat[i]->mf_flt_paddr = (uint64_t)-1;
1074 	}
1075 
1076 	MC_LOG("mc_err_drain:pa = %lx\n", pa);
1077 
1078 	switch (page_retire_check(pa, NULL)) {
1079 	case 0:
1080 	case EAGAIN:
1081 		MC_LOG("Page retired or pending\n");
1082 		return;
1083 	case EIO:
1084 		/*
1085 		 * Do page retirement except for the PCE and ICE cases.
1086 		 * This is taken care by the OPL DE
1087 		 */
1088 		if (mc_aflt->mflt_stat[0]->mf_type !=
1089 		    FLT_TYPE_INTERMITTENT_CE &&
1090 		    mc_aflt->mflt_stat[0]->mf_type != FLT_TYPE_PERMANENT_CE) {
1091 			MC_LOG("offline page at pa %lx error %x\n", pa,
1092 			    mc_aflt->mflt_pr);
1093 			(void) page_retire(pa, mc_aflt->mflt_pr);
1094 		}
1095 		break;
1096 	case EINVAL:
1097 	default:
1098 		/*
1099 		 * Some memory do not have page structure so
1100 		 * we keep going in case of EINVAL.
1101 		 */
1102 		break;
1103 	}
1104 
1105 	for (i = 0; i < mc_aflt->mflt_nflts; i++) {
1106 		mc_aflt_t mc_aflt0;
1107 		if (mc_aflt->mflt_stat[i]->mf_flt_paddr != (uint64_t)-1) {
1108 			mc_aflt0 = *mc_aflt;
1109 			mc_aflt0.mflt_nflts = 1;
1110 			mc_aflt0.mflt_stat[0] = mc_aflt->mflt_stat[i];
1111 			mc_ereport_post(&mc_aflt0);
1112 		}
1113 	}
1114 }
1115 
1116 /*
1117  * The restart address is actually defined in unit of PA[37:6]
1118  * the mac patrol will convert that to dimm offset.  If the
1119  * address is not in the bank, it will continue to search for
1120  * the next PA that is within the bank.
1121  *
1122  * Also the mac patrol scans the dimms based on PA, not
1123  * dimm offset.
1124  */
1125 static int
1126 restart_patrol(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr_info)
1127 {
1128 	uint64_t pa;
1129 	int rv;
1130 
1131 	if (rsaddr_info == NULL || (rsaddr_info->mi_valid == 0)) {
1132 		MAC_PTRL_START(mcp, bank);
1133 		return (0);
1134 	}
1135 
1136 	rv = mcaddr_to_pa(mcp, &rsaddr_info->mi_restartaddr, &pa);
1137 	if (rv != 0) {
1138 		MC_LOG("cannot convert mcaddr to pa. use auto restart\n");
1139 		MAC_PTRL_START(mcp, bank);
1140 		return (0);
1141 	}
1142 
1143 	if (!mc_rangecheck_pa(mcp, pa)) {
1144 		/* pa is not on this board, just retry */
1145 		cmn_err(CE_WARN, "restart_patrol: invalid address %lx "
1146 		    "on board %d\n", pa, mcp->mc_board_num);
1147 		MAC_PTRL_START(mcp, bank);
1148 		return (0);
1149 	}
1150 
1151 	MC_LOG("restart_patrol: pa = %lx\n", pa);
1152 
1153 	if (!rsaddr_info->mi_injectrestart) {
1154 		/*
1155 		 * For non-error injection restart we need to
1156 		 * determine if the current restart pa/page is
1157 		 * a "good" page. A "good" page is a page that
1158 		 * has not been page retired. If the current
1159 		 * page that contains the pa is "good", we will
1160 		 * do a HW auto restart and let HW patrol continue
1161 		 * where it last stopped. Most desired scenario.
1162 		 *
1163 		 * If the current page is not "good", we will advance
1164 		 * to the next page to find the next "good" page and
1165 		 * restart the patrol from there.
1166 		 */
1167 		int wrapcount = 0;
1168 		uint64_t origpa = pa;
1169 		while (wrapcount < 2) {
1170 			if (!pa_is_valid(mcp, pa)) {
1171 				/*
1172 				 * Not in physinstall - advance to the
1173 				 * next memory isolation blocksize
1174 				 */
1175 				MC_LOG("Invalid PA\n");
1176 				pa = roundup(pa + 1, mc_isolation_bsize);
1177 			} else {
1178 				int rv;
1179 				if ((rv = page_retire_check(pa, NULL)) != 0 &&
1180 				    rv != EAGAIN) {
1181 					/*
1182 					 * The page is "good" (not retired),
1183 					 * we will use automatic HW restart
1184 					 * algorithm if this is the original
1185 					 * current starting page.
1186 					 */
1187 					if (pa == origpa) {
1188 						MC_LOG("Page has no error. "
1189 						    "Auto restart\n");
1190 						MAC_PTRL_START(mcp, bank);
1191 						return (0);
1192 					} else {
1193 						/*
1194 						 * found a subsequent good page
1195 						 */
1196 						break;
1197 					}
1198 				}
1199 
1200 				/*
1201 				 * Skip to the next page
1202 				 */
1203 				pa = roundup(pa + 1, PAGESIZE);
1204 				MC_LOG("Skipping bad page to %lx\n", pa);
1205 			}
1206 
1207 			/* Check to see if we hit the end of the memory range */
1208 			if (pa >= (mcp->mc_start_address + mcp->mc_size)) {
1209 				MC_LOG("Wrap around\n");
1210 				pa = mcp->mc_start_address;
1211 				wrapcount++;
1212 			}
1213 		}
1214 
1215 		if (wrapcount > 1) {
1216 			MC_LOG("Failed to find a good page. Just restart\n");
1217 			MAC_PTRL_START(mcp, bank);
1218 			return (0);
1219 		}
1220 	}
1221 
1222 	/*
1223 	 * We reached here either:
1224 	 * 1. We are doing an error injection restart that specify
1225 	 *    the exact pa/page to restart. OR
1226 	 * 2. We found a subsequent good page different from the
1227 	 *    original restart pa/page.
1228 	 * Restart MAC patrol: PA[37:6]
1229 	 */
1230 	MC_LOG("restart at pa = %lx\n", pa);
1231 	ST_MAC_REG(MAC_RESTART_ADD(mcp, bank), MAC_RESTART_PA(pa));
1232 	MAC_PTRL_START_ADD(mcp, bank);
1233 
1234 	return (0);
1235 }
1236 
1237 /*
1238  * Rewriting is used for two purposes.
1239  *  - to correct the error in memory.
1240  *  - to determine whether the error is permanent or intermittent.
1241  * It's done by writing the address in MAC_BANKm_REWRITE_ADD
1242  * and issuing REW_REQ command in MAC_BANKm_PTRL_CNRL. After that,
1243  * REW_END (and REW_CE/REW_UE if some error detected) is set when
1244  * rewrite operation is done. See 4.7.3 and 4.7.11 in Columbus2 PRM.
1245  *
1246  * Note that rewrite operation doesn't change RAW_UE to Marked UE.
1247  * Therefore, we use it only CE case.
1248  */
1249 static uint32_t
1250 do_rewrite(mc_opl_t *mcp, int bank, uint32_t dimm_addr)
1251 {
1252 	uint32_t cntl;
1253 	int count = 0;
1254 
1255 	/* first wait to make sure PTRL_STATUS is 0 */
1256 	while (count++ < mc_max_rewrite_loop) {
1257 		cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
1258 		if (!(cntl & MAC_CNTL_PTRL_STATUS))
1259 			break;
1260 		drv_usecwait(mc_rewrite_delay);
1261 	}
1262 	if (count >= mc_max_rewrite_loop)
1263 		goto bad;
1264 
1265 	count = 0;
1266 
1267 	ST_MAC_REG(MAC_REWRITE_ADD(mcp, bank), dimm_addr);
1268 	MAC_REW_REQ(mcp, bank);
1269 
1270 	do {
1271 		cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
1272 		if (count++ >= mc_max_rewrite_loop) {
1273 			goto bad;
1274 		} else {
1275 			drv_usecwait(mc_rewrite_delay);
1276 		}
1277 	/*
1278 	 * If there are other MEMORY or PCI activities, this
1279 	 * will be BUSY, else it should be set immediately
1280 	 */
1281 	} while (!(cntl & MAC_CNTL_REW_END));
1282 
1283 	MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
1284 	return (cntl);
1285 bad:
1286 	/* This is bad.  Just reset the circuit */
1287 	cmn_err(CE_WARN, "mc-opl rewrite timeout on /LSB%d/B%d\n",
1288 	    mcp->mc_board_num, bank);
1289 	cntl = MAC_CNTL_REW_END;
1290 	MAC_CMD(mcp, bank, MAC_CNTL_PTRL_RESET);
1291 	MAC_CLEAR_ERRS(mcp, bank, MAC_CNTL_REW_ERRS);
1292 	return (cntl);
1293 }
1294 void
1295 mc_process_scf_log(mc_opl_t *mcp)
1296 {
1297 	int count;
1298 	int n = 0;
1299 	scf_log_t *p;
1300 	int bank;
1301 
1302 	for (bank = 0; bank < BANKNUM_PER_SB; bank++) {
1303 		while ((p = mcp->mc_scf_log[bank]) != NULL &&
1304 		    (n < mc_max_errlog_processed)) {
1305 			ASSERT(bank == p->sl_bank);
1306 			count = 0;
1307 			while ((LD_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank))
1308 			    & MAC_STATIC_ERR_VLD)) {
1309 				if (count++ >= (mc_max_scf_loop)) {
1310 					break;
1311 				}
1312 				drv_usecwait(mc_scf_delay);
1313 			}
1314 
1315 			if (count < mc_max_scf_loop) {
1316 				ST_MAC_REG(MAC_STATIC_ERR_LOG(mcp, p->sl_bank),
1317 				    p->sl_err_log);
1318 
1319 				ST_MAC_REG(MAC_STATIC_ERR_ADD(mcp, p->sl_bank),
1320 				    p->sl_err_add|MAC_STATIC_ERR_VLD);
1321 				mcp->mc_scf_retry[bank] = 0;
1322 			} else {
1323 				/*
1324 				 * if we try too many times, just drop the req
1325 				 */
1326 				if (mcp->mc_scf_retry[bank]++ <=
1327 				    mc_max_scf_retry) {
1328 					return;
1329 				} else {
1330 					if ((++mc_pce_dropped & 0xff) == 0) {
1331 						cmn_err(CE_WARN, "Cannot "
1332 						    "report Permanent CE to "
1333 						    "SCF\n");
1334 					}
1335 				}
1336 			}
1337 			n++;
1338 			mcp->mc_scf_log[bank] = p->sl_next;
1339 			mcp->mc_scf_total[bank]--;
1340 			ASSERT(mcp->mc_scf_total[bank] >= 0);
1341 			kmem_free(p, sizeof (scf_log_t));
1342 		}
1343 	}
1344 }
1345 void
1346 mc_queue_scf_log(mc_opl_t *mcp, mc_flt_stat_t *flt_stat, int bank)
1347 {
1348 	scf_log_t *p;
1349 
1350 	if (mcp->mc_scf_total[bank] >= mc_max_scf_logs) {
1351 		if ((++mc_pce_dropped & 0xff) == 0) {
1352 			cmn_err(CE_WARN, "Too many Permanent CE requests.\n");
1353 		}
1354 		return;
1355 	}
1356 	p = kmem_zalloc(sizeof (scf_log_t), KM_SLEEP);
1357 	p->sl_next = 0;
1358 	p->sl_err_add = flt_stat->mf_err_add;
1359 	p->sl_err_log = flt_stat->mf_err_log;
1360 	p->sl_bank = bank;
1361 
1362 	if (mcp->mc_scf_log[bank] == NULL) {
1363 		/*
1364 		 * we rely on mc_scf_log to detect NULL queue.
1365 		 * mc_scf_log_tail is irrelevant is such case.
1366 		 */
1367 		mcp->mc_scf_log_tail[bank] = mcp->mc_scf_log[bank] = p;
1368 	} else {
1369 		mcp->mc_scf_log_tail[bank]->sl_next = p;
1370 		mcp->mc_scf_log_tail[bank] = p;
1371 	}
1372 	mcp->mc_scf_total[bank]++;
1373 }
1374 /*
1375  * This routine determines what kind of CE happens, intermittent
1376  * or permanent as follows. (See 4.7.3 in Columbus2 PRM.)
1377  * - Do rewrite by issuing REW_REQ command to MAC_PTRL_CNTL register.
1378  * - If CE is still detected on the same address even after doing
1379  *   rewrite operation twice, it is determined as permanent error.
1380  * - If error is not detected anymore, it is determined as intermittent
1381  *   error.
1382  * - If UE is detected due to rewrite operation, it should be treated
1383  *   as UE.
1384  */
1385 
1386 /* ARGSUSED */
1387 static void
1388 mc_scrub_ce(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat, int ptrl_error)
1389 {
1390 	uint32_t cntl;
1391 	int i;
1392 
1393 	flt_stat->mf_type = FLT_TYPE_PERMANENT_CE;
1394 	/*
1395 	 * rewrite request 1st time reads and correct error data
1396 	 * and write to DIMM.  2nd rewrite request must be issued
1397 	 * after REW_CE/UE/END is 0.  When the 2nd request is completed,
1398 	 * if REW_CE = 1, then it is permanent CE.
1399 	 */
1400 	for (i = 0; i < 2; i++) {
1401 		cntl = do_rewrite(mcp, bank, flt_stat->mf_err_add);
1402 		/*
1403 		 * If the error becomes UE or CMPE
1404 		 * we return to the caller immediately.
1405 		 */
1406 		if (cntl & MAC_CNTL_REW_UE) {
1407 			if (ptrl_error)
1408 				flt_stat->mf_cntl |= MAC_CNTL_PTRL_UE;
1409 			else
1410 				flt_stat->mf_cntl |= MAC_CNTL_MI_UE;
1411 			flt_stat->mf_type = FLT_TYPE_UE;
1412 			return;
1413 		}
1414 		if (cntl & MAC_CNTL_REW_CMPE) {
1415 			if (ptrl_error)
1416 				flt_stat->mf_cntl |= MAC_CNTL_PTRL_CMPE;
1417 			else
1418 				flt_stat->mf_cntl |= MAC_CNTL_MI_CMPE;
1419 			flt_stat->mf_type = FLT_TYPE_CMPE;
1420 			return;
1421 		}
1422 	}
1423 	if (!(cntl & MAC_CNTL_REW_CE)) {
1424 		flt_stat->mf_type = FLT_TYPE_INTERMITTENT_CE;
1425 	}
1426 
1427 	if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
1428 		/* report PERMANENT_CE to SP via SCF */
1429 		if (!(flt_stat->mf_err_log & MAC_ERR_LOG_INVALID)) {
1430 			mc_queue_scf_log(mcp, flt_stat, bank);
1431 		}
1432 	}
1433 }
1434 
1435 #define	IS_CMPE(cntl, f)	((cntl) & ((f) ? MAC_CNTL_PTRL_CMPE :\
1436 				MAC_CNTL_MI_CMPE))
1437 #define	IS_UE(cntl, f)	((cntl) & ((f) ? MAC_CNTL_PTRL_UE : MAC_CNTL_MI_UE))
1438 #define	IS_CE(cntl, f)	((cntl) & ((f) ? MAC_CNTL_PTRL_CE : MAC_CNTL_MI_CE))
1439 #define	IS_OK(cntl, f)	(!((cntl) & ((f) ? MAC_CNTL_PTRL_ERRS : \
1440 			MAC_CNTL_MI_ERRS)))
1441 
1442 
1443 static int
1444 IS_CE_ONLY(uint32_t cntl, int ptrl_error)
1445 {
1446 	if (ptrl_error) {
1447 		return ((cntl & MAC_CNTL_PTRL_ERRS) == MAC_CNTL_PTRL_CE);
1448 	} else {
1449 		return ((cntl & MAC_CNTL_MI_ERRS) == MAC_CNTL_MI_CE);
1450 	}
1451 }
1452 
1453 void
1454 mc_write_cntl(mc_opl_t *mcp, int bank, uint32_t value)
1455 {
1456 	int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
1457 
1458 	if (mcp->mc_speedup_period[ebank] > 0)
1459 		value |= mc_max_speed;
1460 	else
1461 		value |= mcp->mc_speed;
1462 	ST_MAC_REG(MAC_PTRL_CNTL(mcp, bank), value);
1463 }
1464 
1465 static void
1466 mc_read_ptrl_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
1467 {
1468 	flt_stat->mf_cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1469 	    MAC_CNTL_PTRL_ERRS;
1470 	flt_stat->mf_err_add = LD_MAC_REG(MAC_PTRL_ERR_ADD(mcp, bank));
1471 	flt_stat->mf_err_log = LD_MAC_REG(MAC_PTRL_ERR_LOG(mcp, bank));
1472 	flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
1473 	flt_stat->mf_flt_maddr.ma_phys_bd = mcp->mc_phys_board_num;
1474 	flt_stat->mf_flt_maddr.ma_bank = bank;
1475 	flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
1476 }
1477 
1478 static void
1479 mc_read_mi_reg(mc_opl_t *mcp, int bank, mc_flt_stat_t *flt_stat)
1480 {
1481 	uint32_t status, old_status;
1482 
1483 	status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) & MAC_CNTL_MI_ERRS;
1484 	old_status = 0;
1485 
1486 	/* we keep reading until the status is stable */
1487 	while (old_status != status) {
1488 		old_status = status;
1489 		flt_stat->mf_err_add = LD_MAC_REG(MAC_MI_ERR_ADD(mcp, bank));
1490 		flt_stat->mf_err_log = LD_MAC_REG(MAC_MI_ERR_LOG(mcp, bank));
1491 		status = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank)) &
1492 		    MAC_CNTL_MI_ERRS;
1493 		if (status == old_status) {
1494 			break;
1495 		}
1496 	}
1497 
1498 	flt_stat->mf_cntl = status;
1499 	flt_stat->mf_flt_maddr.ma_bd = mcp->mc_board_num;
1500 	flt_stat->mf_flt_maddr.ma_phys_bd = mcp->mc_phys_board_num;
1501 	flt_stat->mf_flt_maddr.ma_bank = bank;
1502 	flt_stat->mf_flt_maddr.ma_dimm_addr = flt_stat->mf_err_add;
1503 }
1504 
1505 
1506 /*
1507  * Error philosophy for mirror mode:
1508  *
1509  * PTRL (The error address for both banks are same, since ptrl stops if it
1510  * detects error.)
1511  * - Compare error  log CMPE.
1512  *
1513  * - UE-UE           Report MUE.  No rewrite.
1514  *
1515  * - UE-*	     UE-(CE/OK). Rewrite to scrub UE.  Report SUE.
1516  *
1517  * - CE-*            CE-(CE/OK). Scrub to determine if CE is permanent.
1518  *                   If CE is permanent, inform SCF.  Once for each
1519  *		     Dimm.  If CE becomes UE or CMPE, go back to above.
1520  *
1521  *
1522  * MI (The error addresses for each bank are the same or different.)
1523  * - Compare  error  If addresses are the same.  Just CMPE, so log CMPE.
1524  *		     If addresses are different (this could happen
1525  *		     as a result of scrubbing.  Report each separately.
1526  *		     Only report error info on each side.
1527  *
1528  * - UE-UE           Addresses are the same.  Report MUE.
1529  *		     Addresses are different.  Report SUE on each bank.
1530  *		     Rewrite to clear UE.
1531  *
1532  * - UE-*	     UE-(CE/OK)
1533  *		     Rewrite to clear UE.  Report SUE for the bank.
1534  *
1535  * - CE-*            CE-(CE/OK).  Scrub to determine if CE is permanent.
1536  *                   If CE becomes UE or CMPE, go back to above.
1537  *
1538  */
1539 
1540 static int
1541 mc_process_error_mir(mc_opl_t *mcp, mc_aflt_t *mc_aflt, mc_flt_stat_t *flt_stat)
1542 {
1543 	int ptrl_error = mc_aflt->mflt_is_ptrl;
1544 	int i;
1545 	int rv = 0;
1546 
1547 	MC_LOG("process mirror errors cntl[0] = %x, cntl[1] = %x\n",
1548 	    flt_stat[0].mf_cntl, flt_stat[1].mf_cntl);
1549 
1550 	if (ptrl_error) {
1551 		if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl) &
1552 		    MAC_CNTL_PTRL_ERRS) == 0)
1553 			return (0);
1554 	} else {
1555 		if (((flt_stat[0].mf_cntl | flt_stat[1].mf_cntl) &
1556 		    MAC_CNTL_MI_ERRS) == 0)
1557 			return (0);
1558 	}
1559 
1560 	/*
1561 	 * First we take care of the case of CE
1562 	 * because they can become UE or CMPE
1563 	 */
1564 	for (i = 0; i < 2; i++) {
1565 		if (IS_CE_ONLY(flt_stat[i].mf_cntl, ptrl_error)) {
1566 			MC_LOG("CE detected on bank %d\n",
1567 			    flt_stat[i].mf_flt_maddr.ma_bank);
1568 			mc_scrub_ce(mcp, flt_stat[i].mf_flt_maddr.ma_bank,
1569 			    &flt_stat[i], ptrl_error);
1570 			rv = 1;
1571 		}
1572 	}
1573 
1574 	/* The above scrubbing can turn CE into UE or CMPE */
1575 
1576 	/*
1577 	 * Now we distinguish two cases: same address or not
1578 	 * the same address.  It might seem more intuitive to
1579 	 * distinguish PTRL v.s. MI error but it is more
1580 	 * complicated that way.
1581 	 */
1582 
1583 	if (flt_stat[0].mf_err_add == flt_stat[1].mf_err_add) {
1584 
1585 		if (IS_CMPE(flt_stat[0].mf_cntl, ptrl_error) ||
1586 		    IS_CMPE(flt_stat[1].mf_cntl, ptrl_error)) {
1587 			flt_stat[0].mf_type = FLT_TYPE_CMPE;
1588 			flt_stat[1].mf_type = FLT_TYPE_CMPE;
1589 			mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
1590 			mc_aflt->mflt_nflts = 2;
1591 			mc_aflt->mflt_stat[0] = &flt_stat[0];
1592 			mc_aflt->mflt_stat[1] = &flt_stat[1];
1593 			mc_aflt->mflt_pr = PR_UE;
1594 			/*
1595 			 * Compare error is result of MAC internal error, so
1596 			 * simply log it instead of publishing an ereport. SCF
1597 			 * diagnoses all the MAC internal and its i/f error.
1598 			 * mc_err_drain(mc_aflt);
1599 			 */
1600 			MC_LOG("cmpe error detected\n");
1601 			return (1);
1602 		}
1603 
1604 		if (IS_UE(flt_stat[0].mf_cntl, ptrl_error) &&
1605 		    IS_UE(flt_stat[1].mf_cntl, ptrl_error)) {
1606 			/* Both side are UE's */
1607 
1608 			MAC_SET_ERRLOG_INFO(&flt_stat[0]);
1609 			MAC_SET_ERRLOG_INFO(&flt_stat[1]);
1610 			MC_LOG("MUE detected\n");
1611 			flt_stat[0].mf_type = FLT_TYPE_MUE;
1612 			flt_stat[1].mf_type = FLT_TYPE_MUE;
1613 			mc_aflt->mflt_erpt_class = MC_OPL_MUE;
1614 			mc_aflt->mflt_nflts = 2;
1615 			mc_aflt->mflt_stat[0] = &flt_stat[0];
1616 			mc_aflt->mflt_stat[1] = &flt_stat[1];
1617 			mc_aflt->mflt_pr = PR_UE;
1618 			mc_err_drain(mc_aflt);
1619 			return (1);
1620 		}
1621 
1622 		/* Now the only case is UE/CE, UE/OK, or don't care */
1623 		for (i = 0; i < 2; i++) {
1624 			if (!IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
1625 				continue;
1626 			}
1627 
1628 			/* rewrite can clear the one side UE error */
1629 
1630 			if (IS_OK(flt_stat[i^1].mf_cntl, ptrl_error)) {
1631 				(void) do_rewrite(mcp,
1632 				    flt_stat[i].mf_flt_maddr.ma_bank,
1633 				    flt_stat[i].mf_flt_maddr.ma_dimm_addr);
1634 			}
1635 			flt_stat[i].mf_type = FLT_TYPE_UE;
1636 			MAC_SET_ERRLOG_INFO(&flt_stat[i]);
1637 			mc_aflt->mflt_erpt_class = MC_OPL_SUE;
1638 			mc_aflt->mflt_stat[0] = &flt_stat[i];
1639 			mc_aflt->mflt_nflts = 1;
1640 			mc_aflt->mflt_pr = PR_MCE;
1641 			mc_err_drain(mc_aflt);
1642 			/* Once we hit a UE/CE or UE/OK case, done */
1643 			return (1);
1644 		}
1645 
1646 	} else {
1647 		/*
1648 		 * addresses are different. That means errors
1649 		 * on the 2 banks are not related at all.
1650 		 */
1651 		for (i = 0; i < 2; i++) {
1652 			if (IS_CMPE(flt_stat[i].mf_cntl, ptrl_error)) {
1653 				flt_stat[i].mf_type = FLT_TYPE_CMPE;
1654 				mc_aflt->mflt_erpt_class = MC_OPL_CMPE;
1655 				mc_aflt->mflt_nflts = 1;
1656 				mc_aflt->mflt_stat[0] = &flt_stat[i];
1657 				mc_aflt->mflt_pr = PR_UE;
1658 				/*
1659 				 * Compare error is result of MAC internal
1660 				 * error, so simply log it instead of
1661 				 * publishing an ereport. SCF diagnoses all
1662 				 * the MAC internal and its interface error.
1663 				 * mc_err_drain(mc_aflt);
1664 				 */
1665 				MC_LOG("cmpe error detected\n");
1666 				/* no more report on this bank */
1667 				flt_stat[i].mf_cntl = 0;
1668 				rv = 1;
1669 			}
1670 		}
1671 
1672 		/* rewrite can clear the one side UE error */
1673 
1674 		for (i = 0; i < 2; i++) {
1675 			if (IS_UE(flt_stat[i].mf_cntl, ptrl_error)) {
1676 				(void) do_rewrite(mcp,
1677 				    flt_stat[i].mf_flt_maddr.ma_bank,
1678 				    flt_stat[i].mf_flt_maddr.ma_dimm_addr);
1679 				flt_stat[i].mf_type = FLT_TYPE_UE;
1680 				MAC_SET_ERRLOG_INFO(&flt_stat[i]);
1681 				mc_aflt->mflt_erpt_class = MC_OPL_SUE;
1682 				mc_aflt->mflt_stat[0] = &flt_stat[i];
1683 				mc_aflt->mflt_nflts = 1;
1684 				mc_aflt->mflt_pr = PR_MCE;
1685 				mc_err_drain(mc_aflt);
1686 				rv = 1;
1687 			}
1688 		}
1689 	}
1690 	return (rv);
1691 }
1692 static void
1693 mc_error_handler_mir(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
1694 {
1695 	mc_aflt_t mc_aflt;
1696 	mc_flt_stat_t flt_stat[2], mi_flt_stat[2];
1697 	int i;
1698 	int mi_valid;
1699 
1700 	ASSERT(rsaddr);
1701 
1702 	bzero(&mc_aflt, sizeof (mc_aflt_t));
1703 	bzero(&flt_stat, 2 * sizeof (mc_flt_stat_t));
1704 	bzero(&mi_flt_stat, 2 * sizeof (mc_flt_stat_t));
1705 
1706 
1707 	mc_aflt.mflt_mcp = mcp;
1708 	mc_aflt.mflt_id = gethrtime();
1709 
1710 	/* Now read all the registers into flt_stat */
1711 
1712 	for (i = 0; i < 2; i++) {
1713 		MC_LOG("Reading registers of bank %d\n", bank);
1714 		/* patrol registers */
1715 		mc_read_ptrl_reg(mcp, bank, &flt_stat[i]);
1716 
1717 		/*
1718 		 * In mirror mode, it is possible that only one bank
1719 		 * may report the error. We need to check for it to
1720 		 * ensure we pick the right addr value for patrol restart.
1721 		 * Note that if both banks reported errors, we pick the
1722 		 * 2nd one. Both banks should reported the same error address.
1723 		 */
1724 		if (flt_stat[i].mf_cntl & MAC_CNTL_PTRL_ERRS)
1725 			rsaddr->mi_restartaddr = flt_stat[i].mf_flt_maddr;
1726 
1727 		MC_LOG("ptrl registers cntl %x add %x log %x\n",
1728 		    flt_stat[i].mf_cntl, flt_stat[i].mf_err_add,
1729 		    flt_stat[i].mf_err_log);
1730 
1731 		/* MI registers */
1732 		mc_read_mi_reg(mcp, bank, &mi_flt_stat[i]);
1733 
1734 		MC_LOG("MI registers cntl %x add %x log %x\n",
1735 		    mi_flt_stat[i].mf_cntl, mi_flt_stat[i].mf_err_add,
1736 		    mi_flt_stat[i].mf_err_log);
1737 
1738 		bank = bank^1;
1739 	}
1740 
1741 	/* clear errors once we read all the registers */
1742 	MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1743 
1744 	MAC_CLEAR_ERRS(mcp, bank ^ 1, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1745 
1746 	/* Process MI errors first */
1747 
1748 	/* if not error mode, cntl1 is 0 */
1749 	if ((mi_flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
1750 	    (mi_flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
1751 		mi_flt_stat[0].mf_cntl = 0;
1752 
1753 	if ((mi_flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
1754 	    (mi_flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
1755 		mi_flt_stat[1].mf_cntl = 0;
1756 
1757 	mc_aflt.mflt_is_ptrl = 0;
1758 	mi_valid = mc_process_error_mir(mcp, &mc_aflt, &mi_flt_stat[0]);
1759 
1760 	if ((((flt_stat[0].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
1761 	    MAC_CNTL_PTRL_ERR_SHIFT) == ((mi_flt_stat[0].mf_cntl &
1762 	    MAC_CNTL_MI_ERRS) >> MAC_CNTL_MI_ERR_SHIFT)) &&
1763 	    (flt_stat[0].mf_err_add == mi_flt_stat[0].mf_err_add) &&
1764 	    (((flt_stat[1].mf_cntl & MAC_CNTL_PTRL_ERRS) >>
1765 	    MAC_CNTL_PTRL_ERR_SHIFT) == ((mi_flt_stat[1].mf_cntl &
1766 	    MAC_CNTL_MI_ERRS) >> MAC_CNTL_MI_ERR_SHIFT)) &&
1767 	    (flt_stat[1].mf_err_add == mi_flt_stat[1].mf_err_add)) {
1768 #ifdef DEBUG
1769 		MC_LOG("discarding PTRL error because "
1770 		    "it is the same as MI\n");
1771 #endif
1772 		rsaddr->mi_valid = mi_valid;
1773 		return;
1774 	}
1775 	/* if not error mode, cntl1 is 0 */
1776 	if ((flt_stat[0].mf_err_add & MAC_ERR_ADD_INVALID) ||
1777 	    (flt_stat[0].mf_err_log & MAC_ERR_LOG_INVALID))
1778 		flt_stat[0].mf_cntl = 0;
1779 
1780 	if ((flt_stat[1].mf_err_add & MAC_ERR_ADD_INVALID) ||
1781 	    (flt_stat[1].mf_err_log & MAC_ERR_LOG_INVALID))
1782 		flt_stat[1].mf_cntl = 0;
1783 
1784 	mc_aflt.mflt_is_ptrl = 1;
1785 	rsaddr->mi_valid = mc_process_error_mir(mcp, &mc_aflt, &flt_stat[0]);
1786 }
1787 static int
1788 mc_process_error(mc_opl_t *mcp, int bank, mc_aflt_t *mc_aflt,
1789 	mc_flt_stat_t *flt_stat)
1790 {
1791 	int ptrl_error = mc_aflt->mflt_is_ptrl;
1792 	int rv = 0;
1793 
1794 	mc_aflt->mflt_erpt_class = NULL;
1795 	if (IS_UE(flt_stat->mf_cntl, ptrl_error)) {
1796 		MC_LOG("UE detected\n");
1797 		flt_stat->mf_type = FLT_TYPE_UE;
1798 		mc_aflt->mflt_erpt_class = MC_OPL_UE;
1799 		mc_aflt->mflt_pr = PR_UE;
1800 		MAC_SET_ERRLOG_INFO(flt_stat);
1801 		rv = 1;
1802 	} else if (IS_CE(flt_stat->mf_cntl, ptrl_error)) {
1803 		MC_LOG("CE detected\n");
1804 		MAC_SET_ERRLOG_INFO(flt_stat);
1805 
1806 		/* Error type can change after scrubbing */
1807 		mc_scrub_ce(mcp, bank, flt_stat, ptrl_error);
1808 
1809 		if (flt_stat->mf_type == FLT_TYPE_INTERMITTENT_CE) {
1810 			mc_aflt->mflt_erpt_class = MC_OPL_ICE;
1811 			mc_aflt->mflt_pr = PR_MCE;
1812 		} else if (flt_stat->mf_type == FLT_TYPE_PERMANENT_CE) {
1813 			mc_aflt->mflt_erpt_class = MC_OPL_CE;
1814 			mc_aflt->mflt_pr = PR_MCE;
1815 		} else if (flt_stat->mf_type == FLT_TYPE_UE) {
1816 			mc_aflt->mflt_erpt_class = MC_OPL_UE;
1817 			mc_aflt->mflt_pr = PR_UE;
1818 		}
1819 		rv = 1;
1820 	}
1821 	MC_LOG("mc_process_error: fault type %x erpt %s\n", flt_stat->mf_type,
1822 	    mc_aflt->mflt_erpt_class);
1823 	if (mc_aflt->mflt_erpt_class) {
1824 		mc_aflt->mflt_stat[0] = flt_stat;
1825 		mc_aflt->mflt_nflts = 1;
1826 		mc_err_drain(mc_aflt);
1827 	}
1828 	return (rv);
1829 }
1830 
1831 static void
1832 mc_error_handler(mc_opl_t *mcp, int bank, mc_rsaddr_info_t *rsaddr)
1833 {
1834 	mc_aflt_t mc_aflt;
1835 	mc_flt_stat_t flt_stat, mi_flt_stat;
1836 	int mi_valid;
1837 
1838 	bzero(&mc_aflt, sizeof (mc_aflt_t));
1839 	bzero(&flt_stat, sizeof (mc_flt_stat_t));
1840 	bzero(&mi_flt_stat, sizeof (mc_flt_stat_t));
1841 
1842 	mc_aflt.mflt_mcp = mcp;
1843 	mc_aflt.mflt_id = gethrtime();
1844 
1845 	/* patrol registers */
1846 	mc_read_ptrl_reg(mcp, bank, &flt_stat);
1847 
1848 	ASSERT(rsaddr);
1849 	rsaddr->mi_restartaddr = flt_stat.mf_flt_maddr;
1850 
1851 	MC_LOG("ptrl registers cntl %x add %x log %x\n", flt_stat.mf_cntl,
1852 	    flt_stat.mf_err_add, flt_stat.mf_err_log);
1853 
1854 	/* MI registers */
1855 	mc_read_mi_reg(mcp, bank, &mi_flt_stat);
1856 
1857 
1858 	MC_LOG("MI registers cntl %x add %x log %x\n", mi_flt_stat.mf_cntl,
1859 	    mi_flt_stat.mf_err_add, mi_flt_stat.mf_err_log);
1860 
1861 	/* clear errors once we read all the registers */
1862 	MAC_CLEAR_ERRS(mcp, bank, (MAC_CNTL_PTRL_ERRS|MAC_CNTL_MI_ERRS));
1863 
1864 	mc_aflt.mflt_is_ptrl = 0;
1865 	if ((mi_flt_stat.mf_cntl & MAC_CNTL_MI_ERRS) &&
1866 	    ((mi_flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
1867 	    ((mi_flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
1868 		mi_valid = mc_process_error(mcp, bank, &mc_aflt, &mi_flt_stat);
1869 	}
1870 
1871 	if ((((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) >>
1872 	    MAC_CNTL_PTRL_ERR_SHIFT) == ((mi_flt_stat.mf_cntl &
1873 	    MAC_CNTL_MI_ERRS) >> MAC_CNTL_MI_ERR_SHIFT)) &&
1874 	    (flt_stat.mf_err_add == mi_flt_stat.mf_err_add)) {
1875 #ifdef DEBUG
1876 		MC_LOG("discarding PTRL error because "
1877 		    "it is the same as MI\n");
1878 #endif
1879 		rsaddr->mi_valid = mi_valid;
1880 		return;
1881 	}
1882 
1883 	mc_aflt.mflt_is_ptrl = 1;
1884 	if ((flt_stat.mf_cntl & MAC_CNTL_PTRL_ERRS) &&
1885 	    ((flt_stat.mf_err_add & MAC_ERR_ADD_INVALID) == 0) &&
1886 	    ((flt_stat.mf_err_log & MAC_ERR_LOG_INVALID) == 0)) {
1887 		rsaddr->mi_valid = mc_process_error(mcp, bank, &mc_aflt,
1888 		    &flt_stat);
1889 	}
1890 }
1891 /*
1892  *	memory patrol error handling algorithm:
1893  *	timeout() is used to do periodic polling
1894  *	This is the flow chart.
1895  *	timeout ->
1896  *	mc_check_errors()
1897  *	    if memory bank is installed, read the status register
1898  *	    if any error bit is set,
1899  *	    -> mc_error_handler()
1900  *		-> read all error registers
1901  *	        -> mc_process_error()
1902  *	            determine error type
1903  *	            rewrite to clear error or scrub to determine CE type
1904  *	            inform SCF on permanent CE
1905  *	        -> mc_err_drain
1906  *	            page offline processing
1907  *	            -> mc_ereport_post()
1908  */
1909 
1910 static void
1911 mc_check_errors_func(mc_opl_t *mcp)
1912 {
1913 	mc_rsaddr_info_t rsaddr_info;
1914 	int i, error_count = 0;
1915 	uint32_t stat, cntl;
1916 	int running;
1917 	int wrapped;
1918 	int ebk;
1919 
1920 	/*
1921 	 * scan errors.
1922 	 */
1923 	if (mcp->mc_status & MC_MEMORYLESS)
1924 		return;
1925 
1926 	for (i = 0; i < BANKNUM_PER_SB; i++) {
1927 		if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
1928 			stat = ldphysio(MAC_PTRL_STAT(mcp, i));
1929 			cntl = ldphysio(MAC_PTRL_CNTL(mcp, i));
1930 			running = cntl & MAC_CNTL_PTRL_START;
1931 			wrapped = cntl & MAC_CNTL_PTRL_ADD_MAX;
1932 
1933 			/* Compute the effective bank idx */
1934 			ebk = (IS_MIRROR(mcp, i)) ? MIRROR_IDX(i) : i;
1935 
1936 			if (mc_debug_show_all || stat) {
1937 				MC_LOG("/LSB%d/B%d stat %x cntl %x\n",
1938 				    mcp->mc_board_num, i, stat, cntl);
1939 			}
1940 
1941 			/*
1942 			 * Update stats and reset flag if the HW patrol
1943 			 * wrapped around in its scan.
1944 			 */
1945 			if (wrapped) {
1946 				MAC_CLEAR_MAX(mcp, i);
1947 				mcp->mc_period[ebk]++;
1948 				if (IS_MIRROR(mcp, i))
1949 					MC_LOG("mirror mc period %ld on "
1950 					    "/LSB%d/B%d\n", mcp->mc_period[ebk],
1951 					    mcp->mc_board_num, i);
1952 				else {
1953 					MC_LOG("mc period %ld on "
1954 					    "/LSB%d/B%d\n", mcp->mc_period[ebk],
1955 					    mcp->mc_board_num, i);
1956 				}
1957 			}
1958 
1959 			if (running) {
1960 				/*
1961 				 * Mac patrol HW is still running.
1962 				 * Normally when an error is detected,
1963 				 * the HW patrol will stop so that we
1964 				 * can collect error data for reporting.
1965 				 * Certain errors (MI errors) detected may not
1966 				 * cause the HW patrol to stop which is a
1967 				 * problem since we cannot read error data while
1968 				 * the HW patrol is running. SW is not allowed
1969 				 * to stop the HW patrol while it is running
1970 				 * as it may cause HW inconsistency. This is
1971 				 * described in a HW errata.
1972 				 * In situations where we detected errors
1973 				 * that may not cause the HW patrol to stop.
1974 				 * We speed up the HW patrol scanning in
1975 				 * the hope that it will find the 'real' PTRL
1976 				 * errors associated with the previous errors
1977 				 * causing the HW to finally stop so that we
1978 				 * can do the reporting.
1979 				 */
1980 				/*
1981 				 * Check to see if we did speed up
1982 				 * the HW patrol due to previous errors
1983 				 * detected that did not cause the patrol
1984 				 * to stop. We only do it if HW patrol scan
1985 				 * wrapped (counted as completing a 'period').
1986 				 */
1987 				if (mcp->mc_speedup_period[ebk] > 0) {
1988 					if (wrapped &&
1989 					    (--mcp->mc_speedup_period[ebk] ==
1990 					    0)) {
1991 						/*
1992 						 * We did try to speed up.
1993 						 * The speed up period has
1994 						 * expired and the HW patrol
1995 						 * is still running.  The
1996 						 * errors must be intermittent.
1997 						 * We have no choice but to
1998 						 * ignore them, reset the scan
1999 						 * speed to normal and clear
2000 						 * the MI error bits. For
2001 						 * mirror mode, we need to
2002 						 * clear errors on both banks.
2003 						 */
2004 						MC_LOG("Clearing MI errors\n");
2005 						MAC_CLEAR_ERRS(mcp, i,
2006 						    MAC_CNTL_MI_ERRS);
2007 
2008 						if (IS_MIRROR(mcp, i)) {
2009 							MC_LOG("Clearing "
2010 							    "Mirror MI errs\n");
2011 							MAC_CLEAR_ERRS(mcp,
2012 							    i^1,
2013 							    MAC_CNTL_MI_ERRS);
2014 						}
2015 					}
2016 				} else if (stat & MAC_STAT_MI_ERRS) {
2017 					/*
2018 					 * MI errors detected but we cannot
2019 					 * report them since the HW patrol
2020 					 * is still running.
2021 					 * We will attempt to speed up the
2022 					 * scanning and hopefully the HW
2023 					 * can detect PRTL errors at the same
2024 					 * location that cause the HW patrol
2025 					 * to stop.
2026 					 */
2027 					mcp->mc_speedup_period[ebk] = 2;
2028 					MAC_CMD(mcp, i, 0);
2029 				}
2030 			} else if (stat & (MAC_STAT_PTRL_ERRS |
2031 			    MAC_STAT_MI_ERRS)) {
2032 				/*
2033 				 * HW Patrol has stopped and we found errors.
2034 				 * Proceed to collect and report error info.
2035 				 */
2036 				mcp->mc_speedup_period[ebk] = 0;
2037 				rsaddr_info.mi_valid = 0;
2038 				rsaddr_info.mi_injectrestart = 0;
2039 				if (IS_MIRROR(mcp, i)) {
2040 					mc_error_handler_mir(mcp, i,
2041 					    &rsaddr_info);
2042 				} else {
2043 					mc_error_handler(mcp, i, &rsaddr_info);
2044 				}
2045 
2046 				error_count++;
2047 				restart_patrol(mcp, i, &rsaddr_info);
2048 			} else {
2049 				/*
2050 				 * HW patrol scan has apparently stopped
2051 				 * but no errors detected/flagged.
2052 				 * Restart the HW patrol just to be sure.
2053 				 * In mirror mode, the odd bank might have
2054 				 * reported errors that caused the patrol to
2055 				 * stop. We'll defer the restart to the odd
2056 				 * bank in this case.
2057 				 */
2058 				if (!IS_MIRROR(mcp, i) || (i & 0x1))
2059 					restart_patrol(mcp, i, NULL);
2060 			}
2061 		}
2062 	}
2063 	if (error_count > 0)
2064 		mcp->mc_last_error += error_count;
2065 	else
2066 		mcp->mc_last_error = 0;
2067 }
2068 
2069 /*
2070  * mc_polling -- Check errors for only one instance,
2071  * but process errors for all instances to make sure we drain the errors
2072  * faster than they can be accumulated.
2073  *
2074  * Polling on each board should be done only once per each
2075  * mc_patrol_interval_sec.  This is equivalent to setting mc_tick_left
2076  * to OPL_MAX_BOARDS and decrement by 1 on each timeout.
2077  * Once mc_tick_left becomes negative, the board becomes a candidate
2078  * for polling because it has waited for at least
2079  * mc_patrol_interval_sec's long.    If mc_timeout_period is calculated
2080  * differently, this has to be updated accordingly.
2081  */
2082 
2083 static void
2084 mc_polling(void)
2085 {
2086 	int i, scan_error;
2087 	mc_opl_t *mcp;
2088 
2089 
2090 	scan_error = 1;
2091 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
2092 		mutex_enter(&mcmutex);
2093 		if ((mcp = mc_instances[i]) == NULL) {
2094 			mutex_exit(&mcmutex);
2095 			continue;
2096 		}
2097 		mutex_enter(&mcp->mc_lock);
2098 		mutex_exit(&mcmutex);
2099 		if (!(mcp->mc_status & MC_POLL_RUNNING)) {
2100 			mutex_exit(&mcp->mc_lock);
2101 			continue;
2102 		}
2103 		if (scan_error && mcp->mc_tick_left <= 0) {
2104 			mc_check_errors_func((void *)mcp);
2105 			mcp->mc_tick_left = OPL_MAX_BOARDS;
2106 			scan_error = 0;
2107 		} else {
2108 			mcp->mc_tick_left--;
2109 		}
2110 		mc_process_scf_log(mcp);
2111 		mutex_exit(&mcp->mc_lock);
2112 	}
2113 }
2114 
2115 static void
2116 get_ptrl_start_address(mc_opl_t *mcp, int bank, mc_addr_t *maddr)
2117 {
2118 	maddr->ma_bd = mcp->mc_board_num;
2119 	maddr->ma_bank = bank;
2120 	maddr->ma_dimm_addr = 0;
2121 }
2122 
2123 typedef struct mc_mem_range {
2124 	uint64_t	addr;
2125 	uint64_t	size;
2126 } mc_mem_range_t;
2127 
2128 static int
2129 get_base_address(mc_opl_t *mcp)
2130 {
2131 	mc_mem_range_t *mem_range;
2132 	int len;
2133 
2134 	if (ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
2135 	    "sb-mem-ranges", (caddr_t)&mem_range, &len) != DDI_SUCCESS) {
2136 		return (DDI_FAILURE);
2137 	}
2138 
2139 	mcp->mc_start_address = mem_range->addr;
2140 	mcp->mc_size = mem_range->size;
2141 
2142 	kmem_free(mem_range, len);
2143 	return (DDI_SUCCESS);
2144 }
2145 
2146 struct mc_addr_spec {
2147 	uint32_t bank;
2148 	uint32_t phys_hi;
2149 	uint32_t phys_lo;
2150 };
2151 
2152 #define	REGS_PA(m, i) ((((uint64_t)m[i].phys_hi)<<32) | m[i].phys_lo)
2153 
2154 static char *mc_tbl_name[] = {
2155 	"cs0-mc-pa-trans-table",
2156 	"cs1-mc-pa-trans-table"
2157 };
2158 
2159 /*
2160  * This routine performs a rangecheck for a given PA
2161  * to see if it belongs to the memory range for this board.
2162  * Return 1 if it is valid (within the range) and 0 otherwise
2163  */
2164 static int
2165 mc_rangecheck_pa(mc_opl_t *mcp, uint64_t pa)
2166 {
2167 	if ((pa < mcp->mc_start_address) || (mcp->mc_start_address +
2168 	    mcp->mc_size <= pa))
2169 		return (0);
2170 	else
2171 		return (1);
2172 }
2173 
2174 static void
2175 mc_memlist_delete(struct memlist *mlist)
2176 {
2177 	struct memlist *ml;
2178 
2179 	for (ml = mlist; ml; ml = mlist) {
2180 		mlist = ml->next;
2181 		kmem_free(ml, sizeof (struct memlist));
2182 	}
2183 }
2184 
2185 static struct memlist *
2186 mc_memlist_dup(struct memlist *mlist)
2187 {
2188 	struct memlist *hl = NULL, *tl, **mlp;
2189 
2190 	if (mlist == NULL)
2191 		return (NULL);
2192 
2193 	mlp = &hl;
2194 	tl = *mlp;
2195 	for (; mlist; mlist = mlist->next) {
2196 		*mlp = kmem_alloc(sizeof (struct memlist), KM_SLEEP);
2197 		(*mlp)->address = mlist->address;
2198 		(*mlp)->size = mlist->size;
2199 		(*mlp)->prev = tl;
2200 		tl = *mlp;
2201 		mlp = &((*mlp)->next);
2202 	}
2203 	*mlp = NULL;
2204 
2205 	return (hl);
2206 }
2207 
2208 
2209 static struct memlist *
2210 mc_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
2211 {
2212 	uint64_t	end;
2213 	struct memlist	*ml, *tl, *nlp;
2214 
2215 	if (mlist == NULL)
2216 		return (NULL);
2217 
2218 	end = base + len;
2219 	if ((end <= mlist->address) || (base == end))
2220 		return (mlist);
2221 
2222 	for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
2223 		uint64_t	mend;
2224 
2225 		nlp = ml->next;
2226 
2227 		if (end <= ml->address)
2228 			break;
2229 
2230 		mend = ml->address + ml->size;
2231 		if (base < mend) {
2232 			if (base <= ml->address) {
2233 				ml->address = end;
2234 				if (end >= mend)
2235 					ml->size = 0ull;
2236 				else
2237 					ml->size = mend - ml->address;
2238 			} else {
2239 				ml->size = base - ml->address;
2240 				if (end < mend) {
2241 					struct memlist	*nl;
2242 					/*
2243 					 * splitting an memlist entry.
2244 					 */
2245 					nl = kmem_alloc(sizeof (struct memlist),
2246 					    KM_SLEEP);
2247 					nl->address = end;
2248 					nl->size = mend - nl->address;
2249 					if ((nl->next = nlp) != NULL)
2250 						nlp->prev = nl;
2251 					nl->prev = ml;
2252 					ml->next = nl;
2253 					nlp = nl;
2254 				}
2255 			}
2256 			if (ml->size == 0ull) {
2257 				if (ml == mlist) {
2258 					if ((mlist = nlp) != NULL)
2259 						nlp->prev = NULL;
2260 					kmem_free(ml, sizeof (struct memlist));
2261 					if (mlist == NULL)
2262 						break;
2263 					ml = nlp;
2264 				} else {
2265 					if ((tl->next = nlp) != NULL)
2266 						nlp->prev = tl;
2267 					kmem_free(ml, sizeof (struct memlist));
2268 					ml = tl;
2269 				}
2270 			}
2271 		}
2272 	}
2273 
2274 	return (mlist);
2275 }
2276 
2277 static void
2278 mc_get_mlist(mc_opl_t *mcp)
2279 {
2280 	struct memlist *mlist;
2281 
2282 	memlist_read_lock();
2283 	mlist = mc_memlist_dup(phys_install);
2284 	memlist_read_unlock();
2285 
2286 	if (mlist) {
2287 		mlist = mc_memlist_del_span(mlist, 0ull, mcp->mc_start_address);
2288 	}
2289 
2290 	if (mlist) {
2291 		uint64_t startpa, endpa;
2292 
2293 		startpa = mcp->mc_start_address + mcp->mc_size;
2294 		endpa = ptob(physmax + 1);
2295 		if (endpa > startpa) {
2296 			mlist = mc_memlist_del_span(mlist, startpa,
2297 			    endpa - startpa);
2298 		}
2299 	}
2300 
2301 	if (mlist) {
2302 		mcp->mlist = mlist;
2303 	}
2304 }
2305 
2306 int
2307 mc_board_add(mc_opl_t *mcp)
2308 {
2309 	struct mc_addr_spec *macaddr;
2310 	cs_status_t *cs_status;
2311 	int len, len1, i, bk, cc;
2312 	mc_rsaddr_info_t rsaddr;
2313 	uint32_t mirr;
2314 	int nbanks = 0;
2315 	uint64_t nbytes = 0;
2316 	int mirror_mode = 0;
2317 	int ret;
2318 
2319 	/*
2320 	 * Get configurations from "pseudo-mc" node which includes:
2321 	 * board# : LSB number
2322 	 * mac-addr : physical base address of MAC registers
2323 	 * csX-mac-pa-trans-table: translation table from DIMM address
2324 	 *			to physical address or vice versa.
2325 	 */
2326 	mcp->mc_board_num = (int)ddi_getprop(DDI_DEV_T_ANY, mcp->mc_dip,
2327 	    DDI_PROP_DONTPASS, "board#", -1);
2328 
2329 	if (mcp->mc_board_num == -1) {
2330 		return (DDI_FAILURE);
2331 	}
2332 
2333 	/*
2334 	 * Get start address in this CAB. It can be gotten from
2335 	 * "sb-mem-ranges" property.
2336 	 */
2337 
2338 	if (get_base_address(mcp) == DDI_FAILURE) {
2339 		return (DDI_FAILURE);
2340 	}
2341 	/* get mac-pa trans tables */
2342 	for (i = 0; i < MC_TT_CS; i++) {
2343 		len = MC_TT_ENTRIES;
2344 		cc = ddi_getlongprop_buf(DDI_DEV_T_ANY, mcp->mc_dip,
2345 		    DDI_PROP_DONTPASS, mc_tbl_name[i],
2346 		    (caddr_t)mcp->mc_trans_table[i], &len);
2347 
2348 		if (cc != DDI_SUCCESS) {
2349 			bzero(mcp->mc_trans_table[i], MC_TT_ENTRIES);
2350 		}
2351 	}
2352 	mcp->mlist = NULL;
2353 
2354 	mc_get_mlist(mcp);
2355 
2356 	/* initialize bank informations */
2357 	cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
2358 	    "mc-addr", (caddr_t)&macaddr, &len);
2359 	if (cc != DDI_SUCCESS) {
2360 		cmn_err(CE_WARN, "Cannot get mc-addr. err=%d\n", cc);
2361 		return (DDI_FAILURE);
2362 	}
2363 
2364 	cc = ddi_getlongprop(DDI_DEV_T_ANY, mcp->mc_dip, DDI_PROP_DONTPASS,
2365 	    "cs-status", (caddr_t)&cs_status, &len1);
2366 
2367 	if (cc != DDI_SUCCESS) {
2368 		if (len > 0)
2369 			kmem_free(macaddr, len);
2370 		cmn_err(CE_WARN, "Cannot get cs-status. err=%d\n", cc);
2371 		return (DDI_FAILURE);
2372 	}
2373 	/* get the physical board number for a given logical board number */
2374 	mcp->mc_phys_board_num = mc_opl_get_physical_board(mcp->mc_board_num);
2375 
2376 	if (mcp->mc_phys_board_num < 0) {
2377 		if (len > 0)
2378 			kmem_free(macaddr, len);
2379 		cmn_err(CE_WARN, "Unable to obtain the physical board number");
2380 		return (DDI_FAILURE);
2381 	}
2382 
2383 	mutex_init(&mcp->mc_lock, NULL, MUTEX_DRIVER, NULL);
2384 
2385 	for (i = 0; i < len1 / sizeof (cs_status_t); i++) {
2386 		nbytes += ((uint64_t)cs_status[i].cs_avail_hi << 32) |
2387 		    ((uint64_t)cs_status[i].cs_avail_low);
2388 	}
2389 	if (len1 > 0)
2390 		kmem_free(cs_status, len1);
2391 	nbanks = len / sizeof (struct mc_addr_spec);
2392 
2393 	if (nbanks > 0)
2394 		nbytes /= nbanks;
2395 	else {
2396 		/* No need to free macaddr because len must be 0 */
2397 		mcp->mc_status |= MC_MEMORYLESS;
2398 		return (DDI_SUCCESS);
2399 	}
2400 
2401 	for (i = 0; i < BANKNUM_PER_SB; i++) {
2402 		mcp->mc_scf_retry[i] = 0;
2403 		mcp->mc_period[i] = 0;
2404 		mcp->mc_speedup_period[i] = 0;
2405 	}
2406 
2407 	/*
2408 	 * Get the memory size here. Let it be B (bytes).
2409 	 * Let T be the time in u.s. to scan 64 bytes.
2410 	 * If we want to complete 1 round of scanning in P seconds.
2411 	 *
2412 	 *	B * T * 10^(-6)	= P
2413 	 *	---------------
2414 	 *		64
2415 	 *
2416 	 *	T = P * 64 * 10^6
2417 	 *	    -------------
2418 	 *		B
2419 	 *
2420 	 *	  = P * 64 * 10^6
2421 	 *	    -------------
2422 	 *		B
2423 	 *
2424 	 *	The timing bits are set in PTRL_CNTL[28:26] where
2425 	 *
2426 	 *	0	- 1 m.s
2427 	 *	1	- 512 u.s.
2428 	 *	10	- 256 u.s.
2429 	 *	11	- 128 u.s.
2430 	 *	100	- 64 u.s.
2431 	 *	101	- 32 u.s.
2432 	 *	110	- 0 u.s.
2433 	 *	111	- reserved.
2434 	 *
2435 	 *
2436 	 *	a[0] = 110, a[1] = 101, ... a[6] = 0
2437 	 *
2438 	 *	cs-status property is int x 7
2439 	 *	0 - cs#
2440 	 *	1 - cs-status
2441 	 *	2 - cs-avail.hi
2442 	 *	3 - cs-avail.lo
2443 	 *	4 - dimm-capa.hi
2444 	 *	5 - dimm-capa.lo
2445 	 *	6 - #of dimms
2446 	 */
2447 
2448 	if (nbytes > 0) {
2449 		int i;
2450 		uint64_t ms;
2451 		ms = ((uint64_t)mc_scan_period * 64 * 1000000)/nbytes;
2452 		mcp->mc_speed = mc_scan_speeds[MC_MAX_SPEEDS - 1].mc_speeds;
2453 		for (i = 0; i < MC_MAX_SPEEDS - 1; i++) {
2454 			if (ms < mc_scan_speeds[i + 1].mc_period) {
2455 				mcp->mc_speed = mc_scan_speeds[i].mc_speeds;
2456 				break;
2457 			}
2458 		}
2459 	} else
2460 		mcp->mc_speed = 0;
2461 
2462 
2463 	for (i = 0; i < len / sizeof (struct mc_addr_spec); i++) {
2464 		struct mc_bank *bankp;
2465 		uint32_t reg;
2466 
2467 		/*
2468 		 * setup bank
2469 		 */
2470 		bk = macaddr[i].bank;
2471 		bankp = &(mcp->mc_bank[bk]);
2472 		bankp->mcb_status = BANK_INSTALLED;
2473 		bankp->mcb_reg_base = REGS_PA(macaddr, i);
2474 
2475 		reg = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bk));
2476 		bankp->mcb_ptrl_cntl = (reg & MAC_CNTL_PTRL_PRESERVE_BITS);
2477 
2478 		/*
2479 		 * check if mirror mode
2480 		 */
2481 		mirr = LD_MAC_REG(MAC_MIRR(mcp, bk));
2482 
2483 		if (mirr & MAC_MIRR_MIRROR_MODE) {
2484 			MC_LOG("Mirror -> /LSB%d/B%d\n", mcp->mc_board_num,
2485 			    bk);
2486 			bankp->mcb_status |= BANK_MIRROR_MODE;
2487 			mirror_mode = 1;
2488 			/*
2489 			 * The following bit is only used for
2490 			 * error injection.  We should clear it
2491 			 */
2492 			if (mirr & MAC_MIRR_BANK_EXCLUSIVE)
2493 				ST_MAC_REG(MAC_MIRR(mcp, bk), 0);
2494 		}
2495 
2496 		/*
2497 		 * restart if not mirror mode or the other bank
2498 		 * of the mirror is not running
2499 		 */
2500 		if (!(mirr & MAC_MIRR_MIRROR_MODE) ||
2501 		    !(mcp->mc_bank[bk^1].mcb_status & BANK_PTRL_RUNNING)) {
2502 			MC_LOG("Starting up /LSB%d/B%d\n", mcp->mc_board_num,
2503 			    bk);
2504 			get_ptrl_start_address(mcp, bk, &rsaddr.mi_restartaddr);
2505 			rsaddr.mi_valid = 0;
2506 			rsaddr.mi_injectrestart = 0;
2507 			restart_patrol(mcp, bk, &rsaddr);
2508 		} else {
2509 			MC_LOG("Not starting up /LSB%d/B%d\n",
2510 			    mcp->mc_board_num, bk);
2511 		}
2512 		bankp->mcb_status |= BANK_PTRL_RUNNING;
2513 	}
2514 	if (len > 0)
2515 		kmem_free(macaddr, len);
2516 
2517 	ret = ndi_prop_update_int(DDI_DEV_T_NONE, mcp->mc_dip, "mirror-mode",
2518 	    mirror_mode);
2519 	if (ret != DDI_PROP_SUCCESS) {
2520 		cmn_err(CE_WARN, "Unable to update mirror-mode property");
2521 	}
2522 
2523 	mcp->mc_dimm_list = mc_get_dimm_list(mcp);
2524 
2525 	/*
2526 	 * set interval in HZ.
2527 	 */
2528 	mcp->mc_last_error = 0;
2529 
2530 	/* restart memory patrol checking */
2531 	mcp->mc_status |= MC_POLL_RUNNING;
2532 
2533 	return (DDI_SUCCESS);
2534 }
2535 
2536 int
2537 mc_board_del(mc_opl_t *mcp)
2538 {
2539 	int i;
2540 	scf_log_t *p;
2541 
2542 	/*
2543 	 * cleanup mac state
2544 	 */
2545 	mutex_enter(&mcp->mc_lock);
2546 	if (mcp->mc_status & MC_MEMORYLESS) {
2547 		mutex_exit(&mcp->mc_lock);
2548 		mutex_destroy(&mcp->mc_lock);
2549 		return (DDI_SUCCESS);
2550 	}
2551 	for (i = 0; i < BANKNUM_PER_SB; i++) {
2552 		if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
2553 			mcp->mc_bank[i].mcb_status &= ~BANK_INSTALLED;
2554 		}
2555 	}
2556 
2557 	/* stop memory patrol checking */
2558 	mcp->mc_status &= ~MC_POLL_RUNNING;
2559 
2560 	/* just throw away all the scf logs */
2561 	for (i = 0; i < BANKNUM_PER_SB; i++) {
2562 		while ((p = mcp->mc_scf_log[i]) != NULL) {
2563 			mcp->mc_scf_log[i] = p->sl_next;
2564 			mcp->mc_scf_total[i]--;
2565 			kmem_free(p, sizeof (scf_log_t));
2566 		}
2567 	}
2568 
2569 	if (mcp->mlist)
2570 		mc_memlist_delete(mcp->mlist);
2571 
2572 	if (mcp->mc_dimm_list)
2573 		mc_free_dimm_list(mcp->mc_dimm_list);
2574 
2575 	mutex_exit(&mcp->mc_lock);
2576 
2577 	mutex_destroy(&mcp->mc_lock);
2578 	return (DDI_SUCCESS);
2579 }
2580 
2581 int
2582 mc_suspend(mc_opl_t *mcp, uint32_t flag)
2583 {
2584 	/* stop memory patrol checking */
2585 	mutex_enter(&mcp->mc_lock);
2586 	if (mcp->mc_status & MC_MEMORYLESS) {
2587 		mutex_exit(&mcp->mc_lock);
2588 		return (DDI_SUCCESS);
2589 	}
2590 
2591 	mcp->mc_status &= ~MC_POLL_RUNNING;
2592 
2593 	mcp->mc_status |= flag;
2594 	mutex_exit(&mcp->mc_lock);
2595 
2596 	return (DDI_SUCCESS);
2597 }
2598 
2599 void
2600 opl_mc_update_mlist(void)
2601 {
2602 	int i;
2603 	mc_opl_t *mcp;
2604 
2605 	/*
2606 	 * memory information is not updated until
2607 	 * the post attach/detach stage during DR.
2608 	 * This interface is used by dr_mem to inform
2609 	 * mc-opl to update the mlist.
2610 	 */
2611 
2612 	mutex_enter(&mcmutex);
2613 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
2614 		if ((mcp = mc_instances[i]) == NULL)
2615 			continue;
2616 		mutex_enter(&mcp->mc_lock);
2617 		if (mcp->mlist)
2618 			mc_memlist_delete(mcp->mlist);
2619 		mcp->mlist = NULL;
2620 		mc_get_mlist(mcp);
2621 		mutex_exit(&mcp->mc_lock);
2622 	}
2623 	mutex_exit(&mcmutex);
2624 }
2625 
2626 /* caller must clear the SUSPEND bits or this will do nothing */
2627 
2628 int
2629 mc_resume(mc_opl_t *mcp, uint32_t flag)
2630 {
2631 	int i;
2632 	uint64_t basepa;
2633 
2634 	mutex_enter(&mcp->mc_lock);
2635 	if (mcp->mc_status & MC_MEMORYLESS) {
2636 		mutex_exit(&mcp->mc_lock);
2637 		return (DDI_SUCCESS);
2638 	}
2639 	basepa = mcp->mc_start_address;
2640 	if (get_base_address(mcp) == DDI_FAILURE) {
2641 		mutex_exit(&mcp->mc_lock);
2642 		return (DDI_FAILURE);
2643 	}
2644 
2645 	if (basepa != mcp->mc_start_address) {
2646 		if (mcp->mlist)
2647 			mc_memlist_delete(mcp->mlist);
2648 		mcp->mlist = NULL;
2649 		mc_get_mlist(mcp);
2650 	}
2651 
2652 	mcp->mc_status &= ~flag;
2653 
2654 	if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
2655 		mutex_exit(&mcp->mc_lock);
2656 		return (DDI_SUCCESS);
2657 	}
2658 
2659 	if (!(mcp->mc_status & MC_POLL_RUNNING)) {
2660 		/* restart memory patrol checking */
2661 		mcp->mc_status |= MC_POLL_RUNNING;
2662 		for (i = 0; i < BANKNUM_PER_SB; i++) {
2663 			if (mcp->mc_bank[i].mcb_status & BANK_INSTALLED) {
2664 				restart_patrol(mcp, i, NULL);
2665 			}
2666 		}
2667 	}
2668 	mutex_exit(&mcp->mc_lock);
2669 
2670 	return (DDI_SUCCESS);
2671 }
2672 
2673 static mc_opl_t *
2674 mc_pa_to_mcp(uint64_t pa)
2675 {
2676 	mc_opl_t *mcp;
2677 	int i;
2678 
2679 	ASSERT(MUTEX_HELD(&mcmutex));
2680 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
2681 		if ((mcp = mc_instances[i]) == NULL)
2682 			continue;
2683 		/* if mac patrol is suspended, we cannot rely on it */
2684 		if (!(mcp->mc_status & MC_POLL_RUNNING) ||
2685 		    (mcp->mc_status & MC_SOFT_SUSPENDED))
2686 			continue;
2687 		if (mc_rangecheck_pa(mcp, pa)) {
2688 			return (mcp);
2689 		}
2690 	}
2691 	return (NULL);
2692 }
2693 
2694 /*
2695  * Get Physical Board number from Logical one.
2696  */
2697 static int
2698 mc_opl_get_physical_board(int sb)
2699 {
2700 	if (&opl_get_physical_board) {
2701 		return (opl_get_physical_board(sb));
2702 	}
2703 
2704 	cmn_err(CE_NOTE, "!opl_get_physical_board() not loaded\n");
2705 	return (-1);
2706 }
2707 
2708 /* ARGSUSED */
2709 int
2710 mc_get_mem_unum(int synd_code, uint64_t flt_addr, char *buf, int buflen,
2711 	int *lenp)
2712 {
2713 	int i;
2714 	int j;
2715 	int sb;
2716 	int bank;
2717 	int cs;
2718 	mc_opl_t *mcp;
2719 	char memb_num;
2720 
2721 	mutex_enter(&mcmutex);
2722 
2723 	if (((mcp = mc_pa_to_mcp(flt_addr)) == NULL) ||
2724 	    (!pa_is_valid(mcp, flt_addr))) {
2725 		mutex_exit(&mcmutex);
2726 		if (snprintf(buf, buflen, "UNKNOWN") >= buflen) {
2727 			return (ENOSPC);
2728 		} else {
2729 			if (lenp)
2730 				*lenp = strlen(buf);
2731 		}
2732 		return (0);
2733 	}
2734 
2735 	bank = pa_to_bank(mcp, flt_addr - mcp->mc_start_address);
2736 	sb = mcp->mc_phys_board_num;
2737 	cs = pa_to_cs(mcp, flt_addr - mcp->mc_start_address);
2738 
2739 	if (sb == -1) {
2740 		mutex_exit(&mcmutex);
2741 		return (ENXIO);
2742 	}
2743 
2744 	if (plat_model == MODEL_DC) {
2745 		i = BD_BK_SLOT_TO_INDEX(0, bank, 0);
2746 		j = (cs == 0) ? i : i + 2;
2747 		snprintf(buf, buflen, "/%s%02d/MEM%s MEM%s",
2748 		    model_names[plat_model].unit_name, sb,
2749 		    mc_dc_dimm_unum_table[j],
2750 		    mc_dc_dimm_unum_table[j + 1]);
2751 	} else {
2752 		i = BD_BK_SLOT_TO_INDEX(sb, bank, 0);
2753 		j = (cs == 0) ? i : i + 2;
2754 		memb_num = mc_ff_dimm_unum_table[i][0];
2755 		snprintf(buf, buflen, "/%s/%s%c/MEM%s MEM%s",
2756 		    model_names[plat_model].unit_name,
2757 		    model_names[plat_model].mem_name, memb_num,
2758 		    &mc_ff_dimm_unum_table[j][1],
2759 		    &mc_ff_dimm_unum_table[j + 1][1]);
2760 	}
2761 	if (lenp) {
2762 		*lenp = strlen(buf);
2763 	}
2764 	mutex_exit(&mcmutex);
2765 	return (0);
2766 }
2767 
2768 int
2769 opl_mc_suspend(void)
2770 {
2771 	mc_opl_t *mcp;
2772 	int i;
2773 
2774 	mutex_enter(&mcmutex);
2775 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
2776 		if ((mcp = mc_instances[i]) == NULL)
2777 			continue;
2778 		mc_suspend(mcp, MC_SOFT_SUSPENDED);
2779 	}
2780 	mutex_exit(&mcmutex);
2781 
2782 	return (0);
2783 }
2784 
2785 int
2786 opl_mc_resume(void)
2787 {
2788 	mc_opl_t *mcp;
2789 	int i;
2790 
2791 	mutex_enter(&mcmutex);
2792 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
2793 		if ((mcp = mc_instances[i]) == NULL)
2794 			continue;
2795 		mc_resume(mcp, MC_SOFT_SUSPENDED);
2796 	}
2797 	mutex_exit(&mcmutex);
2798 
2799 	return (0);
2800 }
2801 static void
2802 insert_mcp(mc_opl_t *mcp)
2803 {
2804 	mutex_enter(&mcmutex);
2805 	if (mc_instances[mcp->mc_board_num] != NULL) {
2806 		MC_LOG("mc-opl instance for board# %d already exists\n",
2807 		    mcp->mc_board_num);
2808 	}
2809 	mc_instances[mcp->mc_board_num] = mcp;
2810 	mutex_exit(&mcmutex);
2811 }
2812 
2813 static void
2814 delete_mcp(mc_opl_t *mcp)
2815 {
2816 	mutex_enter(&mcmutex);
2817 	mc_instances[mcp->mc_board_num] = 0;
2818 	mutex_exit(&mcmutex);
2819 }
2820 
2821 /* Error injection interface */
2822 
2823 static void
2824 mc_lock_va(uint64_t pa, caddr_t new_va)
2825 {
2826 	tte_t tte;
2827 
2828 	vtag_flushpage(new_va, (uint64_t)ksfmmup);
2829 	sfmmu_memtte(&tte, pa >> PAGESHIFT, PROC_DATA|HAT_NOSYNC, TTE8K);
2830 	tte.tte_intlo |= TTE_LCK_INT;
2831 	sfmmu_dtlb_ld_kva(new_va, &tte);
2832 }
2833 
2834 static void
2835 mc_unlock_va(caddr_t va)
2836 {
2837 	vtag_flushpage(va, (uint64_t)ksfmmup);
2838 }
2839 
2840 /* ARGSUSED */
2841 int
2842 mc_inject_error(int error_type, uint64_t pa, uint32_t flags)
2843 {
2844 	mc_opl_t *mcp;
2845 	int bank;
2846 	uint32_t dimm_addr;
2847 	uint32_t cntl;
2848 	mc_rsaddr_info_t rsaddr;
2849 	uint32_t data, stat;
2850 	int both_sides = 0;
2851 	uint64_t pa0;
2852 	int extra_injection_needed = 0;
2853 	extern void cpu_flush_ecache(void);
2854 
2855 	MC_LOG("HW mc_inject_error(%x, %lx, %x)\n", error_type, pa, flags);
2856 
2857 	mutex_enter(&mcmutex);
2858 	if ((mcp = mc_pa_to_mcp(pa)) == NULL) {
2859 		mutex_exit(&mcmutex);
2860 		MC_LOG("mc_inject_error: invalid pa\n");
2861 		return (ENOTSUP);
2862 	}
2863 
2864 	mutex_enter(&mcp->mc_lock);
2865 	mutex_exit(&mcmutex);
2866 
2867 	if (mcp->mc_status & (MC_SOFT_SUSPENDED | MC_DRIVER_SUSPENDED)) {
2868 		mutex_exit(&mcp->mc_lock);
2869 		MC_LOG("mc-opl has been suspended.  No error injection.\n");
2870 		return (EBUSY);
2871 	}
2872 
2873 	/* convert pa to offset within the board */
2874 	MC_LOG("pa %lx, offset %lx\n", pa, pa - mcp->mc_start_address);
2875 
2876 	if (!pa_is_valid(mcp, pa)) {
2877 		mutex_exit(&mcp->mc_lock);
2878 		return (EINVAL);
2879 	}
2880 
2881 	pa0 = pa - mcp->mc_start_address;
2882 
2883 	bank = pa_to_bank(mcp, pa0);
2884 
2885 	if (flags & MC_INJECT_FLAG_OTHER)
2886 		bank = bank ^ 1;
2887 
2888 	if (MC_INJECT_MIRROR(error_type) && !IS_MIRROR(mcp, bank)) {
2889 		mutex_exit(&mcp->mc_lock);
2890 		MC_LOG("Not mirror mode\n");
2891 		return (EINVAL);
2892 	}
2893 
2894 	dimm_addr = pa_to_dimm(mcp, pa0);
2895 
2896 	MC_LOG("injecting error to /LSB%d/B%d/%x\n", mcp->mc_board_num, bank,
2897 	    dimm_addr);
2898 
2899 
2900 	switch (error_type) {
2901 	case MC_INJECT_INTERMITTENT_MCE:
2902 	case MC_INJECT_PERMANENT_MCE:
2903 	case MC_INJECT_MUE:
2904 		both_sides = 1;
2905 	}
2906 
2907 	if (flags & MC_INJECT_FLAG_RESET)
2908 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank), 0);
2909 
2910 	ST_MAC_REG(MAC_EG_ADD(mcp, bank), dimm_addr & MAC_EG_ADD_MASK);
2911 
2912 	if (both_sides) {
2913 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), 0);
2914 		ST_MAC_REG(MAC_EG_ADD(mcp, bank^1), dimm_addr &
2915 		    MAC_EG_ADD_MASK);
2916 	}
2917 
2918 	switch (error_type) {
2919 	case MC_INJECT_SUE:
2920 		extra_injection_needed = 1;
2921 		/*FALLTHROUGH*/
2922 	case MC_INJECT_UE:
2923 	case MC_INJECT_MUE:
2924 		if (flags & MC_INJECT_FLAG_PATH) {
2925 			cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_READ00 |
2926 			    MAC_EG_FORCE_READ16 | MAC_EG_RDERR_ONCE;
2927 		} else {
2928 			cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_DERR00 |
2929 			    MAC_EG_FORCE_DERR16 | MAC_EG_DERR_ONCE;
2930 		}
2931 		flags |= MC_INJECT_FLAG_ST;
2932 		break;
2933 	case MC_INJECT_INTERMITTENT_CE:
2934 	case MC_INJECT_INTERMITTENT_MCE:
2935 		if (flags & MC_INJECT_FLAG_PATH) {
2936 			cntl = MAC_EG_ADD_FIX |MAC_EG_FORCE_READ00 |
2937 			    MAC_EG_RDERR_ONCE;
2938 		} else {
2939 			cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_DERR16 |
2940 			    MAC_EG_DERR_ONCE;
2941 		}
2942 		extra_injection_needed = 1;
2943 		flags |= MC_INJECT_FLAG_ST;
2944 		break;
2945 	case MC_INJECT_PERMANENT_CE:
2946 	case MC_INJECT_PERMANENT_MCE:
2947 		if (flags & MC_INJECT_FLAG_PATH) {
2948 			cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_READ00 |
2949 			    MAC_EG_RDERR_ALWAYS;
2950 		} else {
2951 			cntl = MAC_EG_ADD_FIX | MAC_EG_FORCE_DERR16 |
2952 			    MAC_EG_DERR_ALWAYS;
2953 		}
2954 		flags |= MC_INJECT_FLAG_ST;
2955 		break;
2956 	case MC_INJECT_CMPE:
2957 		data = 0xabcdefab;
2958 		stphys(pa, data);
2959 		cpu_flush_ecache();
2960 		MC_LOG("CMPE: writing data %x to %lx\n", data, pa);
2961 		ST_MAC_REG(MAC_MIRR(mcp, bank), MAC_MIRR_BANK_EXCLUSIVE);
2962 		stphys(pa, data ^ 0xffffffff);
2963 		membar_sync();
2964 		cpu_flush_ecache();
2965 		ST_MAC_REG(MAC_MIRR(mcp, bank), 0);
2966 		MC_LOG("CMPE: write new data %xto %lx\n", data, pa);
2967 		cntl = 0;
2968 		break;
2969 	case MC_INJECT_NOP:
2970 		cntl = 0;
2971 		break;
2972 	default:
2973 		MC_LOG("mc_inject_error: invalid option\n");
2974 		cntl = 0;
2975 	}
2976 
2977 	if (cntl) {
2978 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl & MAC_EG_SETUP_MASK);
2979 		ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
2980 
2981 		if (both_sides) {
2982 			ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
2983 			    MAC_EG_SETUP_MASK);
2984 			ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
2985 		}
2986 	}
2987 
2988 	/*
2989 	 * For all injection cases except compare error, we
2990 	 * must write to the PA to trigger the error.
2991 	 */
2992 
2993 	if (flags & MC_INJECT_FLAG_ST) {
2994 		data = 0xf0e0d0c0;
2995 		MC_LOG("Writing %x to %lx\n", data, pa);
2996 		stphys(pa, data);
2997 		cpu_flush_ecache();
2998 	}
2999 
3000 
3001 	if (flags & MC_INJECT_FLAG_LD) {
3002 		if (flags & MC_INJECT_FLAG_PREFETCH) {
3003 			/*
3004 			 * Use strong prefetch operation to
3005 			 * inject MI errors.
3006 			 */
3007 			page_t *pp;
3008 			extern void mc_prefetch(caddr_t);
3009 
3010 			MC_LOG("prefetch\n");
3011 
3012 			pp = page_numtopp_nolock(pa >> PAGESHIFT);
3013 			if (pp != NULL) {
3014 				caddr_t	va, va1;
3015 
3016 				va = ppmapin(pp, PROT_READ|PROT_WRITE,
3017 				    (caddr_t)-1);
3018 				kpreempt_disable();
3019 				mc_lock_va((uint64_t)pa, va);
3020 				va1 = va + (pa & (PAGESIZE - 1));
3021 				mc_prefetch(va1);
3022 				mc_unlock_va(va);
3023 				kpreempt_enable();
3024 				ppmapout(va);
3025 
3026 				/*
3027 				 * For MI errors, we need one extra
3028 				 * injection for HW patrol to stop.
3029 				 */
3030 				extra_injection_needed = 1;
3031 			} else {
3032 				cmn_err(CE_WARN, "Cannot find page structure"
3033 				    " for PA %lx\n", pa);
3034 			}
3035 		} else {
3036 			MC_LOG("Reading from %lx\n", pa);
3037 			data = ldphys(pa);
3038 			MC_LOG("data = %x\n", data);
3039 		}
3040 
3041 		if (extra_injection_needed) {
3042 			/*
3043 			 * These are the injection cases where the
3044 			 * requested injected errors will not cause the HW
3045 			 * patrol to stop. For these cases, we need to inject
3046 			 * an extra 'real' PTRL error to force the
3047 			 * HW patrol to stop so that we can report the
3048 			 * errors injected. Note that we cannot read
3049 			 * and report error status while the HW patrol
3050 			 * is running.
3051 			 */
3052 			ST_MAC_REG(MAC_EG_CNTL(mcp, bank),
3053 			    cntl & MAC_EG_SETUP_MASK);
3054 			ST_MAC_REG(MAC_EG_CNTL(mcp, bank), cntl);
3055 
3056 			if (both_sides) {
3057 				ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl &
3058 				    MAC_EG_SETUP_MASK);
3059 				ST_MAC_REG(MAC_EG_CNTL(mcp, bank^1), cntl);
3060 			}
3061 			data = 0xf0e0d0c0;
3062 			MC_LOG("Writing %x to %lx\n", data, pa);
3063 			stphys(pa, data);
3064 			cpu_flush_ecache();
3065 		}
3066 	}
3067 
3068 	if (flags & MC_INJECT_FLAG_RESTART) {
3069 		MC_LOG("Restart patrol\n");
3070 		rsaddr.mi_restartaddr.ma_bd = mcp->mc_board_num;
3071 		rsaddr.mi_restartaddr.ma_bank = bank;
3072 		rsaddr.mi_restartaddr.ma_dimm_addr = dimm_addr;
3073 		rsaddr.mi_valid = 1;
3074 		rsaddr.mi_injectrestart = 1;
3075 		restart_patrol(mcp, bank, &rsaddr);
3076 	}
3077 
3078 	if (flags & MC_INJECT_FLAG_POLL) {
3079 		int running;
3080 		int ebank = (IS_MIRROR(mcp, bank)) ? MIRROR_IDX(bank) : bank;
3081 
3082 		MC_LOG("Poll patrol error\n");
3083 		stat = LD_MAC_REG(MAC_PTRL_STAT(mcp, bank));
3084 		cntl = LD_MAC_REG(MAC_PTRL_CNTL(mcp, bank));
3085 		running = cntl & MAC_CNTL_PTRL_START;
3086 
3087 		if (!running &&
3088 		    (stat & (MAC_STAT_PTRL_ERRS|MAC_STAT_MI_ERRS))) {
3089 			/*
3090 			 * HW patrol stopped and we have errors to
3091 			 * report. Do it.
3092 			 */
3093 			mcp->mc_speedup_period[ebank] = 0;
3094 			rsaddr.mi_valid = 0;
3095 			rsaddr.mi_injectrestart = 0;
3096 			if (IS_MIRROR(mcp, bank)) {
3097 				mc_error_handler_mir(mcp, bank, &rsaddr);
3098 			} else {
3099 				mc_error_handler(mcp, bank, &rsaddr);
3100 			}
3101 
3102 			restart_patrol(mcp, bank, &rsaddr);
3103 		} else {
3104 			/*
3105 			 * We are expecting to report injected
3106 			 * errors but the HW patrol is still running.
3107 			 * Speed up the scanning
3108 			 */
3109 			mcp->mc_speedup_period[ebank] = 2;
3110 			MAC_CMD(mcp, bank, 0);
3111 			restart_patrol(mcp, bank, NULL);
3112 		}
3113 	}
3114 
3115 	mutex_exit(&mcp->mc_lock);
3116 	return (0);
3117 }
3118 
3119 void
3120 mc_stphysio(uint64_t pa, uint32_t data)
3121 {
3122 	MC_LOG("0x%x -> pa(%lx)\n", data, pa);
3123 	stphysio(pa, data);
3124 
3125 	/* force the above write to be processed by mac patrol */
3126 	data = ldphysio(pa);
3127 	MC_LOG("pa(%lx) = 0x%x\n", pa, data);
3128 }
3129 
3130 uint32_t
3131 mc_ldphysio(uint64_t pa)
3132 {
3133 	uint32_t rv;
3134 
3135 	rv = ldphysio(pa);
3136 	MC_LOG("pa(%lx) = 0x%x\n", pa, rv);
3137 	return (rv);
3138 }
3139 
3140 #define	isdigit(ch)	((ch) >= '0' && (ch) <= '9')
3141 
3142 /*
3143  * parse_unum_memory -- extract the board number and the DIMM name from
3144  * the unum.
3145  *
3146  * Return 0 for success and non-zero for a failure.
3147  */
3148 int
3149 parse_unum_memory(char *unum, int *board, char *dname)
3150 {
3151 	char *c;
3152 	char x, y, z;
3153 
3154 	if ((c = strstr(unum, "CMU")) != NULL) {
3155 		/* DC Model */
3156 		c += 3;
3157 		*board = (uint8_t)stoi(&c);
3158 		if ((c = strstr(c, "MEM")) == NULL) {
3159 			return (1);
3160 		}
3161 		c += 3;
3162 		if (strlen(c) < 3) {
3163 			return (2);
3164 		}
3165 		if ((!isdigit(c[0])) || (!(isdigit(c[1]))) ||
3166 		    ((c[2] != 'A') && (c[2] != 'B'))) {
3167 			return (3);
3168 		}
3169 		x = c[0];
3170 		y = c[1];
3171 		z = c[2];
3172 	} else if ((c = strstr(unum, "MBU_")) != NULL) {
3173 		/*  FF1/FF2 Model */
3174 		c += 4;
3175 		if ((c[0] != 'A') && (c[0] != 'B')) {
3176 			return (4);
3177 		}
3178 		if ((c = strstr(c, "MEMB")) == NULL) {
3179 			return (5);
3180 		}
3181 		c += 4;
3182 
3183 		x = c[0];
3184 		*board =  ((uint8_t)stoi(&c)) / 4;
3185 		if ((c = strstr(c, "MEM")) == NULL) {
3186 			return (6);
3187 		}
3188 		c += 3;
3189 		if (strlen(c) < 2) {
3190 			return (7);
3191 		}
3192 		if ((!isdigit(c[0])) || ((c[1] != 'A') && (c[1] != 'B'))) {
3193 			return (8);
3194 		}
3195 		y = c[0];
3196 		z = c[1];
3197 	} else {
3198 		return (9);
3199 	}
3200 	if (*board < 0) {
3201 		return (10);
3202 	}
3203 	dname[0] = x;
3204 	dname[1] = y;
3205 	dname[2] = z;
3206 	dname[3] = '\0';
3207 	return (0);
3208 }
3209 
3210 /*
3211  * mc_get_mem_sid_dimm -- Get the serial-ID for a given board and
3212  * the DIMM name.
3213  */
3214 int
3215 mc_get_mem_sid_dimm(mc_opl_t *mcp, char *dname, char *buf,
3216     int buflen, int *lenp)
3217 {
3218 	int		ret = ENODEV;
3219 	mc_dimm_info_t	*d = NULL;
3220 
3221 	if ((d = mcp->mc_dimm_list) == NULL)
3222 		return (ENOTSUP);
3223 
3224 	for (; d != NULL; d = d->md_next) {
3225 		if (strcmp(d->md_dimmname, dname) == 0) {
3226 			break;
3227 		}
3228 	}
3229 	if (d != NULL) {
3230 		*lenp = strlen(d->md_serial) + strlen(d->md_partnum);
3231 		if (buflen <=  *lenp) {
3232 			cmn_err(CE_WARN, "mc_get_mem_sid_dimm: "
3233 			    "buflen is smaller than %d\n", *lenp);
3234 			ret = ENOSPC;
3235 		} else {
3236 			snprintf(buf, buflen, "%s:%s",
3237 			    d->md_serial, d->md_partnum);
3238 			ret = 0;
3239 		}
3240 	}
3241 	MC_LOG("mc_get_mem_sid_dimm: Ret=%d Name=%s Serial-ID=%s\n",
3242 	    ret, dname, (ret == 0) ? buf : "");
3243 	return (ret);
3244 }
3245 
3246 int
3247 mc_set_mem_sid(mc_opl_t *mcp, char *buf, int buflen, int sb,
3248     int bank, uint32_t mf_type, uint32_t d_slot)
3249 {
3250 	int	lenp = buflen;
3251 	int	id;
3252 	int	ret;
3253 	char	*dimmnm;
3254 
3255 	if (mf_type == FLT_TYPE_INTERMITTENT_CE ||
3256 	    mf_type == FLT_TYPE_PERMANENT_CE) {
3257 		if (plat_model == MODEL_DC) {
3258 			id = BD_BK_SLOT_TO_INDEX(0, bank, d_slot);
3259 			dimmnm = mc_dc_dimm_unum_table[id];
3260 		} else {
3261 			id = BD_BK_SLOT_TO_INDEX(sb, bank, d_slot);
3262 			dimmnm = mc_ff_dimm_unum_table[id];
3263 		}
3264 		if ((ret = mc_get_mem_sid_dimm(mcp, dimmnm, buf, buflen,
3265 		    &lenp)) != 0) {
3266 			return (ret);
3267 		}
3268 	} else {
3269 		return (1);
3270 	}
3271 
3272 	return (0);
3273 }
3274 
3275 /*
3276  * mc_get_mem_sid -- get the DIMM serial-ID corresponding to the unum.
3277  */
3278 int
3279 mc_get_mem_sid(char *unum, char *buf, int buflen, int *lenp)
3280 {
3281 	int	i;
3282 	int	ret = ENODEV;
3283 	int	board;
3284 	char	dname[MCOPL_MAX_DIMMNAME + 1];
3285 	mc_opl_t *mcp;
3286 
3287 	MC_LOG("mc_get_mem_sid: unum=%s buflen=%d\n", unum, buflen);
3288 	if ((ret = parse_unum_memory(unum, &board, dname)) != 0) {
3289 		MC_LOG("mc_get_mem_sid: unum(%s) parsing failed ret=%d\n",
3290 		    unum, ret);
3291 		return (EINVAL);
3292 	}
3293 
3294 	if (board < 0) {
3295 		MC_LOG("mc_get_mem_sid: Invalid board=%d dimm=%s\n",
3296 		    board, dname);
3297 		return (EINVAL);
3298 	}
3299 
3300 	mutex_enter(&mcmutex);
3301 	/*
3302 	 * return ENOENT if we can not find the matching board.
3303 	 */
3304 	ret = ENOENT;
3305 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
3306 		if ((mcp = mc_instances[i]) == NULL)
3307 			continue;
3308 		mutex_enter(&mcp->mc_lock);
3309 		if (mcp->mc_phys_board_num != board) {
3310 			mutex_exit(&mcp->mc_lock);
3311 			continue;
3312 		}
3313 		ret = mc_get_mem_sid_dimm(mcp, dname, buf, buflen, lenp);
3314 		if (ret == 0) {
3315 			mutex_exit(&mcp->mc_lock);
3316 			break;
3317 		}
3318 		mutex_exit(&mcp->mc_lock);
3319 	}
3320 	mutex_exit(&mcmutex);
3321 	return (ret);
3322 }
3323 
3324 /*
3325  * mc_get_mem_offset -- get the offset in a DIMM for a given physical address.
3326  */
3327 int
3328 mc_get_mem_offset(uint64_t paddr, uint64_t *offp)
3329 {
3330 	int		i;
3331 	int		ret = ENODEV;
3332 	mc_addr_t	maddr;
3333 	mc_opl_t	*mcp;
3334 
3335 	mutex_enter(&mcmutex);
3336 	for (i = 0; ((i < OPL_MAX_BOARDS) && (ret != 0)); i++) {
3337 		if ((mcp = mc_instances[i]) == NULL)
3338 			continue;
3339 		mutex_enter(&mcp->mc_lock);
3340 		if (!pa_is_valid(mcp, paddr)) {
3341 			mutex_exit(&mcp->mc_lock);
3342 			continue;
3343 		}
3344 		if (pa_to_maddr(mcp, paddr, &maddr) == 0) {
3345 			*offp = maddr.ma_dimm_addr;
3346 			ret = 0;
3347 		}
3348 		mutex_exit(&mcp->mc_lock);
3349 	}
3350 	mutex_exit(&mcmutex);
3351 	MC_LOG("mc_get_mem_offset: Ret=%d paddr=0x%lx offset=0x%lx\n",
3352 	    ret, paddr, *offp);
3353 	return (ret);
3354 }
3355 
3356 /*
3357  * dname_to_bankslot - Get the bank and slot number from the DIMM name.
3358  */
3359 int
3360 dname_to_bankslot(char *dname, int *bank, int *slot)
3361 {
3362 	int i;
3363 	int tsz;
3364 	char **tbl;
3365 
3366 	if (plat_model == MODEL_DC) { /* DC */
3367 		tbl = mc_dc_dimm_unum_table;
3368 		tsz = OPL_MAX_DIMMS;
3369 	} else {
3370 		tbl = mc_ff_dimm_unum_table;
3371 		tsz = 2 * OPL_MAX_DIMMS;
3372 	}
3373 
3374 	for (i = 0; i < tsz; i++) {
3375 		if (strcmp(dname,  tbl[i]) == 0) {
3376 			break;
3377 		}
3378 	}
3379 	if (i == tsz) {
3380 		return (1);
3381 	}
3382 	*bank = INDEX_TO_BANK(i);
3383 	*slot = INDEX_TO_SLOT(i);
3384 	return (0);
3385 }
3386 
3387 /*
3388  * mc_get_mem_addr -- get the physical address of a DIMM corresponding
3389  * to the unum and sid.
3390  */
3391 int
3392 mc_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *paddr)
3393 {
3394 	int	board;
3395 	int	bank;
3396 	int	slot;
3397 	int	i;
3398 	int	ret = ENODEV;
3399 	char	dname[MCOPL_MAX_DIMMNAME + 1];
3400 	mc_addr_t maddr;
3401 	mc_opl_t *mcp;
3402 
3403 	MC_LOG("mc_get_mem_addr: unum=%s sid=%s offset=0x%lx\n",
3404 	    unum, sid, offset);
3405 	if (parse_unum_memory(unum, &board, dname) != 0) {
3406 		MC_LOG("mc_get_mem_sid: unum(%s) parsing failed ret=%d\n",
3407 		    unum, ret);
3408 		return (EINVAL);
3409 	}
3410 
3411 	if (board < 0) {
3412 		MC_LOG("mc_get_mem_addr: Invalid board=%d dimm=%s\n",
3413 		    board, dname);
3414 		return (EINVAL);
3415 	}
3416 
3417 	mutex_enter(&mcmutex);
3418 	for (i = 0; i < OPL_MAX_BOARDS; i++) {
3419 		if ((mcp = mc_instances[i]) == NULL)
3420 			continue;
3421 		mutex_enter(&mcp->mc_lock);
3422 		if (mcp->mc_phys_board_num != board) {
3423 			mutex_exit(&mcp->mc_lock);
3424 			continue;
3425 		}
3426 
3427 		ret = dname_to_bankslot(dname, &bank, &slot);
3428 		MC_LOG("mc_get_mem_addr: bank=%d slot=%d\n", bank, slot);
3429 		if (ret != 0) {
3430 			MC_LOG("mc_get_mem_addr: dname_to_bankslot failed\n");
3431 			ret = ENODEV;
3432 		} else {
3433 			maddr.ma_bd = mcp->mc_board_num;
3434 			maddr.ma_bank =  bank;
3435 			maddr.ma_dimm_addr = offset;
3436 			ret = mcaddr_to_pa(mcp, &maddr, paddr);
3437 			if (ret != 0) {
3438 				MC_LOG("mc_get_mem_addr: "
3439 				    "mcaddr_to_pa failed\n");
3440 				ret = ENODEV;
3441 			}
3442 			mutex_exit(&mcp->mc_lock);
3443 			break;
3444 		}
3445 		mutex_exit(&mcp->mc_lock);
3446 	}
3447 	mutex_exit(&mcmutex);
3448 	MC_LOG("mc_get_mem_addr: Ret=%d, Paddr=0x%lx\n", ret, *paddr);
3449 	return (ret);
3450 }
3451 
3452 static void
3453 mc_free_dimm_list(mc_dimm_info_t *d)
3454 {
3455 	mc_dimm_info_t *next;
3456 
3457 	while (d != NULL) {
3458 		next = d->md_next;
3459 		kmem_free(d, sizeof (mc_dimm_info_t));
3460 		d = next;
3461 	}
3462 }
3463 
3464 /*
3465  * mc_get_dimm_list -- get the list of dimms with serial-id info
3466  * from the SP.
3467  */
3468 mc_dimm_info_t *
3469 mc_get_dimm_list(mc_opl_t *mcp)
3470 {
3471 	uint32_t	bufsz;
3472 	uint32_t	maxbufsz;
3473 	int		ret;
3474 	int		sexp;
3475 	board_dimm_info_t *bd_dimmp;
3476 	mc_dimm_info_t	*dimm_list = NULL;
3477 
3478 	maxbufsz = bufsz = sizeof (board_dimm_info_t) +
3479 	    ((MCOPL_MAX_DIMMNAME +  MCOPL_MAX_SERIAL +
3480 	    MCOPL_MAX_PARTNUM) * OPL_MAX_DIMMS);
3481 
3482 	bd_dimmp = (board_dimm_info_t *)kmem_alloc(bufsz, KM_SLEEP);
3483 	ret = scf_get_dimminfo(mcp->mc_board_num, (void *)bd_dimmp, &bufsz);
3484 
3485 	MC_LOG("mc_get_dimm_list:  scf_service_getinfo returned=%d\n", ret);
3486 	if (ret == 0) {
3487 		sexp = sizeof (board_dimm_info_t) +
3488 		    ((bd_dimmp->bd_dnamesz +  bd_dimmp->bd_serialsz +
3489 		    bd_dimmp->bd_partnumsz) * bd_dimmp->bd_numdimms);
3490 
3491 		if ((bd_dimmp->bd_version == OPL_DIMM_INFO_VERSION) &&
3492 		    (bd_dimmp->bd_dnamesz <= MCOPL_MAX_DIMMNAME) &&
3493 		    (bd_dimmp->bd_serialsz <= MCOPL_MAX_SERIAL) &&
3494 		    (bd_dimmp->bd_partnumsz <= MCOPL_MAX_PARTNUM) &&
3495 		    (sexp <= bufsz)) {
3496 
3497 #ifdef DEBUG
3498 			if (oplmc_debug)
3499 				mc_dump_dimm_info(bd_dimmp);
3500 #endif
3501 			dimm_list = mc_prepare_dimmlist(bd_dimmp);
3502 
3503 		} else {
3504 			cmn_err(CE_WARN, "DIMM info version mismatch\n");
3505 		}
3506 	}
3507 	kmem_free(bd_dimmp, maxbufsz);
3508 	MC_LOG("mc_get_dimm_list: dimmlist=0x%p\n", dimm_list);
3509 	return (dimm_list);
3510 }
3511 
3512 /*
3513  * mc_prepare_dimmlist - Prepare the dimm list from the information
3514  * received from the SP.
3515  */
3516 mc_dimm_info_t *
3517 mc_prepare_dimmlist(board_dimm_info_t *bd_dimmp)
3518 {
3519 	char	*dimm_name;
3520 	char	*serial;
3521 	char	*part;
3522 	int	dimm;
3523 	int	dnamesz = bd_dimmp->bd_dnamesz;
3524 	int	sersz = bd_dimmp->bd_serialsz;
3525 	int	partsz = bd_dimmp->bd_partnumsz;
3526 	mc_dimm_info_t	*dimm_list = NULL;
3527 	mc_dimm_info_t	*d;
3528 
3529 	dimm_name = (char *)(bd_dimmp + 1);
3530 	for (dimm = 0; dimm < bd_dimmp->bd_numdimms; dimm++) {
3531 
3532 		d = (mc_dimm_info_t *)kmem_alloc(sizeof (mc_dimm_info_t),
3533 		    KM_SLEEP);
3534 
3535 		bcopy(dimm_name, d->md_dimmname, dnamesz);
3536 		d->md_dimmname[dnamesz] = 0;
3537 
3538 		serial = dimm_name + dnamesz;
3539 		bcopy(serial, d->md_serial, sersz);
3540 		d->md_serial[sersz] = 0;
3541 
3542 		part = serial + sersz;
3543 		bcopy(part, d->md_partnum, partsz);
3544 		d->md_partnum[partsz] = 0;
3545 
3546 		d->md_next = dimm_list;
3547 		dimm_list = d;
3548 		dimm_name = part + partsz;
3549 	}
3550 	return (dimm_list);
3551 }
3552 
3553 #ifdef DEBUG
3554 void
3555 mc_dump_dimm(char *buf, int dnamesz, int serialsz, int partnumsz)
3556 {
3557 	char dname[MCOPL_MAX_DIMMNAME + 1];
3558 	char serial[MCOPL_MAX_SERIAL + 1];
3559 	char part[ MCOPL_MAX_PARTNUM + 1];
3560 	char *b;
3561 
3562 	b = buf;
3563 	bcopy(b, dname, dnamesz);
3564 	dname[dnamesz] = 0;
3565 
3566 	b += dnamesz;
3567 	bcopy(b, serial, serialsz);
3568 	serial[serialsz] = 0;
3569 
3570 	b += serialsz;
3571 	bcopy(b, part, partnumsz);
3572 	part[partnumsz] = 0;
3573 
3574 	printf("DIMM=%s  Serial=%s PartNum=%s\n", dname, serial, part);
3575 }
3576 
3577 void
3578 mc_dump_dimm_info(board_dimm_info_t *bd_dimmp)
3579 {
3580 	int	dimm;
3581 	int	dnamesz = bd_dimmp->bd_dnamesz;
3582 	int	sersz = bd_dimmp->bd_serialsz;
3583 	int	partsz = bd_dimmp->bd_partnumsz;
3584 	char	*buf;
3585 
3586 	printf("Version=%d Board=%02d DIMMs=%d NameSize=%d "
3587 	    "SerialSize=%d PartnumSize=%d\n", bd_dimmp->bd_version,
3588 	    bd_dimmp->bd_boardnum, bd_dimmp->bd_numdimms, bd_dimmp->bd_dnamesz,
3589 	    bd_dimmp->bd_serialsz, bd_dimmp->bd_partnumsz);
3590 	printf("======================================================\n");
3591 
3592 	buf = (char *)(bd_dimmp + 1);
3593 	for (dimm = 0; dimm < bd_dimmp->bd_numdimms; dimm++) {
3594 		mc_dump_dimm(buf, dnamesz, sersz, partsz);
3595 		buf += dnamesz + sersz + partsz;
3596 	}
3597 	printf("======================================================\n");
3598 }
3599 
3600 
3601 /* ARGSUSED */
3602 static int
3603 mc_ioctl_debug(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
3604 	int *rvalp)
3605 {
3606 	caddr_t	buf;
3607 	uint64_t pa;
3608 	int rv = 0;
3609 	int i;
3610 	uint32_t flags;
3611 	static uint32_t offset = 0;
3612 
3613 
3614 	flags = (cmd >> 4) & 0xfffffff;
3615 
3616 	cmd &= 0xf;
3617 
3618 	MC_LOG("mc_ioctl(cmd = %x, flags = %x)\n", cmd, flags);
3619 
3620 	if (arg != NULL) {
3621 		if (ddi_copyin((const void *)arg, (void *)&pa,
3622 		    sizeof (uint64_t), 0) < 0) {
3623 			rv = EFAULT;
3624 			return (rv);
3625 		}
3626 		buf = NULL;
3627 	} else {
3628 		buf = (caddr_t)kmem_alloc(PAGESIZE, KM_SLEEP);
3629 
3630 		pa = va_to_pa(buf);
3631 		pa += offset;
3632 
3633 		offset += 64;
3634 		if (offset >= PAGESIZE)
3635 			offset = 0;
3636 	}
3637 
3638 	switch (cmd) {
3639 	case MCI_CE:
3640 		mc_inject_error(MC_INJECT_INTERMITTENT_CE, pa, flags);
3641 		break;
3642 	case MCI_PERM_CE:
3643 		mc_inject_error(MC_INJECT_PERMANENT_CE, pa, flags);
3644 		break;
3645 	case MCI_UE:
3646 		mc_inject_error(MC_INJECT_UE, pa, flags);
3647 		break;
3648 	case MCI_M_CE:
3649 		mc_inject_error(MC_INJECT_INTERMITTENT_MCE, pa, flags);
3650 		break;
3651 	case MCI_M_PCE:
3652 		mc_inject_error(MC_INJECT_PERMANENT_MCE, pa, flags);
3653 		break;
3654 	case MCI_M_UE:
3655 		mc_inject_error(MC_INJECT_MUE, pa, flags);
3656 		break;
3657 	case MCI_CMP:
3658 		mc_inject_error(MC_INJECT_CMPE, pa, flags);
3659 		break;
3660 	case MCI_NOP:
3661 		mc_inject_error(MC_INJECT_NOP, pa, flags); break;
3662 	case MCI_SHOW_ALL:
3663 		mc_debug_show_all = 1;
3664 		break;
3665 	case MCI_SHOW_NONE:
3666 		mc_debug_show_all = 0;
3667 		break;
3668 	case MCI_ALLOC:
3669 		/*
3670 		 * just allocate some kernel memory and never free it
3671 		 * 512 MB seems to be the maximum size supported.
3672 		 */
3673 		cmn_err(CE_NOTE, "Allocating kmem %d MB\n", flags * 512);
3674 		for (i = 0; i < flags; i++) {
3675 			buf = kmem_alloc(512 * 1024 * 1024, KM_SLEEP);
3676 			cmn_err(CE_NOTE, "kmem buf %llx PA %llx\n",
3677 			    (u_longlong_t)buf, (u_longlong_t)va_to_pa(buf));
3678 		}
3679 		break;
3680 	case MCI_SUSPEND:
3681 		(void) opl_mc_suspend();
3682 		break;
3683 	case MCI_RESUME:
3684 		(void) opl_mc_resume();
3685 		break;
3686 	default:
3687 		rv = ENXIO;
3688 	}
3689 	return (rv);
3690 }
3691 
3692 #endif /* DEBUG */
3693