pci.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. /*
  2. * PCI support code.
  3. */
  4. #include "u.h"
  5. #include "../port/lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "../port/error.h"
  11. #define DBG if(0) pcilog
  12. struct
  13. {
  14. char output[16384];
  15. int ptr;
  16. }PCICONS;
  17. int
  18. pcilog(char *fmt, ...)
  19. {
  20. int n;
  21. va_list arg;
  22. char buf[PRINTSIZE];
  23. va_start(arg, fmt);
  24. n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
  25. va_end(arg);
  26. memmove(PCICONS.output+PCICONS.ptr, buf, n);
  27. PCICONS.ptr += n;
  28. return n;
  29. }
  30. enum
  31. { /* configuration mechanism #1 */
  32. PciADDR = 0xCF8, /* CONFIG_ADDRESS */
  33. PciDATA = 0xCFC, /* CONFIG_DATA */
  34. /* configuration mechanism #2 */
  35. PciCSE = 0xCF8, /* configuration space enable */
  36. PciFORWARD = 0xCFA, /* which bus */
  37. MaxFNO = 7,
  38. MaxUBN = 255,
  39. };
  40. enum
  41. { /* command register */
  42. IOen = (1<<0),
  43. MEMen = (1<<1),
  44. MASen = (1<<2),
  45. MemWrInv = (1<<4),
  46. PErrEn = (1<<6),
  47. SErrEn = (1<<8),
  48. };
  49. static Lock pcicfglock;
  50. static QLock pcicfginitlock;
  51. static int pcicfgmode = -1;
  52. static int pcimaxbno = 7;
  53. static int pcimaxdno;
  54. static Pcidev* pciroot;
  55. static Pcidev* pcilist;
  56. static Pcidev* pcitail;
  57. static int pcicfgrw32(int, int, int, int);
  58. static int pcicfgrw8(int, int, int, int);
  59. static char* bustypes[] = {
  60. "CBUSI",
  61. "CBUSII",
  62. "EISA",
  63. "FUTURE",
  64. "INTERN",
  65. "ISA",
  66. "MBI",
  67. "MBII",
  68. "MCA",
  69. "MPI",
  70. "MPSA",
  71. "NUBUS",
  72. "PCI",
  73. "PCMCIA",
  74. "TC",
  75. "VL",
  76. "VME",
  77. "XPRESS",
  78. };
  79. #pragma varargck type "T" int
  80. static int
  81. tbdffmt(Fmt* fmt)
  82. {
  83. char *p;
  84. int l, r, type, tbdf;
  85. if((p = malloc(READSTR)) == nil)
  86. return fmtstrcpy(fmt, "(tbdfconv)");
  87. switch(fmt->r){
  88. case 'T':
  89. tbdf = va_arg(fmt->args, int);
  90. type = BUSTYPE(tbdf);
  91. if(type < nelem(bustypes))
  92. l = snprint(p, READSTR, bustypes[type]);
  93. else
  94. l = snprint(p, READSTR, "%d", type);
  95. snprint(p+l, READSTR-l, ".%d.%d.%d",
  96. BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  97. break;
  98. default:
  99. snprint(p, READSTR, "(tbdfconv)");
  100. break;
  101. }
  102. r = fmtstrcpy(fmt, p);
  103. free(p);
  104. return r;
  105. }
  106. ulong
  107. pcibarsize(Pcidev *p, int rno)
  108. {
  109. ulong v, size;
  110. v = pcicfgrw32(p->tbdf, rno, 0, 1);
  111. pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
  112. size = pcicfgrw32(p->tbdf, rno, 0, 1);
  113. if(v & 1)
  114. size |= 0xFFFF0000;
  115. pcicfgrw32(p->tbdf, rno, v, 0);
  116. return -(size & ~0x0F);
  117. }
  118. static int
  119. pcisizcmp(void *a, void *b)
  120. {
  121. Pcisiz *aa, *bb;
  122. aa = a;
  123. bb = b;
  124. return aa->siz - bb->siz;
  125. }
  126. static ulong
  127. pcimask(ulong v)
  128. {
  129. ulong m;
  130. m = BI2BY*sizeof(v);
  131. for(m = 1<<(m-1); m != 0; m >>= 1) {
  132. if(m & v)
  133. break;
  134. }
  135. m--;
  136. if((v & m) == 0)
  137. return v;
  138. v |= m;
  139. return v+1;
  140. }
  141. static void
  142. pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
  143. {
  144. Pcidev *p;
  145. int ntb, i, size, rno, hole;
  146. ulong v, mema, ioa, sioa, smema, base, limit;
  147. Pcisiz *table, *tptr, *mtb, *itb;
  148. extern void qsort(void*, long, long, int (*)(void*, void*));
  149. ioa = *pioa;
  150. mema = *pmema;
  151. DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n",
  152. wrreg, root->tbdf, mema, ioa);
  153. ntb = 0;
  154. for(p = root; p != nil; p = p->link)
  155. ntb++;
  156. ntb *= (PciCIS-PciBAR0)/4;
  157. table = malloc(2*ntb*sizeof(Pcisiz));
  158. itb = table;
  159. mtb = table+ntb;
  160. /*
  161. * Build a table of sizes
  162. */
  163. for(p = root; p != nil; p = p->link) {
  164. if(p->ccrb == 0x06) {
  165. if(p->ccru == 0x04 && p->bridge != nil) {
  166. sioa = ioa;
  167. smema = mema;
  168. pcibusmap(p->bridge, &smema, &sioa, 0);
  169. hole = pcimask(smema-mema);
  170. if(hole < (1<<20))
  171. hole = 1<<20;
  172. p->mema.size = hole;
  173. hole = pcimask(sioa-ioa);
  174. if(hole < (1<<12))
  175. hole = 1<<12;
  176. p->ioa.size = hole;
  177. itb->dev = p;
  178. itb->bar = -1;
  179. itb->siz = p->ioa.size;
  180. itb++;
  181. mtb->dev = p;
  182. mtb->bar = -1;
  183. mtb->siz = p->mema.size;
  184. mtb++;
  185. }
  186. if((pcicfgr8(p, PciHDT)&0x7f) != 0)
  187. continue;
  188. }
  189. for(i = 0; i <= 5; i++) {
  190. rno = PciBAR0 + i*4;
  191. v = pcicfgrw32(p->tbdf, rno, 0, 1);
  192. size = pcibarsize(p, rno);
  193. if(size == 0)
  194. continue;
  195. if(v & 1) {
  196. itb->dev = p;
  197. itb->bar = i;
  198. itb->siz = size;
  199. itb++;
  200. }
  201. else {
  202. mtb->dev = p;
  203. mtb->bar = i;
  204. mtb->siz = size;
  205. mtb++;
  206. }
  207. p->mem[i].size = size;
  208. }
  209. }
  210. /*
  211. * Sort both tables IO smallest first, Memory largest
  212. */
  213. qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
  214. tptr = table+ntb;
  215. qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
  216. /*
  217. * Allocate IO address space on this bus
  218. */
  219. for(tptr = table; tptr < itb; tptr++) {
  220. hole = tptr->siz;
  221. if(tptr->bar == -1)
  222. hole = 1<<12;
  223. ioa = (ioa+hole-1) & ~(hole-1);
  224. p = tptr->dev;
  225. if(tptr->bar == -1)
  226. p->ioa.bar = ioa;
  227. else {
  228. p->pcr |= IOen;
  229. p->mem[tptr->bar].bar = ioa|1;
  230. if(wrreg)
  231. pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
  232. }
  233. ioa += tptr->siz;
  234. }
  235. /*
  236. * Allocate Memory address space on this bus
  237. */
  238. for(tptr = table+ntb; tptr < mtb; tptr++) {
  239. hole = tptr->siz;
  240. if(tptr->bar == -1)
  241. hole = 1<<20;
  242. mema = (mema+hole-1) & ~(hole-1);
  243. p = tptr->dev;
  244. if(tptr->bar == -1)
  245. p->mema.bar = mema;
  246. else {
  247. p->pcr |= MEMen;
  248. p->mem[tptr->bar].bar = mema;
  249. if(wrreg)
  250. pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
  251. }
  252. mema += tptr->siz;
  253. }
  254. *pmema = mema;
  255. *pioa = ioa;
  256. free(table);
  257. if(wrreg == 0)
  258. return;
  259. /*
  260. * Finally set all the bridge addresses & registers
  261. */
  262. for(p = root; p != nil; p = p->link) {
  263. if(p->bridge == nil) {
  264. pcicfgrw8(p->tbdf, PciLTR, 64, 0);
  265. p->pcr |= MASen;
  266. pcicfgrw32(p->tbdf, PciPCR, p->pcr, 0);
  267. continue;
  268. }
  269. base = p->ioa.bar;
  270. limit = base+p->ioa.size-1;
  271. v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
  272. v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
  273. pcicfgrw32(p->tbdf, PciIBR, v, 0);
  274. v = (limit & 0xFFFF0000)|(base>>16);
  275. pcicfgrw32(p->tbdf, PciIUBR, v, 0);
  276. base = p->mema.bar;
  277. limit = base+p->mema.size-1;
  278. v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
  279. pcicfgrw32(p->tbdf, PciMBR, v, 0);
  280. /*
  281. * Disable memory prefetch
  282. */
  283. pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
  284. pcicfgrw8(p->tbdf, PciLTR, 64, 0);
  285. /*
  286. * Enable the bridge
  287. */
  288. v = 0xFFFF0000 | IOen | MEMen | MASen;
  289. pcicfgrw32(p->tbdf, PciPCR, v, 0);
  290. sioa = p->ioa.bar;
  291. smema = p->mema.bar;
  292. pcibusmap(p->bridge, &smema, &sioa, 1);
  293. }
  294. }
  295. static int
  296. pcilscan(int bno, Pcidev** list)
  297. {
  298. Pcidev *p, *head, *tail;
  299. int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
  300. maxubn = bno;
  301. head = nil;
  302. tail = nil;
  303. for(dno = 0; dno <= pcimaxdno; dno++){
  304. maxfno = 0;
  305. for(fno = 0; fno <= maxfno; fno++){
  306. /*
  307. * For this possible device, form the
  308. * bus+device+function triplet needed to address it
  309. * and try to read the vendor and device ID.
  310. * If successful, allocate a device struct and
  311. * start to fill it in with some useful information
  312. * from the device's configuration space.
  313. */
  314. tbdf = MKBUS(BusPCI, bno, dno, fno);
  315. l = pcicfgrw32(tbdf, PciVID, 0, 1);
  316. if(l == 0xFFFFFFFF || l == 0)
  317. continue;
  318. p = malloc(sizeof(*p));
  319. p->tbdf = tbdf;
  320. p->vid = l;
  321. p->did = l>>16;
  322. if(pcilist != nil)
  323. pcitail->list = p;
  324. else
  325. pcilist = p;
  326. pcitail = p;
  327. p->rid = pcicfgr8(p, PciRID);
  328. p->ccrp = pcicfgr8(p, PciCCRp);
  329. p->ccru = pcicfgr8(p, PciCCRu);
  330. p->ccrb = pcicfgr8(p, PciCCRb);
  331. p->pcr = pcicfgr32(p, PciPCR);
  332. p->intl = pcicfgr8(p, PciINTL);
  333. /*
  334. * If the device is a multi-function device adjust the
  335. * loop count so all possible functions are checked.
  336. */
  337. hdt = pcicfgr8(p, PciHDT);
  338. if(hdt & 0x80)
  339. maxfno = MaxFNO;
  340. /*
  341. * If appropriate, read the base address registers
  342. * and work out the sizes.
  343. */
  344. switch(p->ccrb) {
  345. case 0x01: /* mass storage controller */
  346. case 0x02: /* network controller */
  347. case 0x03: /* display controller */
  348. case 0x04: /* multimedia device */
  349. case 0x06: /* bridge device */
  350. case 0x07: /* simple comm. controllers */
  351. case 0x08: /* base system peripherals */
  352. case 0x09: /* input devices */
  353. case 0x0A: /* docking stations */
  354. case 0x0B: /* processors */
  355. case 0x0C: /* serial bus controllers */
  356. if((hdt & 0x7F) != 0)
  357. break;
  358. rno = PciBAR0 - 4;
  359. for(i = 0; i < nelem(p->mem); i++) {
  360. rno += 4;
  361. p->mem[i].bar = pcicfgr32(p, rno);
  362. p->mem[i].size = pcibarsize(p, rno);
  363. }
  364. break;
  365. case 0x00:
  366. case 0x05: /* memory controller */
  367. default:
  368. break;
  369. }
  370. if(head != nil)
  371. tail->link = p;
  372. else
  373. head = p;
  374. tail = p;
  375. }
  376. }
  377. *list = head;
  378. for(p = head; p != nil; p = p->link){
  379. /*
  380. * Find PCI-PCI bridges and recursively descend the tree.
  381. */
  382. if(p->ccrb != 0x06 || p->ccru != 0x04)
  383. continue;
  384. /*
  385. * If the secondary or subordinate bus number is not
  386. * initialised try to do what the PCI BIOS should have
  387. * done and fill in the numbers as the tree is descended.
  388. * On the way down the subordinate bus number is set to
  389. * the maximum as it's not known how many buses are behind
  390. * this one; the final value is set on the way back up.
  391. */
  392. sbn = pcicfgr8(p, PciSBN);
  393. ubn = pcicfgr8(p, PciUBN);
  394. if(sbn == 0 || ubn == 0) {
  395. sbn = maxubn+1;
  396. /*
  397. * Make sure memory, I/O and master enables are
  398. * off, set the primary, secondary and subordinate
  399. * bus numbers and clear the secondary status before
  400. * attempting to scan the secondary bus.
  401. *
  402. * Initialisation of the bridge should be done here.
  403. */
  404. pcicfgw32(p, PciPCR, 0xFFFF0000);
  405. l = (MaxUBN<<16)|(sbn<<8)|bno;
  406. pcicfgw32(p, PciPBN, l);
  407. pcicfgw16(p, PciSPSR, 0xFFFF);
  408. maxubn = pcilscan(sbn, &p->bridge);
  409. l = (maxubn<<16)|(sbn<<8)|bno;
  410. pcicfgw32(p, PciPBN, l);
  411. }
  412. else {
  413. maxubn = ubn;
  414. pcilscan(sbn, &p->bridge);
  415. }
  416. }
  417. return maxubn;
  418. }
  419. int
  420. pciscan(int bno, Pcidev **list)
  421. {
  422. int ubn;
  423. qlock(&pcicfginitlock);
  424. ubn = pcilscan(bno, list);
  425. qunlock(&pcicfginitlock);
  426. return ubn;
  427. }
  428. static void
  429. pcicfginit(void)
  430. {
  431. char *p;
  432. int bno;
  433. Pcidev **list;
  434. ulong mema, ioa;
  435. qlock(&pcicfginitlock);
  436. if(pcicfgmode != -1)
  437. goto out;
  438. /*
  439. * Try to determine which PCI configuration mode is implemented.
  440. * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
  441. * a DWORD at 0xCF8 and another at 0xCFC and will pass through
  442. * any non-DWORD accesses as normal I/O cycles. There shouldn't be
  443. * a device behind these addresses so if Mode2 accesses fail try
  444. * for Mode1 (which is preferred, Mode2 is deprecated).
  445. */
  446. outb(PciCSE, 0);
  447. if(inb(PciCSE) == 0){
  448. pcicfgmode = 2;
  449. pcimaxdno = 15;
  450. }
  451. else {
  452. outl(PciADDR, 0);
  453. if(inl(PciADDR) == 0){
  454. pcicfgmode = 1;
  455. pcimaxdno = 31;
  456. }
  457. }
  458. if(pcicfgmode < 0)
  459. goto out;
  460. fmtinstall('T', tbdffmt);
  461. if(p = getconf("*pcimaxbno"))
  462. pcimaxbno = strtoul(p, 0, 0);
  463. if(p = getconf("*pcimaxdno"))
  464. pcimaxdno = strtoul(p, 0, 0);
  465. list = &pciroot;
  466. for(bno = 0; bno <= pcimaxbno; bno++) {
  467. int sbno = bno;
  468. bno = pcilscan(bno, list);
  469. while(*list)
  470. list = &(*list)->link;
  471. if (sbno == 0) {
  472. Pcidev *pci;
  473. /*
  474. * If we have found a PCI-to-Cardbus bridge, make sure
  475. * it has no valid mappings anymore.
  476. */
  477. pci = pciroot;
  478. while (pci) {
  479. if (pci->ccrb == 6 && pci->ccru == 7) {
  480. ushort bcr;
  481. /* reset the cardbus */
  482. bcr = pcicfgr16(pci, PciBCR);
  483. pcicfgw16(pci, PciBCR, 0x40 | bcr);
  484. delay(50);
  485. }
  486. pci = pci->link;
  487. }
  488. }
  489. }
  490. if(pciroot == nil)
  491. goto out;
  492. /*
  493. * Work out how big the top bus is
  494. */
  495. mema = 0;
  496. ioa = 0;
  497. pcibusmap(pciroot, &mema, &ioa, 0);
  498. DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n",
  499. mema, pcimask(mema), ioa);
  500. /*
  501. * Align the windows and map it
  502. */
  503. ioa = 0x1000;
  504. mema = 0;
  505. pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
  506. pcibusmap(pciroot, &mema, &ioa, 1);
  507. DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
  508. out:
  509. qunlock(&pcicfginitlock);
  510. }
  511. static int
  512. pcicfgrw8(int tbdf, int rno, int data, int read)
  513. {
  514. int o, type, x;
  515. if(pcicfgmode == -1)
  516. pcicfginit();
  517. if(BUSBNO(tbdf))
  518. type = 0x01;
  519. else
  520. type = 0x00;
  521. x = -1;
  522. if(BUSDNO(tbdf) > pcimaxdno)
  523. return x;
  524. lock(&pcicfglock);
  525. switch(pcicfgmode){
  526. case 1:
  527. o = rno & 0x03;
  528. rno &= ~0x03;
  529. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  530. if(read)
  531. x = inb(PciDATA+o);
  532. else
  533. outb(PciDATA+o, data);
  534. outl(PciADDR, 0);
  535. break;
  536. case 2:
  537. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  538. outb(PciFORWARD, BUSBNO(tbdf));
  539. if(read)
  540. x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  541. else
  542. outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  543. outb(PciCSE, 0);
  544. break;
  545. }
  546. unlock(&pcicfglock);
  547. return x;
  548. }
  549. int
  550. pcicfgr8(Pcidev* pcidev, int rno)
  551. {
  552. return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  553. }
  554. void
  555. pcicfgw8(Pcidev* pcidev, int rno, int data)
  556. {
  557. pcicfgrw8(pcidev->tbdf, rno, data, 0);
  558. }
  559. static int
  560. pcicfgrw16(int tbdf, int rno, int data, int read)
  561. {
  562. int o, type, x;
  563. if(pcicfgmode == -1)
  564. pcicfginit();
  565. if(BUSBNO(tbdf))
  566. type = 0x01;
  567. else
  568. type = 0x00;
  569. x = -1;
  570. if(BUSDNO(tbdf) > pcimaxdno)
  571. return x;
  572. lock(&pcicfglock);
  573. switch(pcicfgmode){
  574. case 1:
  575. o = rno & 0x02;
  576. rno &= ~0x03;
  577. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  578. if(read)
  579. x = ins(PciDATA+o);
  580. else
  581. outs(PciDATA+o, data);
  582. outl(PciADDR, 0);
  583. break;
  584. case 2:
  585. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  586. outb(PciFORWARD, BUSBNO(tbdf));
  587. if(read)
  588. x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  589. else
  590. outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  591. outb(PciCSE, 0);
  592. break;
  593. }
  594. unlock(&pcicfglock);
  595. return x;
  596. }
  597. int
  598. pcicfgr16(Pcidev* pcidev, int rno)
  599. {
  600. return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  601. }
  602. void
  603. pcicfgw16(Pcidev* pcidev, int rno, int data)
  604. {
  605. pcicfgrw16(pcidev->tbdf, rno, data, 0);
  606. }
  607. static int
  608. pcicfgrw32(int tbdf, int rno, int data, int read)
  609. {
  610. int type, x;
  611. if(pcicfgmode == -1)
  612. pcicfginit();
  613. if(BUSBNO(tbdf))
  614. type = 0x01;
  615. else
  616. type = 0x00;
  617. x = -1;
  618. if(BUSDNO(tbdf) > pcimaxdno)
  619. return x;
  620. lock(&pcicfglock);
  621. switch(pcicfgmode){
  622. case 1:
  623. rno &= ~0x03;
  624. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  625. if(read)
  626. x = inl(PciDATA);
  627. else
  628. outl(PciDATA, data);
  629. outl(PciADDR, 0);
  630. break;
  631. case 2:
  632. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  633. outb(PciFORWARD, BUSBNO(tbdf));
  634. if(read)
  635. x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  636. else
  637. outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  638. outb(PciCSE, 0);
  639. break;
  640. }
  641. unlock(&pcicfglock);
  642. return x;
  643. }
  644. int
  645. pcicfgr32(Pcidev* pcidev, int rno)
  646. {
  647. return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  648. }
  649. void
  650. pcicfgw32(Pcidev* pcidev, int rno, int data)
  651. {
  652. pcicfgrw32(pcidev->tbdf, rno, data, 0);
  653. }
  654. Pcidev*
  655. pcimatch(Pcidev* prev, int vid, int did)
  656. {
  657. if(pcicfgmode == -1)
  658. pcicfginit();
  659. if(prev == nil)
  660. prev = pcilist;
  661. else
  662. prev = prev->list;
  663. while(prev != nil){
  664. if((vid == 0 || prev->vid == vid)
  665. && (did == 0 || prev->did == did))
  666. break;
  667. prev = prev->list;
  668. }
  669. return prev;
  670. }
  671. Pcidev*
  672. pcimatchtbdf(int tbdf)
  673. {
  674. Pcidev *pcidev;
  675. if(pcicfgmode == -1)
  676. pcicfginit();
  677. for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
  678. if(pcidev->tbdf == tbdf)
  679. break;
  680. }
  681. return pcidev;
  682. }
  683. uchar
  684. pciipin(Pcidev *pci, uchar pin)
  685. {
  686. if (pci == nil)
  687. pci = pcilist;
  688. while (pci) {
  689. uchar intl;
  690. if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
  691. return pci->intl;
  692. if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
  693. return intl;
  694. pci = pci->list;
  695. }
  696. return 0;
  697. }
  698. static void
  699. pcilhinv(Pcidev* p)
  700. {
  701. int i;
  702. Pcidev *t;
  703. if(p == nil) {
  704. putstrn(PCICONS.output, PCICONS.ptr);
  705. p = pciroot;
  706. print("bus dev type vid did intl memory\n");
  707. }
  708. for(t = p; t != nil; t = t->link) {
  709. print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
  710. BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
  711. t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
  712. for(i = 0; i < nelem(p->mem); i++) {
  713. if(t->mem[i].size == 0)
  714. continue;
  715. print("%d:%.8lux %d ", i,
  716. t->mem[i].bar, t->mem[i].size);
  717. }
  718. if(t->ioa.bar || t->ioa.size)
  719. print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
  720. if(t->mema.bar || t->mema.size)
  721. print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
  722. if(t->bridge)
  723. print("->%d", BUSBNO(t->bridge->tbdf));
  724. print("\n");
  725. }
  726. while(p != nil) {
  727. if(p->bridge != nil)
  728. pcilhinv(p->bridge);
  729. p = p->link;
  730. }
  731. }
  732. void
  733. pcihinv(Pcidev* p)
  734. {
  735. if(pcicfgmode == -1)
  736. pcicfginit();
  737. qlock(&pcicfginitlock);
  738. pcilhinv(p);
  739. qunlock(&pcicfginitlock);
  740. }
  741. void
  742. pcireset(void)
  743. {
  744. Pcidev *p;
  745. int pcr;
  746. if(pcicfgmode == -1)
  747. pcicfginit();
  748. for(p = pcilist; p != nil; p = p->list){
  749. pcr = pcicfgr16(p, PciPCR);
  750. pcr &= ~0x0004;
  751. pcicfgw16(p, PciPCR, pcr);
  752. }
  753. }
  754. void
  755. pcisetbme(Pcidev* p)
  756. {
  757. int pcr;
  758. pcr = pcicfgr16(p, PciPCR);
  759. pcr |= MASen;
  760. pcicfgw16(p, PciPCR, pcr);
  761. }
  762. void
  763. pciclrbme(Pcidev* p)
  764. {
  765. int pcr;
  766. pcr = pcicfgr16(p, PciPCR);
  767. pcr &= ~MASen;
  768. pcicfgw16(p, PciPCR, pcr);
  769. }