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