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

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

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