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