OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [alpha/] [kernel/] [apecs.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * Code common to all APECS chips.
3
 *
4
 * Rewritten for Apecs from the lca.c from:
5
 *
6
 * Written by David Mosberger (davidm@cs.arizona.edu) with some code
7
 * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
8
 * bios code.
9
 */
10
#include <linux/kernel.h>
11
#include <linux/config.h>
12
#include <linux/types.h>
13
#include <linux/bios32.h>
14
#include <linux/pci.h>
15
 
16
#include <asm/system.h>
17
#include <asm/io.h>
18
#include <asm/hwrpb.h>
19
#include <asm/ptrace.h>
20
 
21
extern struct hwrpb_struct *hwrpb;
22
extern asmlinkage void wrmces(unsigned long mces);
23
 
24
/*
25
 * BIOS32-style PCI interface:
26
 */
27
 
28
#ifdef CONFIG_ALPHA_APECS
29
 
30
#ifdef DEBUG
31
# define DBG(args)      printk args
32
#else
33
# define DBG(args)
34
#endif
35
 
36
#define vuip    volatile unsigned int  *
37
 
38
static volatile unsigned int apecs_mcheck_expected = 0;
39
static volatile unsigned int apecs_mcheck_taken = 0;
40
static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
41
 
42
#ifdef CONFIG_ALPHA_SRM_SETUP
43
unsigned int APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
44
unsigned int APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
45
#endif /* SRM_SETUP */
46
 
47
/*
48
 * Given a bus, device, and function number, compute resulting
49
 * configuration space address and setup the APECS_HAXR2 register
50
 * accordingly.  It is therefore not safe to have concurrent
51
 * invocations to configuration space access routines, but there
52
 * really shouldn't be any need for this.
53
 *
54
 * Type 0:
55
 *
56
 *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
57
 *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
58
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59
 * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
60
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61
 *
62
 *      31:11   Device select bit.
63
 *      10:8    Function number
64
 *       7:2    Register number
65
 *
66
 * Type 1:
67
 *
68
 *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
69
 *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
70
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71
 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
72
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73
 *
74
 *      31:24   reserved
75
 *      23:16   bus number (8 bits = 128 possible buses)
76
 *      15:11   Device number (5 bits)
77
 *      10:8    function number
78
 *       7:2    register number
79
 *
80
 * Notes:
81
 *      The function number selects which function of a multi-function device
82
 *      (e.g., scsi and ethernet).
83
 *
84
 *      The register selects a DWORD (32 bit) register offset.  Hence it
85
 *      doesn't get shifted by 2 bits as we want to "drop" the bottom two
86
 *      bits.
87
 */
88
static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
89
                        unsigned char where, unsigned long *pci_addr,
90
                        unsigned char *type1)
91
{
92
        unsigned long addr;
93
 
94
        DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p, type1=0x%p)\n",
95
             bus, device_fn, where, pci_addr, type1));
96
 
97
        if (bus == 0) {
98
                int device = device_fn >> 3;
99
 
100
                /* type 0 configuration cycle: */
101
 
102
                if (device > 20) {
103
                        DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", device));
104
                        return -1;
105
                }
106
 
107
                *type1 = 0;
108
                addr = (device_fn << 8) | (where);
109
        } else {
110
                /* type 1 configuration cycle: */
111
                *type1 = 1;
112
                addr = (bus << 16) | (device_fn << 8) | (where);
113
        }
114
        *pci_addr = addr;
115
        DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
116
        return 0;
117
}
118
 
119
 
