root/arch/x86/pci/direct.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pci_conf1_read
  2. pci_conf1_write
  3. pci_conf2_read
  4. pci_conf2_write
  5. pci_sanity_check
  6. pci_check_type1
  7. pci_check_type2
  8. pci_direct_init
  9. pci_direct_probe

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * direct.c - Low-level direct PCI config space access
   4  */
   5 
   6 #include <linux/pci.h>
   7 #include <linux/init.h>
   8 #include <linux/dmi.h>
   9 #include <asm/pci_x86.h>
  10 
  11 /*
  12  * Functions for accessing PCI base (first 256 bytes) and extended
  13  * (4096 bytes per PCI function) configuration space with type 1
  14  * accesses.
  15  */
  16 
  17 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
  18         (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
  19         | (devfn << 8) | (reg & 0xFC))
  20 
  21 static int pci_conf1_read(unsigned int seg, unsigned int bus,
  22                           unsigned int devfn, int reg, int len, u32 *value)
  23 {
  24         unsigned long flags;
  25 
  26         if (seg || (bus > 255) || (devfn > 255) || (reg > 4095)) {
  27                 *value = -1;
  28                 return -EINVAL;
  29         }
  30 
  31         raw_spin_lock_irqsave(&pci_config_lock, flags);
  32 
  33         outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
  34 
  35         switch (len) {
  36         case 1:
  37                 *value = inb(0xCFC + (reg & 3));
  38                 break;
  39         case 2:
  40                 *value = inw(0xCFC + (reg & 2));
  41                 break;
  42         case 4:
  43                 *value = inl(0xCFC);
  44                 break;
  45         }
  46 
  47         raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  48 
  49         return 0;
  50 }
  51 
  52 static int pci_conf1_write(unsigned int seg, unsigned int bus,
  53                            unsigned int devfn, int reg, int len, u32 value)
  54 {
  55         unsigned long flags;
  56 
  57         if (seg || (bus > 255) || (devfn > 255) || (reg > 4095))
  58                 return -EINVAL;
  59 
  60         raw_spin_lock_irqsave(&pci_config_lock, flags);
  61 
  62         outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
  63 
  64         switch (len) {
  65         case 1:
  66                 outb((u8)value, 0xCFC + (reg & 3));
  67                 break;
  68         case 2:
  69                 outw((u16)value, 0xCFC + (reg & 2));
  70                 break;
  71         case 4:
  72                 outl((u32)value, 0xCFC);
  73                 break;
  74         }
  75 
  76         raw_spin_unlock_irqrestore(&pci_config_lock, flags);
  77 
  78         return 0;
  79 }
  80 
  81 #undef PCI_CONF1_ADDRESS
  82 
  83 const struct pci_raw_ops pci_direct_conf1 = {
  84         .read =         pci_conf1_read,
  85         .write =        pci_conf1_write,
  86 };
  87 
  88 
  89 /*
  90  * Functions for accessing PCI configuration space with type 2 accesses
  91  */
  92 
  93 #define PCI_CONF2_ADDRESS(dev, reg)     (u16)(0xC000 | (dev << 8) | reg)
  94 
  95 static int pci_conf2_read(unsigned int seg, unsigned int bus,
  96                           unsigned int devfn, int reg, int len, u32 *value)
  97 {
  98         unsigned long flags;
  99         int dev, fn;
 100 
 101         WARN_ON(seg);
 102         if ((bus > 255) || (devfn > 255) || (reg > 255)) {
 103                 *value = -1;
 104                 return -EINVAL;
 105         }
 106 
 107         dev = PCI_SLOT(devfn);
 108         fn = PCI_FUNC(devfn);
 109 
 110         if (dev & 0x10) 
 111                 return PCIBIOS_DEVICE_NOT_FOUND;
 112 
 113         raw_spin_lock_irqsave(&pci_config_lock, flags);
 114 
 115         outb((u8)(0xF0 | (fn << 1)), 0xCF8);
 116         outb((u8)bus, 0xCFA);
 117 
 118         switch (len) {
 119         case 1:
 120                 *value = inb(PCI_CONF2_ADDRESS(dev, reg));
 121                 break;
 122         case 2:
 123                 *value = inw(PCI_CONF2_ADDRESS(dev, reg));
 124                 break;
 125         case 4:
 126                 *value = inl(PCI_CONF2_ADDRESS(dev, reg));
 127                 break;
 128         }
 129 
 130         outb(0, 0xCF8);
 131 
 132         raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 133 
 134         return 0;
 135 }
 136 
 137 static int pci_conf2_write(unsigned int seg, unsigned int bus,
 138                            unsigned int devfn, int reg, int len, u32 value)
 139 {
 140         unsigned long flags;
 141         int dev, fn;
 142 
 143         WARN_ON(seg);
 144         if ((bus > 255) || (devfn > 255) || (reg > 255)) 
 145                 return -EINVAL;
 146 
 147         dev = PCI_SLOT(devfn);
 148         fn = PCI_FUNC(devfn);
 149 
 150         if (dev & 0x10) 
 151                 return PCIBIOS_DEVICE_NOT_FOUND;
 152 
 153         raw_spin_lock_irqsave(&pci_config_lock, flags);
 154 
 155         outb((u8)(0xF0 | (fn << 1)), 0xCF8);
 156         outb((u8)bus, 0xCFA);
 157 
 158         switch (len) {
 159         case 1:
 160                 outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
 161                 break;
 162         case 2:
 163                 outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
 164                 break;
 165         case 4:
 166                 outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
 167                 break;
 168         }
 169 
 170         outb(0, 0xCF8);    
 171 
 172         raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 173 
 174         return 0;
 175 }
 176 
 177 #undef PCI_CONF2_ADDRESS
 178 
 179 static const struct pci_raw_ops pci_direct_conf2 = {
 180         .read =         pci_conf2_read,
 181         .write =        pci_conf2_write,
 182 };
 183 
 184 
 185 /*
 186  * Before we decide to use direct hardware access mechanisms, we try to do some
 187  * trivial checks to ensure it at least _seems_ to be working -- we just test
 188  * whether bus 00 contains a host bridge (this is similar to checking
 189  * techniques used in XFree86, but ours should be more reliable since we
 190  * attempt to make use of direct access hints provided by the PCI BIOS).
 191  *
 192  * This should be close to trivial, but it isn't, because there are buggy
 193  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
 194  */
 195 static int __init pci_sanity_check(const struct pci_raw_ops *o)
 196 {
 197         u32 x = 0;
 198         int devfn;
 199 
 200         if (pci_probe & PCI_NO_CHECKS)
 201                 return 1;
 202         /* Assume Type 1 works for newer systems.
 203            This handles machines that don't have anything on PCI Bus 0. */
 204         if (dmi_get_bios_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 
 223 static 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 
 243 static 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 
 263 void __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 
 283 int __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 }

/* [<][>][^][v][top][bottom][index][help] */