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