4 * initialise bridge mappings if the PCI BIOS didn't.
7 #include "../port/lib.h"
12 #include "../port/error.h"
20 { /* command register */
29 static Lock pcicfglock;
30 static Lock pcicfginitlock;
31 static int pcicfgmode = -1;
33 static Pcidev* pciroot;
34 static Pcidev* pcilist;
35 static Pcidev* pcitail;
37 static int pcicfgrw32(int, int, int, int);
42 pciscan(int bno, Pcidev** list)
45 Pcidev *p, *head, *tail;
46 int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
51 for(dno = 0; dno <= pcimaxdno; dno++){
53 for(fno = 0; fno <= maxfno; fno++){
55 * For this possible device, form the
56 * bus+device+function triplet needed to address it
57 * and try to read the vendor and device ID.
58 * If successful, allocate a device struct and
59 * start to fill it in with some useful information
60 * from the device's configuration space.
62 tbdf = MKBUS(BusPCI, bno, dno, fno);
63 l = pcicfgrw32(tbdf, PciVID, 0, 1);
64 if(l == 0xFFFFFFFF || l == 0)
66 /* optional safety checks:
67 if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
69 if(l != pcicfgrw32(tbdf, PciVID, 0, 1))
71 if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
74 p = malloc(sizeof(*p));
85 p->rid = pcicfgr8(p, PciRID);
86 p->ccrp = pcicfgr8(p, PciCCRp);
87 p->ccru = pcicfgr8(p, PciCCRu);
88 p->ccrb = pcicfgr8(p, PciCCRb);
89 p->pcr = pcicfgr32(p, PciPCR);
91 p->intl = pcicfgr8(p, PciINTL);
94 * If the device is a multi-function device adjust the
95 * loop count so all possible functions are checked.
97 hdt = pcicfgr8(p, PciHDT);
102 * If appropriate, read the base address registers
103 * and work out the sizes.
107 case 0x03: /* display controller */
109 v = pcicfgr32(p, PciROM);
110 pcicfgw32(p, PciROM, v|1); /* enable decode */
111 vgabios = kmapv(((uvlong)0x88<<32LL)|(v&~0xffff), 0x10000);
112 // print("VGA BIOS %lux -> %lux\n", v, vgabios);
115 case 0x01: /* mass storage controller */
116 case 0x02: /* network controller */
117 case 0x04: /* multimedia device */
118 case 0x07: /* simple communication controllers */
119 case 0x08: /* base system peripherals */
120 case 0x09: /* input devices */
121 case 0x0A: /* docking stations */
122 case 0x0B: /* processors */
123 case 0x0C: /* serial bus controllers */
124 if((hdt & 0x7F) != 0)
127 for(i = 0; i < nelem(p->mem); i++){
129 p->mem[i].bar = pcicfgr32(p, rno);
130 pcicfgw32(p, rno, -1);
131 v = pcicfgr32(p, rno);
132 pcicfgw32(p, rno, p->mem[i].bar);
133 p->mem[i].size = -(v & ~0xF);
138 case 0x05: /* memory controller */
139 case 0x06: /* bridge device */
153 for(p = head; p != nil; p = p->link){
155 * Find PCI-PCI bridges and recursively descend the tree.
157 if(p->ccrb != 0x06 || p->ccru != 0x04)
161 * If the secondary or subordinate bus number is not initialised
162 * try to do what the PCI BIOS should have done and fill in the
163 * numbers as the tree is descended. On the way down the subordinate
164 * bus number is set to the maximum as it's not known how many
165 * buses are behind this one; the final value is set on the way
168 sbn = pcicfgr8(p, PciSBN);
169 ubn = pcicfgr8(p, PciUBN);
170 if(sbn == 0 || ubn == 0){
173 * Make sure memory, I/O and master enables are off,
174 * set the primary, secondary and subordinate bus numbers
175 * and clear the secondary status before attempting to
176 * scan the secondary bus.
178 * Initialisation of the bridge should be done here.
180 pcicfgw32(p, PciPCR, 0xFFFF0000);
181 l = (MaxUBN<<16)|(sbn<<8)|bno;
182 pcicfgw32(p, PciPBN, l);
183 pcicfgw16(p, PciSPSR, 0xFFFF);
184 maxubn = pciscan(sbn, &p->bridge);
185 l = (maxubn<<16)|(sbn<<8)|bno;
186 pcicfgw32(p, PciPBN, l);
190 pciscan(sbn, &p->bridge);
202 lock(&pcicfginitlock);
203 if(pcicfgmode == -1){
205 pcimaxdno = 15; /* was 20; what is correct value??? */
206 if(p = getconf("*pcimaxdno"))
207 pcimaxdno = strtoul(p, 0, 0);
208 pciscan(0, &pciroot);
210 unlock(&pcicfginitlock);
214 pcicfgrw8(int tbdf, int rno, int data, int read)
222 if(BUSDNO(tbdf) > pcimaxdno)
225 p = (uchar*)arch->pcicfg(tbdf, rno);
235 pcicfgr8(Pcidev* pcidev, int rno)
237 return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
241 pcicfgw8(Pcidev* pcidev, int rno, int data)
243 pcicfgrw8(pcidev->tbdf, rno, data, 0);
247 pcicfgrw16(int tbdf, int rno, int data, int read)
255 if(BUSDNO(tbdf) > pcimaxdno)
258 p = (ushort*)arch->pcicfg(tbdf, rno);
268 pcicfgr16(Pcidev* pcidev, int rno)
270 return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
274 pcicfgw16(Pcidev* pcidev, int rno, int data)
276 pcicfgrw16(pcidev->tbdf, rno, data, 0);
280 pcicfgrw32(int tbdf, int rno, int data, int read)
288 if(BUSDNO(tbdf) > pcimaxdno)
291 p = (ulong*)arch->pcicfg(tbdf, rno);
301 pcicfgr32(Pcidev* pcidev, int rno)
303 return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
307 pcicfgw32(Pcidev* pcidev, int rno, int data)
309 pcicfgrw32(pcidev->tbdf, rno, data, 0);
313 pcimatch(Pcidev* prev, int vid, int did)
324 if((vid == 0 || prev->vid == vid)
325 && (did == 0 || prev->did == did))
333 pcimatchtbdf(int tbdf)
340 for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
341 if(pcidev->tbdf == tbdf)
357 print("bus dev type vid did intl memory\n");
359 for(t = p; t != nil; t = t->link) {
360 print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %2d ",
361 BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
362 t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
364 for(i = 0; i < nelem(p->mem); i++) {
365 if(t->mem[i].size == 0)
367 print("%d:%.8lux %d ", i,
368 t->mem[i].bar, t->mem[i].size);
388 for(p = pcilist; p != nil; p = p->list){
389 pcr = pcicfgr16(p, PciPSR);
390 pcicfgw16(p, PciPSR, pcr & ~0x04);
399 pcr = pcicfgr16(p, PciPCR);
401 pcicfgw16(p, PciPCR, pcr);
409 pcr = pcicfgr16(p, PciPCR);
411 pcicfgw16(p, PciPCR, pcr);