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         spin_lock_irqsave(&pci_config_lock, flags);
224 
225         outb(0x01, 0xCFB);
226         tmp = inl(0xCF8);
227         outl(0x80000000, 0xCF8);
228 
229         if (inl(0xCF8) == 0x80000000) {
230                 spin_unlock_irqrestore(&pci_config_lock, flags);
231 
232                 if (pci_sanity_check(&pci_direct_conf1))
233                         works = 1;
234 
235                 spin_lock_irqsave(&pci_config_lock, flags);
236         }
237         outl(tmp, 0xCF8);
238 
239         spin_unlock_irqrestore(&pci_config_lock, flags);
240 
241         return works;
242 }
243 
244 static int __init pci_check_type2(void)
245 {
246         unsigned long flags;
247         int works = 0;
248 
249         spin_lock_irqsave(&pci_config_lock, flags);
250 
251         outb(0x00, 0xCFB);
252         outb(0x00, 0xCF8);
253         outb(0x00, 0xCFA);
254 
255         if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00) {
256                 spin_unlock_irqrestore(&pci_config_lock, flags);
257 
258                 if (pci_sanity_check(&pci_direct_conf2))
259                         works = 1;
260         } else
261                 spin_unlock_irqrestore(&pci_config_lock, flags);
262 
263         return works;
264 }
265 
266 void __init pci_direct_init(int type)
267 {
268         if (type == 0)
269                 return;
270         printk(KERN_INFO "PCI: Using configuration type %d\n", type);
271         if (type == 1)
272                 raw_pci_ops = &pci_direct_conf1;
273         else
274                 raw_pci_ops = &pci_direct_conf2;
275 }
276 
277 int __init pci_direct_probe(void)
278 {
279         struct resource *region, *region2;
280 
281         if ((pci_probe & PCI_PROBE_CONF1) == 0)
282                 goto type2;
283         region = request_region(0xCF8, 8, "PCI conf1");
284         if (!region)
285                 goto type2;
286 
287         if (pci_check_type1())
288                 return 1;
289         release_resource(region);
290 
291  type2:
292         if ((pci_probe & PCI_PROBE_CONF2) == 0)
293                 return 0;
294         region = request_region(0xCF8, 4, "PCI conf2");
295         if (!region)
296                 return 0;
297         region2 = request_region(0xC000, 0x1000, "PCI conf2");
298         if (!region2)
299                 goto fail2;
300 
301         if (pci_check_type2()) {
302                 printk(KERN_INFO "PCI: Using configuration type 2\n");
303                 raw_pci_ops = &pci_direct_conf2;
304                 return 2;
305         }
306 
307         release_resource(region2);
308  fail2:
309         release_resource(region);
310         return 0;
311 }
312 
  This page was automatically generated by the LXR engine.