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