Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / i386 / pci / direct.c
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 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 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 }