Home | History | Annotate | Download | only in cpumem-diagnosis
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  * Ereport-handling routines for memory errors
     29  */
     30 
     31 #include <cmd_mem.h>
     32 #include <cmd_dimm.h>
     33 #include <cmd_bank.h>
     34 #include <cmd_page.h>
     35 #include <cmd_cpu.h>
     36 #include <cmd.h>
     37 
     38 #include <strings.h>
     39 #include <string.h>
     40 #include <errno.h>
     41 #include <unistd.h>
     42 #include <fm/fmd_api.h>
     43 #include <sys/fm/protocol.h>
     44 #include <sys/fm/cpu/UltraSPARC-III.h>
     45 #include <sys/async.h>
     46 #include <sys/cheetahregs.h>
     47 #include <sys/errclassify.h>
     48 #include <sys/fm/io/sun4upci.h>
     49 #include <sys/pci/pcisch.h>
     50 
     51 /* Jalapeno-specific values from cheetahregs.h */
     52 #define	USIIIi_AFSR_AID		0x0000000000003e00ull /* AID causing UE/CE */
     53 #define	USIIIi_AFSR_AID_SHIFT	9
     54 #define	USIIIi_AFSR_JREQ	0x0000000007000000ull /* Active JBus req */
     55 #define	USIIIi_AFSR_JREQ_SHIFT	24
     56 #define	TOM_AID_MATCH_MASK	0xe
     57 
     58 #define	FIRE_AID		0xe
     59 #define	FIRE_JBC_ADDR_MASK	0x000007ffffffffffull
     60 #define	FIRE_JBC_JITEL1		"jbc-jitel1"
     61 
     62 /*ARGSUSED*/
     63 cmd_evdisp_t
     64 cmd_mem_synd_check(fmd_hdl_t *hdl, uint64_t afar, uint8_t afar_status,
     65     uint16_t synd, uint8_t synd_status, cmd_cpu_t *cpu)
     66 {
     67 	if (synd == CH_POISON_SYND_FROM_XXU_WRITE ||
     68 	    ((cpu->cpu_type == CPU_ULTRASPARC_IIIi ||
     69 	    cpu->cpu_type == CPU_ULTRASPARC_IIIiplus) &&
     70 	    synd == CH_POISON_SYND_FROM_XXU_WRMERGE)) {
     71 		fmd_hdl_debug(hdl,
     72 		    "discarding UE due to magic syndrome %x\n", synd);
     73 		return (CMD_EVD_UNUSED);
     74 	}
     75 	return (CMD_EVD_OK);
     76 }
     77 
     78 static cmd_evdisp_t
     79 xe_common(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
     80     const char *class, cmd_xe_handler_f *hdlr)
     81 {
     82 	uint64_t afar;
     83 	uint16_t synd;
     84 	uint8_t afar_status, synd_status;
     85 	nvlist_t *rsrc;
     86 	char *typenm;
     87 	uint64_t disp;
     88 	int minorvers = 1;
     89 
     90 	if (nvlist_lookup_pairs(nvl, 0,
     91 	    FM_EREPORT_PAYLOAD_NAME_AFAR, DATA_TYPE_UINT64, &afar,
     92 	    FM_EREPORT_PAYLOAD_NAME_AFAR_STATUS, DATA_TYPE_UINT8, &afar_status,
     93 	    FM_EREPORT_PAYLOAD_NAME_SYND, DATA_TYPE_UINT16, &synd,
     94 	    FM_EREPORT_PAYLOAD_NAME_SYND_STATUS, DATA_TYPE_UINT8, &synd_status,
     95 	    FM_EREPORT_PAYLOAD_NAME_ERR_TYPE, DATA_TYPE_STRING, &typenm,
     96 	    FM_EREPORT_PAYLOAD_NAME_RESOURCE, DATA_TYPE_NVLIST, &rsrc,
     97 	    NULL) != 0)
     98 		return (CMD_EVD_BAD);
     99 
    100 	if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_ERR_DISP,
    101 	    &disp) != 0)
    102 		minorvers = 0;
    103 
    104 	return (hdlr(hdl, ep, nvl, class, afar, afar_status, synd,
    105 	    synd_status, cmd_mem_name2type(typenm, minorvers), disp, rsrc));
    106 }
    107 
    108 /*ARGSUSED*/
    109 cmd_evdisp_t
    110 cmd_ce(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    111     cmd_errcl_t clcode)
    112 {
    113 	return (xe_common(hdl, ep, nvl, class, cmd_ce_common));
    114 }
    115 
    116 /*ARGSUSED*/
    117 cmd_evdisp_t
    118 cmd_ue(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    119     cmd_errcl_t clcode)
    120 {
    121 	return (xe_common(hdl, ep, nvl, class, cmd_ue_common));
    122 }
    123 
    124 cmd_evdisp_t
    125 cmd_frx(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    126     cmd_errcl_t clcode)
    127 {
    128 	cmd_errcl_t matchmask = (clcode == CMD_ERRCL_FRC ? (CMD_ERRCL_RCE |
    129 	    CMD_ERRCL_IOCE) : (CMD_ERRCL_RUE | CMD_ERRCL_IOUE));
    130 
    131 	return (cmd_rxefrx_common(hdl, ep, nvl, class, clcode, matchmask));
    132 }
    133 
    134 /*
    135  * When we complete an IOxE/RxE FRx pair, we have enough information to
    136  * create either a CE or a UE, as appropriate.  Before dispatching the
    137  * joined event to the xE handler, we need to generate the FMRI for the
    138  * named DIMM.  While one of the events may already contain a resource FMRI,
    139  * said FMRI is incomplete.  The detector didn't have the necessary
    140  * information (the AFAR, the AFSR, *and* the syndrome) needed to create
    141  * a DIMM-level FMRI.
    142  */
    143 static cmd_evdisp_t
    144 iorxefrx_synthesize(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
    145     const char *class, uint64_t afar, uint8_t afar_status, uint64_t afsr,
    146     uint16_t synd, uint8_t synd_status, ce_dispact_t type, uint64_t disp,
    147     cmd_xe_handler_f *hdlr)
    148 {
    149 	nvlist_t *fmri;
    150 	int rc;
    151 
    152 	if ((fmri = cmd_dimm_fmri_derive(hdl, afar, synd, afsr)) == NULL)
    153 		return (CMD_EVD_UNUSED);
    154 
    155 	rc = hdlr(hdl, ep, nvl, class, afar, afar_status, synd, synd_status,
    156 	    type, disp, fmri);
    157 
    158 	nvlist_free(fmri);
    159 
    160 	return (rc);
    161 }
    162 
    163 static cmd_iorxefrx_t *
    164 iorxefrx_match(fmd_hdl_t *hdl, cmd_errcl_t errcl, cmd_errcl_t matchmask,
    165     uint_t det_agentid, uint_t afsr_agentid)
    166 {
    167 	cmd_iorxefrx_t *rf;
    168 
    169 	for (rf = cmd_list_next(&cmd.cmd_iorxefrx); rf != NULL;
    170 	    rf = cmd_list_next(rf)) {
    171 
    172 		fmd_hdl_debug(hdl, "rf->rf_errcl = %llx, matchmask = %llx\n"
    173 		    "rf->rf_det_agentid = %lx, afsr_agentid = %lx\n"
    174 		    "rf->rf_afsr_agentid = %lx, det_agentid = %lx\n",
    175 		    rf->rf_errcl, matchmask, rf->rf_det_agentid, afsr_agentid,
    176 		    rf->rf_afsr_agentid, det_agentid);
    177 
    178 		if ((rf->rf_errcl & matchmask) == 0)
    179 			continue;
    180 
    181 		/*
    182 		 * For IOxEs we are unable to match based on both the detector
    183 		 * and the captured Agent Id in the AFSR, because the bridge
    184 		 * captures it's own Agent Id instead of the remote CPUs.
    185 		 *
    186 		 * Also, the LSB of Tomatillo's jpid is aliased for each chip
    187 		 * and therefore needs to be factored out of our matching.
    188 		 */
    189 		if ((CMD_ERRCL_ISIOXE(rf->rf_errcl) ||
    190 		    CMD_ERRCL_ISIOXE(errcl)) &&
    191 		    ((rf->rf_afsr_agentid & TOM_AID_MATCH_MASK) ==
    192 		    (afsr_agentid & TOM_AID_MATCH_MASK)))
    193 			return (rf);
    194 
    195 		/*
    196 		 * Check for both here since IOxE is not involved
    197 		 */
    198 		if ((rf->rf_afsr_agentid == det_agentid) &&
    199 		    (rf->rf_det_agentid == afsr_agentid))
    200 			return (rf);
    201 	}
    202 
    203 	return (NULL);
    204 }
    205 
    206 /*
    207  * Got an RxE or an FRx.  FRx ereports can be matched with RxE ereports and
    208  * vice versa.  FRx ereports can also be matched with IOxE ereports.
    209  */
    210 cmd_evdisp_t
    211 cmd_rxefrx_common(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
    212     const char *class, cmd_errcl_t clcode, cmd_errcl_t matchmask)
    213 {
    214 	cmd_xe_handler_f *hdlr;
    215 	cmd_iorxefrx_t *rfmatch, *rferr;
    216 	cmd_cpu_t *cpu;
    217 	char *typenm;
    218 	int isrxe = CMD_ERRCL_MATCH(clcode, CMD_ERRCL_RCE | CMD_ERRCL_RUE);
    219 	int isce = CMD_ERRCL_MATCH(clcode, CMD_ERRCL_RCE | CMD_ERRCL_FRC);
    220 	int rc;
    221 	int minorvers = 1;
    222 	uint8_t level = clcode & CMD_ERRCL_LEVEL_EXTRACT;
    223 
    224 	clcode &= CMD_ERRCL_LEVEL_MASK;
    225 	rferr = fmd_hdl_zalloc(hdl, sizeof (cmd_iorxefrx_t), FMD_SLEEP);
    226 
    227 	if (nvlist_lookup_pairs(nvl, 0,
    228 	    FM_EREPORT_PAYLOAD_NAME_SYND, DATA_TYPE_UINT16, &rferr->rf_synd,
    229 	    FM_EREPORT_PAYLOAD_NAME_SYND_STATUS, DATA_TYPE_UINT8,
    230 	    &rferr->rf_synd_status,
    231 	    FM_EREPORT_PAYLOAD_NAME_AFAR, DATA_TYPE_UINT64, &rferr->rf_afar,
    232 	    FM_EREPORT_PAYLOAD_NAME_AFAR_STATUS, DATA_TYPE_UINT8,
    233 	    &rferr->rf_afar_status,
    234 	    FM_EREPORT_PAYLOAD_NAME_AFSR, DATA_TYPE_UINT64, &rferr->rf_afsr,
    235 	    FM_EREPORT_PAYLOAD_NAME_ERR_TYPE, DATA_TYPE_STRING, &typenm,
    236 	    NULL) != 0) {
    237 		fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    238 		return (CMD_EVD_BAD);
    239 	}
    240 	if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_NAME_ERR_DISP,
    241 	    &rferr->rf_disp) != 0)
    242 		minorvers = 0;
    243 
    244 	rferr->rf_type = cmd_mem_name2type(typenm, minorvers);
    245 
    246 	if ((cpu = cmd_cpu_lookup_from_detector(hdl, nvl, class,
    247 	    level)) == NULL) {
    248 		fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    249 		return (CMD_EVD_UNUSED);
    250 	}
    251 
    252 	if (!isrxe && rferr->rf_synd_status != AFLT_STAT_VALID) {
    253 		fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    254 		return (CMD_EVD_UNUSED);
    255 	}
    256 
    257 	if (isrxe) {
    258 		rferr->rf_afsr_agentid = (rferr->rf_afsr &
    259 		    USIIIi_AFSR_JREQ) >> USIIIi_AFSR_JREQ_SHIFT;
    260 	} else {
    261 		rferr->rf_afsr_agentid = (rferr->rf_afsr &
    262 		    USIIIi_AFSR_AID) >> USIIIi_AFSR_AID_SHIFT;
    263 	}
    264 
    265 	rferr->rf_errcl = clcode;
    266 	rferr->rf_det_agentid = cpu->cpu_cpuid;
    267 
    268 	if ((rfmatch = iorxefrx_match(hdl, clcode, matchmask,
    269 	    rferr->rf_det_agentid, rferr->rf_afsr_agentid)) == NULL) {
    270 		cmd_iorxefrx_queue(hdl, rferr);
    271 		return (CMD_EVD_OK);
    272 	}
    273 
    274 	/*
    275 	 * Found a match.  Send a synthesized ereport to the appropriate
    276 	 * routine.
    277 	 */
    278 	fmd_hdl_debug(hdl, "matched %cE %llx with %llx", "UC"[isce],
    279 	    rferr->rf_errcl, rfmatch->rf_errcl);
    280 
    281 	hdlr = (isce ? cmd_ce_common : cmd_ue_common);
    282 	if (isrxe) {
    283 		rc = iorxefrx_synthesize(hdl, ep, nvl, class, rferr->rf_afar,
    284 		    rferr->rf_afar_status, rfmatch->rf_afsr, rfmatch->rf_synd,
    285 		    rfmatch->rf_synd_status, rferr->rf_type, rferr->rf_disp,
    286 		    hdlr);
    287 	} else {
    288 		rc = iorxefrx_synthesize(hdl, ep, nvl, class, rfmatch->rf_afar,
    289 		    rfmatch->rf_afar_status, rferr->rf_afsr, rferr->rf_synd,
    290 		    rferr->rf_synd_status, rfmatch->rf_type, rferr->rf_disp,
    291 		    hdlr);
    292 	}
    293 
    294 	cmd_iorxefrx_free(hdl, rfmatch);
    295 	fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    296 
    297 	return (rc);
    298 }
    299 
    300 /*
    301  * This fire IOxE must be matched with an FRx before UE/CE processing
    302  * is possible.
    303  *
    304  * Note that for fire ereports we don't receive AFSR, AFAR, AFAR-Status
    305  * and SYND values but we can derive the AFAR from the payload value
    306  * FIRE_JBC_JITEL1.  We may receive a TYPNM value.
    307  */
    308 static cmd_evdisp_t
    309 cmd_ioxefrx_fire(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
    310     const char *class, cmd_errcl_t errcl, cmd_errcl_t matchmask)
    311 {
    312 	cmd_xe_handler_f *hdlr;
    313 	cmd_iorxefrx_t *rfmatch, *rferr;
    314 	uint64_t afar;
    315 	int isce = CMD_ERRCL_MATCH(errcl, CMD_ERRCL_IOCE);
    316 	char *portid_str;
    317 	char *path = NULL;
    318 	char *typenm = NULL;
    319 	nvlist_t *det = NULL;
    320 	int rc;
    321 	int minorvers = 1;
    322 
    323 	rferr = fmd_hdl_zalloc(hdl, sizeof (cmd_iorxefrx_t), FMD_SLEEP);
    324 
    325 	/*
    326 	 * Lookup device path of host bridge.
    327 	 */
    328 	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &det);
    329 	(void) nvlist_lookup_string(det, FM_FMRI_DEV_PATH, &path);
    330 
    331 	/*
    332 	 * get Jbus port id from the device path
    333 	 */
    334 	portid_str = strrchr(path, '@') + 1;
    335 	rferr->rf_det_agentid = strtol(portid_str, NULL, 16);
    336 
    337 	rferr->rf_errcl = errcl;
    338 	rferr->rf_afsr_agentid = FIRE_AID;
    339 	rferr->rf_afar_status = AFLT_STAT_VALID;
    340 	rferr->rf_synd_status = AFLT_STAT_VALID;
    341 
    342 	/*
    343 	 * Extract the afar from the payload
    344 	 */
    345 	(void) nvlist_lookup_uint64(nvl, FIRE_JBC_JITEL1, &afar);
    346 	rferr->rf_afar = afar & FIRE_JBC_ADDR_MASK;
    347 
    348 	rferr->rf_afsr = NULL;
    349 	rferr->rf_synd = NULL;
    350 
    351 	if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_NAME_ERR_TYPE,
    352 	    &typenm) == 0)
    353 		rferr->rf_type = cmd_mem_name2type(typenm, minorvers);
    354 
    355 	/*
    356 	 * Need to send in the io_jpid that we get from the device path above
    357 	 * for both the det_agentid and the afsr_agentid, since the CPU does not
    358 	 * capture the same address as the bridge.  The bridge has the LSB
    359 	 * aliased and the CPU is missing the MSB.
    360 	 */
    361 	if ((rfmatch = iorxefrx_match(hdl, rferr->rf_errcl, matchmask,
    362 	    rferr->rf_det_agentid, rferr->rf_afsr_agentid)) == NULL) {
    363 		cmd_iorxefrx_queue(hdl, rferr);
    364 		return (CMD_EVD_OK);
    365 		}
    366 
    367 	/* Found a match.  Synthesize an ereport for UE/CE processing. */
    368 	fmd_hdl_debug(hdl, "matched %cE %llx with %llx\n", "UC"[isce],
    369 	    rferr->rf_errcl, rfmatch->rf_errcl);
    370 
    371 	hdlr = (isce ? cmd_ce_common : cmd_ue_common);
    372 	rc = iorxefrx_synthesize(hdl, ep, nvl, class, rferr->rf_afar,
    373 	    rferr->rf_afar_status, rfmatch->rf_afsr, rfmatch->rf_synd,
    374 	    rfmatch->rf_synd_status, rferr->rf_type, rferr->rf_disp, hdlr);
    375 
    376 	cmd_iorxefrx_free(hdl, rfmatch);
    377 	fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    378 
    379 	return (rc);
    380 }
    381 
    382 /* This IOxE must be matched with an FRx before UE/CE processing is possible */
    383 static cmd_evdisp_t
    384 cmd_ioxefrx_common(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
    385     const char *class, cmd_errcl_t errcl, cmd_errcl_t matchmask)
    386 {
    387 	cmd_xe_handler_f *hdlr;
    388 	cmd_iorxefrx_t *rfmatch, *rferr;
    389 	char *typenm;
    390 	int isce = CMD_ERRCL_MATCH(errcl, CMD_ERRCL_IOCE);
    391 	char *portid_str;
    392 	char *path = NULL;
    393 	nvlist_t *det = NULL;
    394 	int rc;
    395 	int minorvers = 1;
    396 
    397 	rferr = fmd_hdl_zalloc(hdl, sizeof (cmd_iorxefrx_t), FMD_SLEEP);
    398 
    399 	if (nvlist_lookup_pairs(nvl, 0,
    400 	    PCI_ECC_AFAR, DATA_TYPE_UINT64, &rferr->rf_afar,
    401 	    PCI_ECC_AFSR, DATA_TYPE_UINT64, &rferr->rf_afsr,
    402 	    PCI_ECC_SYND, DATA_TYPE_UINT16, &rferr->rf_synd,
    403 	    PCI_ECC_TYPE, DATA_TYPE_STRING, &typenm,
    404 	    NULL) != 0) {
    405 		fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    406 		return (CMD_EVD_BAD);
    407 	}
    408 
    409 	if (nvlist_lookup_uint64(nvl, PCI_ECC_DISP, &rferr->rf_disp) != 0)
    410 		minorvers = 0;
    411 
    412 	rferr->rf_type = cmd_mem_name2type(typenm, minorvers);
    413 	rferr->rf_errcl = errcl;
    414 
    415 	/*
    416 	 * Lookup device path of host bridge.
    417 	 */
    418 	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &det);
    419 	(void) nvlist_lookup_string(det, FM_FMRI_DEV_PATH, &path);
    420 
    421 	/*
    422 	 * get Jbus port id from the device path
    423 	 */
    424 	portid_str = strrchr(path, '@') + 1;
    425 	rferr->rf_det_agentid = strtol(portid_str, NULL, 16);
    426 
    427 	rferr->rf_afsr_agentid = (rferr->rf_afsr &
    428 	    SCHIZO_ECC_UE_AFSR_AGENT_MID) >> SCHIZO_ECC_UE_AFSR_AGENT_MID_SHIFT;
    429 
    430 	/*
    431 	 * Only 4 bits of the Jbus AID are sent on the Jbus.  MSB is the one
    432 	 * that is chosen not to make the trip.  This is not in any of the Jbus
    433 	 * or Tomatillo documents and was discovered during testing and verified
    434 	 * by Jalapeno H/W designer.
    435 	 */
    436 	rferr->rf_afsr_agentid &= 0xf;
    437 	rferr->rf_afar_status = AFLT_STAT_VALID;
    438 	rferr->rf_synd_status = AFLT_STAT_VALID;
    439 
    440 	/*
    441 	 * Need to send in the io_jpid that we get from the device path above
    442 	 * for both the det_agentid and the afsr_agentid, since the CPU does not
    443 	 * capture the same address as the bridge.  The bridge has the LSB
    444 	 * aliased and the CPU is missing the MSB.
    445 	 */
    446 	if ((rfmatch = iorxefrx_match(hdl, rferr->rf_errcl, matchmask,
    447 	    rferr->rf_det_agentid, rferr->rf_afsr_agentid)) == NULL) {
    448 		cmd_iorxefrx_queue(hdl, rferr);
    449 		return (CMD_EVD_OK);
    450 	}
    451 
    452 	/* Found a match.  Synthesize an ereport for UE/CE processing. */
    453 	fmd_hdl_debug(hdl, "matched %cE %llx with %llx\n", "UC"[isce],
    454 	    rferr->rf_errcl, rfmatch->rf_errcl);
    455 
    456 	hdlr = (isce ? cmd_ce_common : cmd_ue_common);
    457 	rc = iorxefrx_synthesize(hdl, ep, nvl, class, rferr->rf_afar,
    458 	    rferr->rf_afar_status, rfmatch->rf_afsr, rfmatch->rf_synd,
    459 	    rfmatch->rf_synd_status, rferr->rf_type, rferr->rf_disp, hdlr);
    460 
    461 	cmd_iorxefrx_free(hdl, rfmatch);
    462 	fmd_hdl_free(hdl, rferr, sizeof (cmd_iorxefrx_t));
    463 
    464 	return (rc);
    465 }
    466 
    467 /* IOxE ereports that don't need matching with FRx ereports */
    468 static cmd_evdisp_t
    469 ioxe_common(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    470     cmd_errcl_t clcode)
    471 {
    472 	int isce = CMD_ERRCL_MATCH(clcode, CMD_ERRCL_IOCE);
    473 	cmd_xe_handler_f *hdlr = isce ? cmd_ce_common : cmd_ue_common;
    474 	uint64_t afar;
    475 	uint16_t synd;
    476 	nvlist_t *rsrc;
    477 	char *typenm;
    478 	uint64_t disp;
    479 	int minorvers = 1;
    480 
    481 	if (nvlist_lookup_pairs(nvl, 0,
    482 	    PCI_ECC_AFAR, DATA_TYPE_UINT64, &afar,
    483 	    PCI_ECC_SYND, DATA_TYPE_UINT16, &synd,
    484 	    PCI_ECC_TYPE, DATA_TYPE_STRING, &typenm,
    485 	    PCI_ECC_RESOURCE, DATA_TYPE_NVLIST, &rsrc,
    486 	    NULL) != 0)
    487 		return (CMD_EVD_BAD);
    488 
    489 	if (nvlist_lookup_uint64(nvl, PCI_ECC_DISP, &disp) != 0)
    490 		minorvers = 0;
    491 
    492 	return (hdlr(hdl, ep, nvl, class, afar, AFLT_STAT_VALID, synd,
    493 	    AFLT_STAT_VALID, cmd_mem_name2type(typenm, minorvers), disp,
    494 	    rsrc));
    495 }
    496 
    497 cmd_evdisp_t
    498 cmd_rxe(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    499     cmd_errcl_t clcode)
    500 {
    501 	cmd_errcl_t matchmask = (clcode == CMD_ERRCL_RCE ? CMD_ERRCL_FRC :
    502 	    CMD_ERRCL_FRU);
    503 
    504 	return (cmd_rxefrx_common(hdl, ep, nvl, class, clcode, matchmask));
    505 }
    506 
    507 cmd_evdisp_t
    508 cmd_ioxe(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    509     cmd_errcl_t clcode)
    510 {
    511 	cmd_errcl_t matchmask = (clcode == CMD_ERRCL_IOCE ? CMD_ERRCL_FRC :
    512 	    CMD_ERRCL_FRU);
    513 
    514 	if (fmd_nvl_class_match(hdl, nvl, "ereport.io.tom.*")) {
    515 		return (cmd_ioxefrx_common(hdl, ep, nvl, class, clcode,
    516 		    matchmask));
    517 	} else  if (fmd_nvl_class_match(hdl, nvl, "ereport.io.fire.*")) {
    518 			return (cmd_ioxefrx_fire(hdl, ep, nvl, class, clcode,
    519 			    matchmask));
    520 	} else
    521 		return (ioxe_common(hdl, ep, nvl, class, clcode));
    522 }
    523 
    524 /*ARGSUSED*/
    525 cmd_evdisp_t
    526 cmd_ioxe_sec(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
    527     cmd_errcl_t clcode)
    528 {
    529 	/*
    530 	 * Secondary IOxE's can't be used to identify failed or failing
    531 	 * resources, as they don't contain enough information.  Ignore them.
    532 	 */
    533 	return (CMD_EVD_OK);
    534 }
    535 
    536 /*ARGSUSED*/
    537 ulong_t
    538 cmd_mem_get_phys_pages(fmd_hdl_t *hdl)
    539 {
    540 	return (sysconf(_SC_PHYS_PAGES));
    541 }
    542 
    543 /*
    544  * DRAM by bit.  Note that this is independent of check-word or DIMM side.
    545  * Actual DRAM pin *is* dependent on both check-word and DIMM side.
    546  * DRAMs are numbered D0 to D35, but that doesn't tell us what DIMM
    547  * they're on!
    548  *
    549  * Data bits are numbers, 0 - 127.
    550  * ECC bits C0 - C8 => 128-136
    551  * MTAG bits MT0 - MT2 => 137-139
    552  * MTAG ECC bits MTC0 - MTC3 => 140-143
    553  *
    554  *
    555  * Uniboard Server Systems.
    556  */
    557 int unib_upos2dram[] = {
    558 	/* 0 */ 3, /* 1 */ 3, /* 2 */ 3, /* 3 */ 1,
    559 	/* 4 */ 2, /* 5 */ 0, /* 6 */ 1, /* 7 */ 2,
    560 	/* 8 */ 4, /* 9 */ 4, /* 10 */ 4, /* 11 */ 4,
    561 	/* 12 */ 5, /* 13 */ 5, /* 14 */ 5, /* 15 */ 5,
    562 	/* 16 */ 6, /* 17 */ 6, /* 18 */ 6, /* 19 */ 6,
    563 	/* 20 */ 7, /* 21 */ 7, /* 22 */ 7, /* 23 */ 7,
    564 	/* 24 */ 8, /* 25 */ 8, /* 26 */ 8, /* 27 */ 8,
    565 	/* 28 */ 9, /* 29 */ 9, /* 30 */ 9, /* 31 */ 9,
    566 	/* 32 */ 10, /* 33 */ 10, /* 34 */ 10, /* 35 */ 10,
    567 	/* 36 */ 11, /* 37 */ 11, /* 38 */ 11, /* 39 */ 11,
    568 	/* 40 */ 12, /* 41 */ 12, /* 42 */ 12, /* 43 */ 12,
    569 	/* 44 */ 13, /* 45 */ 13, /* 46 */ 13, /* 47 */ 13,
    570 	/* 48 */ 14, /* 49 */ 14, /* 50 */ 14, /* 51 */ 15,
    571 	/* 52 */ 15, /* 53 */ 15, /* 54 */ 16, /* 55 */ 16,
    572 	/* 56 */ 17, /* 57 */ 17, /* 58 */ 17, /* 59 */ 17,
    573 	/* 60 */ 18, /* 61 */ 18, /* 62 */ 18, /* 63 */ 18,
    574 	/* 64 */ 19, /* 65 */ 19, /* 66 */ 19, /* 67 */ 19,
    575 	/* 68 */ 20, /* 69 */ 20, /* 70 */ 20, /* 71 */ 20,
    576 	/* 72 */ 21, /* 73 */ 21, /* 74 */ 22, /* 75 */ 22,
    577 	/* 76 */ 22, /* 77 */ 23, /* 78 */ 23, /* 79 */ 23,
    578 	/* 80 */ 24, /* 81 */ 24, /* 82 */ 24, /* 83 */ 24,
    579 	/* 84 */ 25, /* 85 */ 25, /* 86 */ 25, /* 87 */ 25,
    580 	/* 88 */ 26, /* 89 */ 26, /* 90 */ 26, /* 91 */ 26,
    581 	/* 92 */ 27, /* 93 */ 27, /* 94 */ 27, /* 95 */ 27,
    582 	/* 96 */ 28, /* 97 */ 28, /* 98 */ 28, /* 99 */ 28,
    583 	/* 100 */ 29, /* 101 */ 29, /* 102 */ 29, /* 103 */ 29,
    584 	/* 104 */ 30, /* 105 */ 30, /* 106 */ 30, /* 107 */ 30,
    585 	/* 108 */ 31, /* 109 */ 31, /* 110 */ 31, /* 111 */ 31,
    586 	/* 112 */ 32, /* 113 */ 32, /* 114 */ 32, /* 115 */ 32,
    587 	/* 116 */ 33, /* 117 */ 33, /* 118 */ 33, /* 119 */ 33,
    588 	/* 120 */ 34, /* 121 */ 34, /* 122 */ 34, /* 123 */ 34,
    589 	/* 124 */ 35, /* 125 */ 35, /* 126 */ 35, /* 127 */ 35,
    590 	/* 128 */ 16, /* 129 */ 15, /* 130 */ 14, /* 131 */ 16,
    591 	/* 132 */ 0, /* 133 */ 21, /* 134 */ 23, /* 135 */ 22,
    592 	/* 136 */ 21, /* 137 */ 0, /* 138 */ 1, /* 139 */ 2,
    593 	/* 140 */ 0, /* 141 */ 1, /* 142 */ 2, /* 143 */ 3
    594 };
    595 
    596 /*
    597  * Camelot Server Systems.
    598  */
    599 int cams_upos2dram[] = {
    600 	/* 0 */ 5, /* 1 */ 5, /* 2 */ 5, /* 3 */ 5,
    601 	/* 4 */ 7, /* 5 */ 7, /* 6 */ 7, /* 7 */ 7,
    602 	/* 8 */ 6, /* 9 */ 6, /* 10 */ 6, /* 11 */ 6,
    603 	/* 12 */ 8, /* 13 */ 8, /* 14 */ 8, /* 15 */ 8,
    604 	/* 16 */ 4, /* 17 */ 4, /* 18 */ 4, /* 19 */ 4,
    605 	/* 20 */ 0, /* 21 */ 0, /* 22 */ 0, /* 23 */ 0,
    606 	/* 24 */ 3, /* 25 */ 3, /* 26 */ 3, /* 27 */ 3,
    607 	/* 28 */ 2, /* 29 */ 2, /* 30 */ 2, /* 31 */ 2,
    608 	/* 32 */ 1, /* 33 */ 1, /* 34 */ 1, /* 35 */ 1,
    609 	/* 36 */ 14, /* 37 */ 14, /* 38 */ 14, /* 39 */ 14,
    610 	/* 40 */ 16, /* 41 */ 16, /* 42 */ 16, /* 43 */ 16,
    611 	/* 44 */ 17, /* 45 */ 17, /* 46 */ 15, /* 47 */ 15,
    612 	/* 48 */ 13, /* 49 */ 13, /* 50 */ 13, /* 51 */ 9,
    613 	/* 52 */ 9, /* 53 */ 9, /* 54 */ 12, /* 55 */ 12,
    614 	/* 56 */ 11, /* 57 */ 11, /* 58 */ 11, /* 59 */ 11,
    615 	/* 60 */ 10, /* 61 */ 10, /* 62 */ 10, /* 63 */ 10,
    616 	/* 64 */ 23, /* 65 */ 23, /* 66 */ 23, /* 67 */ 23,
    617 	/* 68 */ 25, /* 69 */ 25, /* 70 */ 25, /* 71 */ 25,
    618 	/* 72 */ 24, /* 73 */ 24, /* 74 */ 26, /* 75 */ 26,
    619 	/* 76 */ 26, /* 77 */ 22, /* 78 */ 22, /* 79 */ 22,
    620 	/* 80 */ 18, /* 81 */ 21, /* 82 */ 21, /* 83 */ 21,
    621 	/* 84 */ 20, /* 85 */ 20, /* 86 */ 20, /* 87 */ 20,
    622 	/* 88 */ 19, /* 89 */ 19, /* 90 */ 19, /* 91 */ 19,
    623 	/* 92 */ 32, /* 93 */ 32, /* 94 */ 32, /* 95 */ 32,
    624 	/* 96 */ 34, /* 97 */ 34, /* 98 */ 34, /* 99 */ 34,
    625 	/* 100 */ 33, /* 101 */ 33, /* 102 */ 33, /* 103 */ 33,
    626 	/* 104 */ 35, /* 105 */ 35, /* 106 */ 35, /* 107 */ 35,
    627 	/* 108 */ 31, /* 109 */ 31, /* 110 */ 31, /* 111 */ 31,
    628 	/* 112 */ 27, /* 113 */ 27, /* 114 */ 27, /* 115 */ 27,
    629 	/* 116 */ 30, /* 117 */ 30, /* 118 */ 30, /* 119 */ 30,
    630 	/* 120 */ 29, /* 121 */ 29, /* 122 */ 29, /* 123 */ 29,
    631 	/* 124 */ 28, /* 125 */ 28, /* 126 */ 28, /* 127 */ 28,
    632 	/* 128 */ 12, /* 129 */ 9, /* 130 */ 13, /* 131 */ 12,
    633 	/* 132 */  18, /* 133 */ 24, /* 134 */ 22, /* 135 */ 26,
    634 	/* 136 */ 24, /* 137 */ 21, /* 138 */ 18, /* 139 */ 18,
    635 	/* 140 */ 15, /* 141 */ 15, /* 142 */ 17, /* 143 */ 17
    636 };
    637 
    638 /*
    639  * Camelot Tower Systems.
    640  */
    641 int camt_upos2dram[] = {
    642 	/* 0 */ 18, /* 1 */ 0, /* 2 */ 0, /* 3 */ 0,
    643 	/* 4 */ 9, /* 5 */ 18, /* 6 */ 27, /* 7 */ 9,
    644 	/* 8 */ 28, /* 9 */ 28, /* 10 */ 28, /* 11 */ 28,
    645 	/* 12 */ 29, /* 13 */ 29, /* 14 */ 29, /* 15 */ 29,
    646 	/* 16 */ 30, /* 17 */ 30, /* 18 */ 30, /* 19 */ 30,
    647 	/* 20 */ 21, /* 21 */ 21, /* 22 */ 21, /* 23 */ 21,
    648 	/* 24 */ 12, /* 25 */ 12, /* 26 */ 12, /* 27 */ 12,
    649 	/* 28 */ 22, /* 29 */ 22, /* 30 */ 22, /* 31 */ 22,
    650 	/* 32 */ 31, /* 33 */ 31, /* 34 */ 31, /* 35 */ 31,
    651 	/* 36 */ 32, /* 37 */ 32, /* 38 */ 32, /* 39 */ 32,
    652 	/* 40 */ 33, /* 41 */ 33, /* 42 */ 33, /* 43 */ 33,
    653 	/* 44 */ 24, /* 45 */ 24, /* 46 */ 24, /* 47 */ 24,
    654 	/* 48 */ 15, /* 49 */ 15, /* 50 */ 15, /* 51 */ 25,
    655 	/* 52 */ 25, /* 53 */ 25, /* 54 */ 34, /* 55 */ 34,
    656 	/* 56 */ 35, /* 57 */ 35, /* 58 */ 35, /* 59 */ 35,
    657 	/* 60 */ 19, /* 61 */ 19, /* 62 */ 19, /* 63 */ 19,
    658 	/* 64 */ 10, /* 65 */ 10, /* 66 */ 10, /* 67 */ 10,
    659 	/* 68 */ 1, /* 69 */ 1, /* 70 */ 1, /* 71 */ 1,
    660 	/* 72 */ 20, /* 73 */ 20, /* 74 */ 11, /* 75 */ 11,
    661 	/* 76 */ 11, /* 77 */ 2, /* 78 */ 2, /* 79 */ 2,
    662 	/* 80 */ 3, /* 81 */ 3, /* 82 */ 3, /* 83 */ 3,
    663 	/* 84 */ 4, /* 85 */ 4, /* 86 */ 4, /* 87 */ 4,
    664 	/* 88 */ 13, /* 89 */ 13, /* 90 */ 13, /* 91 */ 13,
    665 	/* 92 */ 23, /* 93 */ 23, /* 94 */ 23, /* 95 */ 23,
    666 	/* 96 */ 14, /* 97 */ 14, /* 98 */ 14, /* 99 */ 14,
    667 	/* 100 */ 5, /* 101 */ 5, /* 102 */ 5, /* 103 */ 5,
    668 	/* 104 */ 6, /* 105 */ 6, /* 106 */ 6, /* 107 */ 6,
    669 	/* 108 */ 7, /* 109 */ 7, /* 110 */ 7, /* 111 */ 7,
    670 	/* 112 */ 16, /* 113 */ 16, /* 114 */ 16, /* 115 */ 16,
    671 	/* 116 */ 26, /* 117 */ 26, /* 118 */ 26, /* 119 */ 26,
    672 	/* 120 */ 17, /* 121 */ 17, /* 122 */ 17, /* 123 */ 17,
    673 	/* 124 */ 8, /* 125 */ 8, /* 126 */ 8, /* 127 */ 8,
    674 	/* 128 */ 34, /* 129 */ 25, /* 130 */ 15, /* 131 */ 34,
    675 	/* 132 */  27, /* 133 */ 20, /* 134 */ 2, /* 135 */ 11,
    676 	/* 136 */ 20, /* 137 */ 9, /* 138 */ 18, /* 139 */ 27,
    677 	/* 140 */ 0, /* 141 */ 9, /* 142 */ 18, /* 143 */ 27
    678 };
    679 
    680 /*
    681  * Fiesta Server Systems.
    682  */
    683 int fies_upos2dram[] = {
    684 	/* 0 */ 7, /* 1 */ 7, /* 2 */ 7, /* 3 */ 7,
    685 	/* 4 */ 16, /* 5 */ 16, /* 6 */ 16, /* 7 */ 16,
    686 	/* 8 */ 25, /* 9 */ 25, /* 10 */ 25, /* 11 */ 25,
    687 	/* 12 */ 34, /* 13 */ 34, /* 14 */ 34, /* 15 */ 34,
    688 	/* 16 */ 6, /* 17 */ 6, /* 18 */ 6, /* 19 */ 6,
    689 	/* 20 */ 15, /* 21 */ 15, /* 22 */ 15, /* 23 */ 15,
    690 	/* 24 */ 24, /* 25 */ 24, /* 26 */ 24, /* 27 */ 24,
    691 	/* 28 */ 33, /* 29 */ 33, /* 30 */ 33, /* 31 */ 33,
    692 	/* 32 */ 23, /* 33 */ 23, /* 34 */ 23, /* 35 */ 23,
    693 	/* 36 */ 32, /* 37 */ 32, /* 38 */ 32, /* 39 */ 32,
    694 	/* 40 */ 22, /* 41 */ 22, /* 42 */ 22, /* 43 */ 22,
    695 	/* 44 */ 31, /* 45 */ 31, /* 46 */ 31, /* 47 */ 31,
    696 	/* 48 */ 5, /* 49 */ 5, /* 50 */ 5, /* 51 */ 5,
    697 	/* 52 */ 14, /* 53 */ 14, /* 54 */ 14, /* 55 */ 14,
    698 	/* 56 */ 4, /* 57 */ 4, /* 58 */ 4, /* 59 */ 4,
    699 	/* 60 */ 13, /* 61 */ 13, /* 62 */ 13, /* 63 */ 13,
    700 	/* 64 */ 18, /* 65 */ 18, /* 66 */ 18, /* 67 */ 18,
    701 	/* 68 */ 27, /* 69 */ 27, /* 70 */ 27, /* 71 */ 27,
    702 	/* 72 */ 0, /* 73 */ 0, /* 74 */ 0, /* 75 */ 0,
    703 	/* 76 */ 9, /* 77 */ 9, /* 78 */ 9, /* 79 */ 9,
    704 	/* 80 */ 19, /* 81 */ 19, /* 82 */ 19, /* 83 */ 19,
    705 	/* 84 */ 28, /* 85 */ 28, /* 86 */ 28, /* 87 */ 28,
    706 	/* 88 */ 1, /* 89 */ 1, /* 90 */ 1, /* 91 */ 1,
    707 	/* 92 */ 10, /* 93 */ 10, /* 94 */ 10, /* 95 */ 10,
    708 	/* 96 */ 3, /* 97 */ 3, /* 98 */ 3, /* 99 */ 3,
    709 	/* 100 */ 12, /* 101 */ 12, /* 102 */ 12, /* 103 */ 12,
    710 	/* 104 */ 20, /* 105 */ 20, /* 106 */ 20, /* 107 */ 20,
    711 	/* 108 */ 29, /* 109 */ 29, /* 110 */ 29, /* 111 */ 29,
    712 	/* 112 */ 8, /* 113 */ 8, /* 114 */ 8, /* 115 */ 8,
    713 	/* 116 */ 17, /* 117 */ 17, /* 118 */ 17, /* 119 */ 17,
    714 	/* 120 */ 21, /* 121 */ 21, /* 122 */ 21, /* 123 */ 21,
    715 	/* 124 */ 30, /* 125 */ 30, /* 126 */ 30, /* 127 */ 30,
    716 	/* 128 */ 2, /* 129 */ 2, /* 130 */ 2, /* 131 */ 2,
    717 	/* 132 */ 11, /* 133 */ 11, /* 134 */ 11, /* 135 */ 11,
    718 	/* 136 */ 26, /* 137 */ 26, /* 138 */ 26, /* 139 */ 26,
    719 	/* 140 */ 35, /* 141 */ 35, /* 142 */ 35, /* 143 */ 35
    720 };
    721 
    722 /*
    723  * Fiesta Tower Systems.
    724  */
    725 int fiet_upos2dram[] = {
    726 	/* 0 */ 0, /* 1 */ 0, /* 2 */ 0, /* 3 */ 0,
    727 	/* 4 */ 9, /* 5 */ 9, /* 6 */ 9, /* 7 */ 9,
    728 	/* 8 */ 18, /* 9 */ 18, /* 10 */ 18, /* 11 */ 18,
    729 	/* 12 */ 27, /* 13 */ 27, /* 14 */ 27, /* 15 */ 27,
    730 	/* 16 */ 19, /* 17 */ 19, /* 18 */ 19, /* 19 */ 19,
    731 	/* 20 */ 28, /* 21 */ 28, /* 22 */ 28, /* 23 */ 28,
    732 	/* 24 */ 1, /* 25 */ 1, /* 26 */ 1, /* 27 */ 1,
    733 	/* 28 */ 10, /* 29 */ 10, /* 30 */ 10, /* 31 */ 10,
    734 	/* 32 */ 20, /* 33 */ 20, /* 34 */ 20, /* 35 */ 20,
    735 	/* 36 */ 29, /* 37 */ 29, /* 38 */ 29, /* 39 */ 29,
    736 	/* 40 */ 2, /* 41 */ 2, /* 42 */ 2, /* 43 */ 2,
    737 	/* 44 */ 11, /* 45 */ 11, /* 46 */ 11, /* 47 */ 11,
    738 	/* 48 */ 21, /* 49 */ 21, /* 50 */ 21, /* 51 */ 21,
    739 	/* 52 */ 30, /* 53 */ 30, /* 54 */ 30, /* 55 */ 30,
    740 	/* 56 */ 3, /* 57 */ 3, /* 58 */ 3, /* 59 */ 3,
    741 	/* 60 */ 12, /* 61 */ 12, /* 62 */ 12, /* 63 */ 12,
    742 	/* 64 */ 8, /* 65 */ 8, /* 66 */ 8, /* 67 */ 8,
    743 	/* 68 */ 17, /* 69 */ 17, /* 70 */ 17, /* 71 */ 17,
    744 	/* 72 */ 22, /* 73 */ 22, /* 74 */ 22, /* 75 */ 22,
    745 	/* 76 */ 31, /* 77 */ 31, /* 78 */ 31, /* 79 */ 31,
    746 	/* 80 */ 4, /* 81 */ 4, /* 82 */ 4, /* 83 */ 4,
    747 	/* 84 */ 13, /* 85 */ 13, /* 86 */ 13, /* 87 */ 13,
    748 	/* 88 */ 23, /* 89 */ 23, /* 90 */ 23, /* 91 */ 23,
    749 	/* 92 */ 32, /* 93 */ 32, /* 94 */ 32, /* 95 */ 32,
    750 	/* 96 */ 5, /* 97 */ 5, /* 98 */ 5, /* 99 */ 5,
    751 	/* 100 */ 14, /* 101 */ 14, /* 102 */ 14, /* 103 */ 14,
    752 	/* 104 */ 24, /* 105 */ 24, /* 106 */ 24, /* 107 */ 24,
    753 	/* 108 */ 33, /* 109 */ 33, /* 110 */ 33, /* 111 */ 33,
    754 	/* 112 */ 6, /* 113 */ 6, /* 114 */ 6, /* 115 */ 6,
    755 	/* 116 */ 15, /* 117 */ 15, /* 118 */ 15, /* 119 */ 15,
    756 	/* 120 */ 25, /* 121 */ 25, /* 122 */ 25, /* 123 */ 25,
    757 	/* 124 */ 34, /* 125 */ 34, /* 126 */ 34, /* 127 */ 34,
    758 	/* 128 */ 7, /* 129 */ 7, /* 130 */ 7, /* 131 */ 7,
    759 	/* 132 */ 16, /* 133 */ 16, /* 134 */ 16, /* 135 */ 16,
    760 	/* 136 */ 26, /* 137 */ 26, /* 138 */ 26, /* 139 */ 26,
    761 	/* 140 */ 35, /* 141 */ 35, /* 142 */ 35, /* 143 */ 35
    762 };
    763 
    764 /*
    765  * sun4u bit position as function of e_synd,
    766  * from JPS1 Implementation Supplement table P-7
    767  * Encode bit positions as follows:
    768  * 0-127 data bits 0-127
    769  * 128-136 check bits 0-8 (Cn = 128+n)
    770  * no error or multibit error = -1 (not valid CE)
    771  */
    772 
    773 int esynd2bit [] = {
    774 	-1, 128, 129, -1, 130, -1, -1, 47,
    775 	131, -1, -1, 53, -1, 41, 29, -1, /* 000-00F */
    776 	132, -1, -1, 50, -1, 38, 25, -1,
    777 	-1, 33, 24, -1, 11, -1, -1, 16, /* 010-01F */
    778 	133, -1, -1, 46, -1, 37, 19, -1,
    779 	-1, 31, 32, -1,  7, -1, -1, 10, /* 020-02F */
    780 	-1, 40, 13, -1, 59, -1, -1, 66,
    781 	-1, -1, -1,  0, -1, 67, 71, -1, /* 030-03F */
    782 	134, -1, -1, 43, -1, 36, 18, -1,
    783 	-1, 49, 15, -1, 63, -1, -1,  6, /* 040-04F */
    784 	-1, 44, 28, -1, -1, -1, -1, 52,
    785 	68, -1, -1, 62, -1, -1, -1, -1, /* 050-05F */
    786 	-1, 26, 106, -1, 64, -1, -1,  2,
    787 	120, -1, -1, -1, -1, -1, -1, -1, /* 060-06F */
    788 	116, -1, -1, -1, -1, -1, -1, -1,
    789 	-1, 58, 54, -1, -1, -1, -1, -1, /* 070-07F */
    790 	135, -1, -1, 42, -1, 35, 17, -1,
    791 	-1, 45, 14, -1, 21, -1, -1,  5, /* 080-08F */
    792 	-1, 27, -1, -1, 99, -1, -1,  3,
    793 	114, -1, -1, 20, -1, -1, -1, -1, /* 090-09F */
    794 	-1, 23, 113, -1, 112, -1, -1, 51,
    795 	95, -1, -1, -1, -1, -1, -1, -1, /* 0A0-0AF */
    796 	103, -1, -1, -1, -1, -1, -1, -1,
    797 	-1, 48, -1, -1, 73, -1, -1, -1, /* 0B0-0BF */
    798 	-1, 22, 110, -1, 109, -1, -1,  9,
    799 	108, -1, -1, -1, -1, -1, -1, -1, /* 0C0-0CF */
    800 	102, -1, -1, -1, -1, -1, -1, -1,
    801 	-1, -1, -1, -1, -1, -1, -1, -1, /* 0D0-0DF */
    802 	98, -1, -1, -1, -1, -1, -1, -1,
    803 	-1, -1, -1, -1, -1, -1, -1, -1, /* 0E0-0EF */
    804 	-1, -1, -1, -1, -1, -1, -1, -1,
    805 	56, -1, -1, -1, -1, -1, -1, -1, /* 0F0-0FF */
    806 	136, -1, -1, 39, -1, 34, 105, -1,
    807 	-1, 30, 104, -1, 101, -1, -1,  4, /* 100-10F */
    808 	-1, -1, 100, -1, 83, -1, -1, 12,
    809 	87, -1, -1, 57, -1, -1, -1, -1, /* 110-11F */
    810 	-1, 97, 82, -1, 78, -1, -1,  1,
    811 	96, -1, -1, -1, -1, -1, -1, -1, /* 120-12F */
    812 	94, -1, -1, -1, -1, -1, -1, -1,
    813 	-1, -1, 79, -1, 69, -1, -1, -1, /* 130-13F */
    814 	-1, 93, 92, -1, 91, -1, -1,  8,
    815 	90, -1, -1, -1, -1, -1, -1, -1, /* 140-14F */
    816 	89, -1, -1, -1, -1, -1, -1, -1,
    817 	-1, -1, -1, -1, -1, -1, -1, -1, /* 150-15F */
    818 	86, -1, -1, -1, -1, -1, -1, -1,
    819 	-1, -1, -1, -1, -1, -1, -1, -1, /* 160-16F */
    820 	-1, -1, -1, -1, -1, -1, -1, -1,
    821 	60, -1, -1, -1, -1, -1, -1, -1, /* 170-17F */
    822 	-1, 88, 85, -1, 84, -1, -1, 55,
    823 	81, -1, -1, -1, -1, -1, -1, -1, /* 180-18F */
    824 	77, -1, -1, -1, -1, -1, -1, -1,
    825 	-1, -1, -1, -1, -1, -1, -1, -1, /* 190-19F */
    826 	74, -1, -1, -1, -1, -1, -1, -1,
    827 	-1, -1, -1, -1, -1, -1, -1, -1, /* 1A0-1AF */
    828 	-1, 70, 107, -1, 65, -1, -1, -1,
    829 	127, -1, -1, -1, -1, -1, -1, -1, /* 1B0-1BF */
    830 	80, -1, -1, 72, -1, 119, 118, -1,
    831 	-1, 126, 76, -1, 125, -1, -1, -1, /* 1C0-1CF */
    832 	-1, 115, 124, -1, 75, -1, -1, -1,
    833 	61, -1, -1, -1, -1, -1, -1, -1, /* 1D0-1DF */
    834 	-1, 123, 122, -1, 121, -1, -1, -1,
    835 	117, -1, -1, -1, -1, -1, -1, -1, /* 1E0-1EF */
    836 	111, -1, -1, -1, -1, -1, -1, -1,
    837 	-1, -1, -1, -1, -1, -1, -1, -1  /* 1F0-1FF */
    838 };
    839 
    840 int msynd2bit [] = {  /* msynd 0-F */
    841 	-1, 140, 141,  -1,
    842 	142, -1,  -1, 137,
    843 	143, -1,  -1, 138,
    844 	-1, 139,  -1,  -1
    845 };
    846 
    847 typedef enum plats2dram {
    848 	UNI_S_PLAT = 0,	/* UniBoard Server Systems */
    849 	CAM_S_PLAT,	/* Camelot Server Systems */
    850 	CAM_T_PLAT,	/* Camelot Tower Systems */
    851 	FIE_S_PLAT,	/* Fiesta Server Systems */
    852 	FIE_T_PLAT,	/* Fiesta Tower Systems */
    853 	NONE
    854 } plats_t;
    855 
    856 struct plat2dram_map {
    857 	char	*platnm;
    858 	plats_t	plat;
    859 } dram_plat[] = {
    860 	/* Platform name		DRAM Map	Code Name */
    861 	{"SUNW,Sun-Fire-15000",		UNI_S_PLAT}, /* Starcat */
    862 	{"SUNW,Sun-Fire",		UNI_S_PLAT}, /* Serengeti */
    863 	{"SUNW,Netra-T12",		UNI_S_PLAT}, /* Lightweight 8 */
    864 	{"SUNW,Sun-Fire-480R",		CAM_S_PLAT}, /* Cherrystone */
    865 	{"SUNW,Sun-Fire-880",		CAM_S_PLAT}, /* Daktari */
    866 	{"SUNW,Sun-Fire-V490",		CAM_S_PLAT}, /* Sebring */
    867 	{"SUNW,Sun-Fire-V890",		CAM_S_PLAT}, /* Silverstone */
    868 	{"SUNW,Sun-Blade-1000",		CAM_T_PLAT}, /* Excalibur */
    869 	{"SUNW,Netra-T4",		CAM_T_PLAT}, /* Netra 20 */
    870 	{"SUNW,Sun-Fire-V440",		FIE_S_PLAT}, /* Chalupa */
    871 	{"SUNW,Sun-Fire-V445",		FIE_S_PLAT}, /* Boston */
    872 	{"SUNW,A70",			FIE_S_PLAT}, /* Chicago */
    873 	{"SUNW,Sun-Fire-V215",		FIE_S_PLAT}, /* Seattle 1U */
    874 	{"SUNW,Sun-Fire-V245",		FIE_S_PLAT}, /* Seattle 2U */
    875 	{"SUNW,Netra-440",		FIE_S_PLAT}, /* Netra 440 */
    876 	{"SUNW,Sun-Blade-1500",		FIE_T_PLAT}, /* Taco */
    877 	{"SUNW,Sun-Blade-2500",		FIE_T_PLAT}, /* Enchilada */
    878 	{"SUNW,Sun-Fire-V210",		FIE_T_PLAT}, /* Enchilada 1U */
    879 	{"SUNW,Sun-Fire-V240",		FIE_T_PLAT}, /* Enchilada 2U */
    880 	{"SUNW,Sun-Fire-V250",		FIE_T_PLAT}, /* Enchilada 2P */
    881 	{"SUNW,Netra-210",		FIE_T_PLAT}, /* Netra 210 */
    882 	{"SUNW,Netra-240",		FIE_T_PLAT}, /* Netra 240 */
    883 	{NULL,				NONE}
    884 };
    885 
    886 int
    887 cmd_synd2upos(uint16_t syndrome) {
    888 	return (esynd2bit[syndrome]);
    889 }
    890 
    891 const char *fmd_fmri_get_platform();
    892 
    893 /*
    894  * Return the DRAM within the DIMM associated with the unit position.
    895  */
    896 int
    897 cmd_upos2dram(uint16_t unit_position) {
    898 
    899 	int		i, dram;
    900 	plats_t		plat = NONE;
    901 	const char 	*plat_name = fmd_fmri_get_platform();
    902 	int		*plat_upos2dram[] = {
    903 		unib_upos2dram,
    904 		cams_upos2dram,
    905 		camt_upos2dram,
    906 		fies_upos2dram,
    907 		fiet_upos2dram
    908 	};
    909 
    910 	/* get DRAM map from platform name */
    911 	for (i = 0; dram_plat[i].platnm != NULL; i++) {
    912 		if (strcmp(plat_name, dram_plat[i].platnm) == 0) {
    913 			plat = dram_plat[i].plat;
    914 			break;
    915 		}
    916 	}
    917 
    918 	if (plat != NONE) {
    919 		dram = plat_upos2dram[plat][unit_position];
    920 	} else {
    921 		dram = -1;
    922 	}
    923 
    924 	return (dram);
    925 }
    926