root/arch/alpha/kernel/lca.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mk_conf_addr
  2. conf_read
  3. conf_write
  4. pcibios_read_config_byte
  5. pcibios_read_config_word
  6. pcibios_read_config_dword
  7. pcibios_write_config_byte
  8. pcibios_write_config_word
  9. pcibios_write_config_dword
  10. lca_init
  11. lca_machine_check

   1 /*
   2  * Code common to all LCA chips.
   3  *
   4  * Written by David Mosberger (davidm@cs.arizona.edu) with some code
   5  * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
   6  * bios code.
   7  */
   8 #include <linux/kernel.h>
   9 #include <linux/config.h>
  10 #include <linux/types.h>
  11 #include <linux/bios32.h>
  12 #include <linux/pci.h>
  13 
  14 #include <asm/ptrace.h>
  15 #include <asm/system.h>
  16 #include <asm/io.h>
  17 
  18 /*
  19  * BIOS32-style PCI interface:
  20  */
  21 
  22 #ifdef CONFIG_ALPHA_LCA
  23 
  24 #define vulp    volatile unsigned long *
  25 
  26 /*
  27  * Machine check reasons.  Defined according to PALcode sources
  28  * (osf.h and platform.h).
  29  */
  30 #define MCHK_K_TPERR            0x0080
  31 #define MCHK_K_TCPERR           0x0082
  32 #define MCHK_K_HERR             0x0084
  33 #define MCHK_K_ECC_C            0x0086
  34 #define MCHK_K_ECC_NC           0x0088
  35 #define MCHK_K_UNKNOWN          0x008A
  36 #define MCHK_K_CACKSOFT         0x008C
  37 #define MCHK_K_BUGCHECK         0x008E
  38 #define MCHK_K_OS_BUGCHECK      0x0090
  39 #define MCHK_K_DCPERR           0x0092
  40 #define MCHK_K_ICPERR           0x0094
  41 
  42 /*
  43  * Platform-specific machine-check reasons:
  44  */
  45 #define MCHK_K_SIO_SERR         0x204   /* all platforms so far */
  46 #define MCHK_K_SIO_IOCHK        0x206   /* all platforms so far */
  47 #define MCHK_K_DCSR             0x208   /* all but Noname */
  48 
  49 /*
  50  * Given a bus, device, and function number, compute resulting
  51  * configuration space address and setup the LCA_IOC_CONF register
  52  * accordingly.  It is therefore not safe to have concurrent
  53  * invocations to configuration space access routines, but there
  54  * really shouldn't be any need for this.
  55  *
  56  * Type 0:
  57  *
  58  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  59  *  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
  60  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  61  * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
  62  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  63  *
  64  *      31:11   Device select bit.
  65  *      10:8    Function number
  66  *       7:2    Register number
  67  *
  68  * Type 1:
  69  *
  70  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  71  *  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
  72  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  73  * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
  74  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  75  *
  76  *      31:24   reserved
  77  *      23:16   bus number (8 bits = 128 possible buses)
  78  *      15:11   Device number (5 bits)
  79  *      10:8    function number
  80  *       7:2    register number
  81  *  
  82  * Notes:
  83  *      The function number selects which function of a multi-function device 
  84  *      (e.g., scsi and ethernet).
  85  * 
  86  *      The register selects a DWORD (32 bit) register offset.  Hence it
  87  *      doesn't get shifted by 2 bits as we want to "drop" the bottom two
  88  *      bits.
  89  */
  90 static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
  91                         unsigned char where, unsigned long *pci_addr)
  92 {
  93         unsigned long addr;
  94 
  95         if (bus == 0) {
  96                 int device = device_fn >> 3;
  97                 int func = device_fn & 0x7;
  98 
  99                 /* type 0 configuration cycle: */
 100 
 101                 if (device > 12) {
 102                         return -1;
 103                 }
 104 
 105                 *((volatile unsigned long*) LCA_IOC_CONF) = 0;
 106                 addr = (1 << (11 + device)) | (func << 8) | where;
 107         } else {
 108                 /* type 1 configuration cycle: */
 109                 *((volatile unsigned long*) LCA_IOC_CONF) = 1;
 110                 addr = (bus << 16) | (device_fn << 8) | where;
 111         }
 112         *pci_addr = addr;
 113         return 0;
 114 }
 115 
 116 
 117 static unsigned int conf_read(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         unsigned long flags, code, stat0;
 120         unsigned int value;
 121 
 122         save_flags(flags);
 123         cli();
 124 
 125         /* reset status register to avoid loosing errors: */
 126         stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
 127         *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 128         mb();
 129 
 130         /* access configuration space: */
 131 
 132         value = *((volatile unsigned int*)addr);
 133         draina();
 134 
 135         stat0 = *((unsigned long*)LCA_IOC_STAT0);
 136         if (stat0 & LCA_IOC_STAT0_ERR) {
 137                 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
 138                         & LCA_IOC_STAT0_CODE_MASK);
 139                 if (code != 1) {
 140                         printk("lca.c:conf_read: got stat0=%lx\n", stat0);
 141                 }
 142 
 143                 /* reset error status: */
 144                 *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 145                 mb();
 146                 wrmces(0x7);                    /* reset machine check */
 147 
 148                 value = 0xffffffff;
 149         }
 150         restore_flags(flags);
 151         return value;
 152 }
 153 
 154 
 155 static void conf_write(unsigned long addr, unsigned int value)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         unsigned long flags, code, stat0;
 158 
 159         save_flags(flags);      /* avoid getting hit by machine check */
 160         cli();
 161 
 162         /* reset status register to avoid loosing errors: */
 163         stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
 164         *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 165         mb();
 166 
 167         /* access configuration space: */
 168 
 169         *((volatile unsigned int*)addr) = value;
 170         draina();
 171 
 172         stat0 = *((unsigned long*)LCA_IOC_STAT0);
 173         if (stat0 & LCA_IOC_STAT0_ERR) {
 174                 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
 175                         & LCA_IOC_STAT0_CODE_MASK);
 176                 if (code != 1) {
 177                         printk("lca.c:conf_write: got stat0=%lx\n", stat0);
 178                 }
 179 
 180                 /* reset error status: */
 181                 *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 182                 mb();
 183                 wrmces(0x7);                    /* reset machine check */
 184         }
 185         restore_flags(flags);
 186 }
 187 
 188 
 189 int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 190                               unsigned char where, unsigned char *value)
 191 {
 192         unsigned long addr = LCA_CONF;
 193         unsigned long pci_addr;
 194 
 195         *value = 0xff;
 196 
 197         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 198                 return PCIBIOS_SUCCESSFUL;
 199         }
 200         addr |= (pci_addr << 5) + 0x00;
 201         *value = conf_read(addr) >> ((where & 3) * 8);
 202         return PCIBIOS_SUCCESSFUL;
 203 }
 204 
 205 
 206 int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 207                               unsigned char where, unsigned short *value)
 208 {
 209         unsigned long addr = LCA_CONF;
 210         unsigned long pci_addr;
 211 
 212         *value = 0xffff;
 213 
 214         if (where & 0x1) {
 215                 return PCIBIOS_BAD_REGISTER_NUMBER;
 216         }
 217         if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
 218                 return PCIBIOS_SUCCESSFUL;
 219         }
 220         addr |= (pci_addr << 5) + 0x08;
 221         *value = conf_read(addr) >> ((where & 3) * 8);
 222         return PCIBIOS_SUCCESSFUL;
 223 }
 224 
 225 
 226 int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 227                                unsigned char where, unsigned int *value)
 228 {
 229         unsigned long addr = LCA_CONF;
 230         unsigned long pci_addr;
 231 
 232         *value = 0xffffffff;
 233         if (where & 0x3) {
 234                 return PCIBIOS_BAD_REGISTER_NUMBER;
 235         }
 236         if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
 237                 return PCIBIOS_SUCCESSFUL;
 238         }
 239         addr |= (pci_addr << 5) + 0x18;
 240         *value = conf_read(addr);
 241         return PCIBIOS_SUCCESSFUL;
 242 }
 243 
 244 
 245 int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 246                                unsigned char where, unsigned char value)
 247 {
 248         unsigned long addr = LCA_CONF;
 249         unsigned long pci_addr;
 250 
 251         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 252                 return PCIBIOS_SUCCESSFUL;
 253         }
 254         addr |= (pci_addr << 5) + 0x00;
 255         conf_write(addr, value << ((where & 3) * 8));
 256         return PCIBIOS_SUCCESSFUL;
 257 }
 258 
 259 
 260 int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 261                                unsigned char where, unsigned short value)
 262 {
 263         unsigned long addr = LCA_CONF;
 264         unsigned long pci_addr;
 265 
 266         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 267                 return PCIBIOS_SUCCESSFUL;
 268         }
 269         addr |= (pci_addr << 5) + 0x08;
 270         conf_write(addr, value << ((where & 3) * 8));
 271         return PCIBIOS_SUCCESSFUL;
 272 }
 273 
 274 
 275 int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 276                                 unsigned char where, unsigned int value)
 277 {
 278         unsigned long addr = LCA_CONF;
 279         unsigned long pci_addr;
 280 
 281         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 282                 return PCIBIOS_SUCCESSFUL;
 283         }
 284         addr |= (pci_addr << 5) + 0x18;
 285         conf_write(addr, value << ((where & 3) * 8));
 286         return PCIBIOS_SUCCESSFUL;
 287 }
 288 
 289 
 290 unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 291 {
 292         /*
 293          * Set up the PCI->physical memory translation windows.
 294          * For now, window 1 is disabled.  In the future, we may
 295          * want to use it to do scatter/gather DMA.  Window 0
 296          * goes at 1 GB and is 1 GB large.
 297          */
 298         *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
 299         *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE;
 300         *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
 301         *(vulp)LCA_IOC_T_BASE0 = 0;
 302         return mem_start;
 303 }
 304 
 305 
 306 
 307 
 308 /*
 309  * Constants used during machine-check handling.  I suppose these
 310  * could be moved into lca.h but I don't see much reason why anybody
 311  * else would want to use them.
 312  */
 313 #define ESR_EAV (1UL<< 0)       /* error address valid */
 314 #define ESR_CEE (1UL<< 1)       /* correctable error */
 315 #define ESR_UEE (1UL<< 2)       /* uncorrectable error */
 316 #define ESR_NXM (1UL<<12)       /* non-existent memory */
 317 
 318 
 319 void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 320 {
 321         const char * reason;
 322         union el_lca el;
 323         char buf[128];
 324 
 325         printk("lca: machine check (la=0x%lx)\n", la);
 326         el.c = (struct el_common *) la;
 327         /*
 328          * The first quadword after the common header always seems to
 329          * be the machine check reason---don't know why this isn't
 330          * part of the common header instead.
 331          */
 332         switch (el.s->reason) {
 333               case MCHK_K_TPERR:        reason = "tag parity error"; break;
 334               case MCHK_K_TCPERR:       reason = "tag something parity error"; break;
 335               case MCHK_K_HERR:         reason = "access to non-existent memory"; break;
 336               case MCHK_K_ECC_C:        reason = "correctable ECC error"; break;
 337               case MCHK_K_ECC_NC:       reason = "non-correctable ECC error"; break;
 338               case MCHK_K_CACKSOFT:     reason = "MCHK_K_CACKSOFT"; break; /* what's this? */
 339               case MCHK_K_BUGCHECK:     reason = "illegal exception in PAL mode"; break;
 340               case MCHK_K_OS_BUGCHECK:  reason = "callsys in kernel mode"; break;
 341               case MCHK_K_DCPERR:       reason = "d-cache parity error"; break;
 342               case MCHK_K_ICPERR:       reason = "i-cache parity error"; break;
 343               case MCHK_K_SIO_SERR:     reason = "SIO SERR occurred on on PCI bus"; break;
 344               case MCHK_K_SIO_IOCHK:    reason = "SIO IOCHK occurred on ISA bus"; break;
 345               case MCHK_K_DCSR:         reason = "MCHK_K_DCSR"; break;
 346               case MCHK_K_UNKNOWN:
 347               default:
 348                 sprintf(buf, "reason for machine-check unknown (0x%lx)", el.s->reason);
 349                 reason = buf;
 350                 break;
 351         }
 352 
 353         wrmces(rdmces());       /* reset machine check pending flag */
 354 
 355         switch (el.c->size) {
 356               case sizeof(struct el_lca_mcheck_short):
 357                 printk("  Reason: %s (short frame%s):\n",
 358                        reason, el.c->retry ? ", retryable" : "");
 359                 printk("    esr: %lx  ear: %lx\n", el.s->esr, el.s->ear);
 360                 printk("    dc_stat: %lx  ioc_stat0: %lx  ioc_stat1: %lx\n",
 361                        el.s->dc_stat, el.s->ioc_stat0, el.s->ioc_stat1);
 362                 if (el.c->retry &&
 363                     (el.s->esr & (ESR_EAV|ESR_CEE|ESR_UEE|ESR_NXM)) == (ESR_EAV|ESR_CEE))
 364                 {
 365                         unsigned long addr, val;
 366 
 367                         /* temporarily disable processor/system correctable error logging: */
 368                         wrmces(0x18);
 369                         addr = el.s->ear & ~ (0x7<<29 | 0x7);
 370                         addr += IDENT_ADDR;
 371                         printk("  correcting quadword at address %lx\n", addr);
 372                         val = *(volatile long *)addr;
 373                         *(volatile long *)addr = val;
 374                         /* reenable all machine checks: */
 375                         wrmces(0x00);
 376                 }
 377                 break;
 378 
 379               case sizeof(struct el_lca_mcheck_long):
 380                 printk("  Reason: %s (long frame%s):\n",
 381                        reason, el.c->retry ? ", retryable" : "");
 382                 printk("    reason: %lx  exc_addr: %lx  dc_stat: %lx\n", 
 383                        el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
 384                 printk("    esr: %lx  ear: %lx  car: %lx\n", el.l->esr, el.l->ear, el.l->car);
 385                 printk("    ioc_stat0: %lx  ioc_stat1: %lx\n", el.l->ioc_stat0, el.l->ioc_stat1);
 386                 break;
 387 
 388               default:
 389                 printk("  Unknown errorlog size %d\n", el.c->size);
 390         }
 391 }
 392 
 393 #endif /* CONFIG_ALPHA_LCA */

/* [previous][next][first][last][top][bottom][index][help] */