Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / arch / alpha / kernel / err_titan.c
1 /*
2  *      linux/arch/alpha/kernel/err_titan.c
3  *
4  *      Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5  *
6  *      Error handling code supporting TITAN systems
7  */
8
9 #include <linux/init.h>
10 #include <linux/pci.h>
11 #include <linux/sched.h>
12
13 #include <asm/io.h>
14 #include <asm/core_titan.h>
15 #include <asm/hwrpb.h>
16 #include <asm/smp.h>
17 #include <asm/err_common.h>
18 #include <asm/err_ev6.h>
19
20 #include "err_impl.h"
21 #include "proto.h"
22
23
24 static int
25 titan_parse_c_misc(u64 c_misc, int print)
26 {
27 #ifdef CONFIG_VERBOSE_MCHECK
28         char *src;
29         int nxs = 0;
30 #endif
31         int status = MCHK_DISPOSITION_REPORT;
32
33 #define TITAN__CCHIP_MISC__NXM          (1UL << 28)
34 #define TITAN__CCHIP_MISC__NXS__S       (29)
35 #define TITAN__CCHIP_MISC__NXS__M       (0x7)
36
37         if (!(c_misc & TITAN__CCHIP_MISC__NXM))
38                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
39
40 #ifdef CONFIG_VERBOSE_MCHECK
41         if (!print)
42                 return status;
43
44         nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
45         switch(nxs) {
46         case 0: /* CPU 0 */
47         case 1: /* CPU 1 */
48         case 2: /* CPU 2 */
49         case 3: /* CPU 3 */
50                 src = "CPU";
51                 /* num is already the CPU number */
52                 break;
53         case 4: /* Pchip 0 */
54         case 5: /* Pchip 1 */
55                 src = "Pchip";
56                 nxs -= 4;
57                 break;
58         default:/* reserved */
59                 src = "Unknown, NXS =";
60                 /* leave num untouched */
61                 break;
62         }
63
64         printk("%s    Non-existent memory access from: %s %d\n", 
65                err_print_prefix, src, nxs);
66 #endif /* CONFIG_VERBOSE_MCHECK */
67
68         return status;
69 }
70
71 static int
72 titan_parse_p_serror(int which, u64 serror, int print)
73 {
74         int status = MCHK_DISPOSITION_REPORT;
75
76 #ifdef CONFIG_VERBOSE_MCHECK
77         char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"};
78         char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"};
79 #endif /* CONFIG_VERBOSE_MCHECK */
80
81 #define TITAN__PCHIP_SERROR__LOST_UECC  (1UL << 0)
82 #define TITAN__PCHIP_SERROR__UECC       (1UL << 1)
83 #define TITAN__PCHIP_SERROR__CRE        (1UL << 2)
84 #define TITAN__PCHIP_SERROR__NXIO       (1UL << 3)
85 #define TITAN__PCHIP_SERROR__LOST_CRE   (1UL << 4)
86 #define TITAN__PCHIP_SERROR__ECCMASK    (TITAN__PCHIP_SERROR__UECC |      \
87                                          TITAN__PCHIP_SERROR__CRE)
88 #define TITAN__PCHIP_SERROR__ERRMASK    (TITAN__PCHIP_SERROR__LOST_UECC | \
89                                          TITAN__PCHIP_SERROR__UECC |      \
90                                          TITAN__PCHIP_SERROR__CRE |       \
91                                          TITAN__PCHIP_SERROR__NXIO |      \
92                                          TITAN__PCHIP_SERROR__LOST_CRE)
93 #define TITAN__PCHIP_SERROR__SRC__S     (52)
94 #define TITAN__PCHIP_SERROR__SRC__M     (0x3)
95 #define TITAN__PCHIP_SERROR__CMD__S     (54)
96 #define TITAN__PCHIP_SERROR__CMD__M     (0x3)
97 #define TITAN__PCHIP_SERROR__SYN__S     (56)
98 #define TITAN__PCHIP_SERROR__SYN__M     (0xff)
99 #define TITAN__PCHIP_SERROR__ADDR__S    (15)
100 #define TITAN__PCHIP_SERROR__ADDR__M    (0xffffffffUL)
101
102         if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
103                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
104
105 #ifdef CONFIG_VERBOSE_MCHECK
106         if (!print)
107                 return status;
108
109         printk("%s  PChip %d SERROR: %016lx\n", 
110                err_print_prefix, which, serror);
111         if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
112                 printk("%s    %sorrectable ECC Error:\n"
113                        "      Source: %-6s  Command: %-8s  Syndrome: 0x%08x\n"
114                        "      Address: 0x%lx\n", 
115                        err_print_prefix,
116                        (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
117                        serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
118                        serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
119                        (unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
120                        EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
121         }
122         if (serror & TITAN__PCHIP_SERROR__NXIO)
123                 printk("%s    Non Existent I/O Error\n", err_print_prefix);
124         if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
125                 printk("%s    Lost Uncorrectable ECC Error\n", 
126                        err_print_prefix);
127         if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
128                 printk("%s    Lost Correctable ECC Error\n", err_print_prefix);
129 #endif /* CONFIG_VERBOSE_MCHECK */
130
131         return status;
132 }
133
134 static int 
135 titan_parse_p_perror(int which, int port, u64 perror, int print)
136 {
137         int cmd;
138         unsigned long addr;
139         int status = MCHK_DISPOSITION_REPORT;
140
141 #ifdef CONFIG_VERBOSE_MCHECK
142         char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle",
143                                "I/O Read",              "I/O Write",
144                                "Reserved",              "Reserved",
145                                "Memory Read",           "Memory Write",
146                                "Reserved",              "Reserved",
147                                "Configuration Read",    "Configuration Write",
148                                "Memory Read Multiple",  "Dual Address Cycle",
149                                "Memory Read Line","Memory Write and Invalidate"
150         };
151 #endif /* CONFIG_VERBOSE_MCHECK */
152
153 #define TITAN__PCHIP_PERROR__LOST       (1UL << 0)
154 #define TITAN__PCHIP_PERROR__SERR       (1UL << 1)
155 #define TITAN__PCHIP_PERROR__PERR       (1UL << 2)
156 #define TITAN__PCHIP_PERROR__DCRTO      (1UL << 3)
157 #define TITAN__PCHIP_PERROR__SGE        (1UL << 4)
158 #define TITAN__PCHIP_PERROR__APE        (1UL << 5)
159 #define TITAN__PCHIP_PERROR__TA         (1UL << 6)
160 #define TITAN__PCHIP_PERROR__DPE        (1UL << 7)
161 #define TITAN__PCHIP_PERROR__NDS        (1UL << 8)
162 #define TITAN__PCHIP_PERROR__IPTPR      (1UL << 9)
163 #define TITAN__PCHIP_PERROR__IPTPW      (1UL << 10)
164 #define TITAN__PCHIP_PERROR__ERRMASK    (TITAN__PCHIP_PERROR__LOST |    \
165                                          TITAN__PCHIP_PERROR__SERR |    \
166                                          TITAN__PCHIP_PERROR__PERR |    \
167                                          TITAN__PCHIP_PERROR__DCRTO |   \
168                                          TITAN__PCHIP_PERROR__SGE |     \
169                                          TITAN__PCHIP_PERROR__APE |     \
170                                          TITAN__PCHIP_PERROR__TA |      \
171                                          TITAN__PCHIP_PERROR__DPE |     \
172                                          TITAN__PCHIP_PERROR__NDS |     \
173                                          TITAN__PCHIP_PERROR__IPTPR |   \
174                                          TITAN__PCHIP_PERROR__IPTPW)
175 #define TITAN__PCHIP_PERROR__DAC        (1UL << 47)
176 #define TITAN__PCHIP_PERROR__MWIN       (1UL << 48)
177 #define TITAN__PCHIP_PERROR__CMD__S     (52)
178 #define TITAN__PCHIP_PERROR__CMD__M     (0x0f)
179 #define TITAN__PCHIP_PERROR__ADDR__S    (14)
180 #define TITAN__PCHIP_PERROR__ADDR__M    (0x1fffffffful)
181
182         if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
183                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
184
185         cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
186         addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
187
188         /*
189          * Initializing the BIOS on a video card on a bus without
190          * a south bridge (subtractive decode agent) can result in 
191          * master aborts as the BIOS probes the capabilities of the
192          * card. XFree86 does such initialization. If the error
193          * is a master abort (No DevSel as PCI Master) and the command
194          * is an I/O read or write below the address where we start
195          * assigning PCI I/O spaces (SRM uses 0x1000), then mark the
196          * error as dismissable so starting XFree86 doesn't result
197          * in a series of uncorrectable errors being reported. Also
198          * dismiss master aborts to VGA frame buffer space
199          * (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
200          * for the same reason.
201          *
202          * Also mark the error dismissible if it looks like the right
203          * error but only the Lost bit is set. Since the BIOS initialization
204          * can cause multiple master aborts and the error interrupt can
205          * be handled on a different CPU than the BIOS code is run on,
206          * it is possible for a second master abort to occur between the
207          * time the PALcode reads PERROR and the time it writes PERROR
208          * to acknowledge the error. If this timing happens, a second
209          * error will be signalled after the first, and if no additional
210          * errors occur, will look like a Lost error with no additional 
211          * errors on the same transaction as the previous error.
212          */
213         if (((perror & TITAN__PCHIP_PERROR__NDS) || 
214              ((perror & TITAN__PCHIP_PERROR__ERRMASK) == 
215               TITAN__PCHIP_PERROR__LOST)) &&
216             ((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
217              (((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
218                 status = MCHK_DISPOSITION_DISMISS;
219         }
220
221 #ifdef CONFIG_VERBOSE_MCHECK
222         if (!print) 
223                 return status;
224
225         printk("%s  PChip %d %cPERROR: %016lx\n", 
226                err_print_prefix, which, 
227                port ? 'A' : 'G', perror);
228         if (perror & TITAN__PCHIP_PERROR__IPTPW)
229                 printk("%s    Invalid Peer-to-Peer Write\n", err_print_prefix);
230         if (perror & TITAN__PCHIP_PERROR__IPTPR)
231                 printk("%s    Invalid Peer-to-Peer Read\n", err_print_prefix);
232         if (perror & TITAN__PCHIP_PERROR__NDS)
233                 printk("%s    No DEVSEL as PCI Master [Master Abort]\n",
234                        err_print_prefix);
235         if (perror & TITAN__PCHIP_PERROR__DPE)
236                 printk("%s    Data Parity Error\n", err_print_prefix);
237         if (perror & TITAN__PCHIP_PERROR__TA)
238                 printk("%s    Target Abort\n", err_print_prefix);
239         if (perror & TITAN__PCHIP_PERROR__APE)
240                 printk("%s    Address Parity Error\n", err_print_prefix);
241         if (perror & TITAN__PCHIP_PERROR__SGE)
242                 printk("%s    Scatter-Gather Error, Invalid PTE\n", 
243                        err_print_prefix);
244         if (perror & TITAN__PCHIP_PERROR__DCRTO)
245                 printk("%s    Delayed-Completion Retry Timeout\n", 
246                        err_print_prefix);
247         if (perror & TITAN__PCHIP_PERROR__PERR)
248                 printk("%s    PERR Asserted\n", err_print_prefix);
249         if (perror & TITAN__PCHIP_PERROR__SERR)
250                 printk("%s    SERR Asserted\n", err_print_prefix);
251         if (perror & TITAN__PCHIP_PERROR__LOST)
252                 printk("%s    Lost Error\n", err_print_prefix);
253         printk("%s      Command: 0x%x - %s\n"
254                  "      Address: 0x%lx\n",
255                err_print_prefix,
256                cmd, perror_cmd[cmd],
257                addr);
258         if (perror & TITAN__PCHIP_PERROR__DAC)
259                 printk("%s      Dual Address Cycle\n", err_print_prefix);
260         if (perror & TITAN__PCHIP_PERROR__MWIN)
261                 printk("%s      Hit in Monster Window\n", err_print_prefix);
262 #endif /* CONFIG_VERBOSE_MCHECK */
263
264         return status;
265 }
266
267 static int
268 titan_parse_p_agperror(int which, u64 agperror, int print)
269 {
270         int status = MCHK_DISPOSITION_REPORT;
271 #ifdef CONFIG_VERBOSE_MCHECK
272         int cmd, len;
273         unsigned long addr;
274
275         char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)",
276                                  "Write (low-priority)",
277                                  "Write (high-priority)",
278                                  "Reserved",            "Reserved",
279                                  "Flush",               "Fence"
280         };
281 #endif /* CONFIG_VERBOSE_MCHECK */
282
283 #define TITAN__PCHIP_AGPERROR__LOST     (1UL << 0)
284 #define TITAN__PCHIP_AGPERROR__LPQFULL  (1UL << 1)
285 #define TITAN__PCHIP_AGPERROR__HPQFULL  (1UL << 2)
286 #define TITAN__PCHIP_AGPERROR__RESCMD   (1UL << 3)
287 #define TITAN__PCHIP_AGPERROR__IPTE     (1UL << 4)
288 #define TITAN__PCHIP_AGPERROR__PTP      (1UL << 5)
289 #define TITAN__PCHIP_AGPERROR__NOWINDOW (1UL << 6)
290 #define TITAN__PCHIP_AGPERROR__ERRMASK  (TITAN__PCHIP_AGPERROR__LOST |    \
291                                          TITAN__PCHIP_AGPERROR__LPQFULL | \
292                                          TITAN__PCHIP_AGPERROR__HPQFULL | \
293                                          TITAN__PCHIP_AGPERROR__RESCMD |  \
294                                          TITAN__PCHIP_AGPERROR__IPTE |    \
295                                          TITAN__PCHIP_AGPERROR__PTP |     \
296                                          TITAN__PCHIP_AGPERROR__NOWINDOW)
297 #define TITAN__PCHIP_AGPERROR__DAC      (1UL << 48)
298 #define TITAN__PCHIP_AGPERROR__MWIN     (1UL << 49)
299 #define TITAN__PCHIP_AGPERROR__FENCE    (1UL << 59)
300 #define TITAN__PCHIP_AGPERROR__CMD__S   (50)
301 #define TITAN__PCHIP_AGPERROR__CMD__M   (0x07)
302 #define TITAN__PCHIP_AGPERROR__ADDR__S  (15)
303 #define TITAN__PCHIP_AGPERROR__ADDR__M  (0xffffffffUL)
304 #define TITAN__PCHIP_AGPERROR__LEN__S   (53)
305 #define TITAN__PCHIP_AGPERROR__LEN__M   (0x3f)
306
307         if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
308                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
309
310 #ifdef CONFIG_VERBOSE_MCHECK
311         if (!print)
312                 return status;
313
314         cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
315         addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
316         len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
317
318         printk("%s  PChip %d AGPERROR: %016lx\n", err_print_prefix,
319                which, agperror);
320         if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
321                 printk("%s    No Window\n", err_print_prefix);
322         if (agperror & TITAN__PCHIP_AGPERROR__PTP)
323                 printk("%s    Peer-to-Peer set\n", err_print_prefix);
324         if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
325                 printk("%s    Invalid PTE\n", err_print_prefix);
326         if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
327                 printk("%s    Reserved Command\n", err_print_prefix);
328         if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
329                 printk("%s    HP Transaction Received while Queue Full\n", 
330                        err_print_prefix);
331         if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
332                 printk("%s    LP Transaction Received while Queue Full\n", 
333                        err_print_prefix);
334         if (agperror & TITAN__PCHIP_AGPERROR__LOST)
335                 printk("%s    Lost Error\n", err_print_prefix);
336         printk("%s      Command: 0x%x - %s, %d Quadwords%s\n"
337                  "      Address: 0x%lx\n",
338                err_print_prefix, cmd, agperror_cmd[cmd], len,
339                (agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
340                addr);
341         if (agperror & TITAN__PCHIP_AGPERROR__DAC)
342                 printk("%s      Dual Address Cycle\n", err_print_prefix);
343         if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
344                 printk("%s      Hit in Monster Window\n", err_print_prefix);
345 #endif /* CONFIG_VERBOSE_MCHECK */
346
347         return status;
348 }       
349
350 static int
351 titan_parse_p_chip(int which, u64 serror, u64 gperror, 
352                    u64 aperror, u64 agperror, int print)
353 {
354         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
355         status |= titan_parse_p_serror(which, serror, print);
356         status |= titan_parse_p_perror(which, 0, gperror, print);
357         status |= titan_parse_p_perror(which, 1, aperror, print);
358         status |= titan_parse_p_agperror(which, agperror, print);
359         return status;
360 }
361
362 int
363 titan_process_logout_frame(struct el_common *mchk_header, int print)
364 {
365         struct el_TITAN_sysdata_mcheck *tmchk =
366                 (struct el_TITAN_sysdata_mcheck *)
367                 ((unsigned long)mchk_header + mchk_header->sys_offset);
368         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
369
370         status |= titan_parse_c_misc(tmchk->c_misc, print);
371         status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
372                                      tmchk->p0_aperror, tmchk->p0_agperror, 
373                                      print);
374         status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
375                                      tmchk->p1_aperror, tmchk->p1_agperror, 
376                                      print);
377
378         return status;
379 }
380
381 void
382 titan_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
383 {
384         struct el_common *mchk_header = (struct el_common *)la_ptr;
385         struct el_TITAN_sysdata_mcheck *tmchk =
386                 (struct el_TITAN_sysdata_mcheck *)
387                 ((unsigned long)mchk_header + mchk_header->sys_offset);
388         u64 irqmask;
389
390         /*
391          * Mask of Titan interrupt sources which are reported as machine checks
392          *
393          * 63 - CChip Error
394          * 62 - PChip 0 H_Error
395          * 61 - PChip 1 H_Error
396          * 60 - PChip 0 C_Error
397          * 59 - PChip 1 C_Error
398          */
399 #define TITAN_MCHECK_INTERRUPT_MASK     0xF800000000000000UL
400
401         /*
402          * Sync the processor
403          */
404         mb();
405         draina();
406         
407         /*
408          * Only handle system errors here 
409          */
410         if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
411                 ev6_machine_check(vector, la_ptr, regs);
412                 return;
413         }
414
415         /* 
416          * It's a system error, handle it here
417          *
418          * The PALcode has already cleared the error, so just parse it
419          */
420         
421         /* 
422          * Parse the logout frame without printing first. If the only error(s)
423          * found are classified as "dismissable", then just dismiss them and
424          * don't print any message
425          */
426         if (titan_process_logout_frame(mchk_header, 0) != 
427             MCHK_DISPOSITION_DISMISS) {
428                 char *saved_err_prefix = err_print_prefix;
429                 err_print_prefix = KERN_CRIT;
430
431                 /*
432                  * Either a nondismissable error was detected or no
433                  * recognized error was detected  in the logout frame 
434                  * -- report the error in either case
435                  */
436                 printk("%s"
437                        "*System %s Error (Vector 0x%x) reported on CPU %d:\n", 
438                        err_print_prefix,
439                        (vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
440                        (unsigned int)vector, (int)smp_processor_id());
441                 
442 #ifdef CONFIG_VERBOSE_MCHECK
443                 titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
444                 if (alpha_verbose_mcheck)
445                         dik_show_regs(regs, NULL);
446 #endif /* CONFIG_VERBOSE_MCHECK */
447
448                 err_print_prefix = saved_err_prefix;
449
450                 /*
451                  * Convert any pending interrupts which report as system
452                  * machine checks to interrupts
453                  */
454                 irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
455                 titan_dispatch_irqs(irqmask, regs);
456         }       
457
458
459         /* 
460          * Release the logout frame 
461          */
462         wrmces(0x7);
463         mb();
464 }
465
466 /*
467  * Subpacket Annotations
468  */
469 static char *el_titan_pchip0_extended_annotation[] = {
470         "Subpacket Header",     "P0_SCTL",      "P0_SERREN",
471         "P0_APCTL",             "P0_APERREN",   "P0_AGPERREN",
472         "P0_ASPRST",            "P0_AWSBA0",    "P0_AWSBA1",
473         "P0_AWSBA2",            "P0_AWSBA3",    "P0_AWSM0",
474         "P0_AWSM1",             "P0_AWSM2",     "P0_AWSM3",
475         "P0_ATBA0",             "P0_ATBA1",     "P0_ATBA2",
476         "P0_ATBA3",             "P0_GPCTL",     "P0_GPERREN",
477         "P0_GSPRST",            "P0_GWSBA0",    "P0_GWSBA1",
478         "P0_GWSBA2",            "P0_GWSBA3",    "P0_GWSM0",
479         "P0_GWSM1",             "P0_GWSM2",     "P0_GWSM3",
480         "P0_GTBA0",             "P0_GTBA1",     "P0_GTBA2",
481         "P0_GTBA3",             NULL 
482 };
483 static char *el_titan_pchip1_extended_annotation[] = {
484         "Subpacket Header",     "P1_SCTL",      "P1_SERREN",
485         "P1_APCTL",             "P1_APERREN",   "P1_AGPERREN",
486         "P1_ASPRST",            "P1_AWSBA0",    "P1_AWSBA1",
487         "P1_AWSBA2",            "P1_AWSBA3",    "P1_AWSM0",
488         "P1_AWSM1",             "P1_AWSM2",     "P1_AWSM3",
489         "P1_ATBA0",             "P1_ATBA1",     "P1_ATBA2",
490         "P1_ATBA3",             "P1_GPCTL",     "P1_GPERREN",
491         "P1_GSPRST",            "P1_GWSBA0",    "P1_GWSBA1",
492         "P1_GWSBA2",            "P1_GWSBA3",    "P1_GWSM0",
493         "P1_GWSM1",             "P1_GWSM2",     "P1_GWSM3",
494         "P1_GTBA0",             "P1_GTBA1",     "P1_GTBA2",
495         "P1_GTBA3",             NULL 
496 };
497 static char *el_titan_memory_extended_annotation[] = {
498         "Subpacket Header",     "AAR0",         "AAR1",
499         "AAR2",                 "AAR3",         "P0_SCTL",
500         "P0_GPCTL",             "P0_APCTL",     "P1_SCTL",
501         "P1_GPCTL",             "P1_SCTL",      NULL 
502 };
503
504 static struct el_subpacket_annotation el_titan_annotations[] = {
505         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
506                              EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
507                              1,
508                              "Titan PChip 0 Extended Frame",
509                              el_titan_pchip0_extended_annotation),
510         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
511                              EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
512                              1,
513                              "Titan PChip 1 Extended Frame",
514                              el_titan_pchip1_extended_annotation),
515         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
516                              EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
517                              1,
518                              "Titan Memory Extended Frame",
519                              el_titan_memory_extended_annotation),
520         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
521                              EL_TYPE__TERMINATION__TERMINATION,
522                              1,
523                              "Termination Subpacket",
524                              NULL)
525 };
526
527 static struct el_subpacket *
528 el_process_regatta_subpacket(struct el_subpacket *header)
529 {
530         int status;
531
532         if (header->class != EL_CLASS__REGATTA_FAMILY) {
533                 printk("%s  ** Unexpected header CLASS %d TYPE %d, aborting\n",
534                        err_print_prefix,
535                        header->class, header->type);
536                 return NULL;
537         }
538
539         switch(header->type) {
540         case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
541         case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
542         case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
543         case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
544         case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
545                 printk("%s  ** Occurred on CPU %d:\n", 
546                        err_print_prefix,
547                        (int)header->by_type.regatta_frame.cpuid);
548                 status = privateer_process_logout_frame((struct el_common *)
549                         header->by_type.regatta_frame.data_start, 1);
550                 break;
551         default:
552                 printk("%s  ** REGATTA TYPE %d SUBPACKET\n", 
553                        err_print_prefix, header->type);
554                 el_annotate_subpacket(header);
555                 break;
556         }
557
558
559         return (struct el_subpacket *)((unsigned long)header + header->length);
560
561
562 static struct el_subpacket_handler titan_subpacket_handler = 
563         SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY, 
564                                el_process_regatta_subpacket);
565
566 void
567 titan_register_error_handlers(void)
568 {
569         size_t i;
570
571         for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
572                 cdl_register_subpacket_annotation(&el_titan_annotations[i]);
573
574         cdl_register_subpacket_handler(&titan_subpacket_handler);
575
576         ev6_register_error_handlers();
577 }
578
579 \f
580 /*
581  * Privateer
582  */
583
584 static int
585 privateer_process_680_frame(struct el_common *mchk_header, int print)
586 {
587         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
588 #ifdef CONFIG_VERBOSE_MCHECK
589         struct el_PRIVATEER_envdata_mcheck *emchk =
590                 (struct el_PRIVATEER_envdata_mcheck *)
591                 ((unsigned long)mchk_header + mchk_header->sys_offset);
592
593         /* TODO - catagorize errors, for now, no error */
594
595         if (!print)
596                 return status;
597
598         /* TODO - decode instead of just dumping... */
599         printk("%s  Summary Flags:         %016lx\n"
600                  "  CChip DIRx:            %016lx\n"
601                  "  System Management IR:  %016lx\n"
602                  "  CPU IR:                %016lx\n"
603                  "  Power Supply IR:       %016lx\n"
604                  "  LM78 Fault Status:     %016lx\n"
605                  "  System Doors:          %016lx\n"
606                  "  Temperature Warning:   %016lx\n"
607                  "  Fan Control:           %016lx\n"
608                  "  Fatal Power Down Code: %016lx\n",
609                err_print_prefix,
610                emchk->summary,
611                emchk->c_dirx,
612                emchk->smir,
613                emchk->cpuir,
614                emchk->psir,
615                emchk->fault,
616                emchk->sys_doors,
617                emchk->temp_warn,
618                emchk->fan_ctrl,
619                emchk->code);
620 #endif /* CONFIG_VERBOSE_MCHECK */
621
622         return status;
623 }
624
625 int
626 privateer_process_logout_frame(struct el_common *mchk_header, int print)
627 {
628         struct el_common_EV6_mcheck *ev6mchk = 
629                 (struct el_common_EV6_mcheck *)mchk_header;
630         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
631
632         /*
633          * Machine check codes
634          */
635 #define PRIVATEER_MCHK__CORR_ECC                0x86    /* 630 */
636 #define PRIVATEER_MCHK__DC_TAG_PERR             0x9E    /* 630 */
637 #define PRIVATEER_MCHK__PAL_BUGCHECK            0x8E    /* 670 */
638 #define PRIVATEER_MCHK__OS_BUGCHECK             0x90    /* 670 */
639 #define PRIVATEER_MCHK__PROC_HRD_ERR            0x98    /* 670 */
640 #define PRIVATEER_MCHK__ISTREAM_CMOV_PRX        0xA0    /* 670 */
641 #define PRIVATEER_MCHK__ISTREAM_CMOV_FLT        0xA2    /* 670 */
642 #define PRIVATEER_MCHK__SYS_HRD_ERR             0x202   /* 660 */
643 #define PRIVATEER_MCHK__SYS_CORR_ERR            0x204   /* 620 */
644 #define PRIVATEER_MCHK__SYS_ENVIRON             0x206   /* 680 */
645
646         switch(ev6mchk->MCHK_Code) {
647         /*
648          * Vector 630 - Processor, Correctable
649          */
650         case PRIVATEER_MCHK__CORR_ECC:
651         case PRIVATEER_MCHK__DC_TAG_PERR:
652                 /*
653                  * Fall through to vector 670 for processing...
654                  */
655         /*
656          * Vector 670 - Processor, Uncorrectable
657          */
658         case PRIVATEER_MCHK__PAL_BUGCHECK:
659         case PRIVATEER_MCHK__OS_BUGCHECK:
660         case PRIVATEER_MCHK__PROC_HRD_ERR:
661         case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
662         case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
663                 status |= ev6_process_logout_frame(mchk_header, print);
664                 break;
665
666         /*
667          * Vector 620 - System, Correctable
668          */
669         case PRIVATEER_MCHK__SYS_CORR_ERR:
670                 /*
671                  * Fall through to vector 660 for processing...
672                  */
673         /*
674          * Vector 660 - System, Uncorrectable
675          */
676         case PRIVATEER_MCHK__SYS_HRD_ERR:
677                 status |= titan_process_logout_frame(mchk_header, print);
678                 break;
679
680         /* 
681          * Vector 680 - System, Environmental
682          */
683         case PRIVATEER_MCHK__SYS_ENVIRON:       /* System, Environmental */
684                 status |= privateer_process_680_frame(mchk_header, print);
685                 break;
686
687         /* 
688          * Unknown
689          */
690         default:
691                 status |= MCHK_DISPOSITION_REPORT;
692                 if (print) {
693                         printk("%s** Unknown Error, frame follows\n", 
694                                err_print_prefix);
695                         mchk_dump_logout_frame(mchk_header);
696                 }
697
698         }
699
700         return status;
701 }
702
703 void
704 privateer_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
705 {
706         struct el_common *mchk_header = (struct el_common *)la_ptr;
707         struct el_TITAN_sysdata_mcheck *tmchk =
708                 (struct el_TITAN_sysdata_mcheck *)
709                 (la_ptr + mchk_header->sys_offset);
710         u64 irqmask;
711         char *saved_err_prefix = err_print_prefix;
712
713 #define PRIVATEER_680_INTERRUPT_MASK            (0xE00UL)
714 #define PRIVATEER_HOTPLUG_INTERRUPT_MASK        (0xE00UL)
715
716         /*
717          * Sync the processor.
718          */
719         mb();
720         draina();
721
722         /* 
723          * Only handle system events here.
724          */
725         if (vector != SCB_Q_SYSEVENT) 
726                 return titan_machine_check(vector, la_ptr, regs);
727
728         /*
729          * Report the event - System Events should be reported even if no
730          * error is indicated since the event could indicate the return
731          * to normal status.
732          */
733         err_print_prefix = KERN_CRIT;
734         printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n", 
735                err_print_prefix,
736                (unsigned int)vector, (int)smp_processor_id());
737         privateer_process_680_frame(mchk_header, 1);
738         err_print_prefix = saved_err_prefix;
739         
740         /* 
741          * Convert any pending interrupts which report as 680 machine
742          * checks to interrupts.
743          */
744         irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
745
746         /*
747          * Dispatch the interrupt(s).
748          */
749         titan_dispatch_irqs(irqmask, regs);
750
751         /* 
752          * Release the logout frame.
753          */
754         wrmces(0x7);
755         mb();
756 }