FreeBSD/Linux Kernel Cross Reference
sys/pc/pci.c
1 /*
2 * PCI support code.
3 * Needs a massive rewrite.
4 */
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "../port/error.h"
12
13 #define DBG if(0) pcilog
14
15 struct
16 {
17 char output[16384];
18 int ptr;
19 }PCICONS;
20
21 int
22 pcilog(char *fmt, ...)
23 {
24 int n;
25 va_list arg;
26 char buf[PRINTSIZE];
27
28 va_start(arg, fmt);
29 n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
30 va_end(arg);
31
32 memmove(PCICONS.output+PCICONS.ptr, buf, n);
33 PCICONS.ptr += n;
34 return n;
35 }
36
37 enum
38 { /* configuration mechanism #1 */
39 PciADDR = 0xCF8, /* CONFIG_ADDRESS */
40 PciDATA = 0xCFC, /* CONFIG_DATA */
41
42 /* configuration mechanism #2 */
43 PciCSE = 0xCF8, /* configuration space enable */
44 PciFORWARD = 0xCFA, /* which bus */
45
46 MaxFNO = 7,
47 MaxUBN = 255,
48 };
49
50 enum
51 { /* command register */
52 IOen = (1<<0),
53 MEMen = (1<<1),
54 MASen = (1<<2),
55 MemWrInv = (1<<4),
56 PErrEn = (1<<6),
57 SErrEn = (1<<8),
58 };
59
60 static Lock pcicfglock;
61 static Lock pcicfginitlock;
62 static int pcicfgmode = -1;
63 static int pcimaxbno = 7;
64 static int pcimaxdno;
65 static Pcidev* pciroot;
66 static Pcidev* pcilist;
67 static Pcidev* pcitail;
68 static int nobios, nopcirouting;
69 static BIOS32si* pcibiossi;
70
71 static int pcicfgrw8raw(int, int, int, int);
72 static int pcicfgrw16raw(int, int, int, int);
73 static int pcicfgrw32raw(int, int, int, int);
74
75 static int (*pcicfgrw8)(int, int, int, int) = pcicfgrw8raw;
76 static int (*pcicfgrw16)(int, int, int, int) = pcicfgrw16raw;
77 static int (*pcicfgrw32)(int, int, int, int) = pcicfgrw32raw;
78
79 static char* bustypes[] = {
80 "CBUSI",
81 "CBUSII",
82 "EISA",
83 "FUTURE",
84 "INTERN",
85 "ISA",
86 "MBI",
87 "MBII",
88 "MCA",
89 "MPI",
90 "MPSA",
91 "NUBUS",
92 "PCI",
93 "PCMCIA",
94 "TC",
95 "VL",
96 "VME",
97 "XPRESS",
98 };
99
100 #pragma varargck type "T" int
101
102 static int
103 tbdffmt(Fmt* fmt)
104 {
105 char *p;
106 int l, r, type, tbdf;
107
108 if((p = malloc(READSTR)) == nil)
109 return fmtstrcpy(fmt, "(tbdfconv)");
110
111 switch(fmt->r){
112 case 'T':
113 tbdf = va_arg(fmt->args, int);
114 type = BUSTYPE(tbdf);
115 if(type < nelem(bustypes))
116 l = snprint(p, READSTR, bustypes[type]);
117 else
118 l = snprint(p, READSTR, "%d", type);
119 snprint(p+l, READSTR-l, ".%d.%d.%d",
120 BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
121 break;
122
123 default:
124 snprint(p, READSTR, "(tbdfconv)");
125 break;
126 }
127 r = fmtstrcpy(fmt, p);
128 free(p);
129
130 return r;
131 }
132
133 ulong
134 pcibarsize(Pcidev *p, int rno)
135 {
136 ulong v, size;
137
138 v = pcicfgrw32(p->tbdf, rno, 0, 1);
139 pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
140 size = pcicfgrw32(p->tbdf, rno, 0, 1);
141 if(v & 1)
142 size |= 0xFFFF0000;
143 pcicfgrw32(p->tbdf, rno, v, 0);
144
145 return -(size & ~0x0F);
146 }
147
148 static int
149 pcisizcmp(void *a, void *b)
150 {
151 Pcisiz *aa, *bb;
152
153 aa = a;
154 bb = b;
155 return aa->siz - bb->siz;
156 }
157
158 static ulong
159 pcimask(ulong v)
160 {
161 ulong m;
162
163 m = BI2BY*sizeof(v);
164 for(m = 1<<(m-1); m != 0; m >>= 1) {
165 if(m & v)
166 break;
167 }
168
169 m--;
170 if((v & m) == 0)
171 return v;
172
173 v |= m;
174 return v+1;
175 }
176
177 static void
178 pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
179 {
180 Pcidev *p;
181 int ntb, i, size, rno, hole;
182 ulong v, mema, ioa, sioa, smema, base, limit;
183 Pcisiz *table, *tptr, *mtb, *itb;
184
185 if(!nobios)
186 return;
187
188 ioa = *pioa;
189 mema = *pmema;
190
191 DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n",
192 wrreg, root->tbdf, mema, ioa);
193
194 ntb = 0;
195 for(p = root; p != nil; p = p->link)
196 ntb++;
197
198 ntb *= (PciCIS-PciBAR0)/4;
199 table = malloc(2*ntb*sizeof(Pcisiz));
200 itb = table;
201 mtb = table+ntb;
202
203 /*
204 * Build a table of sizes
205 */
206 for(p = root; p != nil; p = p->link) {
207 if(p->ccrb == 0x06) {
208 if(p->ccru != 0x04 || p->bridge == nil) {
209 // DBG("pci: ignored bridge %T\n", p->tbdf);
210 continue;
211 }
212
213 sioa = ioa;
214 smema = mema;
215 pcibusmap(p->bridge, &smema, &sioa, 0);
216
217 hole = pcimask(smema-mema);
218 if(hole < (1<<20))
219 hole = 1<<20;
220 p->mema.size = hole;
221
222 hole = pcimask(sioa-ioa);
223 if(hole < (1<<12))
224 hole = 1<<12;
225
226 p->ioa.size = hole;
227
228 itb->dev = p;
229 itb->bar = -1;
230 itb->siz = p->ioa.size;
231 itb++;
232
233 mtb->dev = p;
234 mtb->bar = -1;
235 mtb->siz = p->mema.size;
236 mtb++;
237 continue;
238 }
239
240 for(i = 0; i <= 5; i++) {
241 rno = PciBAR0 + i*4;
242 v = pcicfgrw32(p->tbdf, rno, 0, 1);
243 size = pcibarsize(p, rno);
244 if(size == 0)
245 continue;
246
247 if(v & 1) {
248 itb->dev = p;
249 itb->bar = i;
250 itb->siz = size;
251 itb++;
252 }
253 else {
254 mtb->dev = p;
255 mtb->bar = i;
256 mtb->siz = size;
257 mtb++;
258 }
259
260 p->mem[i].size = size;
261 }
262 }
263
264 /*
265 * Sort both tables IO smallest first, Memory largest
266 */
267 qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
268 tptr = table+ntb;
269 qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
270
271 /*
272 * Allocate IO address space on this bus
273 */
274 for(tptr = table; tptr < itb; tptr++) {
275 hole = tptr->siz;
276 if(tptr->bar == -1)
277 hole = 1<<12;
278 ioa = (ioa+hole-1) & ~(hole-1);
279
280 p = tptr->dev;
281 if(tptr->bar == -1)
282 p->ioa.bar = ioa;
283 else {
284 p->pcr |= IOen;
285 p->mem[tptr->bar].bar = ioa|1;
286 if(wrreg)
287 pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
288 }
289
290 ioa += tptr->siz;
291 }
292
293 /*
294 * Allocate Memory address space on this bus
295 */
296 for(tptr = table+ntb; tptr < mtb; tptr++) {
297 hole = tptr->siz;
298 if(tptr->bar == -1)
299 hole = 1<<20;
300 mema = (mema+hole-1) & ~(hole-1);
301
302 p = tptr->dev;
303 if(tptr->bar == -1)
304 p->mema.bar = mema;
305 else {
306 p->pcr |= MEMen;
307 p->mem[tptr->bar].bar = mema;
308 if(wrreg)
309 pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
310 }
311 mema += tptr->siz;
312 }
313
314 *pmema = mema;
315 *pioa = ioa;
316 free(table);
317
318 if(wrreg == 0)
319 return;
320
321 /*
322 * Finally set all the bridge addresses & registers
323 */
324 for(p = root; p != nil; p = p->link) {
325 if(p->bridge == nil) {
326 pcicfgrw8(p->tbdf, PciLTR, 64, 0);
327
328 p->pcr |= MASen;
329 pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0);
330 continue;
331 }
332
333 base = p->ioa.bar;
334 limit = base+p->ioa.size-1;
335 v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
336 v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
337 pcicfgrw32(p->tbdf, PciIBR, v, 0);
338 v = (limit & 0xFFFF0000)|(base>>16);
339 pcicfgrw32(p->tbdf, PciIUBR, v, 0);
340
341 base = p->mema.bar;
342 limit = base+p->mema.size-1;
343 v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
344 pcicfgrw32(p->tbdf, PciMBR, v, 0);
345
346 /*
347 * Disable memory prefetch
348 */
349 pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
350 pcicfgrw8(p->tbdf, PciLTR, 64, 0);
351
352 /*
353 * Enable the bridge
354 */
355 p->pcr |= IOen|MEMen|MASen;
356 pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr , 0);
357
358 sioa = p->ioa.bar;
359 smema = p->mema.bar;
360 pcibusmap(p->bridge, &smema, &sioa, 1);
361 }
362 }
363
364 static int
365 pcilscan(int bno, Pcidev** list)
366 {
367 Pcidev *p, *head, *tail;
368 int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
369
370 maxubn = bno;
371 head = nil;
372 tail = nil;
373 for(dno = 0; dno <= pcimaxdno; dno++){
374 maxfno = 0;
375 for(fno = 0; fno <= maxfno; fno++){
376 /*
377 * For this possible device, form the
378 * bus+device+function triplet needed to address it
379 * and try to read the vendor and device ID.
380 * If successful, allocate a device struct and
381 * start to fill it in with some useful information
382 * from the device's configuration space.
383 */
384 tbdf = MKBUS(BusPCI, bno, dno, fno);
385 l = pcicfgrw32(tbdf, PciVID, 0, 1);
386 if(l == 0xFFFFFFFF || l == 0)
387 continue;
388 p = malloc(sizeof(*p));
389 p->tbdf = tbdf;
390 p->vid = l;
391 p->did = l>>16;
392
393 if(pcilist != nil)
394 pcitail->list = p;
395 else
396 pcilist = p;
397 pcitail = p;
398
399 p->pcr = pcicfgr16(p, PciPCR);
400 p->rid = pcicfgr8(p, PciRID);
401 p->ccrp = pcicfgr8(p, PciCCRp);
402 p->ccru = pcicfgr8(p, PciCCRu);
403 p->ccrb = pcicfgr8(p, PciCCRb);
404 p->cls = pcicfgr8(p, PciCLS);
405 p->ltr = pcicfgr8(p, PciLTR);
406
407 p->intl = pcicfgr8(p, PciINTL);
408
409 /*
410 * If the device is a multi-function device adjust the
411 * loop count so all possible functions are checked.
412 */
413 hdt = pcicfgr8(p, PciHDT);
414 if(hdt & 0x80)
415 maxfno = MaxFNO;
416
417 /*
418 * If appropriate, read the base address registers
419 * and work out the sizes.
420 */
421 switch(p->ccrb) {
422 case 0x01: /* mass storage controller */
423 case 0x02: /* network controller */
424 case 0x03: /* display controller */
425 case 0x04: /* multimedia device */
426 case 0x07: /* simple comm. controllers */
427 case 0x08: /* base system peripherals */
428 case 0x09: /* input devices */
429 case 0x0A: /* docking stations */
430 case 0x0B: /* processors */
431 case 0x0C: /* serial bus controllers */
432 if((hdt & 0x7F) != 0)
433 break;
434 rno = PciBAR0 - 4;
435 for(i = 0; i < nelem(p->mem); i++) {
436 rno += 4;
437 p->mem[i].bar = pcicfgr32(p, rno);
438 p->mem[i].size = pcibarsize(p, rno);
439 }
440 break;
441
442 case 0x00:
443 case 0x05: /* memory controller */
444 case 0x06: /* bridge device */
445 default:
446 break;
447 }
448
449 if(head != nil)
450 tail->link = p;
451 else
452 head = p;
453 tail = p;
454 }
455 }
456
457 *list = head;
458 for(p = head; p != nil; p = p->link){
459 /*
460 * Find PCI-PCI bridges and recursively descend the tree.
461 */
462 if(p->ccrb != 0x06 || p->ccru != 0x04)
463 continue;
464
465 /*
466 * If the secondary or subordinate bus number is not
467 * initialised try to do what the PCI BIOS should have
468 * done and fill in the numbers as the tree is descended.
469 * On the way down the subordinate bus number is set to
470 * the maximum as it's not known how many buses are behind
471 * this one; the final value is set on the way back up.
472 */
473 sbn = pcicfgr8(p, PciSBN);
474 ubn = pcicfgr8(p, PciUBN);
475
476 if(sbn == 0 || ubn == 0 || nobios) {
477 sbn = maxubn+1;
478 /*
479 * Make sure memory, I/O and master enables are
480 * off, set the primary, secondary and subordinate
481 * bus numbers and clear the secondary status before
482 * attempting to scan the secondary bus.
483 *
484 * Initialisation of the bridge should be done here.
485 */
486 pcicfgw32(p, PciPCR, 0xFFFF0000);
487 l = (MaxUBN<<16)|(sbn<<8)|bno;
488 pcicfgw32(p, PciPBN, l);
489 pcicfgw16(p, PciSPSR, 0xFFFF);
490 maxubn = pcilscan(sbn, &p->bridge);
491 l = (maxubn<<16)|(sbn<<8)|bno;
492
493 pcicfgw32(p, PciPBN, l);
494 }
495 else {
496 if(ubn > maxubn)
497 maxubn = ubn;
498 pcilscan(sbn, &p->bridge);
499 }
500 }
501
502 return maxubn;
503 }
504
505 int
506 pciscan(int bno, Pcidev **list)
507 {
508 int ubn;
509
510 lock(&pcicfginitlock);
511 ubn = pcilscan(bno, list);
512 unlock(&pcicfginitlock);
513 return ubn;
514 }
515
516 static uchar
517 pIIxget(Pcidev *router, uchar link)
518 {
519 uchar pirq;
520
521 /* link should be 0x60, 0x61, 0x62, 0x63 */
522 pirq = pcicfgr8(router, link);
523 return (pirq < 16)? pirq: 0;
524 }
525
526 static void
527 pIIxset(Pcidev *router, uchar link, uchar irq)
528 {
529 pcicfgw8(router, link, irq);
530 }
531
532 static uchar
533 viaget(Pcidev *router, uchar link)
534 {
535 uchar pirq;
536
537 /* link should be 1, 2, 3, 5 */
538 pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
539
540 return (link & 1)? (pirq >> 4): (pirq & 15);
541 }
542
543 static void
544 viaset(Pcidev *router, uchar link, uchar irq)
545 {
546 uchar pirq;
547
548 pirq = pcicfgr8(router, 0x55 + (link >> 1));
549 pirq &= (link & 1)? 0x0f: 0xf0;
550 pirq |= (link & 1)? (irq << 4): (irq & 15);
551 pcicfgw8(router, 0x55 + (link>>1), pirq);
552 }
553
554 static uchar
555 optiget(Pcidev *router, uchar link)
556 {
557 uchar pirq = 0;
558
559 /* link should be 0x02, 0x12, 0x22, 0x32 */
560 if ((link & 0xcf) == 0x02)
561 pirq = pcicfgr8(router, 0xb8 + (link >> 5));
562 return (link & 0x10)? (pirq >> 4): (pirq & 15);
563 }
564
565 static void
566 optiset(Pcidev *router, uchar link, uchar irq)
567 {
568 uchar pirq;
569
570 pirq = pcicfgr8(router, 0xb8 + (link >> 5));
571 pirq &= (link & 0x10)? 0x0f : 0xf0;
572 pirq |= (link & 0x10)? (irq << 4): (irq & 15);
573 pcicfgw8(router, 0xb8 + (link >> 5), pirq);
574 }
575
576 static uchar
577 aliget(Pcidev *router, uchar link)
578 {
579 /* No, you're not dreaming */
580 static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
581 uchar pirq;
582
583 /* link should be 0x01..0x08 */
584 pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
585 return (link & 1)? map[pirq&15]: map[pirq>>4];
586 }
587
588 static void
589 aliset(Pcidev *router, uchar link, uchar irq)
590 {
591 /* Inverse of map in aliget */
592 static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
593 uchar pirq;
594
595 pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
596 pirq &= (link & 1)? 0x0f: 0xf0;
597 pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
598 pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
599 }
600
601 static uchar
602 cyrixget(Pcidev *router, uchar link)
603 {
604 uchar pirq;
605
606 /* link should be 1, 2, 3, 4 */
607 pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
608 return ((link & 1)? pirq >> 4: pirq & 15);
609 }
610
611 static void
612 cyrixset(Pcidev *router, uchar link, uchar irq)
613 {
614 uchar pirq;
615
616 pirq = pcicfgr8(router, 0x5c + (link>>1));
617 pirq &= (link & 1)? 0x0f: 0xf0;
618 pirq |= (link & 1)? (irq << 4): (irq & 15);
619 pcicfgw8(router, 0x5c + (link>>1), pirq);
620 }
621
622 typedef struct Bridge Bridge;
623 struct Bridge
624 {
625 ushort vid;
626 ushort did;
627 uchar (*get)(Pcidev *, uchar);
628 void (*set)(Pcidev *, uchar, uchar);
629 };
630
631 static Bridge southbridges[] = {
632 { 0x8086, 0x122e, pIIxget, pIIxset }, /* Intel 82371FB */
633 { 0x8086, 0x1234, pIIxget, pIIxset }, /* Intel 82371MX */
634 { 0x8086, 0x7000, pIIxget, pIIxset }, /* Intel 82371SB */
635 { 0x8086, 0x7110, pIIxget, pIIxset }, /* Intel 82371AB */
636 { 0x8086, 0x7198, pIIxget, pIIxset }, /* Intel 82443MX (fn 1) */
637 { 0x8086, 0x2410, pIIxget, pIIxset }, /* Intel 82801AA */
638 { 0x8086, 0x2420, pIIxget, pIIxset }, /* Intel 82801AB */
639 { 0x8086, 0x2440, pIIxget, pIIxset }, /* Intel 82801BA */
640 { 0x8086, 0x244c, pIIxget, pIIxset }, /* Intel 82801BAM */
641 { 0x8086, 0x2480, pIIxget, pIIxset }, /* Intel 82801CA */
642 { 0x8086, 0x248c, pIIxget, pIIxset }, /* Intel 82801CAM */
643 { 0x8086, 0x24c0, pIIxget, pIIxset }, /* Intel 82801DBL */
644 { 0x8086, 0x24cc, pIIxget, pIIxset }, /* Intel 82801DBM */
645 { 0x8086, 0x24d0, pIIxget, pIIxset }, /* Intel 82801EB */
646 { 0x8086, 0x25a1, pIIxget, pIIxset }, /* Intel 6300ESB */
647 { 0x8086, 0x2640, pIIxget, pIIxset }, /* Intel 82801FB */
648 { 0x8086, 0x27b8, pIIxget, pIIxset }, /* Intel 82801GB */
649 { 0x8086, 0x27b9, pIIxget, pIIxset }, /* Intel 82801GBM */
650 { 0x8086, 0x2916, pIIxget, pIIxset }, /* Intel 82801? */
651 { 0x1106, 0x0586, viaget, viaset }, /* Viatech 82C586 */
652 { 0x1106, 0x0596, viaget, viaset }, /* Viatech 82C596 */
653 { 0x1106, 0x0686, viaget, viaset }, /* Viatech 82C686 */
654 { 0x1106, 0x3227, viaget, viaset }, /* Viatech VT8237 */
655 { 0x1045, 0xc700, optiget, optiset }, /* Opti 82C700 */
656 { 0x10b9, 0x1533, aliget, aliset }, /* Al M1533 */
657 { 0x1039, 0x0008, pIIxget, pIIxset }, /* SI 503 */
658 { 0x1039, 0x0496, pIIxget, pIIxset }, /* SI 496 */
659 { 0x1078, 0x0100, cyrixget, cyrixset }, /* Cyrix 5530 Legacy */
660
661 { 0x1022, 0x746B, nil, nil }, /* AMD 8111 */
662 { 0x10DE, 0x00D1, nil, nil }, /* NVIDIA nForce 3 */
663 { 0x10DE, 0x00E0, nil, nil }, /* NVIDIA nForce 3 250 Series */
664 { 0x10DE, 0x00E1, nil, nil }, /* NVIDIA nForce 3 250 Series */
665 { 0x1166, 0x0200, nil, nil }, /* ServerWorks ServerSet III LE */
666 { 0x1002, 0x4377, nil, nil }, /* ATI Radeon Xpress 200M */
667 { 0x1002, 0x4372, nil, nil }, /* ATI SB400 */
668 };
669
670 typedef struct Slot Slot;
671 struct Slot {
672 uchar bus; /* Pci bus number */
673 uchar dev; /* Pci device number */
674 uchar maps[12]; /* Avoid structs! Link and mask. */
675 uchar slot; /* Add-in/built-in slot */
676 uchar reserved;
677 };
678
679 typedef struct Router Router;
680 struct Router {
681 uchar signature[4]; /* Routing table signature */
682 uchar version[2]; /* Version number */
683 uchar size[2]; /* Total table size */
684 uchar bus; /* Interrupt router bus number */
685 uchar devfn; /* Router's devfunc */
686 uchar pciirqs[2]; /* Exclusive PCI irqs */
687 uchar compat[4]; /* Compatible PCI interrupt router */
688 uchar miniport[4]; /* Miniport data */
689 uchar reserved[11];
690 uchar checksum;
691 };
692
693 static ushort pciirqs; /* Exclusive PCI irqs */
694 static Bridge *southbridge; /* Which southbridge to use. */
695
696 static void
697 pcirouting(void)
698 {
699 Slot *e;
700 Router *r;
701 int size, i, fn, tbdf;
702 Pcidev *sbpci, *pci;
703 uchar *p, pin, irq, link, *map;
704
705 /* Search for PCI interrupt routing table in BIOS */
706 for(p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
707 if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
708 break;
709
710 if(p >= (uchar *)KADDR(0xfffff))
711 return;
712
713 r = (Router *)p;
714
715 // print("PCI interrupt routing table version %d.%d at %.6uX\n",
716 // r->version[0], r->version[1], (ulong)r & 0xfffff);
717
718 tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8);
719 sbpci = pcimatchtbdf(tbdf);
720 if(sbpci == nil) {
721 print("pcirouting: Cannot find south bridge %T\n", tbdf);
722 return;
723 }
724
725 for(i = 0; i != nelem(southbridges); i++)
726 if(sbpci->vid == southbridges[i].vid && sbpci->did == southbridges[i].did)
727 break;
728
729 if(i == nelem(southbridges)) {
730 print("pcirouting: ignoring south bridge %T %.4uX/%.4uX\n", tbdf, sbpci->vid, sbpci->did);
731 return;
732 }
733 southbridge = &southbridges[i];
734 if(southbridge->get == nil || southbridge->set == nil)
735 return;
736
737 pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0];
738
739 size = (r->size[1] << 8)|r->size[0];
740 for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) {
741 if (0) {
742 print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot);
743 for (i = 0; i != 4; i++) {
744 uchar *m = &e->maps[i * 3];
745 print("[%d] %.2uX %.4uX ",
746 i, m[0], (m[2] << 8)|m[1]);
747 }
748 print("\n");
749 }
750 for(fn = 0; fn != 8; fn++) {
751 tbdf = (BusPCI << 24)|(e->bus << 16)|((e->dev | fn) << 8);
752 pci = pcimatchtbdf(tbdf);
753 if(pci == nil)
754 continue;
755 pin = pcicfgr8(pci, PciINTP);
756 if(pin == 0 || pin == 0xff)
757 continue;
758
759 map = &e->maps[(pin - 1) * 3];
760 link = map[0];
761 irq = southbridge->get(sbpci, link);
762 if(irq == 0 || irq == pci->intl)
763 continue;
764 if(pci->intl != 0 && pci->intl != 0xFF) {
765 print("pcirouting: BIOS workaround: %T at pin %d link %d irq %d -> %d\n",
766 tbdf, pin, link, irq, pci->intl);
767 southbridge->set(sbpci, link, pci->intl);
768 continue;
769 }
770 print("pcirouting: %T at pin %d link %d irq %d\n", tbdf, pin, link, irq);
771 pcicfgw8(pci, PciINTL, irq);
772 pci->intl = irq;
773 }
774 }
775 }
776
777 static void pcireservemem(void);
778
779 static int
780 pcicfgrw8bios(int tbdf, int rno, int data, int read)
781 {
782 BIOS32ci ci;
783
784 if(pcibiossi == nil)
785 return -1;
786
787 memset(&ci, 0, sizeof(BIOS32ci));
788 ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
789 ci.edi = rno;
790 if(read){
791 ci.eax = 0xB108;
792 if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
793 return ci.ecx & 0xFF;
794 }
795 else{
796 ci.eax = 0xB10B;
797 ci.ecx = data & 0xFF;
798 if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
799 return 0;
800 }
801
802 return -1;
803 }
804
805 static int
806 pcicfgrw16bios(int tbdf, int rno, int data, int read)
807 {
808 BIOS32ci ci;
809
810 if(pcibiossi == nil)
811 return -1;
812
813 memset(&ci, 0, sizeof(BIOS32ci));
814 ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
815 ci.edi = rno;
816 if(read){
817 ci.eax = 0xB109;
818 if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
819 return ci.ecx & 0xFFFF;
820 }
821 else{
822 ci.eax = 0xB10C;
823 ci.ecx = data & 0xFFFF;
824 if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
825 return 0;
826 }
827
828 return -1;
829 }
830
831 static int
832 pcicfgrw32bios(int tbdf, int rno, int data, int read)
833 {
834 BIOS32ci ci;
835
836 if(pcibiossi == nil)
837 return -1;
838
839 memset(&ci, 0, sizeof(BIOS32ci));
840 ci.ebx = (BUSBNO(tbdf)<<8)|(BUSDNO(tbdf)<<3)|BUSFNO(tbdf);
841 ci.edi = rno;
842 if(read){
843 ci.eax = 0xB10A;
844 if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
845 return ci.ecx;
846 }
847 else{
848 ci.eax = 0xB10D;
849 ci.ecx = data;
850 if(!bios32ci(pcibiossi, &ci)/* && !(ci.eax & 0xFF)*/)
851 return 0;
852 }
853
854 return -1;
855 }
856
857 static BIOS32si*
858 pcibiosinit(void)
859 {
860 BIOS32ci ci;
861 BIOS32si *si;
862
863 if((si = bios32open("$PCI")) == nil)
864 return nil;
865
866 memset(&ci, 0, sizeof(BIOS32ci));
867 ci.eax = 0xB101;
868 if(bios32ci(si, &ci) || ci.edx != ((' '<<24)|('I'<<16)|('C'<<8)|'P')){
869 free(si);
870 return nil;
871 }
872 if(ci.eax & 0x01)
873 pcimaxdno = 31;
874 else
875 pcimaxdno = 15;
876 pcimaxbno = ci.ecx & 0xff;
877
878 return si;
879 }
880
881 void
882 pcibussize(Pcidev *root, ulong *msize, ulong *iosize)
883 {
884 *msize = 0;
885 *iosize = 0;
886 pcibusmap(root, msize, iosize, 0);
887 }
888
889 static void
890 pcicfginit(void)
891 {
892 char *p;
893 Pcidev **list;
894 ulong mema, ioa;
895 int bno, n, pcibios;
896
897 lock(&pcicfginitlock);
898 if(pcicfgmode != -1)
899 goto out;
900
901 pcibios = 0;
902 if(getconf("*nobios"))
903 nobios = 1;
904 else if(getconf("*pcibios"))
905 pcibios = 1;
906 if(getconf("*nopcirouting"))
907 nopcirouting = 1;
908
909 /*
910 * Try to determine which PCI configuration mode is implemented.
911 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
912 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
913 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
914 * a device behind these addresses so if Mode1 accesses fail try
915 * for Mode2 (Mode2 is deprecated).
916 */
917 if(!pcibios){
918 /*
919 * Bits [30:24] of PciADDR must be 0,
920 * according to the spec.
921 */
922 n = inl(PciADDR);
923 if(!(n & 0x7F000000)){
924 outl(PciADDR, 0x80000000);
925 outb(PciADDR+3, 0);
926 if(inl(PciADDR) & 0x80000000){
927 pcicfgmode = 1;
928 pcimaxdno = 31;
929 }
930 }
931 outl(PciADDR, n);
932
933 if(pcicfgmode < 0){
934 /*
935 * The 'key' part of PciCSE should be 0.
936 */
937 n = inb(PciCSE);
938 if(!(n & 0xF0)){
939 outb(PciCSE, 0x0E);
940 if(inb(PciCSE) == 0x0E){
941 pcicfgmode = 2;
942 pcimaxdno = 15;
943 }
944 }
945 outb(PciCSE, n);
946 }
947 }
948
949 if(pcicfgmode < 0 || pcibios) {
950 if((pcibiossi = pcibiosinit()) == nil)
951 goto out;
952 pcicfgrw8 = pcicfgrw8bios;
953 pcicfgrw16 = pcicfgrw16bios;
954 pcicfgrw32 = pcicfgrw32bios;
955 pcicfgmode = 3;
956 }
957
958 fmtinstall('T', tbdffmt);
959
960 if(p = getconf("*pcimaxbno")){
961 n = strtoul(p, 0, 0);
962 if(n < pcimaxbno)
963 pcimaxbno = n;
964 }
965 if(p = getconf("*pcimaxdno")){
966 n = strtoul(p, 0, 0);
967 if(n < pcimaxdno)
968 pcimaxdno = n;
969 }
970
971 list = &pciroot;
972 for(bno = 0; bno <= pcimaxbno; bno++) {
973 int sbno = bno;
974 bno = pcilscan(bno, list);
975
976 while(*list)
977 list = &(*list)->link;
978
979 if (sbno == 0) {
980 Pcidev *pci;
981
982 /*
983 * If we have found a PCI-to-Cardbus bridge, make sure
984 * it has no valid mappings anymore.
985 */
986 for(pci = pciroot; pci != nil; pci = pci->link){
987 if (pci->ccrb == 6 && pci->ccru == 7) {
988 ushort bcr;
989
990 /* reset the cardbus */
991 bcr = pcicfgr16(pci, PciBCR);
992 pcicfgw16(pci, PciBCR, 0x40 | bcr);
993 delay(50);
994 }
995 }
996 }
997 }
998
999 if(pciroot == nil)
1000 goto out;
1001
1002 if(nobios) {
1003 /*
1004 * Work out how big the top bus is
1005 */
1006 pcibussize(pciroot, &mema, &ioa);
1007
1008 /*
1009 * Align the windows and map it
1010 */
1011 ioa = 0x1000;
1012 mema = 0x90000000;
1013
1014 pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
1015
1016 pcibusmap(pciroot, &mema, &ioa, 1);
1017 DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
1018
1019 unlock(&pcicfginitlock);
1020 return;
1021 }
1022
1023 if (!nopcirouting)
1024 pcirouting();
1025
1026 out:
1027 pcireservemem();
1028 unlock(&pcicfginitlock);
1029
1030 if(getconf("*pcihinv"))
1031 pcihinv(nil);
1032 }
1033
1034 static void
1035 pcireservemem(void)
1036 {
1037 int i;
1038 Pcidev *p;
1039
1040 /*
1041 * mark all the physical address space claimed by pci devices
1042 * as in use, so that upaalloc doesn't give it out.
1043 */
1044 for(p=pciroot; p; p=p->list)
1045 for(i=0; i<nelem(p->mem); i++)
1046 if(p->mem[i].bar && (p->mem[i].bar&1) == 0)
1047 upareserve(p->mem[i].bar&~0x0F, p->mem[i].size);
1048 }
1049
1050 static int
1051 pcicfgrw8raw(int tbdf, int rno, int data, int read)
1052 {
1053 int o, type, x;
1054
1055 if(pcicfgmode == -1)
1056 pcicfginit();
1057
1058 if(BUSBNO(tbdf))
1059 type = 0x01;
1060 else
1061 type = 0x00;
1062 x = -1;
1063 if(BUSDNO(tbdf) > pcimaxdno)
1064 return x;
1065
1066 lock(&pcicfglock);
1067 switch(pcicfgmode){
1068
1069 case 1:
1070 o = rno & 0x03;
1071 rno &= ~0x03;
1072 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
1073 if(read)
1074 x = inb(PciDATA+o);
1075 else
1076 outb(PciDATA+o, data);
1077 outl(PciADDR, 0);
1078 break;
1079
1080 case 2:
1081 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
1082 outb(PciFORWARD, BUSBNO(tbdf));
1083 if(read)
1084 x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
1085 else
1086 outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
1087 outb(PciCSE, 0);
1088 break;
1089 }
1090 unlock(&pcicfglock);
1091
1092 return x;
1093 }
1094
1095 int
1096 pcicfgr8(Pcidev* pcidev, int rno)
1097 {
1098 return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
1099 }
1100
1101 void
1102 pcicfgw8(Pcidev* pcidev, int rno, int data)
1103 {
1104 pcicfgrw8(pcidev->tbdf, rno, data, 0);
1105 }
1106
1107 static int
1108 pcicfgrw16raw(int tbdf, int rno, int data, int read)
1109 {
1110 int o, type, x;
1111
1112 if(pcicfgmode == -1)
1113 pcicfginit();
1114
1115 if(BUSBNO(tbdf))
1116 type = 0x01;
1117 else
1118 type = 0x00;
1119 x = -1;
1120 if(BUSDNO(tbdf) > pcimaxdno)
1121 return x;
1122
1123 lock(&pcicfglock);
1124 switch(pcicfgmode){
1125
1126 case 1:
1127 o = rno & 0x02;
1128 rno &= ~0x03;
1129 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
1130 if(read)
1131 x = ins(PciDATA+o);
1132 else
1133 outs(PciDATA+o, data);
1134 outl(PciADDR, 0);
1135 break;
1136
1137 case 2:
1138 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
1139 outb(PciFORWARD, BUSBNO(tbdf));
1140 if(read)
1141 x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
1142 else
1143 outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
1144 outb(PciCSE, 0);
1145 break;
1146 }
1147 unlock(&pcicfglock);
1148
1149 return x;
1150 }
1151
1152 int
1153 pcicfgr16(Pcidev* pcidev, int rno)
1154 {
1155 return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
1156 }
1157
1158 void
1159 pcicfgw16(Pcidev* pcidev, int rno, int data)
1160 {
1161 pcicfgrw16(pcidev->tbdf, rno, data, 0);
1162 }
1163
1164 static int
1165 pcicfgrw32raw(int tbdf, int rno, int data, int read)
1166 {
1167 int type, x;
1168
1169 if(pcicfgmode == -1)
1170 pcicfginit();
1171
1172 if(BUSBNO(tbdf))
1173 type = 0x01;
1174 else
1175 type = 0x00;
1176 x = -1;
1177 if(BUSDNO(tbdf) > pcimaxdno)
1178 return x;
1179
1180 lock(&pcicfglock);
1181 switch(pcicfgmode){
1182
1183 case 1:
1184 rno &= ~0x03;
1185 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
1186 if(read)
1187 x = inl(PciDATA);
1188 else
1189 outl(PciDATA, data);
1190 outl(PciADDR, 0);
1191 break;
1192
1193 case 2:
1194 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
1195 outb(PciFORWARD, BUSBNO(tbdf));
1196 if(read)
1197 x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
1198 else
1199 outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
1200 outb(PciCSE, 0);
1201 break;
1202 }
1203 unlock(&pcicfglock);
1204
1205 return x;
1206 }
1207
1208 int
1209 pcicfgr32(Pcidev* pcidev, int rno)
1210 {
1211 return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
1212 }
1213
1214 void
1215 pcicfgw32(Pcidev* pcidev, int rno, int data)
1216 {
1217 pcicfgrw32(pcidev->tbdf, rno, data, 0);
1218 }
1219
1220 Pcidev*
1221 pcimatch(Pcidev* prev, int vid, int did)
1222 {
1223 if(pcicfgmode == -1)
1224 pcicfginit();
1225
1226 if(prev == nil)
1227 prev = pcilist;
1228 else
1229 prev = prev->list;
1230
1231 while(prev != nil){
1232 if((vid == 0 || prev->vid == vid)
1233 && (did == 0 || prev->did == did))
1234 break;
1235 prev = prev->list;
1236 }
1237 return prev;
1238 }
1239
1240 Pcidev*
1241 pcimatchtbdf(int tbdf)
1242 {
1243 Pcidev *pcidev;
1244
1245 if(pcicfgmode == -1)
1246 pcicfginit();
1247
1248 for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
1249 if(pcidev->tbdf == tbdf)
1250 break;
1251 }
1252 return pcidev;
1253 }
1254
1255 uchar
1256 pciipin(Pcidev *pci, uchar pin)
1257 {
1258 if (pci == nil)
1259 pci = pcilist;
1260
1261 while (pci) {
1262 uchar intl;
1263
1264 if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
1265 return pci->intl;
1266
1267 if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
1268 return intl;
1269
1270 pci = pci->list;
1271 }
1272 return 0;
1273 }
1274
1275 static void
1276 pcilhinv(Pcidev* p)
1277 {
1278 int i;
1279 Pcidev *t;
1280
1281 if(p == nil) {
1282 putstrn(PCICONS.output, PCICONS.ptr);
1283 p = pciroot;
1284 print("bus dev type vid did intl memory\n");
1285 }
1286 for(t = p; t != nil; t = t->link) {
1287 print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
1288 BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
1289 t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
1290
1291 for(i = 0; i < nelem(p->mem); i++) {
1292 if(t->mem[i].size == 0)
1293 continue;
1294 print("%d:%.8lux %d ", i,
1295 t->mem[i].bar, t->mem[i].size);
1296 }
1297 if(t->ioa.bar || t->ioa.size)
1298 print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
1299 if(t->mema.bar || t->mema.size)
1300 print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
1301 if(t->bridge)
1302 print("->%d", BUSBNO(t->bridge->tbdf));
1303 print("\n");
1304 }
1305 while(p != nil) {
1306 if(p->bridge != nil)
1307 pcilhinv(p->bridge);
1308 p = p->link;
1309 }
1310 }
1311
1312 void
1313 pcihinv(Pcidev* p)
1314 {
1315 if(pcicfgmode == -1)
1316 pcicfginit();
1317 lock(&pcicfginitlock);
1318 pcilhinv(p);
1319 unlock(&pcicfginitlock);
1320 }
1321
1322 void
1323 pcireset(void)
1324 {
1325 Pcidev *p;
1326
1327 if(pcicfgmode == -1)
1328 pcicfginit();
1329
1330 for(p = pcilist; p != nil; p = p->list) {
1331 /* don't mess with the bridges */
1332 if(p->ccrb == 0x06)
1333 continue;
1334 pciclrbme(p);
1335 }
1336 }
1337
1338 void
1339 pcisetioe(Pcidev* p)
1340 {
1341 p->pcr |= IOen;
1342 pcicfgw16(p, PciPCR, p->pcr);
1343 }
1344
1345 void
1346 pciclrioe(Pcidev* p)
1347 {
1348 p->pcr &= ~IOen;
1349 pcicfgw16(p, PciPCR, p->pcr);
1350 }
1351
1352 void
1353 pcisetbme(Pcidev* p)
1354 {
1355 p->pcr |= MASen;
1356 pcicfgw16(p, PciPCR, p->pcr);
1357 }
1358
1359 void
1360 pciclrbme(Pcidev* p)
1361 {
1362 p->pcr &= ~MASen;
1363 pcicfgw16(p, PciPCR, p->pcr);
1364 }
1365
1366 void
1367 pcisetmwi(Pcidev* p)
1368 {
1369 p->pcr |= MemWrInv;
1370 pcicfgw16(p, PciPCR, p->pcr);
1371 }
1372
1373 void
1374 pciclrmwi(Pcidev* p)
1375 {
1376 p->pcr &= ~MemWrInv;
1377 pcicfgw16(p, PciPCR, p->pcr);
1378 }
1379
1380 static int
1381 pcigetpmrb(Pcidev* p)
1382 {
1383 int ptr;
1384
1385 if(p->pmrb != 0)
1386 return p->pmrb;
1387 p->pmrb = -1;
1388
1389 /*
1390 * If there are no extended capabilities implemented,
1391 * (bit 4 in the status register) assume there's no standard
1392 * power management method.
1393 * Find the capabilities pointer based on PCI header type.
1394 */
1395 if(!(pcicfgr16(p, PciPSR) & 0x0010))
1396 return -1;
1397 switch(pcicfgr8(p, PciHDT)){
1398 default:
1399 return -1;
1400 case 0: /* all other */
1401 case 1: /* PCI to PCI bridge */
1402 ptr = 0x34;
1403 break;
1404 case 2: /* CardBus bridge */
1405 ptr = 0x14;
1406 break;
1407 }
1408 ptr = pcicfgr32(p, ptr);
1409
1410 while(ptr != 0){
1411 /*
1412 * Check for validity.
1413 * Can't be in standard header and must be double
1414 * word aligned.
1415 */
1416 if(ptr < 0x40 || (ptr & ~0xFC))
1417 return -1;
1418 if(pcicfgr8(p, ptr) == 0x01){
1419 p->pmrb = ptr;
1420 return ptr;
1421 }
1422
1423 ptr = pcicfgr8(p, ptr+1);
1424 }
1425
1426 return -1;
1427 }
1428
1429 int
1430 pcigetpms(Pcidev* p)
1431 {
1432 int pmcsr, ptr;
1433
1434 if((ptr = pcigetpmrb(p)) == -1)
1435 return -1;
1436
1437 /*
1438 * Power Management Register Block:
1439 * offset 0: Capability ID
1440 * 1: next item pointer
1441 * 2: capabilities
1442 * 4: control/status
1443 * 6: bridge support extensions
1444 * 7: data
1445 */
1446 pmcsr = pcicfgr16(p, ptr+4);
1447
1448 return pmcsr & 0x0003;
1449 }
1450
1451 int
1452 pcisetpms(Pcidev* p, int state)
1453 {
1454 int ostate, pmc, pmcsr, ptr;
1455
1456 if((ptr = pcigetpmrb(p)) == -1)
1457 return -1;
1458
1459 pmc = pcicfgr16(p, ptr+2);
1460 pmcsr = pcicfgr16(p, ptr+4);
1461 ostate = pmcsr & 0x0003;
1462 pmcsr &= ~0x0003;
1463
1464 switch(state){
1465 default:
1466 return -1;
1467 case 0:
1468 break;
1469 case 1:
1470 if(!(pmc & 0x0200))
1471 return -1;
1472 break;
1473 case 2:
1474 if(!(pmc & 0x0400))
1475 return -1;
1476 break;
1477 case 3:
1478 break;
1479 }
1480 pmcsr |= state;
1481 pcicfgw16(p, ptr+4, pmcsr);
1482
1483 return ostate;
1484 }
Cache object: af9c7d36c6f187004012f4a91c627c53
|