120
static unsigned int conf_read(unsigned long addr, unsigned char type1)
121
{
122
        unsigned long flags;
123
        unsigned int stat0, value;
124
        unsigned int haxr2 = 0; /* to keep gcc quiet */
125
 
126
#ifdef CONFIG_ALPHA_SRM
127
        /* some SRMs step on these registers during a machine check: */
128
        register long s0 asm ("9");
129
        register long s1 asm ("10");
130
        register long s2 asm ("11");
131
        register long s3 asm ("12");
132
        register long s4 asm ("13");
133
        register long s5 asm ("14");
134
        asm volatile ("# %0" : "r="(s0));
135
        asm volatile ("# %0" : "r="(s1));
136
        asm volatile ("# %0" : "r="(s2));
137
        asm volatile ("# %0" : "r="(s3));
138
        asm volatile ("# %0" : "r="(s4));
139
        asm volatile ("# %0" : "r="(s5));
140
#endif
141
 
142
        save_flags(flags);      /* avoid getting hit by machine check */
143
        cli();
144
 
145
        DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
146
 
147
        /* reset status register to avoid losing errors: */
148
        stat0 = *((vuip)APECS_IOC_DCSR);
149
        *((vuip)APECS_IOC_DCSR) = stat0;
150
        mb();
151
        DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
152
        /* if Type1 access, must set HAE #2 */
153
        if (type1) {
154
                haxr2 = *((vuip)APECS_IOC_HAXR2);
155
                mb();
156
                *((vuip)APECS_IOC_HAXR2) = haxr2 | 1;
157
                DBG(("conf_read: TYPE1 access\n"));
158
        }
159
 
160
        draina();
161
        apecs_mcheck_expected = 1;
162
        apecs_mcheck_taken = 0;
163
        mb();
164
        /* access configuration space: */
165
        value = *((vuip)addr);
166
        mb();
167
        mb();
168
        if (apecs_mcheck_taken) {
169
                apecs_mcheck_taken = 0;
170
                value = 0xffffffffU;
171
                mb();
172
        }
173
        apecs_mcheck_expected = 0;
174
        mb();
175
        /*
176
         * david.rusling@reo.mts.dec.com.  This code is needed for the
177
         * EB64+ as it does not generate a machine check (why I don't
178
         * know).  When we build kernels for one particular platform
179
         * then we can make this conditional on the type.
180
         */
181
#if 1
182
        draina();
183
 
184
        /* now look for any errors */
185
        stat0 = *((vuip)APECS_IOC_DCSR);
186
        DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
187
        if (stat0 & 0xffe0U) { /* is any error bit set? */
188
                /* if not NDEV, print status */
189
                if (!(stat0 & 0x0800)) {
190
                        printk("apecs.c:conf_read: got stat0=%x\n", stat0);
191
                }
192
 
193
                /* reset error status: */
194
                *((vuip)APECS_IOC_DCSR) = stat0;
195
                mb();
196
                wrmces(0x7);                    /* reset machine check */
197
                value = 0xffffffff;
198
        }
199
#endif
200
 
201
        /* if Type1 access, must reset HAE #2 so normal IO space ops work */
202
        if (type1) {
203
                *((vuip)APECS_IOC_HAXR2) = haxr2 & ~1;
204
                mb();
205
        }
206
        restore_flags(flags);
207
#ifdef CONFIG_ALPHA_SRM
208
        /* some SRMs step on these registers during a machine check: */
209
        asm volatile ("# %0" :: "r"(s0));
210
        asm volatile ("# %0" :: "r"(s1));
211
        asm volatile ("# %0" :: "r"(s2));
212
        asm volatile ("# %0" :: "r"(s3));
213
        asm volatile ("# %0" :: "r"(s4));
214
        asm volatile ("# %0" :: "r"(s5));
215
#endif
216
        return value;
217
}
218
 
219
 
220
static void conf_write(unsigned long addr, unsigned int value, unsigned char type1)
221
{
222
        unsigned long flags;
223
        unsigned int stat0;
224
        unsigned int haxr2 = 0; /* to keep gcc quiet */
225
 
226
        save_flags(flags);      /* avoid getting hit by machine check */
227
        cli();
228
 
229
        /* reset status register to avoid losing errors: */
230
        stat0 = *((vuip)APECS_IOC_DCSR);
231
        *((vuip)APECS_IOC_DCSR) = stat0;
232
        mb();
233
 
234
        /* if Type1 access, must set HAE #2 */
235
        if (type1) {
236
                haxr2 = *((vuip)APECS_IOC_HAXR2);
237
                mb();
238
                *((vuip)APECS_IOC_HAXR2) = haxr2 | 1;
239
        }
240
 
241
        draina();
242
        apecs_mcheck_expected = 1;
243
        mb();
244
        /* access configuration space: */
245
        *((vuip)addr) = value;
246
        mb();
247
        mb();
248
        apecs_mcheck_expected = 0;
249
        mb();
250
        /*
251
         * david.rusling@reo.mts.dec.com.  This code is needed for the
252
         * EB64+ as it does not generate a machine check (why I don't
253
         * know).  When we build kernels for one particular platform
254
         * then we can make this conditional on the type.
255
         */
256
#if 1
257
        draina();
258
 
259
        /* now look for any errors */
260
        stat0 = *((vuip)APECS_IOC_DCSR);
261
        if (stat0 & 0xffe0U) { /* is any error bit set? */
262
                /* if not NDEV, print status */
263
                if (!(stat0 & 0x0800)) {
264
                        printk("apecs.c:conf_write: got stat0=%x\n", stat0);
265
                }
266
 
267
                /* reset error status: */
268
                *((vuip)APECS_IOC_DCSR) = stat0;
269
                mb();
270
                wrmces(0x7);                    /* reset machine check */
271
        }
272
#endif
273
 
274
        /* if Type1 access, must reset HAE #2 so normal IO space ops work */
275
        if (type1) {
276
                *((vuip)APECS_IOC_HAXR2) = haxr2 & ~1;
277
                mb();
278
        }
279
        restore_flags(flags);
280
}
281
 
