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  * Given a bus, device, and function number, compute resulting
  28  * configuration space address and setup the LCA_IOC_CONF register
  29  * accordingly.  It is therefore not safe to have concurrent
  30  * invocations to configuration space access routines, but there
  31  * really shouldn't be any need for this.
  32  *
  33  * Type 0:
  34  *
  35  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  36  *  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
  37  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  38  * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
  39  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  40  *
  41  *      31:11   Device select bit.
  42  *      10:8    Function number
  43  *       7:2    Register number
  44  *
  45  * Type 1:
  46  *
  47  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  48  *  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
  49  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  50  * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
  51  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  52  *
  53  *      31:24   reserved
  54  *      23:16   bus number (8 bits = 128 possible buses)
  55  *      15:11   Device number (5 bits)
  56  *      10:8    function number
  57  *       7:2    register number
  58  *  
  59  * Notes:
  60  *      The function number selects which function of a multi-function device 
  61  *      (e.g., scsi and ethernet).
  62  * 
  63  *      The register selects a DWORD (32 bit) register offset.  Hence it
  64  *      doesn't get shifted by 2 bits as we want to "drop" the bottom two
  65  *      bits.
  66  */
  67 static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
  68                         unsigned char where, unsigned long *pci_addr)
  69 {
  70         unsigned long addr;
  71 
  72         if (bus == 0) {
  73                 int device = device_fn >> 3;
  74                 int func = device_fn & 0x7;
  75 
  76                 /* type 0 configuration cycle: */
  77 
  78                 if (device > 12) {
  79                         return -1;
  80                 }
  81 
  82                 *((volatile unsigned long*) LCA_IOC_CONF) = 0;
  83                 addr = (1 << (11 + device)) | (func << 8) | where;
  84         } else {
  85                 /* type 1 configuration cycle: */
  86                 *((volatile unsigned long*) LCA_IOC_CONF) = 1;
  87                 addr = (bus << 16) | (device_fn << 8) | where;
  88         }
  89         *pci_addr = addr;
  90         return 0;
  91 }
  92 
  93 
  94 static unsigned int conf_read(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96         unsigned long flags, code, stat0;
  97         unsigned int value;
  98 
  99         save_flags(flags);
 100         cli();
 101 
 102         /* reset status register to avoid loosing errors: */
 103         stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
 104         *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 105         mb();
 106 
 107         /* access configuration space: */
 108 
 109         value = *((volatile unsigned int*)addr);
 110         draina();
 111 
 112         stat0 = *((unsigned long*)LCA_IOC_STAT0);
 113         if (stat0 & LCA_IOC_STAT0_ERR) {
 114                 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
 115                         & LCA_IOC_STAT0_CODE_MASK);
 116                 if (code != 1) {
 117                         printk("lca.c:conf_read: got stat0=%lx\n", stat0);
 118                 }
 119 
 120                 /* reset error status: */
 121                 *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 122                 mb();
 123                 wrmces(0x7);                    /* reset machine check */
 124 
 125                 value = 0xffffffff;
 126         }
 127         restore_flags(flags);
 128         return value;
 129 }
 130 
 131 
 132 static void conf_write(unsigned long addr, unsigned int value)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134         unsigned long flags, code, stat0;
 135 
 136         save_flags(flags);      /* avoid getting hit by machine check */
 137         cli();
 138 
 139         /* reset status register to avoid loosing errors: */
 140         stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
 141         *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 142         mb();
 143 
 144         /* access configuration space: */
 145 
 146         *((volatile unsigned int*)addr) = value;
 147         draina();
 148 
 149         stat0 = *((unsigned long*)LCA_IOC_STAT0);
 150         if (stat0 & LCA_IOC_STAT0_ERR) {
 151                 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
 152                         & LCA_IOC_STAT0_CODE_MASK);
 153                 if (code != 1) {
 154                         printk("lca.c:conf_write: got stat0=%lx\n", stat0);
 155                 }
 156 
 157                 /* reset error status: */
 158                 *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
 159                 mb();
 160                 wrmces(0x7);                    /* reset machine check */
 161         }
 162         restore_flags(flags);
 163 }
 164 
 165 
 166 int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 167                               unsigned char where, unsigned char *value)
 168 {
 169         unsigned long addr = LCA_CONF;
 170         unsigned long pci_addr;
 171 
 172         *value = 0xff;
 173 
 174         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 175                 return PCIBIOS_SUCCESSFUL;
 176         }
 177         addr |= (pci_addr << 5) + 0x00;
 178         *value = conf_read(addr) >> ((where & 3) * 8);
 179         return PCIBIOS_SUCCESSFUL;
 180 }
 181 
 182 
 183 int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 184                               unsigned char where, unsigned short *value)
 185 {
 186         unsigned long addr = LCA_CONF;
 187         unsigned long pci_addr;
 188 
 189         *value = 0xffff;
 190 
 191         if (where & 0x1) {
 192                 return PCIBIOS_BAD_REGISTER_NUMBER;
 193         }
 194         if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
 195                 return PCIBIOS_SUCCESSFUL;
 196         }
 197         addr |= (pci_addr << 5) + 0x08;
 198         *value = conf_read(addr) >> ((where & 3) * 8);
 199         return PCIBIOS_SUCCESSFUL;
 200 }
 201 
 202 
 203 int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 204                                unsigned char where, unsigned int *value)
 205 {
 206         unsigned long addr = LCA_CONF;
 207         unsigned long pci_addr;
 208 
 209         *value = 0xffffffff;
 210         if (where & 0x3) {
 211                 return PCIBIOS_BAD_REGISTER_NUMBER;
 212         }
 213         if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
 214                 return PCIBIOS_SUCCESSFUL;
 215         }
 216         addr |= (pci_addr << 5) + 0x18;
 217         *value = conf_read(addr);
 218         return PCIBIOS_SUCCESSFUL;
 219 }
 220 
 221 
 222 int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 223                                unsigned char where, unsigned char value)
 224 {
 225         unsigned long addr = LCA_CONF;
 226         unsigned long pci_addr;
 227 
 228         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 229                 return PCIBIOS_SUCCESSFUL;
 230         }
 231         addr |= (pci_addr << 5) + 0x00;
 232         conf_write(addr, value << ((where & 3) * 8));
 233         return PCIBIOS_SUCCESSFUL;
 234 }
 235 
 236 
 237 int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 238                                unsigned char where, unsigned short value)
 239 {
 240         unsigned long addr = LCA_CONF;
 241         unsigned long pci_addr;
 242 
 243         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 244                 return PCIBIOS_SUCCESSFUL;
 245         }
 246         addr |= (pci_addr << 5) + 0x08;
 247         conf_write(addr, value << ((where & 3) * 8));
 248         return PCIBIOS_SUCCESSFUL;
 249 }
 250 
 251 
 252 int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
     /* [previous][next][first][last][top][bottom][index][help] */
 253                                 unsigned char where, unsigned int value)
 254 {
 255         unsigned long addr = LCA_CONF;
 256         unsigned long pci_addr;
 257 
 258         if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 259                 return PCIBIOS_SUCCESSFUL;
 260         }
 261         addr |= (pci_addr << 5) + 0x18;
 262         conf_write(addr, value << ((where & 3) * 8));
 263         return PCIBIOS_SUCCESSFUL;
 264 }
 265 
 266 
 267 unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269         /*
 270          * Set up the PCI->physical memory translation windows.
 271          * For now, window 1 is disabled.  In the future, we may
 272          * want to use it to do scatter/gather DMA.  Window 0
 273          * goes at 1 GB and is 1 GB large.
 274          */
 275         *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
 276         *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE;
 277         *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
 278         *(vulp)LCA_IOC_T_BASE0 = 0;
 279         return mem_start;
 280 }
 281 
 282 
 283 void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 284 {
 285         unsigned long mces;
 286 
 287         mces = rdmces();
 288         wrmces(mces);           /* reset machine check asap */
 289         printk("Machine check (la=0x%lx,mces=0x%lx)\n", la, mces);
 290         printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n",
 291                *(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR,
 292                *(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1);
 293 }
 294 
 295 #endif /* CONFIG_ALPHA_LCA */

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