1 #define USER_SPACE 1
2 /*
3 pci.c
4
5 Configure devices on the PCI bus
6
7 Created: Jan 2000 by Philip Homburg <philip@cs.vu.nl>
8 */
9
10 #include "../drivers.h"
11 #define NDEBUG /* disable assertions */
12 #include <assert.h>
13 #include <minix/com.h>
14 #include <minix/syslib.h>
15
16 #include "pci.h"
17 #include "pci_amd.h"
18 #include "pci_intel.h"
19 #include "pci_sis.h"
20 #include "pci_via.h"
21 #if __minix_vmd
22 #include "config.h"
23 #endif
24
25 #if !__minix_vmd
26 #define irq_mode_pci(irq) ((void)0)
27 #endif
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <minix/sysutil.h>
33
34 #define NR_PCIBUS 4
35 #define NR_PCIDEV 40
36
37 #define PBT_INTEL 1
38 #define PBT_PCIBRIDGE 2
39
40 PRIVATE int debug= 0;
41
42 PRIVATE struct pcibus
43 {
44 int pb_type;
45 int pb_isabridge_dev;
46 int pb_isabridge_type;
47
48 int pb_devind;
49 int pb_bus;
50 u8_t (*pb_rreg8)(int busind, int devind, int port);
51 u16_t (*pb_rreg16)(int busind, int devind, int port);
52 u32_t (*pb_rreg32)(int busind, int devind, int port);
53 void (*pb_wreg16)(int busind, int devind, int port, U16_t value);
54 void (*pb_wreg32)(int busind, int devind, int port, u32_t value);
55 u16_t (*pb_rsts)(int busind);
56 void (*pb_wsts)(int busind, U16_t value);
57 } pcibus[NR_PCIBUS];
58 PRIVATE int nr_pcibus= 0;
59
60 PRIVATE struct pcidev
61 {
62 u8_t pd_busind;
63 u8_t pd_dev;
64 u8_t pd_func;
65 u8_t pd_baseclass;
66 u8_t pd_subclass;
67 u8_t pd_infclass;
68 u16_t pd_vid;
69 u16_t pd_did;
70 u8_t pd_inuse;
71 } pcidev[NR_PCIDEV];
72 PRIVATE int nr_pcidev= 0;
73
74 /* Work around the limitation of the PCI emulation in QEMU 0.7.1 */
75 PRIVATE int qemu_pci= 0;
76
77 FORWARD _PROTOTYPE( void pci_intel_init, (void) );
78 FORWARD _PROTOTYPE( void probe_bus, (int busind) );
79 FORWARD _PROTOTYPE( int do_isabridge, (int busind) );
80 FORWARD _PROTOTYPE( void do_pcibridge, (int busind) );
81 FORWARD _PROTOTYPE( int do_piix, (int devind) );
82 FORWARD _PROTOTYPE( int do_amd_isabr, (int devind) );
83 FORWARD _PROTOTYPE( int do_sis_isabr, (int devind) );
84 FORWARD _PROTOTYPE( int do_via_isabr, (int devind) );
85 FORWARD _PROTOTYPE( char *pci_vid_name, (U16_t vid) );
86 FORWARD _PROTOTYPE( char *pci_baseclass_name, (U8_t baseclass) );
87 FORWARD _PROTOTYPE( char *pci_subclass_name, (U8_t baseclass,
88 U8_t subclass, U8_t infclass) );
89 FORWARD _PROTOTYPE( void ntostr, (unsigned n, char **str, char *end) );
90 FORWARD _PROTOTYPE( u16_t pci_attr_rsts, (int devind) );
91 FORWARD _PROTOTYPE( void pci_attr_wsts, (int devind, U16_t value) );
92 FORWARD _PROTOTYPE( u16_t pcibr_intel_rsts, (int busind) );
93 FORWARD _PROTOTYPE( void pcibr_intel_wsts, (int busind, U16_t value) );
94 FORWARD _PROTOTYPE( u16_t pcibr_via_rsts, (int busind) );
95 FORWARD _PROTOTYPE( void pcibr_via_wsts, (int busind, U16_t value) );
96 FORWARD _PROTOTYPE( u8_t pcii_rreg8, (int busind, int devind, int port) );
97 FORWARD _PROTOTYPE( u16_t pcii_rreg16, (int busind, int devind,
98 int port) );
99 FORWARD _PROTOTYPE( u32_t pcii_rreg32, (int busind, int devind,
100 int port) );
101 FORWARD _PROTOTYPE( void pcii_wreg16, (int busind, int devind, int port,
102 U16_t value) );
103 FORWARD _PROTOTYPE( void pcii_wreg32, (int busind, int devind, int port,
104 u32_t value) );
105 FORWARD _PROTOTYPE( u16_t pcii_rsts, (int busind) );
106 FORWARD _PROTOTYPE( void pcii_wsts, (int busind, U16_t value) );
107
108 /*===========================================================================*
109 * helper functions for I/O *
110 *===========================================================================*/
111 PUBLIC unsigned pci_inb(U16_t port) {
112 U8_t value;
113 int s;
114 if ((s=sys_inb(port, &value)) !=OK)
115 printf("PCI: warning, sys_inb failed: %d\n", s);
116 return value;
117 }
118 PUBLIC unsigned pci_inw(U16_t port) {
119 U16_t value;
120 int s;
121 if ((s=sys_inw(port, &value)) !=OK)
122 printf("PCI: warning, sys_inw failed: %d\n", s);
123 return value;
124 }
125 PUBLIC unsigned pci_inl(U16_t port) {
126 U32_t value;
127 int s;
128 if ((s=sys_inl(port, &value)) !=OK)
129 printf("PCI: warning, sys_inl failed: %d\n", s);
130 return value;
131 }
132 PUBLIC void pci_outb(U16_t port, U8_t value) {
133 int s;
134 if ((s=sys_outb(port, value)) !=OK)
135 printf("PCI: warning, sys_outb failed: %d\n", s);
136 }
137 PUBLIC void pci_outw(U16_t port, U16_t value) {
138 int s;
139 if ((s=sys_outw(port, value)) !=OK)
140 printf("PCI: warning, sys_outw failed: %d\n", s);
141 }
142 PUBLIC void pci_outl(U16_t port, U32_t value) {
143 int s;
144 if ((s=sys_outl(port, value)) !=OK)
145 printf("PCI: warning, sys_outl failed: %d\n", s);
146 }
147
148 /*===========================================================================*
149 * pci_init *
150 *===========================================================================*/
151 PUBLIC void pci_init()
152 {
153 static int first_time= 1;
154
155 long v;
156
157 if (!first_time)
158 return;
159
160 v= 0;
161 env_parse("qemu_pci", "d", 0, &v, 0, 1);
162 qemu_pci= v;
163
164 v= 0;
165 env_parse("pci_debug", "d", 0, &v, 0, 1);
166 debug= v;
167
168 /* We don't expect to interrupted */
169 assert(first_time == 1);
170 first_time= -1;
171
172 /* Only Intel (compatible) PCI controllers are supported at the
173 * moment.
174 */
175 pci_intel_init();
176
177 first_time= 0;
178 }
179
180 /*===========================================================================*
181 * pci_find_dev *
182 *===========================================================================*/
183 PUBLIC int pci_find_dev(bus, dev, func, devindp)
184 u8_t bus;
185 u8_t dev;
186 u8_t func;
187 int *devindp;
188 {
189 int devind;
190
191 for (devind= 0; devind < nr_pcidev; devind++)
192 {
193 if (pcidev[devind].pd_busind == bus &&
194 pcidev[devind].pd_dev == dev &&
195 pcidev[devind].pd_func == func)
196 {
197 break;
198 }
199 }
200 if (devind >= nr_pcidev)
201 return 0;
202 if (pcidev[devind].pd_inuse)
203 return 0;
204 *devindp= devind;
205 return 1;
206 }
207
208 /*===========================================================================*
209 * pci_first_dev *
210 *===========================================================================*/
211 PUBLIC int pci_first_dev(devindp, vidp, didp)
212 int *devindp;
213 u16_t *vidp;
214 u16_t *didp;
215 {
216 int devind;
217
218 for (devind= 0; devind < nr_pcidev; devind++)
219 {
220 if (!pcidev[devind].pd_inuse)
221 break;
222 }
223 if (devind >= nr_pcidev)
224 return 0;
225 *devindp= devind;
226 *vidp= pcidev[devind].pd_vid;
227 *didp= pcidev[devind].pd_did;
228 return 1;
229 }
230
231 /*===========================================================================*
232 * pci_next_dev *
233 *===========================================================================*/
234 PUBLIC int pci_next_dev(devindp, vidp, didp)
235 int *devindp;
236 u16_t *vidp;
237 u16_t *didp;
238 {
239 int devind;
240
241 for (devind= *devindp+1; devind < nr_pcidev; devind++)
242 {
243 if (!pcidev[devind].pd_inuse)
244 break;
245 }
246 if (devind >= nr_pcidev)
247 return 0;
248 *devindp= devind;
249 *vidp= pcidev[devind].pd_vid;
250 *didp= pcidev[devind].pd_did;
251 return 1;
252 }
253
254 /*===========================================================================*
255 * pci_reserve *
256 *===========================================================================*/
257 PUBLIC void pci_reserve(devind)
258 int devind;
259 {
260 assert(devind <= nr_pcidev);
261 assert(!pcidev[devind].pd_inuse);
262 pcidev[devind].pd_inuse= 1;
263 }
264
265 /*===========================================================================*
266 * pci_ids *
267 *===========================================================================*/
268 PUBLIC void pci_ids(devind, vidp, didp)
269 int devind;
270 u16_t *vidp;
271 u16_t *didp;
272 {
273 assert(devind <= nr_pcidev);
274 *vidp= pcidev[devind].pd_vid;
275 *didp= pcidev[devind].pd_did;
276 }
277
278 /*===========================================================================*
279 * pci_slot_name *
280 *===========================================================================*/
281 PUBLIC char *pci_slot_name(devind)
282 int devind;
283 {
284 static char label[]= "ddd.ddd.ddd";
285 char *end;
286 char *p;
287
288 p= label;
289 end= label+sizeof(label);
290
291 ntostr(pcidev[devind].pd_busind, &p, end);
292 *p++= '.';
293
294 ntostr(pcidev[devind].pd_dev, &p, end);
295 *p++= '.';
296
297 ntostr(pcidev[devind].pd_func, &p, end);
298
299 return label;
300 }
301
302 /*===========================================================================*
303 * pci_dev_name *
304 *===========================================================================*/
305 PUBLIC char *pci_dev_name(vid, did)
306 u16_t vid;
307 u16_t did;
308 {
309 int i;
310
311 for (i= 0; pci_device_table[i].name; i++)
312 {
313 if (pci_device_table[i].vid == vid &&
314 pci_device_table[i].did == did)
315 {
316 return pci_device_table[i].name;
317 }
318 }
319 return NULL;
320 }
321
322 /*===========================================================================*
323 * pci_attr_r8 *
324 *===========================================================================*/
325 PUBLIC u8_t pci_attr_r8(devind, port)
326 int devind;
327 int port;
328 {
329 int busind;
330
331 busind= pcidev[devind].pd_busind;
332 return pcibus[busind].pb_rreg8(busind, devind, port);
333 }
334
335 /*===========================================================================*
336 * pci_attr_r16 *
337 *===========================================================================*/
338 PUBLIC u16_t pci_attr_r16(devind, port)
339 int devind;
340 int port;
341 {
342 int busind;
343
344 busind= pcidev[devind].pd_busind;
345 return pcibus[busind].pb_rreg16(busind, devind, port);
346 }
347
348 /*===========================================================================*
349 * pci_attr_r32 *
350 *===========================================================================*/
351 PUBLIC u32_t pci_attr_r32(devind, port)
352 int devind;
353 int port;
354 {
355 int busind;
356
357 busind= pcidev[devind].pd_busind;
358 return pcibus[busind].pb_rreg32(busind, devind, port);
359 }
360
361 /*===========================================================================*
362 * pci_attr_w16 *
363 *===========================================================================*/
364 PUBLIC void pci_attr_w16(devind, port, value)
365 int devind;
366 int port;
367 u16_t value;
368 {
369 int busind;
370
371 busind= pcidev[devind].pd_busind;
372 pcibus[busind].pb_wreg16(busind, devind, port, value);
373 }
374
375 /*===========================================================================*
376 * pci_attr_w32 *
377 *===========================================================================*/
378 PUBLIC void pci_attr_w32(devind, port, value)
379 int devind;
380 int port;
381 u32_t value;
382 {
383 int busind;
384
385 busind= pcidev[devind].pd_busind;
386 pcibus[busind].pb_wreg32(busind, devind, port, value);
387 }
388
389 /*===========================================================================*
390 * pci_intel_init *
391 *===========================================================================*/
392 PRIVATE void pci_intel_init()
393 {
394 /* Try to detect a know PCI controller. Read the Vendor ID and
395 * the Device ID for function 0 of device 0.
396 * Two times the value 0xffff suggests a system without a (compatible)
397 * PCI controller. Only controllers with values listed in the table
398 * pci_intel_ctrl are actually used.
399 */
400 u32_t bus, dev, func;
401 u16_t vid, did;
402 int s, i, r, busind;
403 char *dstr;
404
405 bus= 0;
406 dev= 0;
407 func= 0;
408
409 vid= PCII_RREG16_(bus, dev, func, PCI_VID);
410 did= PCII_RREG16_(bus, dev, func, PCI_DID);
411 #if USER_SPACE
412 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
413 printf("PCI: warning, sys_outl failed: %d\n", s);
414 #else
415 outl(PCII_CONFADD, PCII_UNSEL);
416 #endif
417
418 if (vid == 0xffff && did == 0xffff)
419 return; /* Nothing here */
420
421 for (i= 0; pci_intel_ctrl[i].vid; i++)
422 {
423 if (pci_intel_ctrl[i].vid == vid &&
424 pci_intel_ctrl[i].did == did)
425 {
426 break;
427 }
428 }
429
430 if (!pci_intel_ctrl[i].vid)
431 {
432 printf("pci_intel_init (warning): unknown PCI-controller:\n"
433 "\tvendor %04X (%s), device %04X\n",
434 vid, pci_vid_name(vid), did);
435 }
436
437 if (nr_pcibus >= NR_PCIBUS)
438 panic("PCI","too many PCI busses", nr_pcibus);
439 busind= nr_pcibus;
440 nr_pcibus++;
441 pcibus[busind].pb_type= PBT_INTEL;
442 pcibus[busind].pb_isabridge_dev= -1;
443 pcibus[busind].pb_isabridge_type= 0;
444 pcibus[busind].pb_devind= -1;
445 pcibus[busind].pb_bus= 0;
446 pcibus[busind].pb_rreg8= pcii_rreg8;
447 pcibus[busind].pb_rreg16= pcii_rreg16;
448 pcibus[busind].pb_rreg32= pcii_rreg32;
449 pcibus[busind].pb_wreg16= pcii_wreg16;
450 pcibus[busind].pb_wreg32= pcii_wreg32;
451 pcibus[busind].pb_rsts= pcii_rsts;
452 pcibus[busind].pb_wsts= pcii_wsts;
453
454 dstr= pci_dev_name(vid, did);
455 if (!dstr)
456 dstr= "unknown device";
457 if (debug)
458 {
459 printf("pci_intel_init: %s (%04X/%04X)\n",
460 dstr, vid, did);
461 }
462
463 probe_bus(busind);
464
465 r= do_isabridge(busind);
466 if (r != OK)
467 {
468 /* Disable all devices for this bus */
469 for (i= 0; i<nr_pcidev; i++)
470 {
471 if (pcidev[i].pd_busind != busind)
472 continue;
473 pcidev[i].pd_inuse= 1;
474 }
475 return;
476 }
477
478 /* Look for PCI bridges (for AGP) */
479 do_pcibridge(busind);
480 }
481
482 /*===========================================================================*
483 * probe_bus *
484 *===========================================================================*/
485 PRIVATE void probe_bus(busind)
486 int busind;
487 {
488 u32_t dev, func;
489 u16_t vid, did, sts;
490 u8_t headt;
491 u8_t baseclass, subclass, infclass;
492 int devind;
493 char *s, *dstr;
494
495 #if DEBUG
496 printf("probe_bus(%d)\n", busind);
497 #endif
498 if (nr_pcidev >= NR_PCIDEV)
499 panic("PCI","too many PCI devices", nr_pcidev);
500 devind= nr_pcidev;
501
502 for (dev= 0; dev<32; dev++)
503 {
504
505 for (func= 0; func < 8; func++)
506 {
507 pcidev[devind].pd_busind= busind;
508 pcidev[devind].pd_dev= dev;
509 pcidev[devind].pd_func= func;
510
511 pci_attr_wsts(devind,
512 PSR_SSE|PSR_RMAS|PSR_RTAS);
513 vid= pci_attr_r16(devind, PCI_VID);
514 did= pci_attr_r16(devind, PCI_DID);
515 headt= pci_attr_r8(devind, PCI_HEADT);
516 sts= pci_attr_rsts(devind);
517
518 if (vid == NO_VID)
519 break; /* Nothing here */
520
521 if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS))
522 {
523 if (qemu_pci)
524 {
525 printf(
526 "pci: ignoring bad value 0x%x in sts for QEMU\n",
527 sts & (PSR_SSE|PSR_RMAS|PSR_RTAS));
528 }
529 else
530 break;
531 }
532
533 dstr= pci_dev_name(vid, did);
534 if (debug)
535 {
536 if (dstr)
537 {
538 printf("%d.%lu.%lu: %s (%04X/%04X)\n",
539 busind, (unsigned long)dev,
540 (unsigned long)func, dstr,
541 vid, did);
542 }
543 else
544 {
545 printf(
546 "%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n",
547 busind, (unsigned long)dev,
548 (unsigned long)func, vid,
549 pci_vid_name(vid), did);
550 }
551 }
552
553 baseclass= pci_attr_r8(devind, PCI_BCR);
554 subclass= pci_attr_r8(devind, PCI_SCR);
555 infclass= pci_attr_r8(devind, PCI_PIFR);
556 s= pci_subclass_name(baseclass, subclass, infclass);
557 if (!s)
558 s= pci_baseclass_name(baseclass);
559 {
560 if (!s)
561 s= "(unknown class)";
562 }
563 if (debug)
564 {
565 printf("\tclass %s (%X/%X/%X)\n", s,
566 baseclass, subclass, infclass);
567 }
568
569 devind= nr_pcidev;
570 nr_pcidev++;
571 pcidev[devind].pd_baseclass= baseclass;
572 pcidev[devind].pd_subclass= subclass;
573 pcidev[devind].pd_infclass= infclass;
574 pcidev[devind].pd_vid= vid;
575 pcidev[devind].pd_did= did;
576 pcidev[devind].pd_inuse= 0;
577
578 if (nr_pcidev >= NR_PCIDEV)
579 panic("PCI","too many PCI devices", nr_pcidev);
580 devind= nr_pcidev;
581
582 if (func == 0 && !(headt & PHT_MULTIFUNC))
583 break;
584 }
585 }
586 }
587
588 /*===========================================================================*
589 * do_isabridge *
590 *===========================================================================*/
591 PRIVATE int do_isabridge(busind)
592 int busind;
593 {
594 int unknown_bridge= -1;
595 int bridge_dev= -1;
596 int i, j, r, type;
597 u16_t vid, did;
598 char *dstr;
599
600 j= 0; /* lint */
601 vid= did= 0; /* lint */
602 for (i= 0; i< nr_pcidev; i++)
603 {
604 if (pcidev[i].pd_busind != busind)
605 continue;
606 if (pcidev[i].pd_baseclass == 0x06 &&
607 pcidev[i].pd_subclass == 0x01 &&
608 pcidev[i].pd_infclass == 0x00)
609 {
610 /* ISA bridge. Report if no supported bridge is
611 * found.
612 */
613 unknown_bridge= i;
614 }
615
616 vid= pcidev[i].pd_vid;
617 did= pcidev[i].pd_did;
618 for (j= 0; pci_isabridge[j].vid != 0; j++)
619 {
620 if (pci_isabridge[j].vid != vid)
621 continue;
622 if (pci_isabridge[j].did != did)
623 continue;
624 if (pci_isabridge[j].checkclass &&
625 unknown_bridge != i)
626 {
627 /* This part of multifunction device is
628 * not the bridge.
629 */
630 continue;
631 }
632 break;
633 }
634 if (pci_isabridge[j].vid)
635 {
636 bridge_dev= i;
637 break;
638 }
639 }
640
641 if (bridge_dev != -1)
642 {
643 dstr= pci_dev_name(vid, did);
644 if (!dstr)
645 dstr= "unknown device";
646 if (debug)
647 {
648 printf("found ISA bridge (%04X/%04X) %s\n",
649 vid, did, dstr);
650 }
651 pcibus[busind].pb_isabridge_dev= bridge_dev;
652 type= pci_isabridge[j].type;
653 pcibus[busind].pb_isabridge_type= type;
654 switch(type)
655 {
656 case PCI_IB_PIIX:
657 r= do_piix(bridge_dev);
658 break;
659 case PCI_IB_VIA:
660 r= do_via_isabr(bridge_dev);
661 break;
662 case PCI_IB_AMD:
663 r= do_amd_isabr(bridge_dev);
664 break;
665 case PCI_IB_SIS:
666 r= do_sis_isabr(bridge_dev);
667 break;
668 default:
669 panic("PCI","unknown ISA bridge type", type);
670 }
671 return r;
672 }
673
674 if (unknown_bridge == -1)
675 {
676 printf("(warning) no ISA bridge found on bus %d", busind);
677 return 0;
678 }
679 printf("(warning) unsupported ISA bridge %04X/%04X for bus %d\n",
680 pcidev[unknown_bridge].pd_vid,
681 pcidev[unknown_bridge].pd_did,
682 busind);
683 return 0;
684 }
685
686 /*===========================================================================*
687 * do_pcibridge *
688 *===========================================================================*/
689 PRIVATE void do_pcibridge(busind)
690 int busind;
691 {
692 int devind, i;
693 int ind, type;
694 u16_t vid, did;
695 u8_t sbusn, baseclass, subclass, infclass;
696 u32_t t3;
697
698 vid= did= 0; /* lint */
699 for (devind= 0; devind< nr_pcidev; devind++)
700 {
701 if (pcidev[devind].pd_busind != busind)
702 continue;
703
704 vid= pcidev[devind].pd_vid;
705 did= pcidev[devind].pd_did;
706 for (i= 0; pci_pcibridge[i].vid != 0; i++)
707 {
708 if (pci_pcibridge[i].vid != vid)
709 continue;
710 if (pci_pcibridge[i].did != did)
711 continue;
712 break;
713 }
714 if (pci_pcibridge[i].vid == 0)
715 {
716 if (debug)
717 {
718 /* Report unsupported bridges */
719 baseclass= pci_attr_r8(devind, PCI_BCR);
720 subclass= pci_attr_r8(devind, PCI_SCR);
721 infclass= pci_attr_r8(devind, PCI_PIFR);
722 t3= ((baseclass << 16) | (subclass << 8) |
723 infclass);
724 if (t3 != PCI_T3_PCI2PCI &&
725 t3 != PCI_T3_PCI2PCI_SUBTR)
726 {
727 /* No a PCI-to-PCI bridge */
728 continue;
729 }
730 printf(
731 "Ignoring unknown PCI-to-PCI bridge: %04X/%04X\n",
732 vid, did);
733 }
734 continue;
735 }
736 type= pci_pcibridge[i].type;
737
738 if (debug)
739 printf("PCI-to-PCI bridge: %04X/%04X\n", vid, did);
740
741 /* Assume that the BIOS initialized the secondary bus
742 * number.
743 */
744 sbusn= pci_attr_r8(devind, PPB_SBUSN);
745 #if DEBUG
746 printf("sbusn = %d\n", sbusn);
747 #endif
748
749 if (nr_pcibus >= NR_PCIBUS)
750 panic("PCI","too many PCI busses", nr_pcibus);
751 ind= nr_pcibus;
752 nr_pcibus++;
753 pcibus[ind].pb_type= PBT_PCIBRIDGE;
754 pcibus[ind].pb_isabridge_dev= -1;
755 pcibus[ind].pb_isabridge_type= 0;
756 pcibus[ind].pb_devind= devind;
757 pcibus[ind].pb_bus= sbusn;
758 pcibus[ind].pb_rreg8= pcibus[busind].pb_rreg8;
759 pcibus[ind].pb_rreg16= pcibus[busind].pb_rreg16;
760 pcibus[ind].pb_rreg32= pcibus[busind].pb_rreg32;
761 pcibus[ind].pb_wreg16= pcibus[busind].pb_wreg16;
762 pcibus[ind].pb_wreg32= pcibus[busind].pb_wreg32;
763 switch(type)
764 {
765 case PCI_PCIB_INTEL:
766 case PCI_AGPB_INTEL:
767 pcibus[ind].pb_rsts= pcibr_intel_rsts;
768 pcibus[ind].pb_wsts= pcibr_intel_wsts;
769 break;
770 case PCI_AGPB_VIA:
771 pcibus[ind].pb_rsts= pcibr_via_rsts;
772 pcibus[ind].pb_wsts= pcibr_via_wsts;
773 break;
774 default:
775 panic("PCI","unknown PCI-PCI bridge type", type);
776 }
777
778 probe_bus(ind);
779 }
780 }
781
782 /*===========================================================================*
783 * do_piix *
784 *===========================================================================*/
785 PRIVATE int do_piix(devind)
786 int devind;
787 {
788 int i, s, dev, func, irqrc, irq;
789 u16_t elcr1, elcr2, elcr;
790
791 #if DEBUG
792 printf("in piix\n");
793 #endif
794 dev= pcidev[devind].pd_dev;
795 func= pcidev[devind].pd_func;
796 #if USER_SPACE
797 if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1)))
798 printf("Warning, sys_inb failed: %d\n", s);
799 if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2)))
800 printf("Warning, sys_inb failed: %d\n", s);
801 #else
802 elcr1= inb(PIIX_ELCR1);
803 elcr2= inb(PIIX_ELCR2);
804 #endif
805 elcr= elcr1 | (elcr2 << 8);
806 for (i= 0; i<4; i++)
807 {
808 irqrc= pci_attr_r8(devind, PIIX_PIRQRCA+i);
809 if (irqrc & PIIX_IRQ_DI)
810 {
811 if (debug)
812 printf("INT%c: disabled\n", 'A'+i);
813 }
814 else
815 {
816 irq= irqrc & PIIX_IRQ_MASK;
817 if (debug)
818 printf("INT%c: %d\n", 'A'+i, irq);
819 if (!(elcr & (1 << irq)))
820 {
821 if (debug)
822 {
823 printf(
824 "(warning) IRQ %d is not level triggered\n",
825 irq);
826 }
827 }
828 irq_mode_pci(irq);
829 }
830 }
831 return 0;
832 }
833
834 /*===========================================================================*
835 * do_amd_isabr *
836 *===========================================================================*/
837 PRIVATE int do_amd_isabr(devind)
838 int devind;
839 {
840 int i, bus, dev, func, xdevind, irq, edge;
841 u8_t levmask;
842 u16_t pciirq;
843
844 /* Find required function */
845 func= AMD_ISABR_FUNC;
846 bus= pcidev[devind].pd_busind;
847 dev= pcidev[devind].pd_dev;
848
849 /* Fake a device with the required function */
850 if (nr_pcidev >= NR_PCIDEV)
851 panic("PCI","too many PCI devices", nr_pcidev);
852 xdevind= nr_pcidev;
853 pcidev[xdevind].pd_busind= bus;
854 pcidev[xdevind].pd_dev= dev;
855 pcidev[xdevind].pd_func= func;
856 pcidev[xdevind].pd_inuse= 1;
857 nr_pcidev++;
858
859 levmask= pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV);
860 pciirq= pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE);
861 for (i= 0; i<4; i++)
862 {
863 edge= (levmask >> i) & 1;
864 irq= (pciirq >> (4*i)) & 0xf;
865 if (!irq)
866 {
867 if (debug)
868 printf("INT%c: disabled\n", 'A'+i);
869 }
870 else
871 {
872 if (debug)
873 printf("INT%c: %d\n", 'A'+i, irq);
874 if (edge && debug)
875 {
876 printf(
877 "(warning) IRQ %d is not level triggered\n",
878 irq);
879 }
880 irq_mode_pci(irq);
881 }
882 }
883 nr_pcidev--;
884 return 0;
885 }
886
887 /*===========================================================================*
888 * do_sis_isabr *
889 *===========================================================================*/
890 PRIVATE int do_sis_isabr(devind)
891 int devind;
892 {
893 int i, dev, func, irq;
894
895 dev= pcidev[devind].pd_dev;
896 func= pcidev[devind].pd_func;
897 irq= 0; /* lint */
898 for (i= 0; i<4; i++)
899 {
900 irq= pci_attr_r8(devind, SIS_ISABR_IRQ_A+i);
901 if (irq & SIS_IRQ_DISABLED)
902 {
903 if (debug)
904 printf("INT%c: disabled\n", 'A'+i);
905 }
906 else
907 {
908 irq &= SIS_IRQ_MASK;
909 if (debug)
910 printf("INT%c: %d\n", 'A'+i, irq);
911 irq_mode_pci(irq);
912 }
913 }
914 return 0;
915 }
916
917 /*===========================================================================*
918 * do_via_isabr *
919 *===========================================================================*/
920 PRIVATE int do_via_isabr(devind)
921 int devind;
922 {
923 int i, dev, func, irq, edge;
924 u8_t levmask;
925
926 dev= pcidev[devind].pd_dev;
927 func= pcidev[devind].pd_func;
928 levmask= pci_attr_r8(devind, VIA_ISABR_EL);
929 irq= 0; /* lint */
930 edge= 0; /* lint */
931 for (i= 0; i<4; i++)
932 {
933 switch(i)
934 {
935 case 0:
936 edge= (levmask & VIA_ISABR_EL_INTA);
937 irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R2) >> 4;
938 break;
939 case 1:
940 edge= (levmask & VIA_ISABR_EL_INTB);
941 irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R2);
942 break;
943 case 2:
944 edge= (levmask & VIA_ISABR_EL_INTC);
945 irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R3) >> 4;
946 break;
947 case 3:
948 edge= (levmask & VIA_ISABR_EL_INTD);
949 irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R1) >> 4;
950 break;
951 default:
952 assert(0);
953 }
954 irq &= 0xf;
955 if (!irq)
956 {
957 if (debug)
958 printf("INT%c: disabled\n", 'A'+i);
959 }
960 else
961 {
962 if (debug)
963 printf("INT%c: %d\n", 'A'+i, irq);
964 if (edge && debug)
965 {
966 printf(
967 "(warning) IRQ %d is not level triggered\n",
968 irq);
969 }
970 irq_mode_pci(irq);
971 }
972 }
973 return 0;
974 }
975
976 /*===========================================================================*
977 * pci_vid_name *
978 *===========================================================================*/
979 PRIVATE char *pci_vid_name(vid)
980 u16_t vid;
981 {
982 int i;
983
984 for (i= 0; pci_vendor_table[i].name; i++)
985 {
986 if (pci_vendor_table[i].vid == vid)
987 return pci_vendor_table[i].name;
988 }
989 return "unknown";
990 }
991
992 /*===========================================================================*
993 * pci_baseclass_name *
994 *===========================================================================*/
995 PRIVATE char *pci_baseclass_name(baseclass)
996 u8_t baseclass;
997 {
998 int i;
999
1000 for (i= 0; pci_baseclass_table[i].name; i++)
1001 {
1002 if (pci_baseclass_table[i].baseclass == baseclass)
1003 return pci_baseclass_table[i].name;
1004 }
1005 return NULL;
1006 }
1007
1008 /*===========================================================================*
1009 * pci_subclass_name *
1010 *===========================================================================*/
1011 PRIVATE char *pci_subclass_name(baseclass, subclass, infclass)
1012 u8_t baseclass;
1013 u8_t subclass;
1014 u8_t infclass;
1015 {
1016 int i;
1017
1018 for (i= 0; pci_subclass_table[i].name; i++)
1019 {
1020 if (pci_subclass_table[i].baseclass != baseclass)
1021 continue;
1022 if (pci_subclass_table[i].subclass != subclass)
1023 continue;
1024 if (pci_subclass_table[i].infclass != infclass &&
1025 pci_subclass_table[i].infclass != (u16_t)-1)
1026 {
1027 continue;
1028 }
1029 return pci_subclass_table[i].name;
1030 }
1031 return NULL;
1032 }
1033
1034 /*===========================================================================*
1035 * ntostr *
1036 *===========================================================================*/
1037 PRIVATE void ntostr(n, str, end)
1038 unsigned n;
1039 char **str;
1040 char *end;
1041 {
1042 char tmpstr[20];
1043 int i;
1044
1045 if (n == 0)
1046 {
1047 tmpstr[0]= '';
1048 i= 1;
1049 }
1050 else
1051 {
1052 for (i= 0; n; i++)
1053 {
1054 tmpstr[i]= '' + (n%10);
1055 n /= 10;
1056 }
1057 }
1058 for (; i>0; i--)
1059 {
1060 if (*str == end)
1061 {
1062 break;
1063 }
1064 **str= tmpstr[i-1];
1065 (*str)++;
1066 }
1067 if (*str == end)
1068 end[-1]= '\0';
1069 else
1070 **str= '\0';
1071 }
1072
1073 /*===========================================================================*
1074 * pci_attr_rsts *
1075 *===========================================================================*/
1076 PRIVATE u16_t pci_attr_rsts(devind)
1077 int devind;
1078 {
1079 int busind;
1080
1081 busind= pcidev[devind].pd_busind;
1082 return pcibus[busind].pb_rsts(busind);
1083 }
1084
1085
1086 /*===========================================================================*
1087 * pcibr_intel_rsts *
1088 *===========================================================================*/
1089 PRIVATE u16_t pcibr_intel_rsts(busind)
1090 int busind;
1091 {
1092 int devind;
1093 devind= pcibus[busind].pb_devind;
1094
1095 return pci_attr_r16(devind, PPB_SSTS);
1096 }
1097
1098 /*===========================================================================*
1099 * pcibr_intel_wsts *
1100 *===========================================================================*/
1101 PRIVATE void pcibr_intel_wsts(busind, value)
1102 int busind;
1103 u16_t value;
1104 {
1105 int devind;
1106 devind= pcibus[busind].pb_devind;
1107
1108 #if 0
1109 printf("pcibr_intel_wsts(%d, 0x%X), devind= %d\n",
1110 busind, value, devind);
1111 #endif
1112 pci_attr_w16(devind, PPB_SSTS, value);
1113 }
1114
1115 /*===========================================================================*
1116 * pcibr_via_rsts *
1117 *===========================================================================*/
1118 PRIVATE u16_t pcibr_via_rsts(busind)
1119 int busind;
1120 {
1121 int devind;
1122 devind= pcibus[busind].pb_devind;
1123
1124 return 0;
1125 }
1126
1127 /*===========================================================================*
1128 * pcibr_via_wsts *
1129 *===========================================================================*/
1130 PRIVATE void pcibr_via_wsts(busind, value)
1131 int busind;
1132 u16_t value;
1133 {
1134 int devind;
1135 devind= pcibus[busind].pb_devind;
1136
1137 #if 0
1138 printf("pcibr_via_wsts(%d, 0x%X), devind= %d (not implemented)\n",
1139 busind, value, devind);
1140 #endif
1141 }
1142
1143 /*===========================================================================*
1144 * pci_attr_wsts *
1145 *===========================================================================*/
1146 PRIVATE void pci_attr_wsts(devind, value)
1147 int devind;
1148 u16_t value;
1149 {
1150 int busind;
1151
1152 busind= pcidev[devind].pd_busind;
1153 pcibus[busind].pb_wsts(busind, value);
1154 }
1155
1156
1157 /*===========================================================================*
1158 * pcii_rreg8 *
1159 *===========================================================================*/
1160 PRIVATE u8_t pcii_rreg8(busind, devind, port)
1161 int busind;
1162 int devind;
1163 int port;
1164 {
1165 u8_t v;
1166 int s;
1167
1168 v= PCII_RREG8_(pcibus[busind].pb_bus,
1169 pcidev[devind].pd_dev, pcidev[devind].pd_func,
1170 port);
1171 #if USER_SPACE
1172 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1173 printf("PCI: warning, sys_outl failed: %d\n", s);
1174 #else
1175 outl(PCII_CONFADD, PCII_UNSEL);
1176 #endif
1177 #if 0
1178 printf("pcii_rreg8(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
1179 busind, devind, port,
1180 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1181 pcidev[devind].pd_func, v);
1182 #endif
1183 return v;
1184 }
1185
1186 /*===========================================================================*
1187 * pcii_rreg16 *
1188 *===========================================================================*/
1189 PRIVATE u16_t pcii_rreg16(busind, devind, port)
1190 int busind;
1191 int devind;
1192 int port;
1193 {
1194 u16_t v;
1195 int s;
1196
1197 v= PCII_RREG16_(pcibus[busind].pb_bus,
1198 pcidev[devind].pd_dev, pcidev[devind].pd_func,
1199 port);
1200 #if USER_SPACE
1201 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1202 printf("PCI: warning, sys_outl failed: %d\n");
1203 #else
1204 outl(PCII_CONFADD, PCII_UNSEL);
1205 #endif
1206 #if 0
1207 printf("pcii_rreg16(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
1208 busind, devind, port,
1209 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1210 pcidev[devind].pd_func, v);
1211 #endif
1212 return v;
1213 }
1214
1215 /*===========================================================================*
1216 * pcii_rreg32 *
1217 *===========================================================================*/
1218 PRIVATE u32_t pcii_rreg32(busind, devind, port)
1219 int busind;
1220 int devind;
1221 int port;
1222 {
1223 u32_t v;
1224 int s;
1225
1226 v= PCII_RREG32_(pcibus[busind].pb_bus,
1227 pcidev[devind].pd_dev, pcidev[devind].pd_func,
1228 port);
1229 #if USER_SPACE
1230 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1231 printf("PCI: warning, sys_outl failed: %d\n", s);
1232 #else
1233 outl(PCII_CONFADD, PCII_UNSEL);
1234 #endif
1235 #if 0
1236 printf("pcii_rreg32(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
1237 busind, devind, port,
1238 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1239 pcidev[devind].pd_func, v);
1240 #endif
1241 return v;
1242 }
1243
1244 /*===========================================================================*
1245 * pcii_wreg16 *
1246 *===========================================================================*/
1247 PRIVATE void pcii_wreg16(busind, devind, port, value)
1248 int busind;
1249 int devind;
1250 int port;
1251 u16_t value;
1252 {
1253 int s;
1254 #if 0
1255 printf("pcii_wreg16(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
1256 busind, devind, port, value,
1257 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1258 pcidev[devind].pd_func);
1259 #endif
1260 PCII_WREG16_(pcibus[busind].pb_bus,
1261 pcidev[devind].pd_dev, pcidev[devind].pd_func,
1262 port, value);
1263 #if USER_SPACE
1264 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1265 printf("PCI: warning, sys_outl failed: %d\n", s);
1266 #else
1267 outl(PCII_CONFADD, PCII_UNSEL);
1268 #endif
1269 }
1270
1271 /*===========================================================================*
1272 * pcii_wreg32 *
1273 *===========================================================================*/
1274 PRIVATE void pcii_wreg32(busind, devind, port, value)
1275 int busind;
1276 int devind;
1277 int port;
1278 u32_t value;
1279 {
1280 int s;
1281 #if 0
1282 printf("pcii_wreg32(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
1283 busind, devind, port, value,
1284 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1285 pcidev[devind].pd_func);
1286 #endif
1287 PCII_WREG32_(pcibus[busind].pb_bus,
1288 pcidev[devind].pd_dev, pcidev[devind].pd_func,
1289 port, value);
1290 #if USER_SPACE
1291 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1292 printf("PCI: warning, sys_outl failed: %d\n");
1293 #else
1294 outl(PCII_CONFADD, PCII_UNSEL);
1295 #endif
1296 }
1297
1298 /*===========================================================================*
1299 * pcii_rsts *
1300 *===========================================================================*/
1301 PRIVATE u16_t pcii_rsts(busind)
1302 int busind;
1303 {
1304 u16_t v;
1305 int s;
1306
1307 v= PCII_RREG16_(pcibus[busind].pb_bus, 0, 0, PCI_PCISTS);
1308 #if USER_SPACE
1309 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1310 printf("PCI: warning, sys_outl failed: %d\n", s);
1311 #else
1312 outl(PCII_CONFADD, PCII_UNSEL);
1313 #endif
1314 return v;
1315 }
1316
1317 /*===========================================================================*
1318 * pcii_wsts *
1319 *===========================================================================*/
1320 PRIVATE void pcii_wsts(busind, value)
1321 int busind;
1322 u16_t value;
1323 {
1324 int s;
1325 PCII_WREG16_(pcibus[busind].pb_bus, 0, 0, PCI_PCISTS, value);
1326 #if USER_SPACE
1327 if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1328 printf("PCI: warning, sys_outl failed: %d\n", s);
1329 #else
1330 outl(PCII_CONFADD, PCII_UNSEL);
1331 #endif
1332 }
1333
1334 /*
1335 * $PchId: pci.c,v 1.7 2003/08/07 09:06:51 philip Exp $
1336 */
Cache object: 287e00bdc8832383527b4bcfeb1f2192
|