Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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