282
 
283
int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
284
                              unsigned char where, unsigned char *value)
285
{
286
        unsigned long addr = APECS_CONF;
287
        unsigned long pci_addr;
288
        unsigned char type1;
289
 
290
        *value = 0xff;
291
 
292
        if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
293
                return PCIBIOS_SUCCESSFUL;
294
        }
295
 
296
        addr |= (pci_addr << 5) + 0x00;
297
 
298
        *value = conf_read(addr, type1) >> ((where & 3) * 8);
299
 
300
        return PCIBIOS_SUCCESSFUL;
301
}
302
 
303
 
304
int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
305
                              unsigned char where, unsigned short *value)
306
{
307
        unsigned long addr = APECS_CONF;
308
        unsigned long pci_addr;
309
        unsigned char type1;
310
 
311
        *value = 0xffff;
312
 
313
        if (where & 0x1) {
314
                return PCIBIOS_BAD_REGISTER_NUMBER;
315
        }
316
 
317
        if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
318
                return PCIBIOS_SUCCESSFUL;
319
        }
320
 
321
        addr |= (pci_addr << 5) + 0x08;
322
 
323
        *value = conf_read(addr, type1) >> ((where & 3) * 8);
324
        return PCIBIOS_SUCCESSFUL;
325
}
326
 
327
 
328
int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
329
                               unsigned char where, unsigned int *value)
330
{
331
        unsigned long addr = APECS_CONF;
332
        unsigned long pci_addr;
333
        unsigned char type1;
334
 
335
        *value = 0xffffffff;
336
        if (where & 0x3) {
337
                return PCIBIOS_BAD_REGISTER_NUMBER;
338
        }
339
 
340
        if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
341
                return PCIBIOS_SUCCESSFUL;
342
        }
343
        addr |= (pci_addr << 5) + 0x18;
344
        *value = conf_read(addr, type1);
345
        return PCIBIOS_SUCCESSFUL;
346
}
347
 
348
 
349
int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
350
                               unsigned char where, unsigned char value)
351
{
352
        unsigned long addr = APECS_CONF;
353
        unsigned long pci_addr;
354
        unsigned char type1;
355
 
356
        if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
357
                return PCIBIOS_SUCCESSFUL;
358
        }
359
        addr |= (pci_addr << 5) + 0x00;
360
        conf_write(addr, value << ((where & 3) * 8), type1);
361
        return PCIBIOS_SUCCESSFUL;
362
}
363
 
364
 
365
int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
366
                               unsigned char where, unsigned short value)
367
{
368
        unsigned long addr = APECS_CONF;
369
        unsigned long pci_addr;
370
        unsigned char type1;
371
 
372
        if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
373
                return PCIBIOS_SUCCESSFUL;
374
        }
375
        addr |= (pci_addr << 5) + 0x08;
376
        conf_write(addr, value << ((where & 3) * 8), type1);
377
        return PCIBIOS_SUCCESSFUL;
378
}
379
 
380
 
381
int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
382
                                unsigned char where, unsigned int value)
383
{
384
        unsigned long addr = APECS_CONF;
385
        unsigned long pci_addr;
386
        unsigned char type1;
387
 
388
        if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
389
                return PCIBIOS_SUCCESSFUL;
390
        }
391
        addr |= (pci_addr << 5) + 0x18;
392
        conf_write(addr, value << ((where & 3) * 8), type1);
