This source file includes following definitions.
- bios32_service
- pcibios_init
- 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
- NCR53c810_test
- pcibios_strerror
- multi_function
- interrupt_decod
- bist_probe
- revision_decode
- class_decode
- device_decode
- vendor_decode
- info
- probe_devices
- probe_pci
- bios32_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 #include <linux/config.h>
42 #include <linux/kernel.h>
43 #include <linux/bios32.h>
44 #include <linux/pci.h>
45
46 #include <asm/segment.h>
47
48 #define PCIBIOS_PCI_FUNCTION_ID 0xb1XX
49 #define PCIBIOS_PCI_BIOS_PRESENT 0xb101
50 #define PCIBIOS_FIND_PCI_DEVICE 0xb102
51 #define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103
52 #define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
53 #define PCIBIOS_READ_CONFIG_BYTE 0xb108
54 #define PCIBIOS_READ_CONFIG_WORD 0xb109
55 #define PCIBIOS_READ_CONFIG_DWORD 0xb10a
56 #define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b
57 #define PCIBIOS_WRITE_CONFIG_WORD 0xb10c
58 #define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d
59
60
61 #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
62
63
64 #define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
65
66
67 #define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
68
69
70
71
72
73
74
75
76
77
78
79 union bios32 {
80 struct {
81 unsigned long signature;
82 unsigned long entry;
83 unsigned char revision;
84 unsigned char length;
85 unsigned char checksum;
86 unsigned char reserved[5];
87 } fields;
88 char chars[16];
89 };
90
91
92
93
94
95
96
97
98 static unsigned long bios32_entry = 0;
99 static struct {
100 unsigned long address;
101 unsigned short segment;
102 } bios32_indirect = { 0, KERNEL_CS };
103
104 #ifdef CONFIG_PCI
105
106
107
108
109 static unsigned long bios32_service(unsigned long service)
110 {
111 unsigned char return_code;
112 unsigned long address;
113 unsigned long length;
114 unsigned long entry;
115
116 __asm__("lcall (%%edi)"
117 : "=a" (return_code),
118 "=b" (address),
119 "=c" (length),
120 "=d" (entry)
121 : "0" (service),
122 "1" (0),
123 "D" (&bios32_indirect));
124
125 switch (return_code) {
126 case 0:
127 return address + entry;
128 case 0x80:
129 printk("bios32_service(%ld) : not present\n", service);
130 return 0;
131 default:
132 printk("bios32_service(%ld) : returned 0x%x, mail drew@colorado.edu\n",
133 service, return_code);
134 return 0;
135 }
136 }
137
138 static long pcibios_entry = 0;
139 static struct {
140 unsigned long address;
141 unsigned short segment;
142 } pci_indirect = { 0, KERNEL_CS };
143
144 void NCR53c810_test(void);
145
146 static unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
147 {
148 unsigned long signature;
149 unsigned char present_status;
150 unsigned char major_revision;
151 unsigned char minor_revision;
152 int pack;
153
154 if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
155 pci_indirect.address = pcibios_entry;
156
157 __asm__("lcall (%%edi)\n\t"
158 "jc 1f\n\t"
159 "xor %%ah, %%ah\n"
160 "1:\tshl $8, %%eax\n\t"
161 "movw %%bx, %%ax"
162 : "=d" (signature),
163 "=a" (pack)
164 : "1" (PCIBIOS_PCI_BIOS_PRESENT),
165 "D" (&pci_indirect)
166 : "bx", "cx");
167
168 present_status = (pack >> 16) & 0xff;
169 major_revision = (pack >> 8) & 0xff;
170 minor_revision = pack & 0xff;
171 if (present_status || (signature != PCI_SIGNATURE)) {
172 printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
173 " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
174 " and signature of 0x%08lx (%c%c%c%c). mail drew@Colorado.EDU\n",
175 (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR",
176 present_status, signature,
177 (char) (signature >> 0), (char) (signature >> 8),
178 (char) (signature >> 16), (char) (signature >> 24));
179
180 if (signature != PCI_SIGNATURE)
181 pcibios_entry = 0;
182 }
183 if (pcibios_entry) {
184 printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
185 major_revision, minor_revision, pcibios_entry);
186 }
187 }
188
189 #if 0
190 NCR53c810_test();
191 #endif
192 return memory_start;
193 }
194
195 int pcibios_present(void)
196 {
197 return pcibios_entry ? 1 : 0;
198 }
199
200 int pcibios_find_class (unsigned long class_code, unsigned short index,
201 unsigned char *bus, unsigned char *device_fn)
202 {
203 unsigned long bx;
204 unsigned long ret;
205
206 __asm__ ("lcall (%%edi)\n\t"
207 "jc 1f\n\t"
208 "xor %%ah, %%ah\n"
209 "1:"
210 : "=b" (bx),
211 "=a" (ret)
212 : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
213 "c" (class_code),
214 "S" ((int) index),
215 "D" (&pci_indirect));
216 *bus = (bx >> 8) & 0xff;
217 *device_fn = bx & 0xff;
218 return (int) (ret & 0xff00) >> 8;
219 }
220
221
222 int pcibios_find_device (unsigned short vendor, unsigned short device_id,
223 unsigned short index, unsigned char *bus, unsigned char *device_fn)
224 {
225 unsigned short bx;
226 unsigned short ret;
227
228 __asm__("lcall (%%edi)\n\t"
229 "jc 1f\n\t"
230 "xor %%ah, %%ah\n"
231 "1:"
232 : "=b" (bx),
233 "=a" (ret)
234 : "1" (PCIBIOS_FIND_PCI_DEVICE),
235 "c" (device_id),
236 "d" (vendor),
237 "S" ((int) index),
238 "D" (&pci_indirect));
239 *bus = (bx >> 8) & 0xff;
240 *device_fn = bx & 0xff;
241 return (int) (ret & 0xff00) >> 8;
242 }
243
244 int pcibios_read_config_byte(unsigned char bus,
245 unsigned char device_fn, unsigned char where, unsigned char *value)
246 {
247 unsigned long ret;
248 unsigned long bx = (bus << 8) | device_fn;
249
250 __asm__("lcall (%%esi)\n\t"
251 "jc 1f\n\t"
252 "xor %%ah, %%ah\n"
253 "1:"
254 : "=c" (*value),
255 "=a" (ret)
256 : "1" (PCIBIOS_READ_CONFIG_BYTE),
257 "b" (bx),
258 "D" ((long) where),
259 "S" (&pci_indirect));
260 return (int) (ret & 0xff00) >> 8;
261 }
262
263 int pcibios_read_config_word (unsigned char bus,
264 unsigned char device_fn, unsigned char where, unsigned short *value)
265 {
266 unsigned long ret;
267 unsigned long bx = (bus << 8) | device_fn;
268
269 __asm__("lcall (%%esi)\n\t"
270 "jc 1f\n\t"
271 "xor %%ah, %%ah\n"
272 "1:"
273 : "=c" (*value),
274 "=a" (ret)
275 : "1" (PCIBIOS_READ_CONFIG_WORD),
276 "b" (bx),
277 "D" ((long) where),
278 "S" (&pci_indirect));
279 return (int) (ret & 0xff00) >> 8;
280 }
281
282 int pcibios_read_config_dword (unsigned char bus,
283 unsigned char device_fn, unsigned char where, unsigned long *value)
284 {
285 unsigned long ret;
286 unsigned long bx = (bus << 8) | device_fn;
287
288 __asm__("lcall (%%esi)\n\t"
289 "jc 1f\n\t"
290 "xor %%ah, %%ah\n"
291 "1:"
292 : "=c" (*value),
293 "=a" (ret)
294 : "1" (PCIBIOS_READ_CONFIG_DWORD),
295 "b" (bx),
296 "D" ((long) where),
297 "S" (&pci_indirect));
298 return (int) (ret & 0xff00) >> 8;
299 }
300
301 int pcibios_write_config_byte (unsigned char bus,
302 unsigned char device_fn, unsigned char where, unsigned char value)
303 {
304 unsigned long ret;
305 unsigned long bx = (bus << 8) | device_fn;
306
307 __asm__("lcall (%%esi)\n\t"
308 "jc 1f\n\t"
309 "xor %%ah, %%ah\n"
310 "1:"
311 : "=a" (ret)
312 : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
313 "c" (value),
314 "b" (bx),
315 "D" ((long) where),
316 "S" (&pci_indirect));
317 return (int) (ret & 0xff00) >> 8;
318 }
319
320 int pcibios_write_config_word (unsigned char bus,
321 unsigned char device_fn, unsigned char where, unsigned short value)
322 {
323 unsigned long ret;
324 unsigned long bx = (bus << 8) | device_fn;
325
326 __asm__("lcall (%%esi)\n\t"
327 "jc 1f\n\t"
328 "xor %%ah, %%ah\n"
329 "1:"
330 : "=a" (ret)
331 : "0" (PCIBIOS_WRITE_CONFIG_WORD),
332 "c" (value),
333 "b" (bx),
334 "D" ((long) where),
335 "S" (&pci_indirect));
336 return (int) (ret & 0xff00) >> 8;
337 }
338
339 int pcibios_write_config_dword (unsigned char bus,
340 unsigned char device_fn, unsigned char where, unsigned long value)
341 {
342 unsigned long ret;
343 unsigned long bx = (bus << 8) | device_fn;
344
345 __asm__("lcall (%%esi)\n\t"
346 "jc 1f\n\t"
347 "xor %%ah, %%ah\n"
348 "1:"
349 : "=a" (ret)
350 : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
351 "c" (value),
352 "b" (bx),
353 "D" ((long) where),
354 "S" (&pci_indirect));
355 return (int) (ret & 0xff00) >> 8;
356 }
357
358 void NCR53c810_test(void)
359 {
360 unsigned char bus, device_fn;
361 unsigned short index;
362 int ret;
363 unsigned char row, col;
364 unsigned long val;
365
366 for (index = 0; index < 4; ++index) {
367 ret = pcibios_find_device (
368 (unsigned short) PCI_VENDOR_ID_NCR,
369 (unsigned short) PCI_DEVICE_ID_NCR_53C810,
370 index, &bus, &device_fn);
371 if (ret)
372 break;
373 printk ("ncr53c810 : at PCI bus %d, device %d, function %d.",
374 bus, ((device_fn & 0xf8) >> 3), (device_fn & 7));
375 for (row = 0; row < 0x3c; row += 0x10) {
376 printk ("\n reg 0x%02x ", row);
377 for (col = 0; col < 0x10; col += 4) {
378 if (!(ret = pcibios_read_config_dword (bus, device_fn, row+col, &val)))
379 printk ("0x%08lx ", val);
380 else
381 printk ("error 0x%02x ", ret);
382 }
383 }
384 printk ("\n");
385 }
386 }
387
388 char *pcibios_strerror (int error)
389 {
390 static char buf[80];
391
392 switch (error) {
393 case PCIBIOS_SUCCESSFUL:
394 return "SUCCESSFUL";
395
396 case PCIBIOS_FUNC_NOT_SUPPORTED:
397 return "FUNC_NOT_SUPPORTED";
398
399 case PCIBIOS_BAD_VENDOR_ID:
400 return "SUCCESSFUL";
401
402 case PCIBIOS_DEVICE_NOT_FOUND:
403 return "DEVICE_NOT_FOUND";
404
405 case PCIBIOS_BAD_REGISTER_NUMBER:
406 return "BAD_REGISTER_NUMBER";
407
408 default:
409 sprintf (buf, "UNKNOWN RETURN 0x%x", error);
410 return buf;
411 }
412 }
413
414
415
416
417 int multi_function(unsigned char bus,unsigned char dev_fn)
418 {
419 unsigned char header;
420 pcibios_read_config_byte(
421 bus, dev_fn, (unsigned char) PCI_HEADER_TYPE, &header);
422 return (header&7==7);
423 }
424
425
426
427 int interrupt_decod(unsigned char bus,unsigned char dev_fn)
428 {
429 unsigned char interrupt;
430 pcibios_read_config_byte(
431 bus, dev_fn, (unsigned char) PCI_INTERRUPT_LINE, &interrupt);
432 if (interrupt>16) return 0;
433 return interrupt;
434 }
435
436
437
438 int bist_probe(unsigned char bus,unsigned char dev_fn)
439 {
440 unsigned char bist;
441 pcibios_read_config_byte(
442 bus, dev_fn, (unsigned char) PCI_BIST, &bist);
443 return (bist & PCI_BIST_CAPABLE !=0);
444 }
445
446
447
448
449 int revision_decode(unsigned char bus,unsigned char dev_fn)
450 {
451 unsigned char revision;
452 pcibios_read_config_byte(
453 bus, dev_fn, (unsigned char) PCI_CLASS_REVISION, &revision);
454 return revision;
455 }
456
457
458
459
460
461
462 int class_decode(unsigned char bus,unsigned char dev_fn)
463 {
464 struct pci_class_type pci_class[PCI_CLASS_NUM+1] = PCI_CLASS_TYPE;
465 int i;
466 unsigned long class;
467 pcibios_read_config_dword(
468 bus, dev_fn, (unsigned char) PCI_CLASS_REVISION, &class);
469 class=class >> 16;
470 for (i=0;i<PCI_CLASS_NUM;i++)
471 if (class==pci_class[i].class_id) break;
472 return i;
473 }
474
475
476
477
478 int device_decode(unsigned char bus,unsigned char dev_fn,unsigned short vendor)
479 {
480 struct pci_device_type pci_device[PCI_DEVICE_NUM+1] = PCI_DEVICE_TYPE;
481 int i;
482 unsigned short device;
483 pcibios_read_config_word(
484 bus, dev_fn, (unsigned char) PCI_DEVICE_ID, &device);
485 for (i=0;i<PCI_DEVICE_NUM;i++)
486 if ((device==pci_device[i].device_id)
487 && (vendor==pci_device[i].vendor_id)) break;
488 return i;
489 }
490
491
492
493
494
495
496 int vendor_decode(unsigned char bus,unsigned char dev_fn)
497 {
498 struct pci_vendor_type pci_vendor[PCI_VENDOR_NUM+1] = PCI_VENDOR_TYPE;
499 int i;
500 unsigned short vendor;
501
502 pcibios_read_config_word(
503 bus, dev_fn, (unsigned char) PCI_VENDOR_ID, &vendor);
504 for (i=0;i<PCI_VENDOR_NUM;i++)
505 if (vendor==pci_vendor[i].vendor_id) return i;
506 return i;
507 }
508
509
510
511
512
513
514 void info(unsigned char bus,unsigned char dev_fn)
515 {
516 struct pci_class_type pci_class[PCI_CLASS_NUM+1] = PCI_CLASS_TYPE;
517 struct pci_vendor_type pci_vendor[PCI_VENDOR_NUM+1] = PCI_VENDOR_TYPE;
518 struct pci_device_type pci_device[PCI_DEVICE_NUM+1] = PCI_DEVICE_TYPE;
519 int pr;
520 pr=vendor_decode(bus,dev_fn);
521 printk(" %s : %s %s (rev %d). "
522 ,pci_class[class_decode(bus,dev_fn)].class_name
523 ,pci_vendor[pr].vendor_name
524 ,pci_device[device_decode(bus,dev_fn,pci_vendor[pr].vendor_id)].device_name
525 ,revision_decode(bus,dev_fn));
526
527 if (bist_probe(bus,dev_fn))
528 printk("BIST capable. ");
529 if ((pr=interrupt_decod(bus,dev_fn))!=0)
530 printk("8259's interrupt %d.",pr);
531 printk("\n");
532 }
533
534
535
536
537 void probe_devices(unsigned char bus)
538 {
539 unsigned long res;
540 unsigned char dev_fn;
541
542
543
544
545
546
547 for (dev_fn=0x0;dev_fn<0xff;dev_fn++) {
548 pcibios_read_config_dword(
549 bus, dev_fn, (unsigned char) PCI_CLASS_REVISION, &res);
550
551
552
553
554
555 if ((res!=0xffffffff) &&
556 (((dev_fn & 7) == 0) || multi_function(bus,dev_fn))) {
557 printk("Bus %d Device %d Function %d.\n",
558 (int) bus,
559 (int) ((dev_fn & 0xf8) >> 3),
560 (int) (dev_fn & 7));
561 info(bus,dev_fn);
562 }
563 }
564 }
565
566
567
568
569
570
571
572 void probe_pci(void)
573 {
574 if (pcibios_present()==0) printk("ProbePci PCI bios not detected.\n");
575 else {
576 printk( "Probing PCI hardware.\n");
577 probe_devices(0);
578 }
579 }
580
581 #endif
582
583 unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
584 {
585 union bios32 *check;
586 unsigned char sum;
587 int i, length;
588
589
590
591
592
593
594
595
596
597
598 for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
599 if (check->fields.signature != BIOS32_SIGNATURE)
600 continue;
601 length = check->fields.length * 16;
602 if (!length)
603 continue;
604 sum = 0;
605 for (i = 0; i < length ; ++i)
606 sum += check->chars[i];
607 if (sum != 0)
608 continue;
609 if (check->fields.revision != 0) {
610 printk("bios32_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
611 check->fields.revision, check);
612 continue;
613 }
614 printk ("bios32_init : BIOS32 Service Directory structure at 0x%p\n", check);
615 if (!bios32_entry) {
616 bios32_indirect.address = bios32_entry = check->fields.entry;
617 printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
618 } else {
619 printk ("bios32_init : multiple entries, mail drew@colorado.edu\n");
620
621
622
623
624
625
626 #if 0
627 return memory_start;
628 #endif
629 }
630 }
631 #ifdef CONFIG_PCI
632 if (bios32_entry) {
633 memory_start = pcibios_init (memory_start, memory_end);
634 probe_pci();
635 }
636 #endif
637 return memory_start;
638 }