source: branches/minix3-book/drivers/libpci/pci.c@ 15

Last change on this file since 15 was 4, checked in by Mattia Monga, 14 years ago

Importazione sorgenti libro

File size: 31.5 KB
Line 
1#define USER_SPACE 1
2/*
3pci.c
4
5Configure devices on the PCI bus
6
7Created: 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
40PRIVATE int debug= 0;
41
42PRIVATE 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];
58PRIVATE int nr_pcibus= 0;
59
60PRIVATE 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];
72PRIVATE int nr_pcidev= 0;
73
74/* Work around the limitation of the PCI emulation in QEMU 0.7.1 */
75PRIVATE int qemu_pci= 0;
76
77FORWARD _PROTOTYPE( void pci_intel_init, (void) );
78FORWARD _PROTOTYPE( void probe_bus, (int busind) );
79FORWARD _PROTOTYPE( int do_isabridge, (int busind) );
80FORWARD _PROTOTYPE( void do_pcibridge, (int busind) );
81FORWARD _PROTOTYPE( int do_piix, (int devind) );
82FORWARD _PROTOTYPE( int do_amd_isabr, (int devind) );
83FORWARD _PROTOTYPE( int do_sis_isabr, (int devind) );
84FORWARD _PROTOTYPE( int do_via_isabr, (int devind) );
85FORWARD _PROTOTYPE( char *pci_vid_name, (U16_t vid) );
86FORWARD _PROTOTYPE( char *pci_baseclass_name, (U8_t baseclass) );
87FORWARD _PROTOTYPE( char *pci_subclass_name, (U8_t baseclass,
88 U8_t subclass, U8_t infclass) );
89FORWARD _PROTOTYPE( void ntostr, (unsigned n, char **str, char *end) );
90FORWARD _PROTOTYPE( u16_t pci_attr_rsts, (int devind) );
91FORWARD _PROTOTYPE( void pci_attr_wsts, (int devind, U16_t value) );
92FORWARD _PROTOTYPE( u16_t pcibr_intel_rsts, (int busind) );
93FORWARD _PROTOTYPE( void pcibr_intel_wsts, (int busind, U16_t value) );
94FORWARD _PROTOTYPE( u16_t pcibr_via_rsts, (int busind) );
95FORWARD _PROTOTYPE( void pcibr_via_wsts, (int busind, U16_t value) );
96FORWARD _PROTOTYPE( u8_t pcii_rreg8, (int busind, int devind, int port) );
97FORWARD _PROTOTYPE( u16_t pcii_rreg16, (int busind, int devind,
98 int port) );
99FORWARD _PROTOTYPE( u32_t pcii_rreg32, (int busind, int devind,
100 int port) );
101FORWARD _PROTOTYPE( void pcii_wreg16, (int busind, int devind, int port,
102 U16_t value) );
103FORWARD _PROTOTYPE( void pcii_wreg32, (int busind, int devind, int port,
104 u32_t value) );
105FORWARD _PROTOTYPE( u16_t pcii_rsts, (int busind) );
106FORWARD _PROTOTYPE( void pcii_wsts, (int busind, U16_t value) );
107
108/*===========================================================================*
109 * helper functions for I/O *
110 *===========================================================================*/
111PUBLIC 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}
118PUBLIC 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}
125PUBLIC 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}
132PUBLIC 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}
137PUBLIC 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}
142PUBLIC 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 *===========================================================================*/
151PUBLIC 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 *===========================================================================*/
183PUBLIC int pci_find_dev(bus, dev, func, devindp)
184u8_t bus;
185u8_t dev;
186u8_t func;
187int *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 *===========================================================================*/
211PUBLIC int pci_first_dev(devindp, vidp, didp)
212int *devindp;
213u16_t *vidp;
214u16_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 *===========================================================================*/
234PUBLIC int pci_next_dev(devindp, vidp, didp)
235int *devindp;
236u16_t *vidp;
237u16_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 *===========================================================================*/
257PUBLIC void pci_reserve(devind)
258int 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 *===========================================================================*/
268PUBLIC void pci_ids(devind, vidp, didp)
269int devind;
270u16_t *vidp;
271u16_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 *===========================================================================*/
281PUBLIC char *pci_slot_name(devind)
282int 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 *===========================================================================*/
305PUBLIC char *pci_dev_name(vid, did)
306u16_t vid;
307u16_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 *===========================================================================*/
325PUBLIC u8_t pci_attr_r8(devind, port)
326int devind;
327int 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 *===========================================================================*/
338PUBLIC u16_t pci_attr_r16(devind, port)
339int devind;
340int 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 *===========================================================================*/
351PUBLIC u32_t pci_attr_r32(devind, port)
352int devind;
353int 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 *===========================================================================*/
364PUBLIC void pci_attr_w16(devind, port, value)
365int devind;
366int port;
367u16_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 *===========================================================================*/
378PUBLIC void pci_attr_w32(devind, port, value)
379int devind;
380int port;
381u32_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 *===========================================================================*/
392PRIVATE 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 *===========================================================================*/
485PRIVATE void probe_bus(busind)
486int 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
496printf("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 *===========================================================================*/
591PRIVATE int do_isabridge(busind)
592int 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 *===========================================================================*/
689PRIVATE void do_pcibridge(busind)
690int 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 *===========================================================================*/
785PRIVATE int do_piix(devind)
786int 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 *===========================================================================*/
837PRIVATE int do_amd_isabr(devind)
838int 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 *===========================================================================*/
890PRIVATE int do_sis_isabr(devind)
891int 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 *===========================================================================*/
920PRIVATE int do_via_isabr(devind)
921int 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 *===========================================================================*/
979PRIVATE char *pci_vid_name(vid)
980u16_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 *===========================================================================*/
995PRIVATE char *pci_baseclass_name(baseclass)
996u8_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 *===========================================================================*/
1011PRIVATE char *pci_subclass_name(baseclass, subclass, infclass)
1012u8_t baseclass;
1013u8_t subclass;
1014u8_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 *===========================================================================*/
1037PRIVATE void ntostr(n, str, end)
1038unsigned n;
1039char **str;
1040char *end;
1041{
1042 char tmpstr[20];
1043 int i;
1044
1045 if (n == 0)
1046 {
1047 tmpstr[0]= '0';
1048 i= 1;
1049 }
1050 else
1051 {
1052 for (i= 0; n; i++)
1053 {
1054 tmpstr[i]= '0' + (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 *===========================================================================*/
1076PRIVATE u16_t pci_attr_rsts(devind)
1077int 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 *===========================================================================*/
1089PRIVATE u16_t pcibr_intel_rsts(busind)
1090int 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 *===========================================================================*/
1101PRIVATE void pcibr_intel_wsts(busind, value)
1102int busind;
1103u16_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 *===========================================================================*/
1118PRIVATE u16_t pcibr_via_rsts(busind)
1119int busind;
1120{
1121 int devind;
1122 devind= pcibus[busind].pb_devind;
1123
1124 return 0;
1125}
1126
1127/*===========================================================================*
1128 * pcibr_via_wsts *
1129 *===========================================================================*/
1130PRIVATE void pcibr_via_wsts(busind, value)
1131int busind;
1132u16_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 *===========================================================================*/
1146PRIVATE void pci_attr_wsts(devind, value)
1147int devind;
1148u16_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 *===========================================================================*/
1160PRIVATE u8_t pcii_rreg8(busind, devind, port)
1161int busind;
1162int devind;
1163int 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 *===========================================================================*/
1189PRIVATE u16_t pcii_rreg16(busind, devind, port)
1190int busind;
1191int devind;
1192int 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 *===========================================================================*/
1218PRIVATE u32_t pcii_rreg32(busind, devind, port)
1219int busind;
1220int devind;
1221int 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 *===========================================================================*/
1247PRIVATE void pcii_wreg16(busind, devind, port, value)
1248int busind;
1249int devind;
1250int port;
1251u16_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 *===========================================================================*/
1274PRIVATE void pcii_wreg32(busind, devind, port, value)
1275int busind;
1276int devind;
1277int port;
1278u32_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 *===========================================================================*/
1301PRIVATE u16_t pcii_rsts(busind)
1302int 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 *===========================================================================*/
1320PRIVATE void pcii_wsts(busind, value)
1321int busind;
1322u16_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 */
Note: See TracBrowser for help on using the repository browser.