393
        return PCIBIOS_SUCCESSFUL;
394
}
395
 
396
 
397
unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end)
398
{
399
 
400
#ifdef CONFIG_ALPHA_XL
401
        /*
402
         * Set up the PCI->physical memory translation windows.
403
         * For the XL we *must* use both windows, in order to
404
         * maximize the amount of physical memory that can be used
405
         * to DMA from the ISA bus, and still allow PCI bus devices
406
         * access to all of host memory.
407
         *
408
         * see <asm/apecs.h> for window bases and sizes.
409
         *
410
         * this restriction due to the true XL motherboards' 82379AB SIO
411
         * PCI<->ISA bridge chip which passes only 27 bits of address...
412
         */
413
 
414
        *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
415
        *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
416
        *(vuip)APECS_IOC_TB1R = 0;
417
 
418
        *(vuip)APECS_IOC_PB2R = 1U<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
419
        *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
420
        *(vuip)APECS_IOC_TB2R = 0;
421
 
422
#else  /* CONFIG_ALPHA_XL */
423
#ifdef CONFIG_ALPHA_SRM_SETUP
424
        /* check window 1 for enabled and mapped to 0 */
425
        if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) && (*(vuip)APECS_IOC_TB1R == 0))
426
        {
427
          APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
428
          APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
429
          APECS_DMA_WIN_SIZE += 0x00100000U;
430
#if 0
431
          printk("apecs_init: using Window 1 settings\n");
432
          printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
433
                 *(vuip)APECS_IOC_PB1R,
434
                 *(vuip)APECS_IOC_PM1R,
435
                 *(vuip)APECS_IOC_TB1R);
436
#endif
437
        }
438
        else    /* check window 2 for enabled and mapped to 0 */
439
        if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) && (*(vuip)APECS_IOC_TB2R == 0))
440
        {
441
          APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
442
          APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
443
          APECS_DMA_WIN_SIZE += 0x00100000U;
444
#if 0
445
          printk("apecs_init: using Window 2 settings\n");
446
          printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
447
                 *(vuip)APECS_IOC_PB2R,
448
                 *(vuip)APECS_IOC_PM2R,
449
                 *(vuip)APECS_IOC_TB2R);
450
#endif
451
        }
452
        else /* we must use our defaults... */
453
#endif /* SRM_SETUP */
454
        {
455
        /*
456
         * Set up the PCI->physical memory translation windows.
457
         * For now, window 2 is disabled.  In the future, we may
458
         * want to use it to do scatter/gather DMA.  Window 1
459
         * goes at 1 GB and is 1 GB large.
460
         */
461
        *(vuip)APECS_IOC_PB2R  = 0U; /* disable window 2 */
462
 
463
        *(vuip)APECS_IOC_PB1R  = 1U<<19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
464
        *(vuip)APECS_IOC_PM1R  = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
465
        *(vuip)APECS_IOC_TB1R  = 0;
466
        }
467
#endif /* CONFIG_ALPHA_XL */
468
 
469
#ifdef CONFIG_ALPHA_CABRIOLET
470
#if 0
471
        /*
472
         * JAE: HACK!!! for now, hardwire if configured...
473
         * davidm: Older miniloader versions don't set the clockfrequency
474
         * right, so hardcode it for now.
475
         */
476
        if (hwrpb->sys_type == ST_DEC_EB64P) {
477
                hwrpb->sys_type = ST_DEC_EBPC64;
478
        }
479
        if (hwrpb->cycle_freq == 0) {
480
            hwrpb->cycle_freq = 275000000;
481
        }
482
 
483
        /* update checksum: */
484
        {
485
            unsigned long *l, sum;
486
 
487
            sum = 0;
488
            for (l = (unsigned long *) hwrpb;
489
                 l < (unsigned long *) &hwrpb->chksum;
490
                 ++l)
491
              sum += *l;
492
            hwrpb->chksum = sum;
493
        }
494
#endif
495
#endif /* CONFIG_ALPHA_CABRIOLET */
496
 
497
       /*
498
        * Finally, clear the HAXR2 register, which gets used
499
        *  for PCI Config Space accesses. That is the way
500
        *  we want to use it, and we do not want to depend on
501
        *  what ARC or SRM might have left behind...
502
        */
