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.
|