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