503
       {
504
#if 0
505
         unsigned int haxr2 = *((vuip)APECS_IOC_HAXR2); mb();
506
         if (haxr2) printk("apecs_init: HAXR2 was 0x%x\n", haxr2);
507
#endif
508
         *((vuip)APECS_IOC_HAXR2) = 0; mb();
509
       }
510
 
511
 
512
        return mem_start;
513
}
514
 
515
int apecs_pci_clr_err(void)
516
{
517
        apecs_jd = *((vuip)APECS_IOC_DCSR);
518
        if (apecs_jd & 0xffe0L) {
519
                apecs_jd1 = *((vuip)APECS_IOC_SEAR);
520
                *((vuip)APECS_IOC_DCSR) = apecs_jd | 0xffe1L;
521
                apecs_jd = *((vuip)APECS_IOC_DCSR);
522
                mb();
523
        }
524
        *((vuip)APECS_IOC_TBIA) = APECS_IOC_TBIA;
525
        apecs_jd2 = *((vuip)APECS_IOC_TBIA);
526
        mb();
527
        return 0;
528
}
529
 
530
void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
531
                         struct pt_regs * regs)
532
{
533
        struct el_common *mchk_header;
534
        struct el_procdata *mchk_procdata;
535
        struct el_apecs_sysdata_mcheck *mchk_sysdata;
536
        unsigned long *ptr;
537
        int i;
538
 
539
 
540
        mchk_header = (struct el_common *)la_ptr;
541
        mchk_procdata = (struct el_procdata *)
542
          (la_ptr + mchk_header->proc_offset - sizeof(mchk_procdata->paltemp));
543
        mchk_sysdata =
544
          (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
545
 
546
#ifdef DEBUG
547
        printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
548
               vector, la_ptr);
549
        printk("        pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
550
               regs->pc, mchk_header->size, mchk_header->proc_offset,
551
               mchk_header->sys_offset);
552
        printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
553
               apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
554
               mchk_sysdata->epic_pear);
555
        ptr = (unsigned long *)la_ptr;
556
        for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
557
                printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
558
        }
559
#endif /* DEBUG */
560
 
561
        /*
562
         * Check if machine check is due to a badaddr() and if so,
563
         * ignore the machine check.
564
         */
565
#ifdef CONFIG_ALPHA_MIKASA
566
#define MCHK_NO_DEVSEL 0x205L
567
#define MCHK_NO_TABT 0x204L
568
        if (apecs_mcheck_expected &&
569
            (((unsigned int)mchk_header->code == MCHK_NO_DEVSEL) ||
570
             ((unsigned int)mchk_header->code == MCHK_NO_TABT))
571
            )
572
        {
573
#else
574
        if (apecs_mcheck_expected && (mchk_sysdata->epic_dcsr && 0x0c00UL)) {
575
#endif
576
                apecs_mcheck_expected = 0;
577
                apecs_mcheck_taken = 1;
578
                mb();
579
                mb();
580
                apecs_pci_clr_err();
581
                wrmces(0x7);
582
                mb();
583
                draina();
584
                DBG(("apecs_machine_check: EXPECTED\n"));
585
        }
586
        else if (vector == 0x620 || vector == 0x630) {
587
                wrmces(0x1f); /* disable correctable from now on */
588
                mb();
589
                draina();
590
                printk("apecs_machine_check: HW correctable (0x%lx)\n", vector);
591
        }
592
        else {
593
                printk(KERN_CRIT "APECS machine check:\n");
594
                printk(KERN_CRIT "  vector=0x%lx la_ptr=0x%lx\n",
595
                       vector, la_ptr);
596
                printk(KERN_CRIT
597
                       "  pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
598
                       regs->pc, mchk_header->size, mchk_header->proc_offset,
599
                       mchk_header->sys_offset);
600
                printk(KERN_CRIT "  expected %d DCSR 0x%lx PEAR 0x%lx\n",
601
                       apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
602
                       mchk_sysdata->epic_pear);
603
 
604
                ptr = (unsigned long *)la_ptr;
605
                for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
606
                    printk(KERN_CRIT " +%lx %lx %lx\n",
607
                           i*sizeof(long), ptr[i], ptr[i+1]);
608
                }
609
#if 0
610
                /* doesn't work with MILO */
611
                show_regs(regs);
612
#endif
613
        }
614
}
615
#endif /* CONFIG_ALPHA_APECS */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.