linux/arch/x86/pci/direct.c
<<
>>
Prefs
   1/*
   2 * direct.c - Low-level direct PCI config space access
   3 */
   4
   5#include <linux/pci.h>
   6#include <linux/init.h>
   7#include <linux/dmi.h>
   8#include <asm/pci_x86.h>
   9
  10/*
  11 * Functions for accessing PCI base (first 256 bytes) and extended
  12 * (4096 bytes per PCI function) configuration space with type 1
  13 * accesses.
  14 */
  15
  16#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
  17        (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
  18        | (devfn << 8) | (reg & 0xFC))
  19
  20static int pci_conf1_read(unsigned int seg, unsigned int bus,
  21                          unsigned int devfn, int reg, int len, u32 *value)
  22{
  23        unsigned long flags;
  24
  25        if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) {
  26                *value = -1;
  27                return -EINVAL;
  28        }
  29
  30        raw_spin_lock_irqsave(&pci_config_lock, flags);
  31
  32        outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
  33
  34        switch (len) {
  35        case 1:
  36                *value = inb(0xCFC + (reg & 3));
  37                break;
  38        case 2:
  39                *value = inw(0xCFC + (reg & 2));
  40                break;
  41        case 4:
  42                *value = inl(0xCFC);
  43                break;
  44        }
  45
  46        raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  47
  48        return 0;
  49}
  50
  51static int pci_conf1_write(unsigned int seg, unsigned int bus,
  52                           unsigned int devfn, int reg, int len, u32 value)
  53{
  54        unsigned long flags;
  55
  56        if (seg || (bus > 255) || (devfn > 255) || (reg > 4095))
  57                return -EINVAL;
  58
  59        raw_spin_lock_irqsave(&pci_config_lock, flags);
  60
  61        outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
  62
  63        switch (len) {
  64        case 1:
  65                outb((u8)value, 0xCFC + (reg & 3));
  66                break;
  67        case 2:
  68                outw((u16)value, 0xCFC + (reg & 2));
  69                break;
  70        case 4:
  71                outl((u32)value, 0xCFC);
  72                break;
  73        }
  74
  75        raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  76
  77        return 0;
  78}
  79
  80#undef PCI_CONF1_ADDRESS
  81
  82const struct pci_raw_ops pci_direct_conf1 = {
  83        .read =         pci_conf1_read,
  84        .write =        pci_conf1_write,
  85};
  86
  87
  88/*
  89 * Functions for accessing PCI configuration space with type 2 accesses
  90 */
  91
  92#define PCI_CONF2_ADDRESS(dev, reg)     (u16)(0xC000 | (dev << 8) | reg)
  93
  94static int pci_conf2_read(unsigned int seg, unsigned int bus,
  95                          unsigned int devfn, int reg, int len, u32 *value)
  96{
  97        unsigned long flags;
  98        int dev, fn;
  99
 100        WARN_ON(seg);
 101        if ((bus > 255) || (devfn > 255) || (reg > 255)) {
 102                *value = -1;
 103                return -EINVAL;
 104        }
 105
 106        dev = PCI_SLOT(devfn);
 107        fn = PCI_FUNC(devfn);
 108
 109        if (dev & 0x10) 
 110                return PCIBIOS_DEVICE_NOT_FOUND;
 111
 112        raw_spin_lock_irqsave(&pci_config_lock, flags);
 113
 114        outb((u8)(0xF0 | (fn << 1)), 0xCF8);
 115        outb((u8)bus, 0xCFA);
 116
 117        switch (len) {
 118        case 1:
 119                *value = inb(PCI_CONF2_ADDRESS(dev, reg));
 120                break;
 121        case 2:
 122                *value = inw(PCI_CONF2_ADDRESS(dev, reg));
 123                break;
 124        case 4:
 125                *value = inl(PCI_CONF2_ADDRESS(dev, reg));
 126                break;
 127        }
 128
 129        outb(0, 0xCF8);
 130
 131        raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 132
 133        return 0;
 134}
 135
 136static int pci_conf2_write(unsigned int seg, unsigned int bus,
 137                           unsigned int devfn, int reg, int len, u32 value)
 138{
 139        unsigned long flags;
 140        int dev, fn;
 141
 142        WARN_ON(seg);
 143        if ((bus > 255) || (devfn > 255) || (reg > 255)) 
 144                return -EINVAL;
 145
 146        dev = PCI_SLOT(devfn);
 147        fn = PCI_FUNC(devfn);
 148
 149        if (dev & 0x10) 
 150                return PCIBIOS_DEVICE_NOT_FOUND;
 151
 152        raw_spin_lock_irqsave(&pci_config_lock, flags);
 153
 154        outb((u8)(0xF0 | (fn << 1)), 0xCF8);
 155        outb((u8)bus, 0xCFA);
 156
 157        switch (len) {
 158        case 1:
 159                outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
 160                break;
 161        case 2:
 162                outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
 163                break;
 164        case 4:
 165                outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
 166                break;
 167        }
 168
 169        outb(0, 0xCF8);    
 170
 171        raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 172
 173        return 0;
 174}
 175
 176#undef PCI_CONF2_ADDRESS
 177
 178static const struct pci_raw_ops pci_direct_conf2 = {
 179        .read =         pci_conf2_read,
 180        .write =        pci_conf2_write,
 181};
 182
 183
 184/*
 185 * Before we decide to use direct hardware access mechanisms, we try to do some
 186 * trivial checks to ensure it at least _seems_ to be working -- we just test
 187 * whether bus 00 contains a host bridge (this is similar to checking
 188 * techniques used in XFree86, but ours should be more reliable since we
 189 * attempt to make use of direct access hints provided by the PCI BIOS).
 190 *
 191 * This should be close to trivial, but it isn't, because there are buggy
 192 * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
 193 */
 194static int __init pci_sanity_check(const struct pci_raw_ops *o)
 195{
 196        u32 x = 0;
 197        int year, devfn;
 198
 199        if (pci_probe & PCI_NO_CHECKS)
 200                return 1;
 201        /* Assume Type 1 works for newer systems.
 202           This handles machines that don't have anything on PCI Bus 0. */
 203        dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL);
 204        if (year >= 2001)
 205                return 1;
 206
 207        for (devfn = 0; devfn < 0x100; devfn++) {
 208                if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x))
 209                        continue;
 210                if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)
 211                        return 1;
 212
 213                if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x))
 214                        continue;
 215                if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)
 216                        return 1;
 217        }
 218
 219        DBG(KERN_WARNING "PCI: Sanity check failed\n");
 220        return 0;
 221}
 222
 223static int __init pci_check_type1(void)
 224{
 225        unsigned long flags;
 226        unsigned int tmp;
 227        int works = 0;
 228
 229        local_irq_save(flags);
 230
 231        outb(0x01, 0xCFB);
 232        tmp = inl(0xCF8);
 233        outl(0x80000000, 0xCF8);
 234        if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
 235                works = 1;
 236        }
 237        outl(tmp, 0xCF8);
 238        local_irq_restore(flags);
 239
 240        return works;
 241}
 242
 243static int __init pci_check_type2(void)
 244{
 245        unsigned long flags;
 246        int works = 0;
 247
 248        local_irq_save(flags);
 249
 250        outb(0x00, 0xCFB);
 251        outb(0x00, 0xCF8);
 252        outb(0x00, 0xCFA);
 253        if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
 254            pci_sanity_check(&pci_direct_conf2)) {
 255                works = 1;
 256        }
 257
 258        local_irq_restore(flags);
 259
 260        return works;
 261}
 262
 263void __init pci_direct_init(int type)
 264{
 265        if (type == 0)
 266                return;
 267        printk(KERN_INFO "PCI: Using configuration type %d for base access\n",
 268                 type);
 269        if (type == 1) {
 270                raw_pci_ops = &pci_direct_conf1;
 271                if (raw_pci_ext_ops)
 272                        return;
 273                if (!(pci_probe & PCI_HAS_IO_ECS))
 274                        return;
 275                printk(KERN_INFO "PCI: Using configuration type 1 "
 276                       "for extended access\n");
 277                raw_pci_ext_ops = &pci_direct_conf1;
 278                return;
 279        }
 280        raw_pci_ops = &pci_direct_conf2;
 281}
 282
 283int __init pci_direct_probe(void)
 284{
 285        if ((pci_probe & PCI_PROBE_CONF1) == 0)
 286                goto type2;
 287        if (!request_region(0xCF8, 8, "PCI conf1"))
 288                goto type2;
 289
 290        if (pci_check_type1()) {
 291                raw_pci_ops = &pci_direct_conf1;
 292                port_cf9_safe = true;
 293                return 1;
 294        }
 295        release_region(0xCF8, 8);
 296
 297 type2:
 298        if ((pci_probe & PCI_PROBE_CONF2) == 0)
 299                return 0;
 300        if (!request_region(0xCF8, 4, "PCI conf2"))
 301                return 0;
 302        if (!request_region(0xC000, 0x1000, "PCI conf2"))
 303                goto fail2;
 304
 305        if (pci_check_type2()) {
 306                raw_pci_ops = &pci_direct_conf2;
 307                port_cf9_safe = true;
 308                return 2;
 309        }
 310
 311        release_region(0xC000, 0x1000);
 312 fail2:
 313        release_region(0xCF8, 4);
 314        return 0;
 315}
 316