1 /* 2 * PCI support code. 3 * To do: 4 * initialise bridge mappings if the PCI BIOS didn't. 5 */ 6 #include "u.h" 7 #include "lib.h" 8 #include "mem.h" 9 #include "dat.h" 10 #include "fns.h" 11 #include "io.h" 12 #include "error.h" 13 14 enum { /* configuration mechanism #1 */ 15 PciADDR = 0xCF8, /* CONFIG_ADDRESS */ 16 PciDATA = 0xCFC, /* CONFIG_DATA */ 17 18 /* configuration mechanism #2 */ 19 PciCSE = 0xCF8, /* configuration space enable */ 20 PciFORWARD = 0xCFA, /* which bus */ 21 22 MaxFNO = 7, 23 MaxUBN = 255, 24 }; 25 26 enum 27 { /* command register */ 28 IOen = (1<<0), 29 MEMen = (1<<1), 30 MASen = (1<<2), 31 MemWrInv = (1<<4), 32 PErrEn = (1<<6), 33 SErrEn = (1<<8), 34 }; 35 36 static Lock pcicfglock; 37 static Lock pcicfginitlock; 38 static int pcicfgmode = -1; 39 static int pcimaxbno = 7; 40 static int pcimaxdno; 41 static Pcidev* pciroot; 42 static Pcidev* pcilist; 43 static Pcidev* pcitail; 44 45 static int pcicfgrw32(int, int, int, int); 46 static int pcicfgrw8(int, int, int, int); 47 48 ulong 49 pcibarsize(Pcidev *p, int rno) 50 { 51 ulong v, size; 52 53 v = pcicfgrw32(p->tbdf, rno, 0, 1); 54 pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); 55 size = pcicfgrw32(p->tbdf, rno, 0, 1); 56 if(v & 1) 57 size |= 0xFFFF0000; 58 pcicfgrw32(p->tbdf, rno, v, 0); 59 60 return -(size & ~0x0F); 61 } 62 63 int 64 pciscan(int bno, Pcidev** list) 65 { 66 Pcidev *p, *head, *tail; 67 int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; 68 69 maxubn = bno; 70 head = nil; 71 tail = nil; 72 for(dno = 0; dno <= pcimaxdno; dno++){ 73 maxfno = 0; 74 for(fno = 0; fno <= maxfno; fno++){ 75 /* 76 * For this possible device, form the 77 * bus+device+function triplet needed to address it 78 * and try to read the vendor and device ID. 79 * If successful, allocate a device struct and 80 * start to fill it in with some useful information 81 * from the device's configuration space. 82 */ 83 tbdf = MKBUS(BusPCI, bno, dno, fno); 84 l = pcicfgrw32(tbdf, PciVID, 0, 1); 85 if(l == 0xFFFFFFFF || l == 0) 86 continue; 87 p = malloc(sizeof(*p)); 88 p->tbdf = tbdf; 89 p->vid = l; 90 p->did = l>>16; 91 92 if(pcilist != nil) 93 pcitail->list = p; 94 else 95 pcilist = p; 96 pcitail = p; 97 98 p->rid = pcicfgr8(p, PciRID); 99 p->ccrp = pcicfgr8(p, PciCCRp); 100 p->ccru = pcicfgr8(p, PciCCRu); 101 p->ccrb = pcicfgr8(p, PciCCRb); 102 p->pcr = pcicfgr32(p, PciPCR); 103 104 p->intl = pcicfgr8(p, PciINTL); 105 106 /* 107 * If the device is a multi-function device adjust the 108 * loop count so all possible functions are checked. 109 */ 110 hdt = pcicfgr8(p, PciHDT); 111 if(hdt & 0x80) 112 maxfno = MaxFNO; 113 114 /* 115 * If appropriate, read the base address registers 116 * and work out the sizes. 117 */ 118 switch(p->ccrb){ 119 120 case 0x01: /* mass storage controller */ 121 case 0x02: /* network controller */ 122 case 0x03: /* display controller */ 123 case 0x04: /* multimedia device */ 124 case 0x07: /* simple comm. controllers */ 125 case 0x08: /* base system peripherals */ 126 case 0x09: /* input devices */ 127 case 0x0A: /* docking stations */ 128 case 0x0B: /* processors */ 129 case 0x0C: /* serial bus controllers */ 130 if((hdt & 0x7F) != 0) 131 break; 132 rno = PciBAR0 - 4; 133 for(i = 0; i < nelem(p->mem); i++){ 134 rno += 4; 135 p->mem[i].bar = pcicfgr32(p, rno); 136 p->mem[i].size = pcibarsize(p, rno); 137 } 138 break; 139 140 case 0x00: 141 case 0x05: /* memory controller */ 142 case 0x06: /* bridge device */ 143 default: 144 break; 145 } 146 147 if(head != nil) 148 tail->link = p; 149 else 150 head = p; 151 tail = p; 152 } 153 } 154 155 *list = head; 156 for(p = head; p != nil; p = p->link){ 157 /* 158 * Find PCI-PCI and PCI-Cardbus bridges 159 * and recursively descend the tree. 160 */ 161 if(p->ccrb != 0x06 || p->ccru != 0x04) 162 continue; 163 164 /* 165 * If the secondary or subordinate bus number is not 166 * initialised try to do what the PCI BIOS should have 167 * done and fill in the numbers as the tree is descended. 168 * On the way down the subordinate bus number is set to 169 * the maximum as it's not known how many buses are behind 170 * this one; the final value is set on the way back up. 171 */ 172 ubn = pcicfgr8(p, PciUBN); 173 sbn = pcicfgr8(p, PciSBN); 174 175 if(sbn == 0 || ubn == 0){ 176 sbn = maxubn+1; 177 /* 178 * Make sure memory, I/O and master enables are 179 * off, set the primary, secondary and subordinate 180 * bus numbers and clear the secondary status before 181 * attempting to scan the secondary bus. 182 * 183 * Initialisation of the bridge should be done here. 184 */ 185 pcicfgw32(p, PciPCR, 0xFFFF0000); 186 l = (MaxUBN<<16)|(sbn<<8)|bno; 187 pcicfgw32(p, PciPBN, l); 188 pcicfgw16(p, PciSPSR, 0xFFFF); 189 maxubn = pciscan(sbn, &p->bridge); 190 l = (maxubn<<16)|(sbn<<8)|bno; 191 192 pcicfgw32(p, PciPBN, l); 193 } 194 else{ 195 /* 196 * You can't go back. 197 * This shouldn't be possible, but the 198 * Iwill DK8-HTX seems to have subordinate 199 * bus numbers which get smaller on the 200 * way down. Need to look more closely at 201 * this. 202 */ 203 if(ubn > maxubn) 204 maxubn = ubn; 205 pciscan(sbn, &p->bridge); 206 } 207 } 208 209 return maxubn; 210 } 211 212 static uchar 213 null_link(Pcidev *, uchar ) 214 { 215 return 0; 216 } 217 218 static void 219 null_init(Pcidev *, uchar , uchar ) 220 { 221 } 222 223 static uchar 224 pIIx_link(Pcidev *router, uchar link) 225 { 226 uchar pirq; 227 228 /* link should be 0x60, 0x61, 0x62, 0x63 */ 229 pirq = pcicfgr8(router, link); 230 return (pirq < 16)? pirq: 0; 231 } 232 233 static void 234 pIIx_init(Pcidev *router, uchar link, uchar irq) 235 { 236 pcicfgw8(router, link, irq); 237 } 238 239 static uchar 240 via_link(Pcidev *router, uchar link) 241 { 242 uchar pirq; 243 244 /* link should be 1, 2, 3, 5 */ 245 pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0; 246 247 return (link & 1)? (pirq >> 4): (pirq & 15); 248 } 249 250 static void 251 via_init(Pcidev *router, uchar link, uchar irq) 252 { 253 uchar pirq; 254 255 pirq = pcicfgr8(router, 0x55 + (link >> 1)); 256 pirq &= (link & 1)? 0x0f: 0xf0; 257 pirq |= (link & 1)? (irq << 4): (irq & 15); 258 pcicfgw8(router, 0x55 + (link>>1), pirq); 259 } 260 261 static uchar 262 opti_link(Pcidev *router, uchar link) 263 { 264 uchar pirq = 0; 265 266 /* link should be 0x02, 0x12, 0x22, 0x32 */ 267 if ((link & 0xcf) == 0x02) 268 pirq = pcicfgr8(router, 0xb8 + (link >> 5)); 269 return (link & 0x10)? (pirq >> 4): (pirq & 15); 270 } 271 272 static void 273 opti_init(Pcidev *router, uchar link, uchar irq) 274 { 275 uchar pirq; 276 277 pirq = pcicfgr8(router, 0xb8 + (link >> 5)); 278 pirq &= (link & 0x10)? 0x0f : 0xf0; 279 pirq |= (link & 0x10)? (irq << 4): (irq & 15); 280 pcicfgw8(router, 0xb8 + (link >> 5), pirq); 281 } 282 283 static uchar 284 ali_link(Pcidev *router, uchar link) 285 { 286 /* No, you're not dreaming */ 287 static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 }; 288 uchar pirq; 289 290 /* link should be 0x01..0x08 */ 291 pirq = pcicfgr8(router, 0x48 + ((link-1)>>1)); 292 return (link & 1)? map[pirq&15]: map[pirq>>4]; 293 } 294 295 static void 296 ali_init(Pcidev *router, uchar link, uchar irq) 297 { 298 /* Inverse of map in ali_link */ 299 static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 }; 300 uchar pirq; 301 302 pirq = pcicfgr8(router, 0x48 + ((link-1)>>1)); 303 pirq &= (link & 1)? 0x0f: 0xf0; 304 pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15); 305 pcicfgw8(router, 0x48 + ((link-1)>>1), pirq); 306 } 307 308 static uchar 309 cyrix_link(Pcidev *router, uchar link) 310 { 311 uchar pirq; 312 313 /* link should be 1, 2, 3, 4 */ 314 pirq = pcicfgr8(router, 0x5c + ((link-1)>>1)); 315 return ((link & 1)? pirq >> 4: pirq & 15); 316 } 317 318 static void 319 cyrix_init(Pcidev *router, uchar link, uchar irq) 320 { 321 uchar pirq; 322 323 pirq = pcicfgr8(router, 0x5c + (link>>1)); 324 pirq &= (link & 1)? 0x0f: 0xf0; 325 pirq |= (link & 1)? (irq << 4): (irq & 15); 326 pcicfgw8(router, 0x5c + (link>>1), pirq); 327 } 328 329 typedef struct { 330 ushort sb_vid, sb_did; 331 uchar (*sb_translate)(Pcidev *, uchar); 332 void (*sb_initialize)(Pcidev *, uchar, uchar); 333 } bridge_t; 334 335 static bridge_t southbridges[] = { 336 { 0x8086, 0x122e, pIIx_link, pIIx_init }, // Intel 82371FB 337 { 0x8086, 0x1234, pIIx_link, pIIx_init }, // Intel 82371MX 338 { 0x8086, 0x7000, pIIx_link, pIIx_init }, // Intel 82371SB 339 { 0x8086, 0x7110, pIIx_link, pIIx_init }, // Intel 82371AB 340 { 0x8086, 0x7198, pIIx_link, pIIx_init }, // Intel 82443MX (fn 1) 341 { 0x8086, 0x2410, pIIx_link, pIIx_init }, // Intel 82801AA 342 { 0x8086, 0x2420, pIIx_link, pIIx_init }, // Intel 82801AB 343 { 0x8086, 0x2440, pIIx_link, pIIx_init }, // Intel 82801BA 344 { 0x8086, 0x244c, pIIx_link, pIIx_init }, // Intel 82801BAM 345 { 0x8086, 0x2480, pIIx_link, pIIx_init }, // Intel 82801CA 346 { 0x8086, 0x248c, pIIx_link, pIIx_init }, // Intel 82801CAM 347 { 0x8086, 0x24c0, pIIx_link, pIIx_init }, // Intel 82801DBL 348 { 0x8086, 0x24cc, pIIx_link, pIIx_init }, // Intel 82801DBM 349 { 0x8086, 0x24d0, pIIx_link, pIIx_init }, // Intel 82801EB 350 { 0x8086, 0x2640, pIIx_link, pIIx_init }, // Intel 82801FB 351 { 0x8086, 0x27b8, pIIx_link, pIIx_init }, // Intel 82801GB 352 { 0x8086, 0x27b9, pIIx_link, pIIx_init }, // Intel 82801GBM 353 { 0x1106, 0x0586, via_link, via_init }, // Viatech 82C586 354 { 0x1106, 0x0596, via_link, via_init }, // Viatech 82C596 355 { 0x1106, 0x0686, via_link, via_init }, // Viatech 82C686 356 { 0x1106, 0x3227, via_link, via_init }, // Viatech VT8237 357 { 0x1045, 0xc700, opti_link, opti_init }, // Opti 82C700 358 { 0x10b9, 0x1533, ali_link, ali_init }, // Al M1533 359 { 0x1039, 0x0008, pIIx_link, pIIx_init }, // SI 503 360 { 0x1039, 0x0496, pIIx_link, pIIx_init }, // SI 496 361 { 0x1078, 0x0100, cyrix_link, cyrix_init }, // Cyrix 5530 Legacy 362 363 { 0x1002, 0x4377, nil, nil }, // ATI Radeon Xpress 200M 364 { 0x1002, 0x4372, nil, nil }, // ATI SB400 365 { 0x1022, 0x746B, nil, nil }, // AMD 8111 366 { 0x10DE, 0x00D1, nil, nil }, // NVIDIA nForce 3 367 { 0x10DE, 0x00E0, nil, nil }, // NVIDIA nForce 3 250 Series 368 { 0x1166, 0x0200, nil, nil }, // ServerWorks ServerSet III LE 369 }; 370 371 typedef struct { 372 uchar e_bus; // Pci bus number 373 uchar e_dev; // Pci device number 374 uchar e_maps[12]; // Avoid structs! Link and mask. 375 uchar e_slot; // Add-in/built-in slot 376 uchar e_reserved; 377 } slot_t; 378 379 typedef struct { 380 uchar rt_signature[4]; // Routing table signature 381 uchar rt_version[2]; // Version number 382 uchar rt_size[2]; // Total table size 383 uchar rt_bus; // Interrupt router bus number 384 uchar rt_devfn; // Router's devfunc 385 uchar rt_pciirqs[2]; // Exclusive PCI irqs 386 uchar rt_compat[4]; // Compatible PCI interrupt router 387 uchar rt_miniport[4]; // Miniport data 388 uchar rt_reserved[11]; 389 uchar rt_checksum; 390 } router_t; 391 392 static ushort pciirqs; // Exclusive PCI irqs 393 static bridge_t *southbridge; // Which southbridge to use. 394 395 static void 396 pcirouting(void) 397 { 398 uchar *p, pin, irq; 399 ulong tbdf, vdid; 400 ushort vid, did; 401 router_t *r; 402 slot_t *e; 403 int size, i, fn; 404 Pcidev *sbpci, *pci; 405 406 // Peek in the BIOS 407 for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16) 408 if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R') 409 break; 410 411 if (p >= (uchar *)KADDR(0xfffff)) 412 return; 413 414 r = (router_t *)p; 415 416 // print("PCI interrupt routing table version %d.%d at %.6uX\n", 417 // r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff); 418 419 tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8); 420 vdid = pcicfgrw32(tbdf, PciVID, 0, 1); 421 vid = vdid; 422 did = vdid >> 16; 423 424 for (i = 0; i != nelem(southbridges); i++) 425 if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did) 426 break; 427 428 if (i == nelem(southbridges)) { 429 print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did); 430 return; 431 } 432 southbridge = &southbridges[i]; 433 434 if ((sbpci = pcimatch(nil, vid, did)) == nil) { 435 print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n", 436 vid, did); 437 return; 438 } 439 440 pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0]; 441 442 size = (r->rt_size[1] << 8)|r->rt_size[0]; 443 for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) { 444 // print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot); 445 // for (i = 0; i != 4; i++) { 446 // uchar *m = &e->e_maps[i * 3]; 447 // print("[%d] %.2uX %.4uX ", 448 // i, m[0], (m[2] << 8)|m[1]); 449 // } 450 // print("\n"); 451 452 for (fn = 0; fn != 8; fn++) { 453 uchar *m; 454 455 // Retrieve the did and vid through the devfn before 456 // obtaining the Pcidev structure. 457 tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8); 458 vdid = pcicfgrw32(tbdf, PciVID, 0, 1); 459 if (vdid == 0xFFFFFFFF || vdid == 0) 460 continue; 461 462 vid = vdid; 463 did = vdid >> 16; 464 465 pci = nil; 466 while ((pci = pcimatch(pci, vid, did)) != nil) { 467 468 if (pci->intl != 0 && pci->intl != 0xFF) 469 continue; 470 471 pin = pcicfgr8(pci, PciINTP); 472 if (pin == 0 || pin == 0xff) 473 continue; 474 475 m = &e->e_maps[(pin - 1) * 3]; 476 irq = southbridge->sb_translate(sbpci, m[0]); 477 if (irq) { 478 print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n", 479 vid, did, pin, irq); 480 pcicfgw8(pci, PciINTL, irq); 481 pci->intl = irq; 482 } 483 } 484 } 485 } 486 } 487 488 static void 489 pcicfginit(void) 490 { 491 char *p; 492 int bno, n; 493 Pcidev **list; 494 495 lock(&pcicfginitlock); 496 if(pcicfgmode != -1) 497 goto out; 498 499 /* 500 * Try to determine which PCI configuration mode is implemented. 501 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses 502 * a DWORD at 0xCF8 and another at 0xCFC and will pass through 503 * any non-DWORD accesses as normal I/O cycles. There shouldn't be 504 * a device behind these addresses so if Mode1 accesses fail try 505 * for Mode2 (Mode2 is deprecated). 506 */ 507 508 /* 509 * Bits [30:24] of PciADDR must be 0, 510 * according to the spec. 511 */ 512 n = inl(PciADDR); 513 if(!(n & 0x7FF00000)){ 514 outl(PciADDR, 0x80000000); 515 outb(PciADDR+3, 0); 516 if(inl(PciADDR) & 0x80000000){ 517 pcicfgmode = 1; 518 pcimaxdno = 31; 519 } 520 } 521 outl(PciADDR, n); 522 523 if(pcicfgmode < 0){ 524 /* 525 * The 'key' part of PciCSE should be 0. 526 */ 527 n = inb(PciCSE); 528 if(!(n & 0xF0)){ 529 outb(PciCSE, 0x0E); 530 if(inb(PciCSE) == 0x0E){ 531 pcicfgmode = 2; 532 pcimaxdno = 15; 533 } 534 } 535 outb(PciCSE, n); 536 } 537 538 if(pcicfgmode < 0) 539 goto out; 540 541 542 if(p = getconf("*pcimaxbno")) 543 pcimaxbno = strtoul(p, 0, 0); 544 if(p = getconf("*pcimaxdno")) 545 pcimaxdno = strtoul(p, 0, 0); 546 547 list = &pciroot; 548 for(bno = 0; bno <= pcimaxbno; bno++) { 549 bno = pciscan(bno, list); 550 while(*list) 551 list = &(*list)->link; 552 } 553 554 pcirouting(); 555 556 out: 557 unlock(&pcicfginitlock); 558 559 if(getconf("*pcihinv")) 560 pcihinv(nil); 561 } 562 563 564 static int 565 pcicfgrw8(int tbdf, int rno, int data, int read) 566 { 567 int o, type, x; 568 569 if(pcicfgmode == -1) 570 pcicfginit(); 571 572 if(BUSBNO(tbdf)) 573 type = 0x01; 574 else 575 type = 0x00; 576 x = -1; 577 if(BUSDNO(tbdf) > pcimaxdno) 578 return x; 579 580 lock(&pcicfglock); 581 switch(pcicfgmode){ 582 583 case 1: 584 o = rno & 0x03; 585 rno &= ~0x03; 586 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); 587 if(read) 588 x = inb(PciDATA+o); 589 else 590 outb(PciDATA+o, data); 591 outl(PciADDR, 0); 592 break; 593 594 case 2: 595 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); 596 outb(PciFORWARD, BUSBNO(tbdf)); 597 if(read) 598 x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno); 599 else 600 outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); 601 outb(PciCSE, 0); 602 break; 603 } 604 unlock(&pcicfglock); 605 606 return x; 607 } 608 609 int 610 pcicfgr8(Pcidev* pcidev, int rno) 611 { 612 return pcicfgrw8(pcidev->tbdf, rno, 0, 1); 613 } 614 615 void 616 pcicfgw8(Pcidev* pcidev, int rno, int data) 617 { 618 pcicfgrw8(pcidev->tbdf, rno, data, 0); 619 } 620 621 static int 622 pcicfgrw16(int tbdf, int rno, int data, int read) 623 { 624 int o, type, x; 625 626 if(pcicfgmode == -1) 627 pcicfginit(); 628 629 if(BUSBNO(tbdf)) 630 type = 0x01; 631 else 632 type = 0x00; 633 x = -1; 634 if(BUSDNO(tbdf) > pcimaxdno) 635 return x; 636 637 lock(&pcicfglock); 638 switch(pcicfgmode){ 639 640 case 1: 641 o = rno & 0x02; 642 rno &= ~0x03; 643 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); 644 if(read) 645 x = ins(PciDATA+o); 646 else 647 outs(PciDATA+o, data); 648 outl(PciADDR, 0); 649 break; 650 651 case 2: 652 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); 653 outb(PciFORWARD, BUSBNO(tbdf)); 654 if(read) 655 x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno); 656 else 657 outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); 658 outb(PciCSE, 0); 659 break; 660 } 661 unlock(&pcicfglock); 662 663 return x; 664 } 665 666 int 667 pcicfgr16(Pcidev* pcidev, int rno) 668 { 669 return pcicfgrw16(pcidev->tbdf, rno, 0, 1); 670 } 671 672 void 673 pcicfgw16(Pcidev* pcidev, int rno, int data) 674 { 675 pcicfgrw16(pcidev->tbdf, rno, data, 0); 676 } 677 678 static int 679 pcicfgrw32(int tbdf, int rno, int data, int read) 680 { 681 int type, x; 682 683 if(pcicfgmode == -1) 684 pcicfginit(); 685 686 if(BUSBNO(tbdf)) 687 type = 0x01; 688 else 689 type = 0x00; 690 x = -1; 691 if(BUSDNO(tbdf) > pcimaxdno) 692 return x; 693 694 lock(&pcicfglock); 695 switch(pcicfgmode){ 696 697 case 1: 698 rno &= ~0x03; 699 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type); 700 if(read) 701 x = inl(PciDATA); 702 else 703 outl(PciDATA, data); 704 outl(PciADDR, 0); 705 break; 706 707 case 2: 708 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1)); 709 outb(PciFORWARD, BUSBNO(tbdf)); 710 if(read) 711 x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno); 712 else 713 outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data); 714 outb(PciCSE, 0); 715 break; 716 } 717 unlock(&pcicfglock); 718 719 return x; 720 } 721 722 int 723 pcicfgr32(Pcidev* pcidev, int rno) 724 { 725 return pcicfgrw32(pcidev->tbdf, rno, 0, 1); 726 } 727 728 void 729 pcicfgw32(Pcidev* pcidev, int rno, int data) 730 { 731 pcicfgrw32(pcidev->tbdf, rno, data, 0); 732 } 733 734 Pcidev* 735 pcimatch(Pcidev* prev, int vid, int did) 736 { 737 if(pcicfgmode == -1) 738 pcicfginit(); 739 740 if(prev == nil) 741 prev = pcilist; 742 else 743 prev = prev->list; 744 745 while(prev != nil) { 746 if((vid == 0 || prev->vid == vid) 747 && (did == 0 || prev->did == did)) 748 break; 749 prev = prev->list; 750 } 751 return prev; 752 } 753 754 uchar 755 pciipin(Pcidev *pci, uchar pin) 756 { 757 if (pci == nil) 758 pci = pcilist; 759 760 while (pci) { 761 uchar intl; 762 763 if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff) 764 return pci->intl; 765 766 if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0) 767 return intl; 768 769 pci = pci->list; 770 } 771 return 0; 772 } 773 774 static ushort 775 pciimask(Pcidev *pci) 776 { 777 ushort imask; 778 779 imask = 0; 780 while (pci) { 781 if (pcicfgr8(pci, PciINTP) && pci->intl < 16) 782 imask |= 1 << pci->intl; 783 784 if (pci->bridge) 785 imask |= pciimask(pci->bridge); 786 787 pci = pci->list; 788 } 789 return imask; 790 } 791 792 uchar 793 pciintl(Pcidev *pci) 794 { 795 ushort imask; 796 int i; 797 798 if (pci == nil) 799 pci = pcilist; 800 801 imask = pciimask(pci) | 1; 802 for (i = 0; i != 16; i++) 803 if ((imask & (1 << i)) == 0) 804 return i; 805 return 0; 806 } 807 808 void 809 pcihinv(Pcidev* p) 810 { 811 int i; 812 Pcidev *t; 813 814 if(pcicfgmode == -1) 815 pcicfginit(); 816 817 if(p == nil) { 818 p = pciroot; 819 print("bus dev type vid did intl memory\n"); 820 } 821 for(t = p; t != nil; t = t->link) { 822 print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ", 823 BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf), 824 t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl); 825 826 for(i = 0; i < nelem(p->mem); i++) { 827 if(t->mem[i].size == 0) 828 continue; 829 print("%d:%.8lux %d ", i, 830 t->mem[i].bar, t->mem[i].size); 831 } 832 print("\n"); 833 } 834 while(p != nil) { 835 if(p->bridge != nil) 836 pcihinv(p->bridge); 837 p = p->link; 838 } 839 } 840 841 void 842 pcireset(void) 843 { 844 Pcidev *p; 845 int pcr; 846 847 if(pcicfgmode == -1) 848 pcicfginit(); 849 850 for(p = pcilist; p != nil; p = p->list){ 851 pcr = pcicfgr16(p, PciPSR); 852 pcicfgw16(p, PciPSR, pcr & ~0x04); 853 } 854 } 855 856 void 857 pcisetioe(Pcidev* p) 858 { 859 p->pcr |= IOen; 860 pcicfgw16(p, PciPCR, p->pcr); 861 } 862 863 void 864 pciclrioe(Pcidev* p) 865 { 866 p->pcr &= ~IOen; 867 pcicfgw16(p, PciPCR, p->pcr); 868 } 869 870 void 871 pcisetbme(Pcidev* p) 872 { 873 p->pcr |= MASen; 874 pcicfgw16(p, PciPCR, p->pcr); 875 } 876 877 void 878 pciclrbme(Pcidev* p) 879 { 880 p->pcr &= ~MASen; 881 pcicfgw16(p, PciPCR, p->pcr); 882 } 883 884 void 885 pcisetmwi(Pcidev* p) 886 { 887 p->pcr |= MemWrInv; 888 pcicfgw16(p, PciPCR, p->pcr); 889 } 890 891 void 892 pciclrmwi(Pcidev* p) 893 { 894 p->pcr &= ~MemWrInv; 895 pcicfgw16(p, PciPCR, p->pcr); 896 } 897 898 static int 899 pcigetpmrb(Pcidev* p) 900 { 901 int ptr; 902 903 if(p->pmrb != 0) 904 return p->pmrb; 905 p->pmrb = -1; 906 907 /* 908 * If there are no extended capabilities implemented, 909 * (bit 4 in the status register) assume there's no standard 910 * power management method. 911 * Find the capabilities pointer based on PCI header type. 912 */ 913 if(!(pcicfgr16(p, PciPSR) & 0x0010)) 914 return -1; 915 switch(pcicfgr8(p, PciHDT)){ 916 default: 917 return -1; 918 case 0: /* all other */ 919 case 1: /* PCI to PCI bridge */ 920 ptr = 0x34; 921 break; 922 case 2: /* CardBus bridge */ 923 ptr = 0x14; 924 break; 925 } 926 ptr = pcicfgr32(p, ptr); 927 928 while(ptr != 0){ 929 /* 930 * Check for validity. 931 * Can't be in standard header and must be double 932 * word aligned. 933 */ 934 if(ptr < 0x40 || (ptr & ~0xFC)) 935 return -1; 936 if(pcicfgr8(p, ptr) == 0x01){ 937 p->pmrb = ptr; 938 return ptr; 939 } 940 941 ptr = pcicfgr8(p, ptr+1); 942 } 943 944 return -1; 945 } 946 947 int 948 pcigetpms(Pcidev* p) 949 { 950 int pmcsr, ptr; 951 952 if((ptr = pcigetpmrb(p)) == -1) 953 return -1; 954 955 /* 956 * Power Management Register Block: 957 * offset 0: Capability ID 958 * 1: next item pointer 959 * 2: capabilities 960 * 4: control/status 961 * 6: bridge support extensions 962 * 7: data 963 */ 964 pmcsr = pcicfgr16(p, ptr+4); 965 966 return pmcsr & 0x0003; 967 } 968 969 int 970 pcisetpms(Pcidev* p, int state) 971 { 972 int ostate, pmc, pmcsr, ptr; 973 974 if((ptr = pcigetpmrb(p)) == -1) 975 return -1; 976 977 pmc = pcicfgr16(p, ptr+2); 978 pmcsr = pcicfgr16(p, ptr+4); 979 ostate = pmcsr & 0x0003; 980 pmcsr &= ~0x0003; 981 982 switch(state){ 983 default: 984 return -1; 985 case 0: 986 break; 987 case 1: 988 if(!(pmc & 0x0200)) 989 return -1; 990 break; 991 case 2: 992 if(!(pmc & 0x0400)) 993 return -1; 994 break; 995 case 3: 996 break; 997 } 998 pmcsr |= state; 999 pcicfgw16(p, ptr+4, pmcsr); 1000 1001 return ostate; 1002 } 1003