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