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