This source file includes following definitions.
- bios32_service
- check_pcibios
- pcibios_present
- pcibios_find_class
- pcibios_find_device
- pcibios_read_config_byte
- pcibios_read_config_word
- pcibios_read_config_dword
- pcibios_write_config_byte
- pcibios_write_config_word
- pcibios_write_config_dword
- pcibios_strerror
- pcibios_fixup
- pcibios_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 #include <linux/config.h>
53 #include <linux/types.h>
54 #include <linux/kernel.h>
55 #include <linux/bios32.h>
56 #include <linux/pci.h>
57
58 #include <asm/segment.h>
59
60 #define PCIBIOS_PCI_FUNCTION_ID 0xb1XX
61 #define PCIBIOS_PCI_BIOS_PRESENT 0xb101
62 #define PCIBIOS_FIND_PCI_DEVICE 0xb102
63 #define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103
64 #define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
65 #define PCIBIOS_READ_CONFIG_BYTE 0xb108
66 #define PCIBIOS_READ_CONFIG_WORD 0xb109
67 #define PCIBIOS_READ_CONFIG_DWORD 0xb10a
68 #define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b
69 #define PCIBIOS_WRITE_CONFIG_WORD 0xb10c
70 #define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d
71
72
73
74 #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
75
76
77 #define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
78
79
80 #define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
81
82
83
84
85
86
87
88
89
90
91
92 union bios32 {
93 struct {
94 unsigned long signature;
95 unsigned long entry;
96 unsigned char revision;
97 unsigned char length;
98 unsigned char checksum;
99 unsigned char reserved[5];
100 } fields;
101 char chars[16];
102 };
103
104
105
106
107
108
109
110
111 static unsigned long bios32_entry = 0;
112 static struct {
113 unsigned long address;
114 unsigned short segment;
115 } bios32_indirect = { 0, KERNEL_CS };
116
117 #ifdef CONFIG_PCI
118
119
120
121
122 static unsigned long bios32_service(unsigned long service)
123 {
124 unsigned char return_code;
125 unsigned long address;
126 unsigned long length;
127 unsigned long entry;
128
129 __asm__("lcall (%%edi)"
130 : "=a" (return_code),
131 "=b" (address),
132 "=c" (length),
133 "=d" (entry)
134 : "0" (service),
135 "1" (0),
136 "D" (&bios32_indirect));
137
138 switch (return_code) {
139 case 0:
140 return address + entry;
141 case 0x80:
142 printk("bios32_service(%ld) : not present\n", service);
143 return 0;
144 default:
145 printk("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n",
146 service, return_code);
147 return 0;
148 }
149 }
150
151 static long pcibios_entry = 0;
152 static struct {
153 unsigned long address;
154 unsigned short segment;
155 } pci_indirect = { 0, KERNEL_CS };
156
157
158 extern unsigned long check_pcibios(unsigned long memory_start, unsigned long memory_end)
159 {
160 unsigned long signature;
161 unsigned char present_status;
162 unsigned char major_revision;
163 unsigned char minor_revision;
164 int pack;
165
166 if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
167 pci_indirect.address = pcibios_entry;
168
169 __asm__("lcall (%%edi)\n\t"
170 "jc 1f\n\t"
171 "xor %%ah, %%ah\n"
172 "1:\tshl $8, %%eax\n\t"
173 "movw %%bx, %%ax"
174 : "=d" (signature),
175 "=a" (pack)
176 : "1" (PCIBIOS_PCI_BIOS_PRESENT),
177 "D" (&pci_indirect)
178 : "bx", "cx");
179
180 present_status = (pack >> 16) & 0xff;
181 major_revision = (pack >> 8) & 0xff;
182 minor_revision = pack & 0xff;
183 if (present_status || (signature != PCI_SIGNATURE)) {
184 printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
185 " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
186 " and signature of 0x%08lx (%c%c%c%c). mail drew@Colorado.EDU\n",
187 (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR",
188 present_status, signature,
189 (char) (signature >> 0), (char) (signature >> 8),
190 (char) (signature >> 16), (char) (signature >> 24));
191
192 if (signature != PCI_SIGNATURE)
193 pcibios_entry = 0;
194 }
195 if (pcibios_entry) {
196 printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
197 major_revision, minor_revision, pcibios_entry);
198 }
199 }
200 return memory_start;
201 }
202
203 int pcibios_present(void)
204 {
205 return pcibios_entry ? 1 : 0;
206 }
207
208 int pcibios_find_class (unsigned int class_code, unsigned short index,
209 unsigned char *bus, unsigned char *device_fn)
210 {
211 unsigned long bx;
212 unsigned long ret;
213
214 __asm__ ("lcall (%%edi)\n\t"
215 "jc 1f\n\t"
216 "xor %%ah, %%ah\n"
217 "1:"
218 : "=b" (bx),
219 "=a" (ret)
220 : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
221 "c" (class_code),
222 "S" ((int) index),
223 "D" (&pci_indirect));
224 *bus = (bx >> 8) & 0xff;
225 *device_fn = bx & 0xff;
226 return (int) (ret & 0xff00) >> 8;
227 }
228
229
230 int pcibios_find_device (unsigned short vendor, unsigned short device_id,
231 unsigned short index, unsigned char *bus, unsigned char *device_fn)
232 {
233 unsigned short bx;
234 unsigned short ret;
235
236 __asm__("lcall (%%edi)\n\t"
237 "jc 1f\n\t"
238 "xor %%ah, %%ah\n"
239 "1:"
240 : "=b" (bx),
241 "=a" (ret)
242 : "1" (PCIBIOS_FIND_PCI_DEVICE),
243 "c" (device_id),
244 "d" (vendor),
245 "S" ((int) index),
246 "D" (&pci_indirect));
247 *bus = (bx >> 8) & 0xff;
248 *device_fn = bx & 0xff;
249 return (int) (ret & 0xff00) >> 8;
250 }
251
252 int pcibios_read_config_byte(unsigned char bus,
253 unsigned char device_fn, unsigned char where, unsigned char *value)
254 {
255 unsigned long ret;
256 unsigned long bx = (bus << 8) | device_fn;
257
258 __asm__("lcall (%%esi)\n\t"
259 "jc 1f\n\t"
260 "xor %%ah, %%ah\n"
261 "1:"
262 : "=c" (*value),
263 "=a" (ret)
264 : "1" (PCIBIOS_READ_CONFIG_BYTE),
265 "b" (bx),
266 "D" ((long) where),
267 "S" (&pci_indirect));
268 return (int) (ret & 0xff00) >> 8;
269 }
270
271 int pcibios_read_config_word (unsigned char bus,
272 unsigned char device_fn, unsigned char where, unsigned short *value)
273 {
274 unsigned long ret;
275 unsigned long bx = (bus << 8) | device_fn;
276
277 __asm__("lcall (%%esi)\n\t"
278 "jc 1f\n\t"
279 "xor %%ah, %%ah\n"
280 "1:"
281 : "=c" (*value),
282 "=a" (ret)
283 : "1" (PCIBIOS_READ_CONFIG_WORD),
284 "b" (bx),
285 "D" ((long) where),
286 "S" (&pci_indirect));
287 return (int) (ret & 0xff00) >> 8;
288 }
289
290 int pcibios_read_config_dword (unsigned char bus,
291 unsigned char device_fn, unsigned char where, unsigned int *value)
292 {
293 unsigned long ret;
294 unsigned long bx = (bus << 8) | device_fn;
295
296 __asm__("lcall (%%esi)\n\t"
297 "jc 1f\n\t"
298 "xor %%ah, %%ah\n"
299 "1:"
300 : "=c" (*value),
301 "=a" (ret)
302 : "1" (PCIBIOS_READ_CONFIG_DWORD),
303 "b" (bx),
304 "D" ((long) where),
305 "S" (&pci_indirect));
306 return (int) (ret & 0xff00) >> 8;
307 }
308
309 int pcibios_write_config_byte (unsigned char bus,
310 unsigned char device_fn, unsigned char where, unsigned char value)
311 {
312 unsigned long ret;
313 unsigned long bx = (bus << 8) | device_fn;
314
315 __asm__("lcall (%%esi)\n\t"
316 "jc 1f\n\t"
317 "xor %%ah, %%ah\n"
318 "1:"
319 : "=a" (ret)
320 : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
321 "c" (value),
322 "b" (bx),
323 "D" ((long) where),
324 "S" (&pci_indirect));
325 return (int) (ret & 0xff00) >> 8;
326 }
327
328 int pcibios_write_config_word (unsigned char bus,
329 unsigned char device_fn, unsigned char where, unsigned short value)
330 {
331 unsigned long ret;
332 unsigned long bx = (bus << 8) | device_fn;
333
334 __asm__("lcall (%%esi)\n\t"
335 "jc 1f\n\t"
336 "xor %%ah, %%ah\n"
337 "1:"
338 : "=a" (ret)
339 : "0" (PCIBIOS_WRITE_CONFIG_WORD),
340 "c" (value),
341 "b" (bx),
342 "D" ((long) where),
343 "S" (&pci_indirect));
344 return (int) (ret & 0xff00) >> 8;
345 }
346
347 int pcibios_write_config_dword (unsigned char bus,
348 unsigned char device_fn, unsigned char where, unsigned int value)
349 {
350 unsigned long ret;
351 unsigned long bx = (bus << 8) | device_fn;
352
353 __asm__("lcall (%%esi)\n\t"
354 "jc 1f\n\t"
355 "xor %%ah, %%ah\n"
356 "1:"
357 : "=a" (ret)
358 : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
359 "c" (value),
360 "b" (bx),
361 "D" ((long) where),
362 "S" (&pci_indirect));
363 return (int) (ret & 0xff00) >> 8;
364 }
365
366 const char *pcibios_strerror (int error)
367 {
368 static char buf[80];
369
370 switch (error) {
371 case PCIBIOS_SUCCESSFUL:
372 return "SUCCESSFUL";
373
374 case PCIBIOS_FUNC_NOT_SUPPORTED:
375 return "FUNC_NOT_SUPPORTED";
376
377 case PCIBIOS_BAD_VENDOR_ID:
378 return "SUCCESSFUL";
379
380 case PCIBIOS_DEVICE_NOT_FOUND:
381 return "DEVICE_NOT_FOUND";
382
383 case PCIBIOS_BAD_REGISTER_NUMBER:
384 return "BAD_REGISTER_NUMBER";
385
386 case PCIBIOS_SET_FAILED:
387 return "SET_FAILED";
388
389 case PCIBIOS_BUFFER_TOO_SMALL:
390 return "BUFFER_TOO_SMALL";
391
392 default:
393 sprintf (buf, "UNKNOWN RETURN 0x%x", error);
394 return buf;
395 }
396 }
397
398
399 unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
400 {
401 return mem_start;
402 }
403
404
405 #endif
406
407 unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
408 {
409 union bios32 *check;
410 unsigned char sum;
411 int i, length;
412
413
414
415
416
417
418
419
420 for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
421 if (check->fields.signature != BIOS32_SIGNATURE)
422 continue;
423 length = check->fields.length * 16;
424 if (!length)
425 continue;
426 sum = 0;
427 for (i = 0; i < length ; ++i)
428 sum += check->chars[i];
429 if (sum != 0)
430 continue;
431 if (check->fields.revision != 0) {
432 printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
433 check->fields.revision, check);
434 continue;
435 }
436 printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
437 if (!bios32_entry) {
438 if (check->fields.entry >= 0x100000) {
439 printk("pcibios_init: entry in high memory, unable to access\n");
440 } else {
441 bios32_indirect.address = bios32_entry = check->fields.entry;
442 printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
443 }
444 } else {
445 printk ("pcibios_init : multiple entries, mail drew@colorado.edu\n");
446
447
448
449
450
451
452 }
453 }
454 #ifdef CONFIG_PCI
455 if (bios32_entry) {
456 memory_start = check_pcibios (memory_start, memory_end);
457 }
458 #endif
459 return memory_start;
460 }