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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#include <sys/types.h>
27#include <sys/cmn_err.h>
28#include <sys/errno.h>
29#include <sys/log.h>
30#include <sys/systm.h>
31#include <sys/modctl.h>
32#include <sys/errorq.h>
33#include <sys/controlregs.h>
34#include <sys/fm/util.h>
35#include <sys/fm/protocol.h>
36#include <sys/sysevent.h>
37#include <sys/pghw.h>
38#include <sys/cyclic.h>
39#include <sys/pci_cfgspace.h>
40#include <sys/mc_intel.h>
41#include <sys/smbios.h>
42#include "nb5000.h"
43#include "nb_log.h"
44#include "dimm_phys.h"
45
46int nb_check_validlog = 1;
47
48static uint32_t uerrcnt[2];
49static uint32_t cerrcnta[2][2];
50static uint32_t cerrcntb[2][2];
51static uint32_t cerrcntc[2][2];
52static uint32_t cerrcntd[2][2];
53static nb_logout_t nb_log;
54
55struct mch_error_code {
56	int intel_error_list;	/* error number in Chipset Error List */
57	uint32_t emask;		/* mask for machine check */
58	uint32_t error_bit;	/* error bit in fault register */
59};
60
61static struct mch_error_code fat_fbd_error_code[] = {
62	{ 23, EMASK_FBD_M23, ERR_FAT_FBD_M23 },
63	{ 3, EMASK_FBD_M3, ERR_FAT_FBD_M3 },
64	{ 2, EMASK_FBD_M2, ERR_FAT_FBD_M2 },
65	{ 1, EMASK_FBD_M1, ERR_FAT_FBD_M1 }
66};
67
68static int
69intel_fat_fbd_err(uint32_t fat_fbd)
70{
71	int rt = -1;
72	int nerr = 0;
73	uint32_t emask_fbd = 0;
74	int i;
75	int sz;
76
77	sz = sizeof (fat_fbd_error_code) / sizeof (struct mch_error_code);
78
79	for (i = 0; i < sz; i++) {
80		if (fat_fbd & fat_fbd_error_code[i].error_bit) {
81			rt = fat_fbd_error_code[i].intel_error_list;
82			emask_fbd |= fat_fbd_error_code[i].emask;
83			nerr++;
84		}
85	}
86
87	if (emask_fbd)
88		nb_fbd_mask_mc(emask_fbd);
89	if (nerr > 1)
90		rt = -1;
91	return (rt);
92}
93
94static char *
95fat_memory_error(const nb_regs_t *rp, void *data)
96{
97	int channel;
98	uint32_t ferr_fat_fbd, nrecmemb;
99	uint32_t nrecmema;
100	char *intr = "nb.unknown";
101	nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms;
102
103	ferr_fat_fbd = rp->nb.fat_fbd_regs.ferr_fat_fbd;
104	if ((ferr_fat_fbd & ERR_FAT_FBD_MASK) == 0) {
105		sp->intel_error_list =
106		    intel_fat_fbd_err(rp->nb.fat_fbd_regs.nerr_fat_fbd);
107		sp->branch = -1;
108		sp->channel = -1;
109		sp->rank = -1;
110		sp->dimm = -1;
111		sp->bank = -1;
112		sp->cas = -1;
113		sp->ras = -1;
114		sp->pa = -1LL;
115		sp->offset = -1;
116		return (intr);
117	}
118	sp->intel_error_list = intel_fat_fbd_err(ferr_fat_fbd);
119	channel = (ferr_fat_fbd >> 28) & 3;
120	sp->branch = channel >> 1;
121	sp->channel = channel;
122	if ((ferr_fat_fbd & (ERR_FAT_FBD_M2|ERR_FAT_FBD_M1)) != 0) {
123		if ((ferr_fat_fbd & ERR_FAT_FBD_M1) != 0)
124			intr = "nb.fbd.alert";	/* Alert on FB-DIMM M1 */
125		else
126			intr = "nb.fbd.crc";	/* CRC error FB_DIMM M2 */
127		nrecmema = rp->nb.fat_fbd_regs.nrecmema;
128		nrecmemb = rp->nb.fat_fbd_regs.nrecmemb;
129		sp->rank = (nrecmema >> 8) & RANK_MASK;
130		sp->dimm = sp->rank >> 1;
131		sp->bank = (nrecmema >> 12) & BANK_MASK;
132		sp->cas = (nrecmemb >> 16) & CAS_MASK;
133		sp->ras = nrecmemb & RAS_MASK;
134		/*
135		 * If driver was built with closed tree present then we will
136		 * have Intel proprietary code for finding physaddr
137		 */
138		if (&dimm_getphys) {
139			sp->pa = dimm_getphys((uint16_t)sp->branch,
140			    (uint16_t)sp->rank, (uint64_t)sp->bank,
141			    (uint64_t)sp->ras, (uint64_t)sp->cas);
142			if (sp->pa >= MAXPHYS_ADDR)
143				sp->pa = -1ULL;
144		} else {
145			sp->pa = -1ULL;
146		}
147		/*
148		 * If there is an offset decoder use it otherwise encode
149		 * rank/bank/ras/cas
150		 */
151		if (&dimm_getoffset) {
152			sp->offset = dimm_getoffset(sp->branch, sp->rank,
153			    sp->bank, sp->ras, sp->cas);
154		} else {
155			sp->offset = TCODE_OFFSET(sp->rank, sp->bank, sp->ras,
156			    sp->cas);
157		}
158	} else {
159		if ((ferr_fat_fbd & ERR_FAT_FBD_M3) != 0)
160			intr = "nb.fbd.otf";	/* thermal temp > Tmid M3 */
161		else if ((ferr_fat_fbd & ERR_FAT_FBD_M23) != 0) {
162			intr = "nb.fbd.reset_timeout";
163			sp->channel = -1;
164		}
165		sp->rank = -1;
166		sp->dimm = -1;
167		sp->bank = -1;
168		sp->cas = -1;
169		sp->ras = -1;
170		sp->pa = -1LL;
171		sp->offset = -1;
172	}
173	return (intr);
174}
175
176
177static struct mch_error_code nf_fbd_error_code[] = {
178	{ 29, EMASK_FBD_M29, ERR_NF_FBD_M29 },
179	{ 28, EMASK_FBD_M28, ERR_NF_FBD_M28 },
180	{ 27, EMASK_FBD_M27, ERR_NF_FBD_M27 },
181	{ 26, EMASK_FBD_M26, ERR_NF_FBD_M26 },
182	{ 25, EMASK_FBD_M25, ERR_NF_FBD_M25 },
183	{ 24, EMASK_FBD_M24, ERR_NF_FBD_M24 },
184	{ 22, EMASK_FBD_M22, ERR_NF_FBD_M22 },
185	{ 21, EMASK_FBD_M21, ERR_NF_FBD_M21 },
186	{ 20, EMASK_FBD_M20, ERR_NF_FBD_M20 },
187	{ 19, EMASK_FBD_M19, ERR_NF_FBD_M19 },
188	{ 18, EMASK_FBD_M18, ERR_NF_FBD_M18 },
189	{ 17, EMASK_FBD_M17, ERR_NF_FBD_M17 },
190	{ 16, EMASK_FBD_M16, ERR_NF_FBD_M16 },
191	{ 15, EMASK_FBD_M15, ERR_NF_FBD_M15 },
192	{ 14, EMASK_FBD_M14, ERR_NF_FBD_M14 },
193	{ 13, EMASK_FBD_M13, ERR_NF_FBD_M13 },
194	{ 12, EMASK_FBD_M12, ERR_NF_FBD_M12 },
195	{ 11, EMASK_FBD_M11, ERR_NF_FBD_M11 },
196	{ 10, EMASK_FBD_M10, ERR_NF_FBD_M10 },
197	{ 9, EMASK_FBD_M9, ERR_NF_FBD_M9 },
198	{ 8, EMASK_FBD_M8, ERR_NF_FBD_M8 },
199	{ 7, EMASK_FBD_M7, ERR_NF_FBD_M7 },
200	{ 6, EMASK_FBD_M6, ERR_NF_FBD_M6 },
201	{ 5, EMASK_FBD_M5, ERR_NF_FBD_M5 },
202	{ 4, EMASK_FBD_M4, ERR_NF_FBD_M4 }
203};
204
205static int
206intel_nf_fbd_err(uint32_t nf_fbd)
207{
208	int rt = -1;
209	int nerr = 0;
210	uint32_t emask_fbd = 0;
211	int i;
212	int sz;
213
214	sz = sizeof (nf_fbd_error_code) / sizeof (struct mch_error_code);
215
216	for (i = 0; i < sz; i++) {
217		if (nf_fbd & nf_fbd_error_code[i].error_bit) {
218			rt = nf_fbd_error_code[i].intel_error_list;
219			emask_fbd |= nf_fbd_error_code[i].emask;
220			nerr++;
221		}
222	}
223	if (emask_fbd)
224		nb_fbd_mask_mc(emask_fbd);
225	if (nerr > 1)
226		rt = -1;
227	return (rt);
228}
229
230static char *
231nf_memory_error(const nb_regs_t *rp, void *data)
232{
233	uint32_t ferr_nf_fbd, recmemb, redmemb;
234	uint32_t recmema;
235	int branch, channel, ecc_locator;
236	char *intr = "nb.unknown";
237	nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms;
238
239	sp->rank = -1;
240	sp->dimm = -1;
241	sp->bank = -1;
242	sp->cas = -1;
243	sp->ras = -1LL;
244	sp->pa = -1LL;
245	sp->offset = -1;
246	ferr_nf_fbd = rp->nb.nf_fbd_regs.ferr_nf_fbd;
247	if ((ferr_nf_fbd & ERR_NF_FBD_MASK) == 0) {
248		/* unknown ereport if a recognizable error was not found */
249		sp->branch = -1;
250		sp->channel = -1;
251		sp->intel_error_list = -1;
252		return (intr);
253	}
254	sp->intel_error_list = intel_nf_fbd_err(ferr_nf_fbd);
255	channel = (ferr_nf_fbd >> ERR_FBD_CH_SHIFT) & 3;
256	branch = channel >> 1;
257	sp->branch = branch;
258	sp->channel = channel;
259	if (ferr_nf_fbd & ERR_NF_FBD_MASK) {
260		if (ferr_nf_fbd & ERR_NF_FBD_ECC_UE) {
261			/*
262			 * uncorrectable ECC M4 - M12
263			 * we can only isolate to pair of dimms
264			 * for single dimm configuration let eversholt
265			 * sort it out with out needing a special rule
266			 */
267			sp->channel = -1;
268			recmema = rp->nb.nf_fbd_regs.recmema;
269			recmemb = rp->nb.nf_fbd_regs.recmemb;
270			sp->rank = (recmema >> 8) & RANK_MASK;
271			sp->bank = (recmema >> 12) & BANK_MASK;
272			sp->cas = (recmemb >> 16) & CAS_MASK;
273			sp->ras = recmemb & RAS_MASK;
274			intr = "nb.mem_ue";
275		} else if (ferr_nf_fbd & ERR_NF_FBD_M13) {
276			/*
277			 * write error M13
278			 * we can only isolate to pair of dimms
279			 */
280			sp->channel = -1;
281			if (nb_mode != NB_MEMORY_MIRROR) {
282				recmema = rp->nb.nf_fbd_regs.recmema;
283				recmemb = rp->nb.nf_fbd_regs.recmemb;
284				sp->rank = (recmema >> 8) & RANK_MASK;
285				sp->bank = (recmema >> 12) & BANK_MASK;
286				sp->cas = (recmemb >> 16) & CAS_MASK;
287				sp->ras = recmemb & RAS_MASK;
288			}
289			intr = "nb.fbd.ma"; /* memory alert */
290		} else if (ferr_nf_fbd & ERR_NF_FBD_MA) { /* M14, M15 and M21 */
291			intr = "nb.fbd.ch"; /* FBD on channel */
292		} else if ((ferr_nf_fbd & ERR_NF_FBD_ECC_CE) != 0) {
293			/* correctable ECC M17-M20 */
294			recmema = rp->nb.nf_fbd_regs.recmema;
295			recmemb = rp->nb.nf_fbd_regs.recmemb;
296			sp->rank = (recmema >> 8) & RANK_MASK;
297			redmemb = rp->nb.nf_fbd_regs.redmemb;
298			ecc_locator = redmemb & 0x3ffff;
299			if (ecc_locator & 0x1ff)
300				sp->channel = branch << 1;
301			else if (ecc_locator & 0x3fe00)
302				sp->channel = (branch << 1) + 1;
303			sp->dimm = sp->rank >> 1;
304			sp->bank = (recmema >> 12) & BANK_MASK;
305			sp->cas = (recmemb >> 16) & CAS_MASK;
306			sp->ras = recmemb & RAS_MASK;
307			intr = "nb.mem_ce";
308		} else if ((ferr_nf_fbd & ERR_NF_FBD_SPARE) != 0) {
309			/* spare dimm M27, M28 */
310			intr = "nb.mem_ds";
311			sp->channel = -1;
312			if (rp->nb.nf_fbd_regs.spcps & SPCPS_SPARE_DEPLOYED) {
313				sp->rank =
314				    SPCPS_FAILED_RANK(rp->nb.nf_fbd_regs.spcps);
315				nb_used_spare_rank(sp->branch, sp->rank);
316				nb_config_gen++;
317			}
318		} else if ((ferr_nf_fbd & ERR_NF_FBD_M22) != 0) {
319			intr = "nb.spd";	/* SPD protocol */
320		}
321	}
322	if (sp->ras != -1) {
323		/*
324		 * If driver was built with closed tree present then we will
325		 * have Intel proprietary code for finding physaddr
326		 */
327		if (&dimm_getphys) {
328			sp->pa = dimm_getphys((uint16_t)sp->branch,
329			    (uint16_t)sp->rank, (uint64_t)sp->bank,
330			    (uint64_t)sp->ras, (uint64_t)sp->cas);
331			if (sp->pa >= MAXPHYS_ADDR)
332				sp->pa = -1ULL;
333		} else {
334			sp->pa = -1ULL;
335		}
336		if (&dimm_getoffset) {
337			sp->offset = dimm_getoffset(sp->branch, sp->rank,
338			    sp->bank, sp->ras, sp->cas);
339		} else {
340			sp->offset = TCODE_OFFSET(sp->rank, sp->bank, sp->ras,
341			    sp->cas);
342		}
343	}
344	return (intr);
345}
346
347static struct mch_error_code nf_mem_error_code[] = {
348	{ 21, EMASK_MEM_M21, ERR_NF_MEM_M21 },
349	{ 20, EMASK_MEM_M20, ERR_NF_MEM_M20 },
350	{ 18, EMASK_MEM_M18, ERR_NF_MEM_M18 },
351	{ 16, EMASK_MEM_M16, ERR_NF_MEM_M16 },
352	{ 15, EMASK_MEM_M15, ERR_NF_MEM_M15 },
353	{ 14, EMASK_MEM_M14, ERR_NF_MEM_M14 },
354	{ 12, EMASK_MEM_M12, ERR_NF_MEM_M12 },
355	{ 11, EMASK_MEM_M11, ERR_NF_MEM_M11 },
356	{ 10, EMASK_MEM_M10, ERR_NF_MEM_M10 },
357	{ 6, EMASK_MEM_M6, ERR_NF_MEM_M6 },
358	{ 5, EMASK_MEM_M5, ERR_NF_MEM_M5 },
359	{ 4, EMASK_MEM_M4, ERR_NF_MEM_M4 },
360	{ 1, EMASK_MEM_M1, ERR_NF_MEM_M1 }
361};
362
363static int
364intel_nf_mem_err(uint32_t nf_mem)
365{
366	int rt = -1;
367	int nerr = 0;
368	uint32_t emask_mem = 0;
369	int i;
370	int sz;
371
372	sz = sizeof (nf_mem_error_code) / sizeof (struct mch_error_code);
373
374	for (i = 0; i < sz; i++) {
375		if (nf_mem & nf_mem_error_code[i].error_bit) {
376			rt = nf_mem_error_code[i].intel_error_list;
377			emask_mem |= nf_mem_error_code[i].emask;
378			nerr++;
379		}
380	}
381	if (emask_mem)
382		nb_mem_mask_mc(emask_mem);
383	if (nerr > 1)
384		rt = -1;
385	return (rt);
386}
387
388static char *
389nf_mem_error(const nb_regs_t *rp, void *data)
390{
391	uint32_t ferr_nf_mem, recmema, recmemb;
392	uint32_t nrecmema, nrecmemb, validlog;
393	int channel;
394	char *intr = "nb.unknown";
395	nb_mem_scatchpad_t *sp = &((nb_scatchpad_t *)data)->ms;
396
397	sp->rank = -1;
398	sp->dimm = -1;
399	sp->bank = -1;
400	sp->cas = -1;
401	sp->ras = -1LL;
402	sp->pa = -1LL;
403	sp->offset = -1;
404	ferr_nf_mem = rp->nb.nf_mem_regs.ferr_nf_mem;
405	if ((ferr_nf_mem & ERR_NF_MEM_MASK) == 0) {
406		/* no first error found */
407		sp->branch = -1;
408		sp->channel = -1;
409		sp->intel_error_list =
410		    intel_nf_mem_err(rp->nb.nf_mem_regs.nerr_nf_mem);
411		return (intr);
412	}
413	sp->intel_error_list = intel_nf_mem_err(ferr_nf_mem);
414
415	channel = (ferr_nf_mem >> ERR_MEM_CH_SHIFT) & 0x1;
416	sp->branch = channel;
417	sp->channel = -1;
418	if (ferr_nf_mem & ERR_NF_MEM_MASK) {
419		if (ferr_nf_mem & ERR_NF_MEM_ECC_UE) {
420			/*
421			 * uncorrectable ECC M1,M4-M6,M10-M12
422			 * There is only channel per branch
423			 * Invalidate the channel number so the mem ereport
424			 * has the same detector with existing 5000 ereports.
425			 * so we can leverage the existing Everhsolt rule.
426			 */
427			validlog = rp->nb.nf_mem_regs.validlog;
428			if (ferr_nf_mem & ERR_NF_MEM_M1) {
429				nrecmema = rp->nb.nf_mem_regs.nrecmema;
430				nrecmemb = rp->nb.nf_mem_regs.nrecmemb;
431				/* check if the nrecmem log is valid */
432				if (validlog & 0x1 || nb_check_validlog == 0) {
433					sp->rank = (nrecmema >> 8) & RANK_MASK;
434					sp->bank = (nrecmema >> 12) & BANK_MASK;
435					sp->cas = (nrecmemb >> 16) & CAS_MASK;
436					sp->ras = nrecmemb & RAS_MASK;
437				}
438			} else {
439				recmema = rp->nb.nf_mem_regs.recmema;
440				recmemb = rp->nb.nf_mem_regs.recmemb;
441				/* check if the recmem log is valid */
442				if (validlog & 0x2 || nb_check_validlog == 0) {
443					sp->rank = (recmema >> 8) & RANK_MASK;
444					sp->bank = (recmema >> 12) & BANK_MASK;
445					sp->cas = (recmemb >> 16) & CAS_MASK;
446					sp->ras = recmemb & RAS_MASK;
447				}
448			}
449			intr = "nb.ddr2_mem_ue";
450		} else if ((ferr_nf_mem & ERR_NF_MEM_ECC_CE) != 0) {
451			/* correctable ECC M14-M16 */
452			recmema = rp->nb.nf_mem_regs.recmema;
453			recmemb = rp->nb.nf_mem_regs.recmemb;
454			validlog = rp->nb.nf_mem_regs.validlog;
455			/* check if the recmem log is valid */
456			if (validlog & 0x2 || nb_check_validlog == 0) {
457				sp->channel = channel;
458				sp->rank = (recmema >> 8) & RANK_MASK;
459				sp->dimm = nb_rank2dimm(sp->channel, sp->rank);
460				sp->bank = (recmema >> 12) & BANK_MASK;
461				sp->cas = (recmemb >> 16) & CAS_MASK;
462				sp->ras = recmemb & RAS_MASK;
463			}
464			intr = "nb.ddr2_mem_ce";
465		} else if ((ferr_nf_mem & ERR_NF_MEM_SPARE) != 0) {
466			/* spare dimm M20, M21 */
467			intr = "nb.ddr2_mem_ds";
468
469			/*
470			 * The channel can be valid here.
471			 * However, there is only one channel per branch and
472			 * to leverage the eversolt rules of other chipsets,
473			 * the channel is ignored and let the rule find it out
474			 * from the topology.
475			 */
476			if (rp->nb.nf_mem_regs.spcps & SPCPS_SPARE_DEPLOYED) {
477				sp->rank =
478				    SPCPS_FAILED_RANK(rp->nb.nf_mem_regs.spcps);
479				nb_used_spare_rank(sp->branch, sp->rank);
480				nb_config_gen++;
481			}
482		} else if ((ferr_nf_mem & ERR_NF_MEM_M18) != 0) {
483			sp->channel = channel;
484			intr = "nb.ddr2_spd";	/* SPD protocol */
485
486		}
487	}
488	if (sp->ras != -1) {
489		/*
490		 * If driver was built with closed tree present then we will
491		 * have Intel proprietary code for finding physaddr
492		 */
493		if (&dimm_getphys) {
494			sp->pa = dimm_getphys((uint16_t)sp->branch,
495			    (uint16_t)sp->rank, (uint64_t)sp->bank,
496			    (uint64_t)sp->ras, (uint64_t)sp->cas);
497			if (sp->pa >= MAXPHYS_ADDR)
498				sp->pa = -1ULL;
499		} else {
500			sp->pa = -1ULL;
501		}
502		if (&dimm_getoffset) {
503			sp->offset = dimm_getoffset(sp->branch, sp->rank,
504			    sp->bank, sp->ras, sp->cas);
505		} else {
506			sp->offset = TCODE_OFFSET(sp->rank, sp->bank, sp->ras,
507			    sp->cas);
508		}
509	}
510	return (intr);
511}
512
513static struct mch_error_code fat_int_error_code[] = {
514	{ 14, EMASK_INT_B14, ERR_FAT_INT_B14 },
515	{ 12, EMASK_INT_B12, ERR_FAT_INT_B12 },
516	{ 25, EMASK_INT_B25, ERR_FAT_INT_B25 },
517	{ 23, EMASK_INT_B23, ERR_FAT_INT_B23 },
518	{ 21, EMASK_INT_B21, ERR_FAT_INT_B21 },
519	{ 7, EMASK_INT_B7, ERR_FAT_INT_B7 },
520	{ 4, EMASK_INT_B4, ERR_FAT_INT_B4 },
521	{ 3, EMASK_INT_B3, ERR_FAT_INT_B3 },
522	{ 2, EMASK_INT_B2, ERR_FAT_INT_B2 },
523	{ 1, EMASK_INT_B1, ERR_FAT_INT_B1 }
524};
525
526static struct mch_error_code nf_int_error_code[] = {
527	{ 27, 0, ERR_NF_INT_B27 },
528	{ 24, 0, ERR_NF_INT_B24 },
529	{ 22, EMASK_INT_B22, ERR_NF_INT_B22 },
530	{ 20, EMASK_INT_B20, ERR_NF_INT_B20 },
531	{ 19, EMASK_INT_B19, ERR_NF_INT_B19 },
532	{ 18, 0, ERR_NF_INT_B18 },
533	{ 17, 0, ERR_NF_INT_B17 },
534	{ 16, 0, ERR_NF_INT_B16 },
535	{ 11, EMASK_INT_B11, ERR_NF_INT_B11 },
536	{ 10, EMASK_INT_B10, ERR_NF_INT_B10 },
537	{ 9, EMASK_INT_B9, ERR_NF_INT_B9 },
538	{ 8, EMASK_INT_B8, ERR_NF_INT_B8 },
539	{ 6, EMASK_INT_B6, ERR_NF_INT_B6 },
540	{ 5, EMASK_INT_B5, ERR_NF_INT_B5 }
541};
542
543static int
544intel_int_err(uint16_t err_fat_int, uint16_t err_nf_int)
545{
546	int rt = -1;
547	int nerr = 0;
548	uint32_t emask_int = 0;
549	int i;
550	int sz;
551
552	sz = sizeof (fat_int_error_code) / sizeof (struct mch_error_code);
553
554	for (i = 0; i < sz; i++) {
555		if (err_fat_int & fat_int_error_code[i].error_bit) {
556			rt = fat_int_error_code[i].intel_error_list;
557			emask_int |= fat_int_error_code[i].emask;
558			nerr++;
559		}
560	}
561
562	if (nb_chipset == INTEL_NB_5400 &&
563	    (err_nf_int & NERR_NF_5400_INT_B26) != 0) {
564		err_nf_int &= ~NERR_NF_5400_INT_B26;
565		rt = 26;
566		nerr++;
567	}
568
569	if (rt)
570		err_nf_int &= ~ERR_NF_INT_B18;
571
572	sz = sizeof (nf_int_error_code) / sizeof (struct mch_error_code);
573
574	for (i = 0; i < sz; i++) {
575		if (err_nf_int & nf_int_error_code[i].error_bit) {
576			rt = nf_int_error_code[i].intel_error_list;
577			emask_int |= nf_int_error_code[i].emask;
578			nerr++;
579		}
580	}
581
582	if (emask_int)
583		nb_int_mask_mc(emask_int);
584	if (nerr > 1)
585		rt = -1;
586	return (rt);
587}
588
589static int
590log_int_err(nb_regs_t *rp, int willpanic, int *interpose)
591{
592	int t = 0;
593	int rt = 0;
594
595	rp->flag = NB_REG_LOG_INT;
596	rp->nb.int_regs.ferr_fat_int = FERR_FAT_INT_RD(interpose);
597	rp->nb.int_regs.ferr_nf_int = FERR_NF_INT_RD(&t);
598	*interpose |= t;
599	rp->nb.int_regs.nerr_fat_int = NERR_FAT_INT_RD(&t);
600	*interpose |= t;
601	rp->nb.int_regs.nerr_nf_int = NERR_NF_INT_RD(&t);
602	*interpose |= t;
603	rp->nb.int_regs.nrecint = NRECINT_RD();
604	rp->nb.int_regs.recint = RECINT_RD();
605	rp->nb.int_regs.nrecsf = NRECSF_RD();
606	rp->nb.int_regs.recsf = RECSF_RD();
607
608	if (!willpanic) {
609		if (rp->nb.int_regs.ferr_fat_int || *interpose)
610			FERR_FAT_INT_WR(rp->nb.int_regs.ferr_fat_int);
611		if (rp->nb.int_regs.ferr_nf_int || *interpose)
612			FERR_NF_INT_WR(rp->nb.int_regs.ferr_nf_int);
613		if (rp->nb.int_regs.nerr_fat_int)
614			NERR_FAT_INT_WR(rp->nb.int_regs.nerr_fat_int);
615		if (rp->nb.int_regs.nerr_nf_int)
616			NERR_NF_INT_WR(rp->nb.int_regs.nerr_nf_int);
617		/*
618		 * if interpose write read-only registers to clear from pcii
619		 * cache
620		 */
621		if (*interpose) {
622			NRECINT_WR();
623			RECINT_WR();
624			NRECSF_WR();
625			RECSF_WR();
626		}
627	}
628	if (rp->nb.int_regs.ferr_fat_int == 0 &&
629	    rp->nb.int_regs.nerr_fat_int == 0 &&
630	    (rp->nb.int_regs.ferr_nf_int == ERR_NF_INT_B18 ||
631	    (rp->nb.int_regs.ferr_nf_int == 0 &&
632	    rp->nb.int_regs.nerr_nf_int == ERR_NF_INT_B18))) {
633		rt = 1;
634	}
635	return (rt);
636}
637
638static void
639log_thermal_err(nb_regs_t *rp, int willpanic, int *interpose)
640{
641	int t = 0;
642
643	rp->flag = NB_REG_LOG_THR;
644	rp->nb.thr_regs.ferr_fat_thr = FERR_FAT_THR_RD(interpose);
645	rp->nb.thr_regs.nerr_fat_thr = NERR_FAT_THR_RD(&t);
646	*interpose |= t;
647	rp->nb.thr_regs.ferr_nf_thr = FERR_NF_THR_RD(&t);
648	*interpose |= t;
649	rp->nb.thr_regs.nerr_nf_thr = NERR_NF_THR_RD(&t);
650	*interpose |= t;
651	rp->nb.thr_regs.ctsts = CTSTS_RD();
652	rp->nb.thr_regs.thrtsts = THRTSTS_RD();
653
654	if (!willpanic) {
655		if (rp->nb.thr_regs.ferr_fat_thr || *interpose)
656			FERR_FAT_THR_WR(rp->nb.thr_regs.ferr_fat_thr);
657		if (rp->nb.thr_regs.nerr_fat_thr || *interpose)
658			NERR_FAT_THR_WR(rp->nb.thr_regs.nerr_fat_thr);
659		if (rp->nb.thr_regs.ferr_nf_thr || *interpose)
660			FERR_NF_THR_WR(rp->nb.thr_regs.ferr_nf_thr);
661		if (rp->nb.thr_regs.nerr_nf_thr || *interpose)
662			NERR_NF_THR_WR(rp->nb.thr_regs.nerr_nf_thr);
663
664		if (*interpose) {
665			CTSTS_WR(rp->nb.thr_regs.ctsts);
666			THRTSTS_WR(rp->nb.thr_regs.thrtsts);
667		}
668	}
669}
670
671static void
672log_dma_err(nb_regs_t *rp, int *interpose)
673{
674	rp->flag = NB_REG_LOG_DMA;
675
676	rp->nb.dma_regs.pcists = PCISTS_RD(interpose);
677	rp->nb.dma_regs.pexdevsts = PCIDEVSTS_RD();
678}
679
680static struct mch_error_code fat_fsb_error_code[] = {
681	{ 9, EMASK_FSB_F9, ERR_FAT_FSB_F9 },
682	{ 2, EMASK_FSB_F2, ERR_FAT_FSB_F2 },
683	{ 1, EMASK_FSB_F1, ERR_FAT_FSB_F1 }
684};
685
686static struct mch_error_code nf_fsb_error_code[] = {
687	{ 8, EMASK_FSB_F8, ERR_NF_FSB_F8 },
688	{ 7, EMASK_FSB_F7, ERR_NF_FSB_F7 },
689	{ 6, EMASK_FSB_F6, ERR_NF_FSB_F6 }
690};
691
692static int
693intel_fsb_err(int fsb, uint8_t err_fat_fsb, uint8_t err_nf_fsb)
694{
695	int rt = -1;
696	int nerr = 0;
697	uint16_t emask_fsb = 0;
698	int i;
699	int sz;
700
701	sz = sizeof (fat_fsb_error_code) / sizeof (struct mch_error_code);
702
703	for (i = 0; i < sz; i++) {
704		if (err_fat_fsb & fat_fsb_error_code[i].error_bit) {
705			rt = fat_fsb_error_code[i].intel_error_list;
706			emask_fsb |= fat_fsb_error_code[i].emask;
707			nerr++;
708		}
709	}
710
711	sz = sizeof (nf_fsb_error_code) / sizeof (struct mch_error_code);
712
713	for (i = 0; i < sz; i++) {
714		if (err_nf_fsb & nf_fsb_error_code[i].error_bit) {
715			rt = nf_fsb_error_code[i].intel_error_list;
716			emask_fsb |= nf_fsb_error_code[i].emask;
717			nerr++;
718		}
719	}
720
721	if (emask_fsb)
722		nb_fsb_mask_mc(fsb, emask_fsb);
723	if (nerr > 1)
724		rt = -1;
725	return (rt);
726}
727
728static void
729log_fsb_err(uint64_t ferr, nb_regs_t *rp, int willpanic, int *interpose)
730{
731	uint8_t fsb;
732	int t = 0;
733
734	fsb = GE_FERR_FSB(ferr);
735	rp->flag = NB_REG_LOG_FSB;
736
737	rp->nb.fsb_regs.fsb = fsb;
738	rp->nb.fsb_regs.ferr_fat_fsb = FERR_FAT_FSB_RD(fsb, interpose);
739	rp->nb.fsb_regs.ferr_nf_fsb = FERR_NF_FSB_RD(fsb, &t);
740	*interpose |= t;
741	rp->nb.fsb_regs.nerr_fat_fsb = NERR_FAT_FSB_RD(fsb, &t);
742	*interpose |= t;
743	rp->nb.fsb_regs.nerr_nf_fsb = NERR_NF_FSB_RD(fsb, &t);
744	*interpose |= t;
745	rp->nb.fsb_regs.nrecfsb = NRECFSB_RD(fsb);
746	rp->nb.fsb_regs.nrecfsb_addr = NRECADDR_RD(fsb);
747	rp->nb.fsb_regs.recfsb = RECFSB_RD(fsb);
748	if (!willpanic) {
749		/* Clear the fatal/non-fatal first/next FSB errors */
750		if (rp->nb.fsb_regs.ferr_fat_fsb || *interpose)
751			FERR_FAT_FSB_WR(fsb, rp->nb.fsb_regs.ferr_fat_fsb);
752		if (rp->nb.fsb_regs.ferr_nf_fsb || *interpose)
753			FERR_NF_FSB_WR(fsb, rp->nb.fsb_regs.ferr_nf_fsb);
754		if (rp->nb.fsb_regs.nerr_fat_fsb || *interpose)
755			NERR_FAT_FSB_WR(fsb, rp->nb.fsb_regs.nerr_fat_fsb);
756		if (rp->nb.fsb_regs.nerr_nf_fsb || *interpose)
757			NERR_NF_FSB_WR(fsb, rp->nb.fsb_regs.nerr_nf_fsb);
758
759		/*
760		 * if interpose write read-only registers to clear from pcii
761		 * cache
762		 */
763		if (*interpose) {
764			NRECFSB_WR(fsb);
765			NRECADDR_WR(fsb);
766			RECFSB_WR(fsb);
767		}
768	}
769}
770
771static struct mch_error_code fat_pex_error_code[] = {
772	{ 19, EMASK_UNCOR_PEX_IO19, PEX_FAT_IO19 },
773	{ 18, EMASK_UNCOR_PEX_IO18, PEX_FAT_IO18 },
774	{ 10, EMASK_UNCOR_PEX_IO10, PEX_FAT_IO10 },
775	{ 9, EMASK_UNCOR_PEX_IO9, PEX_FAT_IO9 },
776	{ 8, EMASK_UNCOR_PEX_IO8, PEX_FAT_IO8 },
777	{ 7, EMASK_UNCOR_PEX_IO7, PEX_FAT_IO7 },
778	{ 6, EMASK_UNCOR_PEX_IO6, PEX_FAT_IO6 },
779	{ 5, EMASK_UNCOR_PEX_IO5, PEX_FAT_IO5 },
780	{ 4, EMASK_UNCOR_PEX_IO4, PEX_FAT_IO4 },
781	{ 3, EMASK_UNCOR_PEX_IO3, PEX_FAT_IO3 },
782	{ 2, EMASK_UNCOR_PEX_IO2, PEX_FAT_IO2 },
783	{ 0, EMASK_UNCOR_PEX_IO0, PEX_FAT_IO0 }
784};
785
786static struct mch_error_code fat_unit_pex_5400_error_code[] = {
787	{ 32, EMASK_UNIT_PEX_IO32, PEX_5400_FAT_IO32 },
788	{ 31, EMASK_UNIT_PEX_IO31, PEX_5400_FAT_IO31 },
789	{ 30, EMASK_UNIT_PEX_IO30, PEX_5400_FAT_IO30 },
790	{ 29, EMASK_UNIT_PEX_IO29, PEX_5400_FAT_IO29 },
791	{ 27, EMASK_UNIT_PEX_IO27, PEX_5400_FAT_IO27 },
792	{ 26, EMASK_UNIT_PEX_IO26, PEX_5400_FAT_IO26 },
793	{ 25, EMASK_UNIT_PEX_IO25, PEX_5400_FAT_IO25 },
794	{ 24, EMASK_UNIT_PEX_IO24, PEX_5400_FAT_IO24 },
795	{ 23, EMASK_UNIT_PEX_IO23, PEX_5400_FAT_IO23 },
796	{ 22, EMASK_UNIT_PEX_IO22, PEX_5400_FAT_IO22 },
797};
798
799static struct mch_error_code fat_pex_5400_error_code[] = {
800	{ 19, EMASK_UNCOR_PEX_IO19, PEX_5400_FAT_IO19 },
801	{ 18, EMASK_UNCOR_PEX_IO18, PEX_5400_FAT_IO18 },
802	{ 10, EMASK_UNCOR_PEX_IO10, PEX_5400_FAT_IO10 },
803	{ 9, EMASK_UNCOR_PEX_IO9, PEX_5400_FAT_IO9 },
804	{ 8, EMASK_UNCOR_PEX_IO8, PEX_5400_FAT_IO8 },
805	{ 7, EMASK_UNCOR_PEX_IO7, PEX_5400_FAT_IO7 },
806	{ 6, EMASK_UNCOR_PEX_IO6, PEX_5400_FAT_IO6 },
807	{ 5, EMASK_UNCOR_PEX_IO5, PEX_5400_FAT_IO5 },
808	{ 4, EMASK_UNCOR_PEX_IO4, PEX_5400_FAT_IO4 },
809	{ 2, EMASK_UNCOR_PEX_IO2, PEX_5400_FAT_IO2 },
810	{ 0, EMASK_UNCOR_PEX_IO0, PEX_5400_FAT_IO0 }
811};
812
813static struct mch_error_code fat_rp_5400_error_code[] = {
814	{ 1, EMASK_RP_PEX_IO1, PEX_5400_FAT_IO1 }
815};
816
817static struct mch_error_code fat_rp_error_code[] = {
818	{ 1, EMASK_RP_PEX_IO1, PEX_FAT_IO1 }
819};
820
821static struct mch_error_code uncor_pex_error_code[] = {
822	{ 19, EMASK_UNCOR_PEX_IO19, PEX_NF_IO19 },
823	{ 9, EMASK_UNCOR_PEX_IO9, PEX_NF_IO9 },
824	{ 8, EMASK_UNCOR_PEX_IO8, PEX_NF_IO8 },
825	{ 7, EMASK_UNCOR_PEX_IO7, PEX_NF_IO7 },
826	{ 6, EMASK_UNCOR_PEX_IO6, PEX_NF_IO6 },
827	{ 5, EMASK_UNCOR_PEX_IO5, PEX_NF_IO5 },
828	{ 4, EMASK_UNCOR_PEX_IO4, PEX_NF_IO4 },
829	{ 3, EMASK_UNCOR_PEX_IO3, PEX_NF_IO3 },
830	{ 0, EMASK_UNCOR_PEX_IO0, PEX_NF_IO0 }
831};
832
833static struct mch_error_code uncor_pex_5400_error_code[] = {
834	{ 33, EMASK_UNIT_PEX_IO33, PEX_5400_NF_IO33 },
835	{ 32, EMASK_UNIT_PEX_IO32, PEX_5400_NF_IO32 },
836	{ 31, EMASK_UNIT_PEX_IO31, PEX_5400_NF_IO31 },
837	{ 30, EMASK_UNIT_PEX_IO30, PEX_5400_NF_IO30 },
838	{ 29, EMASK_UNIT_PEX_IO29, PEX_5400_NF_IO29 },
839	{ 28, EMASK_UNIT_PEX_IO28, PEX_5400_NF_IO28 },
840	{ 27, EMASK_UNIT_PEX_IO27, PEX_5400_NF_IO27 },
841	{ 26, EMASK_UNIT_PEX_IO26, PEX_5400_NF_IO26 },
842	{ 25, EMASK_UNIT_PEX_IO25, PEX_5400_NF_IO25 },
843	{ 24, EMASK_UNIT_PEX_IO24, PEX_5400_NF_IO24 },
844	{ 23, EMASK_UNIT_PEX_IO23, PEX_5400_NF_IO23 },
845};
846
847static struct mch_error_code cor_pex_error_code[] = {
848	{ 20, EMASK_COR_PEX_IO20, PEX_5400_NF_IO20 },
849	{ 16, EMASK_COR_PEX_IO16, PEX_NF_IO16 },
850	{ 15, EMASK_COR_PEX_IO15, PEX_NF_IO15 },
851	{ 14, EMASK_COR_PEX_IO14, PEX_NF_IO14 },
852	{ 13, EMASK_COR_PEX_IO13, PEX_NF_IO13 },
853	{ 12, EMASK_COR_PEX_IO12, PEX_NF_IO12 },
854	{ 10, 0, PEX_NF_IO10 },
855	{ 2, 0, PEX_NF_IO2 }
856};
857
858static struct mch_error_code rp_pex_5400_error_code[] = {
859	{ 17, EMASK_RP_PEX_IO17, PEX_5400_NF_IO17 },
860	{ 11, EMASK_RP_PEX_IO11, PEX_5400_NF_IO11 }
861};
862
863static struct mch_error_code cor_pex_5400_error_code1[] = {
864	{ 19, EMASK_UNCOR_PEX_IO19, PEX_5400_NF_IO19 },
865	{ 10, EMASK_UNCOR_PEX_IO10, PEX_5400_NF_IO10 },
866	{ 9, EMASK_UNCOR_PEX_IO9, PEX_5400_NF_IO9 },
867	{ 8, EMASK_UNCOR_PEX_IO8, PEX_5400_NF_IO8 },
868	{ 7, EMASK_UNCOR_PEX_IO7, PEX_5400_NF_IO7 },
869	{ 6, EMASK_UNCOR_PEX_IO6, PEX_5400_NF_IO6 },
870	{ 5, EMASK_UNCOR_PEX_IO5, PEX_5400_NF_IO5 },
871	{ 4, EMASK_UNCOR_PEX_IO4, PEX_5400_NF_IO4 },
872	{ 2, EMASK_UNCOR_PEX_IO2, PEX_5400_NF_IO2 },
873	{ 0, EMASK_UNCOR_PEX_IO0, PEX_5400_NF_IO0 }
874};
875
876static struct mch_error_code cor_pex_5400_error_code2[] = {
877	{ 20, EMASK_COR_PEX_IO20, PEX_5400_NF_IO20 },
878	{ 16, EMASK_COR_PEX_IO16, PEX_5400_NF_IO16 },
879	{ 15, EMASK_COR_PEX_IO15, PEX_5400_NF_IO15 },
880	{ 14, EMASK_COR_PEX_IO14, PEX_5400_NF_IO14 },
881	{ 13, EMASK_COR_PEX_IO13, PEX_5400_NF_IO13 },
882	{ 12, EMASK_COR_PEX_IO12, PEX_5400_NF_IO12 }
883};
884
885static struct mch_error_code cor_pex_5400_error_code3[] = {
886	{ 33, EMASK_UNIT_PEX_IO33, PEX_5400_NF_IO33 },
887	{ 32, EMASK_UNIT_PEX_IO32, PEX_5400_NF_IO32 },
888	{ 31, EMASK_UNIT_PEX_IO31, PEX_5400_NF_IO31 },
889	{ 30, EMASK_UNIT_PEX_IO30, PEX_5400_NF_IO30 },
890	{ 29, EMASK_UNIT_PEX_IO29, PEX_5400_NF_IO29 },
891	{ 28, EMASK_UNIT_PEX_IO28, PEX_5400_NF_IO28 },
892	{ 27, EMASK_UNIT_PEX_IO27, PEX_5400_NF_IO27 },
893	{ 26, EMASK_UNIT_PEX_IO26, PEX_5400_NF_IO26 },
894	{ 25, EMASK_UNIT_PEX_IO25, PEX_5400_NF_IO25 },
895	{ 24, EMASK_UNIT_PEX_IO24, PEX_5400_NF_IO24 },
896	{ 23, EMASK_UNIT_PEX_IO23, PEX_5400_NF_IO23 }
897};
898
899static struct mch_error_code rp_pex_error_code[] = {
900	{ 17, EMASK_RP_PEX_IO17, PEX_NF_IO17 },
901	{ 11, EMASK_RP_PEX_IO11, PEX_NF_IO11 },
902};
903
904static int
905intel_pex_err(uint32_t pex_fat, uint32_t pex_nf_cor)
906{
907	int rt = -1;
908	int nerr = 0;
909	int i;
910	int sz;
911
912	sz = sizeof (fat_pex_error_code) / sizeof (struct mch_error_code);
913
914	for (i = 0; i < sz; i++) {
915		if (pex_fat & fat_pex_error_code[i].error_bit) {
916			rt = fat_pex_error_code[i].intel_error_list;
917			nerr++;
918		}
919	}
920	sz = sizeof (fat_rp_error_code) / sizeof (struct mch_error_code);
921
922	for (i = 0; i < sz; i++) {
923		if (pex_fat & fat_rp_error_code[i].error_bit) {
924			rt = fat_rp_error_code[i].intel_error_list;
925			nerr++;
926		}
927	}
928	sz = sizeof (uncor_pex_error_code) / sizeof (struct mch_error_code);
929
930	for (i = 0; i < sz; i++) {
931		if (pex_nf_cor & uncor_pex_error_code[i].error_bit) {
932			rt = uncor_pex_error_code[i].intel_error_list;
933			nerr++;
934		}
935	}
936
937	sz = sizeof (cor_pex_error_code) / sizeof (struct mch_error_code);
938
939	for (i = 0; i < sz; i++) {
940		if (pex_nf_cor & cor_pex_error_code[i].error_bit) {
941			rt = cor_pex_error_code[i].intel_error_list;
942			nerr++;
943		}
944	}
945	sz = sizeof (rp_pex_error_code) / sizeof (struct mch_error_code);
946
947	for (i = 0; i < sz; i++) {
948		if (pex_nf_cor & rp_pex_error_code[i].error_bit) {
949			rt = rp_pex_error_code[i].intel_error_list;
950			nerr++;
951		}
952	}
953
954	if (nerr > 1)
955		rt = -1;
956	return (rt);
957}
958
959static struct mch_error_code fat_thr_error_code[] = {
960	{ 2, EMASK_THR_F2, ERR_FAT_THR_F2 },
961	{ 1, EMASK_THR_F1, ERR_FAT_THR_F1 }
962};
963
964static struct mch_error_code nf_thr_error_code[] = {
965	{ 5, EMASK_THR_F5, ERR_NF_THR_F5 },
966	{ 4, EMASK_THR_F4, ERR_NF_THR_F4 },
967	{ 3, EMASK_THR_F3, ERR_NF_THR_F3 }
968};
969
970static int
971intel_thr_err(uint8_t err_fat_thr, uint8_t err_nf_thr)
972{
973	int rt = -1;
974	int nerr = 0;
975	uint16_t emask_thr = 0;
976	int i;
977	int sz;
978
979	sz = sizeof (fat_thr_error_code) / sizeof (struct mch_error_code);
980
981	for (i = 0; i < sz; i++) {
982		if (err_fat_thr & fat_thr_error_code[i].error_bit) {
983			rt = fat_thr_error_code[i].intel_error_list;
984			emask_thr |= fat_thr_error_code[i].emask;
985			nerr++;
986		}
987	}
988
989	sz = sizeof (nf_thr_error_code) / sizeof (struct mch_error_code);
990
991	for (i = 0; i < sz; i++) {
992		if (err_nf_thr & nf_thr_error_code[i].error_bit) {
993			rt = nf_thr_error_code[i].intel_error_list;
994			emask_thr |= nf_thr_error_code[i].emask;
995			nerr++;
996		}
997	}
998
999	if (emask_thr)
1000		nb_thr_mask_mc(emask_thr);
1001	if (nerr > 1)
1002		rt = -1;
1003	return (rt);
1004}
1005
1006static int
1007intel_pex_5400_err(uint32_t pex_fat, uint32_t pex_nf_cor)
1008{
1009	int rt = -1;
1010	int nerr = 0;
1011	int i;
1012	int sz;
1013
1014	sz = sizeof (fat_pex_5400_error_code) / sizeof (struct mch_error_code);
1015
1016	for (i = 0; i < sz; i++) {
1017		if (pex_fat & fat_pex_5400_error_code[i].error_bit) {
1018			rt = fat_pex_5400_error_code[i].intel_error_list;
1019			nerr++;
1020		}
1021	}
1022	sz = sizeof (fat_rp_5400_error_code) / sizeof (struct mch_error_code);
1023
1024	for (i = 0; i < sz; i++) {
1025		if (pex_fat & fat_rp_5400_error_code[i].error_bit) {
1026			rt = fat_rp_5400_error_code[i].intel_error_list;
1027			nerr++;
1028		}
1029	}
1030	sz = sizeof (fat_unit_pex_5400_error_code) /
1031	    sizeof (struct mch_error_code);
1032
1033	for (i = 0; i < sz; i++) {
1034		if (pex_fat &
1035		    fat_unit_pex_5400_error_code[i].error_bit) {
1036			rt = fat_unit_pex_5400_error_code[i].intel_error_list;
1037			nerr++;
1038		}
1039	}
1040	sz = sizeof (uncor_pex_5400_error_code) /
1041	    sizeof (struct mch_error_code);
1042
1043	for (i = 0; i < sz; i++) {
1044		if (pex_fat & uncor_pex_5400_error_code[i].error_bit) {
1045			rt = uncor_pex_5400_error_code[i].intel_error_list;
1046			nerr++;
1047		}
1048	}
1049
1050	sz = sizeof (rp_pex_5400_error_code) / sizeof (struct mch_error_code);
1051
1052	for (i = 0; i < sz; i++) {
1053		if (pex_nf_cor & rp_pex_5400_error_code[i].error_bit) {
1054			rt = rp_pex_5400_error_code[i].intel_error_list;
1055			nerr++;
1056		}
1057	}
1058
1059	sz = sizeof (cor_pex_5400_error_code1) / sizeof (struct mch_error_code);
1060
1061	for (i = 0; i < sz; i++) {
1062		if (pex_nf_cor & cor_pex_5400_error_code1[i].error_bit) {
1063			rt = cor_pex_5400_error_code1[i].intel_error_list;
1064			nerr++;
1065		}
1066	}
1067
1068	sz = sizeof (cor_pex_5400_error_code2) / sizeof (struct mch_error_code);
1069
1070	for (i = 0; i < sz; i++) {
1071		if (pex_nf_cor & cor_pex_5400_error_code2[i].error_bit) {
1072			rt = cor_pex_5400_error_code2[i].intel_error_list;
1073			nerr++;
1074		}
1075	}
1076
1077	sz = sizeof (cor_pex_5400_error_code3) / sizeof (struct mch_error_code);
1078
1079	for (i = 0; i < sz; i++) {
1080		if (pex_nf_cor & cor_pex_5400_error_code3[i].error_bit) {
1081			rt = cor_pex_5400_error_code3[i].intel_error_list;
1082			nerr++;
1083		}
1084	}
1085
1086	if (nerr > 1)
1087		rt = -1;
1088	return (rt);
1089}
1090
1091static int
1092log_pex_err(uint64_t ferr, nb_regs_t *rp, int willpanic, int *interpose)
1093{
1094	uint8_t pex = (uint8_t)-1;
1095	int t = 0;
1096
1097	rp->flag = NB_REG_LOG_PEX;
1098	pex = GE_ERR_PEX(ferr);
1099
1100	rp->nb.pex_regs.pex = pex;
1101	rp->nb.pex_regs.pex_fat_ferr =  PEX_FAT_FERR_RD(pex, interpose);
1102	rp->nb.pex_regs.pex_fat_nerr = PEX_FAT_NERR_RD(pex, &t);
1103	*interpose |= t;
1104	rp->nb.pex_regs.pex_nf_corr_ferr = PEX_NF_FERR_RD(pex, &t);
1105	*interpose |= t;
1106	rp->nb.pex_regs.pex_nf_corr_nerr = PEX_NF_NERR_RD(pex, &t);
1107	*interpose |= t;
1108	if (rp->nb.pex_regs.pex_fat_ferr == 0 &&
1109	    rp->nb.pex_regs.pex_fat_nerr == 0 &&
1110	    rp->nb.pex_regs.pex_nf_corr_ferr == 0 &&
1111	    rp->nb.pex_regs.pex_nf_corr_nerr == 0)
1112		return (0);
1113	rp->nb.pex_regs.uncerrsev = UNCERRSEV_RD(pex);
1114	rp->nb.pex_regs.rperrsts = RPERRSTS_RD(pex);
1115	rp->nb.pex_regs.rperrsid = RPERRSID_RD(pex);
1116	if (pex != (uint8_t)-1)
1117		rp->nb.pex_regs.uncerrsts = UNCERRSTS_RD(pex);
1118	else
1119		rp->nb.pex_regs.uncerrsts = 0;
1120	rp->nb.pex_regs.aerrcapctrl = AERRCAPCTRL_RD(pex);
1121	rp->nb.pex_regs.corerrsts = CORERRSTS_RD(pex);
1122	rp->nb.pex_regs.pexdevsts = PEXDEVSTS_RD(pex);
1123
1124	if (!willpanic) {
1125		if (rp->nb.pex_regs.pex_fat_ferr || *interpose)
1126			PEX_FAT_FERR_WR(pex, rp->nb.pex_regs.pex_fat_ferr);
1127		if (rp->nb.pex_regs.pex_fat_nerr)
1128			PEX_FAT_NERR_WR(pex, rp->nb.pex_regs.pex_fat_nerr);
1129		if (rp->nb.pex_regs.pex_nf_corr_ferr || *interpose)
1130			PEX_NF_FERR_WR(pex, rp->nb.pex_regs.pex_nf_corr_ferr);
1131		if (rp->nb.pex_regs.pex_nf_corr_nerr)
1132			PEX_NF_NERR_WR(pex, rp->nb.pex_regs.pex_nf_corr_nerr);
1133		if (*interpose)
1134			UNCERRSTS_WR(pex, rp->nb.pex_regs.uncerrsts);
1135		if (*interpose)
1136			RPERRSTS_WR(pex, rp->nb.pex_regs.rperrsts);
1137		if (*interpose)
1138			PEXDEVSTS_WR(pex, 0);
1139	}
1140	return (1);
1141}
1142
1143static void
1144log_fat_fbd_err(nb_regs_t *rp, int willpanic, int *interpose)
1145{
1146	int channel, branch;
1147	int t = 0;
1148
1149	rp->flag = NB_REG_LOG_FAT_FBD;
1150	rp->nb.fat_fbd_regs.ferr_fat_fbd = FERR_FAT_FBD_RD(interpose);
1151	channel = (rp->nb.fat_fbd_regs.ferr_fat_fbd >> 28) & 3;
1152	branch = channel >> 1;
1153	rp->nb.fat_fbd_regs.nerr_fat_fbd = NERR_FAT_FBD_RD(&t);
1154	*interpose |= t;
1155	rp->nb.fat_fbd_regs.nrecmema = NRECMEMA_RD(branch);
1156	rp->nb.fat_fbd_regs.nrecmemb = NRECMEMB_RD(branch);
1157	rp->nb.fat_fbd_regs.nrecfglog = NRECFGLOG_RD(branch);
1158	rp->nb.fat_fbd_regs.nrecfbda = NRECFBDA_RD(branch);
1159	rp->nb.fat_fbd_regs.nrecfbdb = NRECFBDB_RD(branch);
1160	rp->nb.fat_fbd_regs.nrecfbdc = NRECFBDC_RD(branch);
1161	rp->nb.fat_fbd_regs.nrecfbdd = NRECFBDD_RD(branch);
1162	rp->nb.fat_fbd_regs.nrecfbde = NRECFBDE_RD(branch);
1163	rp->nb.fat_fbd_regs.nrecfbdf = NRECFBDF_RD(branch);
1164	rp->nb.fat_fbd_regs.spcps = SPCPS_RD(branch);
1165	rp->nb.fat_fbd_regs.spcpc = SPCPC_RD(branch);
1166	rp->nb.fat_fbd_regs.uerrcnt = UERRCNT_RD(branch);
1167	rp->nb.fat_fbd_regs.uerrcnt_last = uerrcnt[branch];
1168	uerrcnt[branch] = rp->nb.fat_fbd_regs.uerrcnt;
1169	rp->nb.fat_fbd_regs.badrama = BADRAMA_RD(branch);
1170	rp->nb.fat_fbd_regs.badramb = BADRAMB_RD(branch);
1171	rp->nb.fat_fbd_regs.badcnt = BADCNT_RD(branch);
1172	if (!willpanic) {
1173		if (rp->nb.fat_fbd_regs.ferr_fat_fbd || *interpose)
1174			FERR_FAT_FBD_WR(rp->nb.fat_fbd_regs.ferr_fat_fbd);
1175		if (rp->nb.fat_fbd_regs.nerr_fat_fbd)
1176			NERR_FAT_FBD_WR(rp->nb.fat_fbd_regs.nerr_fat_fbd);
1177		/*
1178		 * if interpose write read-only registers to clear from pcii
1179		 * cache
1180		 */
1181		if (*interpose) {
1182			NRECMEMA_WR(branch);
1183			NRECMEMB_WR(branch);
1184			NRECFGLOG_WR(branch);
1185			NRECFBDA_WR(branch);
1186			NRECFBDB_WR(branch);
1187			NRECFBDC_WR(branch);
1188			NRECFBDD_WR(branch);
1189			NRECFBDE_WR(branch);
1190			NRECFBDF_WR(branch);
1191		}
1192	}
1193}
1194
1195static void
1196log_nf_fbd_err(nb_regs_t *rp, int willpanic, int *interpose)
1197{
1198	int channel, branch;
1199	int t = 0;
1200
1201	rp->flag = NB_REG_LOG_NF_FBD;
1202	rp->nb.nf_fbd_regs.ferr_nf_fbd = FERR_NF_FBD_RD(interpose);
1203	channel = (rp->nb.nf_fbd_regs.ferr_nf_fbd >> 28) & 3;
1204	branch = channel >> 1;
1205	rp->nb.nf_fbd_regs.nerr_nf_fbd = NERR_NF_FBD_RD(&t);
1206	*interpose |= t;
1207	rp->nb.nf_fbd_regs.redmemb = REDMEMB_RD();
1208	rp->nb.nf_fbd_regs.recmema = RECMEMA_RD(branch);
1209	rp->nb.nf_fbd_regs.recmemb = RECMEMB_RD(branch);
1210	rp->nb.nf_fbd_regs.recfglog = RECFGLOG_RD(branch);
1211	rp->nb.nf_fbd_regs.recfbda = RECFBDA_RD(branch);
1212	rp->nb.nf_fbd_regs.recfbdb = RECFBDB_RD(branch);
1213	rp->nb.nf_fbd_regs.recfbdc = RECFBDC_RD(branch);
1214	rp->nb.nf_fbd_regs.recfbdd = RECFBDD_RD(branch);
1215	rp->nb.nf_fbd_regs.recfbde = RECFBDE_RD(branch);
1216	rp->nb.nf_fbd_regs.recfbdf = RECFBDF_RD(branch);
1217	rp->nb.nf_fbd_regs.spcps = SPCPS_RD(branch);
1218	rp->nb.nf_fbd_regs.spcpc = SPCPC_RD(branch);
1219	if (nb_chipset == INTEL_NB_7300 || nb_chipset == INTEL_NB_5400) {
1220		rp->nb.nf_fbd_regs.cerrcnta = CERRCNTA_RD(branch, channel);
1221		rp->nb.nf_fbd_regs.cerrcntb = CERRCNTB_RD(branch, channel);
1222		rp->nb.nf_fbd_regs.cerrcntc = CERRCNTC_RD(branch, channel);
1223		rp->nb.nf_fbd_regs.cerrcntd = CERRCNTD_RD(branch, channel);
1224	} else {
1225		rp->nb.nf_fbd_regs.cerrcnta = CERRCNT_RD(branch);
1226		rp->nb.nf_fbd_regs.cerrcntb = 0;
1227		rp->nb.nf_fbd_regs.cerrcntc = 0;
1228		rp->nb.nf_fbd_regs.cerrcntd = 0;
1229	}
1230	rp->nb.nf_fbd_regs.cerrcnta_last = cerrcnta[branch][channel & 1];
1231	rp->nb.nf_fbd_regs.cerrcntb_last = cerrcntb[branch][channel & 1];
1232	rp->nb.nf_fbd_regs.cerrcntc_last = cerrcntc[branch][channel & 1];
1233	rp->nb.nf_fbd_regs.cerrcntd_last = cerrcntd[branch][channel & 1];
1234	cerrcnta[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcnta;
1235	cerrcntb[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntb;
1236	cerrcntc[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntc;
1237	cerrcntd[branch][channel & 1] = rp->nb.nf_fbd_regs.cerrcntd;
1238	rp->nb.nf_fbd_regs.badrama = BADRAMA_RD(branch);
1239	rp->nb.nf_fbd_regs.badramb = BADRAMB_RD(branch);
1240	rp->nb.nf_fbd_regs.badcnt = BADCNT_RD(branch);
1241	if (!willpanic) {
1242		if (rp->nb.nf_fbd_regs.ferr_nf_fbd || *interpose)
1243			FERR_NF_FBD_WR(rp->nb.nf_fbd_regs.ferr_nf_fbd);
1244		if (rp->nb.nf_fbd_regs.nerr_nf_fbd)
1245			NERR_NF_FBD_WR(rp->nb.nf_fbd_regs.nerr_nf_fbd);
1246		/*
1247		 * if interpose write read-only registers to clear from pcii
1248		 * cache
1249		 */
1250		if (*interpose) {
1251			RECMEMA_WR(branch);
1252			RECMEMB_WR(branch);
1253			RECFGLOG_WR(branch);
1254			RECFBDA_WR(branch);
1255			RECFBDB_WR(branch);
1256			RECFBDC_WR(branch);
1257			RECFBDD_WR(branch);
1258			RECFBDE_WR(branch);
1259			RECFBDF_WR(branch);
1260			SPCPS_WR(branch);
1261		}
1262	}
1263}
1264
1265static int
1266log_nf_mem_err(nb_regs_t *rp, int willpanic, int *interpose)
1267{
1268	int channel, branch;
1269	int t = 0;
1270	int rt = 0;
1271
1272	rp->flag = NB_REG_LOG_NF_MEM;
1273
1274	/* Memmory err registers */
1275	rp->nb.nf_mem_regs.ferr_nf_mem = FERR_NF_MEM_RD(interpose);
1276	channel = (rp->nb.nf_mem_regs.ferr_nf_mem >> 28) & 0x1;
1277	branch = channel;
1278	rp->nb.nf_mem_regs.nerr_nf_mem = NERR_NF_MEM_RD(&t);
1279	*interpose |= t;
1280	rp->nb.nf_mem_regs.redmema = MEM_REDMEMA_RD(branch);
1281	rp->nb.nf_mem_regs.redmemb = MEM_REDMEMB_RD(branch);
1282	rp->nb.nf_mem_regs.recmema = MEM_RECMEMA_RD(branch);
1283	rp->nb.nf_mem_regs.recmemb = MEM_RECMEMB_RD(branch);
1284	rp->nb.nf_mem_regs.nrecmema = MEM_NRECMEMA_RD(branch);
1285	rp->nb.nf_mem_regs.nrecmemb = MEM_NRECMEMB_RD(branch);
1286
1287	/* spare rank */
1288	rp->nb.nf_mem_regs.spcps = SPCPS_RD(branch);
1289	rp->nb.nf_mem_regs.spcpc = SPCPC_RD(branch);
1290
1291	/* RAS registers */
1292	rp->nb.nf_mem_regs.cerrcnt = MEM_CERRCNT_RD(branch);
1293	rp->nb.nf_mem_regs.cerrcnt_ext = (uint32_t)MEM_CERRCNT_EXT_RD(branch);
1294	rp->nb.nf_mem_regs.cerrcnt_last = cerrcnta[branch][channel & 1];
1295	rp->nb.nf_mem_regs.cerrcnt_ext_last = cerrcntb[branch][channel & 1];
1296	cerrcnta[branch][channel & 1] = rp->nb.nf_mem_regs.cerrcnt;
1297	cerrcntb[branch][channel & 1] = rp->nb.nf_mem_regs.cerrcnt_ext;
1298	rp->nb.nf_mem_regs.badram = BADRAMA_RD(branch);
1299	rp->nb.nf_mem_regs.badcnt = BADCNT_RD(branch);
1300	rp->nb.nf_mem_regs.validlog = VALIDLOG_RD(branch);
1301
1302	if (!willpanic) {
1303		if (rp->nb.nf_mem_regs.ferr_nf_mem || *interpose)
1304			FERR_NF_MEM_WR(rp->nb.nf_mem_regs.ferr_nf_mem);
1305		if (rp->nb.nf_mem_regs.nerr_nf_mem)
1306			NERR_NF_MEM_WR(rp->nb.nf_mem_regs.nerr_nf_mem);
1307		/*
1308		 * if interpose, write read-only registers to clear from pci
1309		 * cache
1310		 */
1311		if (*interpose) {
1312			MEM_NRECMEMA_WR(branch);
1313			MEM_NRECMEMB_WR(branch);
1314			MEM_REDMEMA_WR(branch);
1315			MEM_REDMEMB_WR(branch);
1316			MEM_RECMEMA_WR(branch);
1317			MEM_RECMEMB_WR(branch);
1318			SPCPS_WR(branch);
1319		}
1320	}
1321	if (nb_mode == NB_MEMORY_SINGLE_CHANNEL && channel != 0) {
1322		/*
1323		 * In the single channel mode, all dimms are on the channel 0.
1324		 * Invalidate this error if the channel number is invalid.
1325		 */
1326		rt = 1;
1327	}
1328	return (rt);
1329}
1330
1331static void
1332log_ferr(uint64_t ferr, uint32_t *nerrp, nb_logout_t *log, int willpanic)
1333{
1334	nb_regs_t *rp = &log->nb_regs;
1335	uint32_t nerr = *nerrp;
1336	int interpose = 0;
1337	int spurious = 0;
1338
1339	log->acl_timestamp = gethrtime_waitfree();
1340	if ((ferr & (GE_PCIEX_FATAL | GE_PCIEX_NF)) != 0) {
1341		*nerrp = nerr & ~(GE_PCIEX_FATAL | GE_PCIEX_NF);
1342		if (log_pex_err(ferr, rp, willpanic, &interpose) == 0)
1343			return;
1344	} else if ((ferr & GE_FBD_FATAL) != 0) {
1345		log_fat_fbd_err(rp, willpanic, &interpose);
1346		*nerrp = nerr & ~GE_NERR_FBD_FATAL;
1347	} else if ((ferr & GE_FBD_NF) != 0) {
1348		log_nf_fbd_err(rp, willpanic, &interpose);
1349		*nerrp = nerr & ~GE_NERR_FBD_NF;
1350	} else if ((ferr & GE_MEM_NF) != 0) {
1351		spurious = log_nf_mem_err(rp, willpanic, &interpose);
1352		*nerrp = nerr & ~GE_NERR_MEM_NF;
1353	} else if ((ferr & (GE_FERR_FSB_FATAL | GE_FERR_FSB_NF)) != 0) {
1354		log_fsb_err(ferr, rp, willpanic, &interpose);
1355		*nerrp = nerr & ~(GE_NERR_FSB_FATAL | GE_NERR_FSB_NF);
1356	} else if ((ferr & (GE_DMA_FATAL | GE_DMA_NF)) != 0) {
1357		log_dma_err(rp, &interpose);
1358		*nerrp = nerr & ~(GE_DMA_FATAL | GE_DMA_NF);
1359	} else if ((ferr & (GE_INT_FATAL | GE_INT_NF)) != 0) {
1360		spurious = log_int_err(rp, willpanic, &interpose);
1361		*nerrp = nerr & ~(GE_INT_FATAL | GE_INT_NF);
1362	} else if (nb_chipset == INTEL_NB_5400 &&
1363	    (ferr & (GE_FERR_THERMAL_FATAL | GE_FERR_THERMAL_NF)) != 0) {
1364		log_thermal_err(rp, willpanic, &interpose);
1365		*nerrp = nerr & ~(GE_FERR_THERMAL_FATAL | GE_FERR_THERMAL_NF);
1366	}
1367	if (interpose)
1368		log->type = "inject";
1369	else
1370		log->type = "error";
1371	if (!spurious) {
1372		errorq_dispatch(nb_queue, log, sizeof (nb_logout_t),
1373		    willpanic ? ERRORQ_SYNC : ERRORQ_ASYNC);
1374	}
1375}
1376
1377static void
1378log_nerr(uint32_t *errp, nb_logout_t *log, int willpanic)
1379{
1380	uint32_t err;
1381	nb_regs_t *rp = &log->nb_regs;
1382	int interpose = 0;
1383	int spurious = 0;
1384
1385	err = *errp;
1386	log->acl_timestamp = gethrtime_waitfree();
1387	if ((err & (GE_PCIEX_FATAL | GE_PCIEX_NF)) != 0) {
1388		*errp = err & ~(GE_PCIEX_FATAL | GE_PCIEX_NF);
1389		if (log_pex_err(err, rp, willpanic, &interpose) == 0)
1390			return;
1391	} else if ((err & GE_NERR_FBD_FATAL) != 0) {
1392		log_fat_fbd_err(rp, willpanic, &interpose);
1393		*errp = err & ~GE_NERR_FBD_FATAL;
1394	} else if ((err & GE_NERR_FBD_NF) != 0) {
1395		log_nf_fbd_err(rp, willpanic, &interpose);
1396		*errp = err & ~GE_NERR_FBD_NF;
1397	} else if ((err & GE_NERR_MEM_NF) != 0) {
1398		spurious = log_nf_mem_err(rp, willpanic, &interpose);
1399		*errp = err & ~GE_NERR_MEM_NF;
1400	} else if ((err & (GE_NERR_FSB_FATAL | GE_NERR_FSB_NF)) != 0) {
1401		log_fsb_err(GE_NERR_TO_FERR_FSB(err), rp, willpanic,
1402		    &interpose);
1403		*errp = err & ~(GE_NERR_FSB_FATAL | GE_NERR_FSB_NF);
1404	} else if ((err & (GE_DMA_FATAL | GE_DMA_NF)) != 0) {
1405		log_dma_err(rp, &interpose);
1406		*errp = err & ~(GE_DMA_FATAL | GE_DMA_NF);
1407	} else if ((err & (GE_INT_FATAL | GE_INT_NF)) != 0) {
1408		spurious = log_int_err(rp, willpanic, &interpose);
1409		*errp = err & ~(GE_INT_FATAL | GE_INT_NF);
1410	}
1411	if (interpose)
1412		log->type = "inject";
1413	else
1414		log->type = "error";
1415	if (!spurious) {
1416		errorq_dispatch(nb_queue, log, sizeof (nb_logout_t),
1417		    willpanic ? ERRORQ_SYNC : ERRORQ_ASYNC);
1418	}
1419}
1420
1421/*ARGSUSED*/
1422void
1423nb_error_trap(cmi_hdl_t hdl, boolean_t ismc, boolean_t willpanic)
1424{
1425	uint64_t ferr;
1426	uint32_t nerr, err;
1427	int nmc = 0;
1428	int i;
1429
1430	if (mutex_tryenter(&nb_mutex) == 0)
1431		return;
1432
1433	nerr = NERR_GLOBAL_RD();
1434	err = nerr;
1435	for (i = 0; i < NB_MAX_ERRORS; i++) {
1436		ferr = FERR_GLOBAL_RD();
1437		nb_log.nb_regs.chipset = nb_chipset;
1438		nb_log.nb_regs.ferr = ferr;
1439		nb_log.nb_regs.nerr = nerr;
1440		if (ferr) {
1441			log_ferr(ferr, &err, &nb_log, willpanic);
1442			FERR_GLOBAL_WR(ferr);
1443			nmc++;
1444		} else if (err) {
1445			log_nerr(&err, &nb_log, willpanic);
1446			nmc++;
1447		}
1448	}
1449	if (nerr) {
1450		NERR_GLOBAL_WR(nerr);
1451	}
1452	if (nmc == 0 && nb_mask_mc_set)
1453		nb_mask_mc_reset();
1454	mutex_exit(&nb_mutex);
1455}
1456
1457static void
1458nb_fsb_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1459    nb_scatchpad_t *data)
1460{
1461	int intel_error_list;
1462	char buf[32];
1463
1464	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FSB,
1465	    DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.fsb, NULL);
1466	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_FSB,
1467	    DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.ferr_fat_fsb, NULL);
1468	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_FSB,
1469	    DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.nerr_fat_fsb, NULL);
1470	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_FSB,
1471	    DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.ferr_nf_fsb, NULL);
1472	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_FSB,
1473	    DATA_TYPE_UINT8, nb_regs->nb.fsb_regs.nerr_nf_fsb, NULL);
1474	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFSB,
1475	    DATA_TYPE_UINT32, nb_regs->nb.fsb_regs.nrecfsb, NULL);
1476	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFSB_ADDR,
1477	    DATA_TYPE_UINT64, nb_regs->nb.fsb_regs.nrecfsb_addr, NULL);
1478	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFSB,
1479	    DATA_TYPE_UINT32, nb_regs->nb.fsb_regs.recfsb, NULL);
1480	intel_error_list = data->intel_error_list;
1481	if (intel_error_list >= 0)
1482		(void) snprintf(buf, sizeof (buf), "F%d", intel_error_list);
1483	else
1484		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1485	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1486	    DATA_TYPE_STRING, buf, NULL);
1487}
1488
1489static void
1490nb_pex_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1491    nb_scatchpad_t *data)
1492{
1493	int intel_error_list;
1494	char buf[32];
1495
1496	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX,
1497	    DATA_TYPE_UINT8, nb_regs->nb.pex_regs.pex, NULL);
1498	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_FAT_FERR,
1499	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_fat_ferr, NULL);
1500	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_FAT_NERR,
1501	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_fat_nerr, NULL);
1502	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_NF_CORR_FERR,
1503	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_nf_corr_ferr, NULL);
1504	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEX_NF_CORR_NERR,
1505	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.pex_nf_corr_nerr, NULL);
1506	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UNCERRSEV,
1507	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.uncerrsev, NULL);
1508	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RPERRSTS,
1509	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.rperrsts, NULL);
1510	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RPERRSID,
1511	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.rperrsid, NULL);
1512	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UNCERRSTS,
1513	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.uncerrsts, NULL);
1514	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_AERRCAPCTRL,
1515	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.aerrcapctrl, NULL);
1516	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CORERRSTS,
1517	    DATA_TYPE_UINT32, nb_regs->nb.pex_regs.corerrsts, NULL);
1518	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEXDEVSTS,
1519	    DATA_TYPE_UINT16, nb_regs->nb.pex_regs.pexdevsts, NULL);
1520	intel_error_list = data->intel_error_list;
1521	if (intel_error_list >= 0)
1522		(void) snprintf(buf, sizeof (buf), "IO%d", intel_error_list);
1523	else
1524		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1525	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1526	    DATA_TYPE_STRING, buf, NULL);
1527}
1528
1529static void
1530nb_int_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1531    nb_scatchpad_t *data)
1532{
1533	int intel_error_list;
1534	char buf[32];
1535
1536	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_INT,
1537	    DATA_TYPE_UINT16, nb_regs->nb.int_regs.ferr_fat_int, NULL);
1538	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_INT,
1539	    DATA_TYPE_UINT16, nb_regs->nb.int_regs.ferr_nf_int, NULL);
1540	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_INT,
1541	    DATA_TYPE_UINT16, nb_regs->nb.int_regs.nerr_fat_int, NULL);
1542	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_INT,
1543	    DATA_TYPE_UINT16, nb_regs->nb.int_regs.nerr_nf_int, NULL);
1544	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECINT,
1545	    DATA_TYPE_UINT32, nb_regs->nb.int_regs.nrecint, NULL);
1546	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECINT,
1547	    DATA_TYPE_UINT32, nb_regs->nb.int_regs.recint, NULL);
1548	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECSF,
1549	    DATA_TYPE_UINT64, nb_regs->nb.int_regs.nrecsf, NULL);
1550	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECSF,
1551	    DATA_TYPE_UINT64, nb_regs->nb.int_regs.recsf, NULL);
1552	intel_error_list = data->intel_error_list;
1553	if (intel_error_list >= 0)
1554		(void) snprintf(buf, sizeof (buf), "B%d", intel_error_list);
1555	else
1556		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1557	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1558	    DATA_TYPE_STRING, buf, NULL);
1559}
1560
1561static void
1562nb_fat_fbd_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1563    nb_scatchpad_t *data)
1564{
1565	nb_mem_scatchpad_t *sp;
1566	char buf[32];
1567
1568	sp = &((nb_scatchpad_t *)data)->ms;
1569
1570	if (sp->ras != -1) {
1571		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK,
1572		    DATA_TYPE_INT32, sp->bank, NULL);
1573		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS,
1574		    DATA_TYPE_INT32, sp->cas, NULL);
1575		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS,
1576		    DATA_TYPE_INT32, sp->ras, NULL);
1577		if (sp->offset != -1LL) {
1578			fm_payload_set(payload, FM_FMRI_MEM_OFFSET,
1579			    DATA_TYPE_UINT64, sp->offset, NULL);
1580		}
1581		if (sp->pa != -1LL) {
1582			fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR,
1583			    DATA_TYPE_UINT64, sp->pa, NULL);
1584		}
1585	}
1586	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_FBD,
1587	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.ferr_fat_fbd, NULL);
1588	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_FBD,
1589	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nerr_fat_fbd, NULL);
1590	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMA,
1591	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecmema, NULL);
1592	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMB,
1593	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecmemb, NULL);
1594	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFGLOG,
1595	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfglog, NULL);
1596	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDA,
1597	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbda, NULL);
1598	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDB,
1599	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdb, NULL);
1600	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDC,
1601	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdc, NULL);
1602	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDD,
1603	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdd, NULL);
1604	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDE,
1605	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbde, NULL);
1606	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECFBDF,
1607	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.nrecfbdf, NULL);
1608	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS,
1609	    DATA_TYPE_UINT8, nb_regs->nb.fat_fbd_regs.spcps, NULL);
1610	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC,
1611	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.spcpc, NULL);
1612	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UERRCNT,
1613	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.uerrcnt, NULL);
1614	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_UERRCNT_LAST,
1615	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.uerrcnt_last, NULL);
1616	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMA,
1617	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.badrama, NULL);
1618	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMB,
1619	    DATA_TYPE_UINT16, nb_regs->nb.fat_fbd_regs.badramb, NULL);
1620	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT,
1621	    DATA_TYPE_UINT32, nb_regs->nb.fat_fbd_regs.badcnt, NULL);
1622
1623	if (sp->intel_error_list >= 0)
1624		(void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list);
1625	else
1626		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1627	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1628	    DATA_TYPE_STRING, buf, NULL);
1629}
1630
1631static void
1632nb_nf_fbd_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1633    nb_scatchpad_t *data)
1634{
1635	nb_mem_scatchpad_t *sp;
1636	char buf[32];
1637
1638	sp = &((nb_scatchpad_t *)data)->ms;
1639
1640	if (sp->dimm == -1 && sp->rank != -1) {
1641		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RANK,
1642		    DATA_TYPE_INT32, sp->rank, NULL);
1643	}
1644	if (sp->ras != -1) {
1645		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK,
1646		    DATA_TYPE_INT32, sp->bank, NULL);
1647		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS,
1648		    DATA_TYPE_INT32, sp->cas, NULL);
1649		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS,
1650		    DATA_TYPE_INT32, sp->ras, NULL);
1651		if (sp->offset != -1LL) {
1652			fm_payload_set(payload, FM_FMRI_MEM_OFFSET,
1653			    DATA_TYPE_UINT64, sp->offset, NULL);
1654		}
1655		if (sp->pa != -1LL) {
1656			fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR,
1657			    DATA_TYPE_UINT64, sp->pa, NULL);
1658		}
1659	}
1660	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_FBD,
1661	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.ferr_nf_fbd, NULL);
1662	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_FBD,
1663	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.nerr_nf_fbd, NULL);
1664	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMA,
1665	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recmema, NULL);
1666	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMB,
1667	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recmemb, NULL);
1668	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFGLOG,
1669	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfglog, NULL);
1670	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDA,
1671	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbda, NULL);
1672	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDB,
1673	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdb, NULL);
1674	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDC,
1675	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdc, NULL);
1676	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDD,
1677	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdd, NULL);
1678	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDE,
1679	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbde, NULL);
1680	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECFBDF,
1681	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.recfbdf, NULL);
1682	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS,
1683	    DATA_TYPE_UINT8, nb_regs->nb.nf_fbd_regs.spcps, NULL);
1684	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC,
1685	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.spcpc, NULL);
1686	if (nb_chipset == INTEL_NB_7300 || nb_chipset == INTEL_NB_5400) {
1687		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTA,
1688		    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta, NULL);
1689		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTB,
1690		    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntb, NULL);
1691		if (nb_chipset == INTEL_NB_7300) {
1692			fm_payload_set(payload,
1693			    FM_EREPORT_PAYLOAD_NAME_CERRCNTC,
1694			    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntc,
1695			    NULL);
1696			fm_payload_set(payload,
1697			    FM_EREPORT_PAYLOAD_NAME_CERRCNTD,
1698			    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntd,
1699			    NULL);
1700		}
1701		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTA_LAST,
1702		    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta_last,
1703		    NULL);
1704		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNTB_LAST,
1705		    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcntb_last,
1706		    NULL);
1707		if (nb_chipset == INTEL_NB_7300) {
1708			fm_payload_set(payload,
1709			    FM_EREPORT_PAYLOAD_NAME_CERRCNTC_LAST,
1710			    DATA_TYPE_UINT32,
1711			    nb_regs->nb.nf_fbd_regs.cerrcntc_last, NULL);
1712			fm_payload_set(payload,
1713			    FM_EREPORT_PAYLOAD_NAME_CERRCNTD_LAST,
1714			    DATA_TYPE_UINT32,
1715			    nb_regs->nb.nf_fbd_regs.cerrcntd_last, NULL);
1716		}
1717	} else {
1718		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT,
1719		    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta, NULL);
1720		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_LAST,
1721		    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.cerrcnta_last,
1722		    NULL);
1723	}
1724	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMA,
1725	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.badrama, NULL);
1726	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAMB,
1727	    DATA_TYPE_UINT16, nb_regs->nb.nf_fbd_regs.badramb, NULL);
1728	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT,
1729	    DATA_TYPE_UINT32, nb_regs->nb.nf_fbd_regs.badcnt, NULL);
1730
1731	if (sp->intel_error_list >= 0)
1732		(void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list);
1733	else
1734		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1735	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1736	    DATA_TYPE_STRING, buf, NULL);
1737}
1738
1739static void
1740nb_nf_mem_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1741    nb_scatchpad_t *data)
1742{
1743	nb_mem_scatchpad_t *sp;
1744	char buf[32];
1745
1746	sp = &((nb_scatchpad_t *)data)->ms;
1747
1748	if (sp->dimm == -1 && sp->rank != -1) {
1749		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RANK,
1750		    DATA_TYPE_INT32, sp->rank, NULL);
1751	}
1752	if (sp->ras != -1) {
1753		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK,
1754		    DATA_TYPE_INT32, sp->bank, NULL);
1755		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CAS,
1756		    DATA_TYPE_INT32, sp->cas, NULL);
1757		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RAS,
1758		    DATA_TYPE_INT32, sp->ras, NULL);
1759		if (sp->offset != -1LL) {
1760			fm_payload_set(payload, FM_FMRI_MEM_OFFSET,
1761			    DATA_TYPE_UINT64, sp->offset, NULL);
1762		}
1763		if (sp->pa != -1LL) {
1764			fm_payload_set(payload, FM_FMRI_MEM_PHYSADDR,
1765			    DATA_TYPE_UINT64, sp->pa, NULL);
1766		}
1767	}
1768	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_MEM,
1769	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.ferr_nf_mem, NULL);
1770	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_MEM,
1771	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.nerr_nf_mem, NULL);
1772	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMA,
1773	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.recmema, NULL);
1774	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RECMEMB,
1775	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.recmemb, NULL);
1776	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_REDMEMA,
1777	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.redmema, NULL);
1778	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_REDMEMB,
1779	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.redmemb, NULL);
1780	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMA,
1781	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.nrecmema, NULL);
1782	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NRECMEMB,
1783	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.nrecmemb, NULL);
1784	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPS,
1785	    DATA_TYPE_UINT8, nb_regs->nb.nf_mem_regs.spcps, NULL);
1786	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SPCPC,
1787	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.spcpc, NULL);
1788	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT,
1789	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt, NULL);
1790	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_LAST,
1791	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt_last, NULL);
1792	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_EXT,
1793	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt_ext, NULL);
1794	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CERRCNT_EXT_LAST,
1795	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.cerrcnt_ext_last, NULL);
1796	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADRAM,
1797	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.badram, NULL);
1798	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BADCNT,
1799	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.badcnt, NULL);
1800	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_VALIDLOG,
1801	    DATA_TYPE_UINT32, nb_regs->nb.nf_mem_regs.validlog, NULL);
1802
1803	if (sp->intel_error_list >= 0)
1804		(void) snprintf(buf, sizeof (buf), "M%d", sp->intel_error_list);
1805	else
1806		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1807	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1808	    DATA_TYPE_STRING, buf, NULL);
1809}
1810
1811static void
1812nb_dma_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload)
1813{
1814	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PCISTS,
1815	    DATA_TYPE_UINT16, nb_regs->nb.dma_regs.pcists, NULL);
1816	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PEXDEVSTS,
1817	    DATA_TYPE_UINT16, nb_regs->nb.dma_regs.pexdevsts, NULL);
1818}
1819
1820static void
1821nb_thr_err_payload(const nb_regs_t *nb_regs, nvlist_t *payload,
1822    nb_scatchpad_t *data)
1823{
1824	char buf[32];
1825
1826	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_FAT_THR,
1827	    DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ferr_fat_thr, NULL);
1828	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_FAT_THR,
1829	    DATA_TYPE_UINT8, nb_regs->nb.thr_regs.nerr_fat_thr, NULL);
1830	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_NF_THR,
1831	    DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ferr_nf_thr, NULL);
1832	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_NF_THR,
1833	    DATA_TYPE_UINT8, nb_regs->nb.thr_regs.nerr_nf_thr, NULL);
1834	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_CTSTS,
1835	    DATA_TYPE_UINT8, nb_regs->nb.thr_regs.ctsts, NULL);
1836	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_THRTSTS,
1837	    DATA_TYPE_UINT16, nb_regs->nb.thr_regs.thrtsts, NULL);
1838	if (data->intel_error_list >= 0) {
1839		(void) snprintf(buf, sizeof (buf), "TH%d",
1840		    data->intel_error_list);
1841	} else {
1842		(void) snprintf(buf, sizeof (buf), "Multiple or unknown error");
1843	}
1844	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ERROR_NO,
1845	    DATA_TYPE_STRING, buf, NULL);
1846}
1847
1848static void
1849nb_ereport_add_logout(nvlist_t *payload, const nb_logout_t *acl,
1850    nb_scatchpad_t *data)
1851{
1852	const nb_regs_t *nb_regs = &acl->nb_regs;
1853
1854	fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_MC_TYPE,
1855	    DATA_TYPE_STRING, acl->type, NULL);
1856	switch (nb_regs->flag) {
1857	case NB_REG_LOG_FSB:
1858		nb_fsb_err_payload(nb_regs, payload, data);
1859		break;
1860	case NB_REG_LOG_PEX:
1861		nb_pex_err_payload(nb_regs, payload, data);
1862		break;
1863	case NB_REG_LOG_INT:
1864		nb_int_err_payload(nb_regs, payload, data);
1865		break;
1866	case NB_REG_LOG_FAT_FBD:
1867		nb_fat_fbd_err_payload(nb_regs, payload, data);
1868		break;
1869	case NB_REG_LOG_NF_FBD:
1870		nb_nf_fbd_err_payload(nb_regs, payload, data);
1871		break;
1872	case NB_REG_LOG_DMA:
1873		nb_dma_err_payload(nb_regs, payload);
1874		break;
1875	case NB_REG_LOG_THR:
1876		nb_thr_err_payload(nb_regs, payload, data);
1877		break;
1878	case NB_REG_LOG_NF_MEM:
1879		nb_nf_mem_err_payload(nb_regs, payload, data);
1880		break;
1881	default:
1882		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_FERR_GLOBAL,
1883		    DATA_TYPE_UINT64, nb_regs->ferr, NULL);
1884		fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_NERR_GLOBAL,
1885		    DATA_TYPE_UINT32, nb_regs->nerr, NULL);
1886		break;
1887	}
1888}
1889
1890void
1891nb_fsb_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
1892    nb_scatchpad_t *data)
1893{
1894	int chip;
1895
1896	if (nb_chipset == INTEL_NB_7300)
1897		chip = nb_regs->nb.fsb_regs.fsb * 2;
1898	else
1899		chip = nb_regs->nb.fsb_regs.fsb;
1900	fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2,
1901	    "motherboard", 0, "chip", chip);
1902
1903	if (nb_regs->nb.fsb_regs.ferr_fat_fsb == 0 &&
1904	    nb_regs->nb.fsb_regs.ferr_nf_fsb == 0) {
1905		data->intel_error_list = intel_fsb_err(nb_regs->nb.fsb_regs.fsb,
1906		    nb_regs->nb.fsb_regs.nerr_fat_fsb,
1907		    nb_regs->nb.fsb_regs.nerr_nf_fsb);
1908	} else {
1909		data->intel_error_list = intel_fsb_err(nb_regs->nb.fsb_regs.fsb,
1910		    nb_regs->nb.fsb_regs.ferr_fat_fsb,
1911		    nb_regs->nb.fsb_regs.ferr_nf_fsb);
1912	}
1913	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
1914	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "fsb");
1915}
1916
1917void
1918nb_pex_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
1919    nb_scatchpad_t *data)
1920{
1921	int hostbridge;
1922
1923	if (nb_regs->nb.pex_regs.pex == 0) {
1924		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
1925		    "motherboard", 0);
1926	} else {
1927		hostbridge = nb_regs->nb.pex_regs.pex - 1;
1928		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2,
1929		    "motherboard", 0,
1930		    "hostbridge", hostbridge);
1931	}
1932
1933	if (nb_regs->nb.pex_regs.pex_fat_ferr == 0 &&
1934	    nb_regs->nb.pex_regs.pex_nf_corr_ferr == 0) {
1935		if (nb_chipset == INTEL_NB_5400) {
1936			data->intel_error_list =
1937			    intel_pex_5400_err(
1938			    nb_regs->nb.pex_regs.pex_fat_nerr,
1939			    nb_regs->nb.pex_regs.pex_nf_corr_nerr);
1940		} else {
1941			data->intel_error_list =
1942			    intel_pex_err(nb_regs->nb.pex_regs.pex_fat_nerr,
1943			    nb_regs->nb.pex_regs.pex_nf_corr_nerr);
1944		}
1945	} else {
1946		if (nb_chipset == INTEL_NB_5400) {
1947			data->intel_error_list =
1948			    intel_pex_5400_err(
1949			    nb_regs->nb.pex_regs.pex_fat_ferr,
1950			    nb_regs->nb.pex_regs.pex_nf_corr_ferr);
1951		} else {
1952			data->intel_error_list =
1953			    intel_pex_err(nb_regs->nb.pex_regs.pex_fat_ferr,
1954			    nb_regs->nb.pex_regs.pex_nf_corr_ferr);
1955		}
1956	}
1957
1958	if (nb_regs->nb.pex_regs.pex == 0) {
1959		(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
1960		    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "esi");
1961	} else {
1962		(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
1963		    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "pex");
1964	}
1965}
1966
1967void
1968nb_int_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
1969    void *data)
1970{
1971	fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
1972	    "motherboard", 0);
1973
1974	if (nb_regs->nb.int_regs.ferr_fat_int == 0 &&
1975	    nb_regs->nb.int_regs.ferr_nf_int == 0) {
1976		((nb_scatchpad_t *)data)->intel_error_list =
1977		    intel_int_err(nb_regs->nb.int_regs.nerr_fat_int,
1978		    nb_regs->nb.int_regs.nerr_nf_int);
1979	} else {
1980		((nb_scatchpad_t *)data)->intel_error_list =
1981		    intel_int_err(nb_regs->nb.int_regs.ferr_fat_int,
1982		    nb_regs->nb.int_regs.ferr_nf_int);
1983	}
1984	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
1985	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "ie");
1986}
1987
1988void
1989nb_fat_fbd_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
1990    void *data)
1991{
1992	char *intr;
1993	nb_mem_scatchpad_t *sp;
1994
1995	intr = fat_memory_error(nb_regs, data);
1996	sp = &((nb_scatchpad_t *)data)->ms;
1997
1998	if (sp->dimm != -1) {
1999		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5,
2000		    "motherboard", 0,
2001		    "memory-controller", sp->branch,
2002		    "dram-channel", sp->channel,
2003		    "dimm", sp->dimm,
2004		    "rank", sp->rank);
2005	} else if (sp->channel != -1) {
2006		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
2007		    "motherboard", 0,
2008		    "memory-controller", sp->branch,
2009		    "dram-channel", sp->channel);
2010	} else if (sp->branch != -1) {
2011		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2,
2012		    "motherboard", 0,
2013		    "memory-controller", sp->branch);
2014	} else {
2015		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
2016		    "motherboard", 0);
2017	}
2018
2019	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s",
2020	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr);
2021}
2022
2023void
2024nb_nf_fbd_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
2025    void *data)
2026{
2027	char *intr;
2028	nb_mem_scatchpad_t *sp;
2029
2030	intr = nf_memory_error(nb_regs, data);
2031	sp = &((nb_scatchpad_t *)data)->ms;
2032
2033	if (sp->dimm != -1) {
2034		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5,
2035		    "motherboard", 0,
2036		    "memory-controller", sp->branch,
2037		    "dram-channel", sp->channel,
2038		    "dimm", sp->dimm,
2039		    "rank", sp->rank);
2040	} else if (sp->channel != -1) {
2041		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
2042		    "motherboard", 0,
2043		    "memory-controller", sp->branch,
2044		    "dram-channel", sp->channel);
2045	} else if (sp->branch != -1) {
2046		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2,
2047		    "motherboard", 0,
2048		    "memory-controller", sp->branch);
2049	} else {
2050		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
2051		    "motherboard", 0);
2052	}
2053
2054	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s",
2055	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr);
2056}
2057
2058void
2059nb_dma_report(char *class, nvlist_t *detector)
2060{
2061	fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
2062	    "motherboard", 0);
2063
2064	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
2065	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "dma");
2066}
2067
2068void
2069nb_thr_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
2070    void *data)
2071{
2072	((nb_scatchpad_t *)data)->intel_error_list =
2073	    intel_thr_err(nb_regs->nb.thr_regs.ferr_fat_thr,
2074	    nb_regs->nb.thr_regs.ferr_nf_thr);
2075	fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
2076	    "motherboard", 0);
2077
2078	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
2079	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "otf");
2080}
2081
2082void
2083nb_nf_mem_report(const nb_regs_t *nb_regs, char *class, nvlist_t *detector,
2084    void *data)
2085{
2086	char *intr;
2087	nb_mem_scatchpad_t *sp;
2088
2089	intr = nf_mem_error(nb_regs, data);
2090	sp = &((nb_scatchpad_t *)data)->ms;
2091
2092	if (sp->dimm != -1) {
2093		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 5,
2094		    "motherboard", 0,
2095		    "memory-controller", sp->branch,
2096		    "dram-channel", sp->channel,
2097		    "dimm", sp->dimm,
2098		    "rank", sp->rank);
2099	} else if (sp->channel != -1) {
2100		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 3,
2101		    "motherboard", 0,
2102		    "memory-controller", sp->branch,
2103		    "dram-channel", sp->channel);
2104	} else if (sp->branch != -1) {
2105		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 2,
2106		    "motherboard", 0,
2107		    "memory-controller", sp->branch);
2108	} else {
2109		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
2110		    "motherboard", 0);
2111	}
2112
2113	(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s",
2114	    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, intr);
2115}
2116
2117
2118nvlist_t *
2119nb_report(const nb_regs_t *nb_regs, char *class, nv_alloc_t *nva, void *scratch)
2120{
2121	nvlist_t *detector = fm_nvlist_create(nva);
2122
2123	switch (nb_regs->flag) {
2124	case NB_REG_LOG_FSB:
2125		nb_fsb_report(nb_regs, class, detector, scratch);
2126		break;
2127	case NB_REG_LOG_PEX:
2128		nb_pex_report(nb_regs, class, detector, scratch);
2129		break;
2130	case NB_REG_LOG_INT:
2131		nb_int_report(nb_regs, class, detector, scratch);
2132		break;
2133	case NB_REG_LOG_FAT_FBD:
2134		nb_fat_fbd_report(nb_regs, class, detector, scratch);
2135		break;
2136	case NB_REG_LOG_NF_FBD:
2137		nb_nf_fbd_report(nb_regs, class, detector, scratch);
2138		break;
2139	case NB_REG_LOG_DMA:
2140		nb_dma_report(class, detector);
2141		break;
2142	case NB_REG_LOG_THR:
2143		nb_thr_report(nb_regs, class, detector, scratch);
2144		break;
2145	case NB_REG_LOG_NF_MEM:
2146		nb_nf_mem_report(nb_regs, class, detector, scratch);
2147		break;
2148	default:
2149		fm_fmri_hc_set(detector, FM_HC_SCHEME_VERSION, NULL, NULL, 1,
2150		    "motherboard", 0);
2151
2152		(void) snprintf(class, FM_MAX_CLASS, "%s.%s.%s.%s",
2153		    FM_ERROR_CPU, FM_EREPORT_CPU_INTEL, "nb", "unknown");
2154	}
2155	return (detector);
2156}
2157
2158/*ARGSUSED*/
2159void
2160nb_drain(void *ignored, const void *data, const errorq_elem_t *eqe)
2161{
2162	nb_logout_t *acl = (nb_logout_t *)data;
2163	errorq_elem_t *eqep, *scr_eqep;
2164	nvlist_t *ereport, *detector;
2165	nv_alloc_t *nva = NULL;
2166	char buf[FM_MAX_CLASS];
2167	nb_scatchpad_t nb_scatchpad;
2168
2169	eqep = NULL;
2170	scr_eqep = NULL;
2171	if (panicstr) {
2172		if ((eqep = errorq_reserve(ereport_errorq)) == NULL)
2173			return;
2174		ereport = errorq_elem_nvl(ereport_errorq, eqep);
2175		/*
2176		 * Now try to allocate another element for scratch space and
2177		 * use that for further scratch space (eg for constructing
2178		 * nvlists to add the main ereport).  If we can't reserve
2179		 * a scratch element just fallback to working within the
2180		 * element we already have, and hope for the best.  All this
2181		 * is necessary because the fixed buffer nv allocator does
2182		 * not reclaim freed space and nvlist construction is
2183		 * expensive.
2184		 */
2185		if ((scr_eqep = errorq_reserve(ereport_errorq)) != NULL)
2186			nva = errorq_elem_nva(ereport_errorq, scr_eqep);
2187		else
2188			nva = errorq_elem_nva(ereport_errorq, eqep);
2189	} else {
2190		ereport = fm_nvlist_create(NULL);
2191	}
2192	detector = nb_report(&acl->nb_regs, buf, nva, &nb_scatchpad);
2193	if (detector == NULL)
2194		return;
2195	fm_ereport_set(ereport, FM_EREPORT_VERSION, buf,
2196	    fm_ena_generate(acl->acl_timestamp, FM_ENA_FMT1), detector, NULL);
2197	/*
2198	 * We're done with 'detector' so reclaim the scratch space.
2199	 */
2200	if (panicstr) {
2201		fm_nvlist_destroy(detector, FM_NVA_RETAIN);
2202		nv_alloc_reset(nva);
2203	} else {
2204		fm_nvlist_destroy(detector, FM_NVA_FREE);
2205	}
2206
2207	/*
2208	 * Encode the error-specific data that was saved in the logout area.
2209	 */
2210	nb_ereport_add_logout(ereport, acl, &nb_scatchpad);
2211
2212	if (panicstr) {
2213		errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC);
2214		if (scr_eqep)
2215			errorq_cancel(ereport_errorq, scr_eqep);
2216	} else {
2217		(void) fm_ereport_post(ereport, EVCH_TRYHARD);
2218		fm_nvlist_destroy(ereport, FM_NVA_FREE);
2219	}
2220}
2221