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