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