pci.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  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. enum { /* configuration mechanism #1 */
  14. PciADDR = 0xCF8, /* CONFIG_ADDRESS */
  15. PciDATA = 0xCFC, /* CONFIG_DATA */
  16. /* configuration mechanism #2 */
  17. PciCSE = 0xCF8, /* configuration space enable */
  18. PciFORWARD = 0xCFA, /* which bus */
  19. MaxFNO = 7,
  20. MaxUBN = 255,
  21. };
  22. static Lock pcicfglock;
  23. static Lock pcicfginitlock;
  24. static int pcicfgmode = -1;
  25. static int pcimaxbno = 7;
  26. static int pcimaxdno;
  27. static Pcidev* pciroot;
  28. static Pcidev* pcilist;
  29. static Pcidev* pcitail;
  30. static int pcicfgrw32(int, int, int, int);
  31. static int pcicfgrw8(int, int, int, int);
  32. ulong
  33. pcibarsize(Pcidev *p, int rno)
  34. {
  35. ulong v, size;
  36. v = pcicfgrw32(p->tbdf, rno, 0, 1);
  37. pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
  38. size = pcicfgrw32(p->tbdf, rno, 0, 1);
  39. if(v & 1)
  40. size |= 0xFFFF0000;
  41. pcicfgrw32(p->tbdf, rno, v, 0);
  42. return -(size & ~0x0F);
  43. }
  44. int
  45. pciscan(int bno, Pcidev** list)
  46. {
  47. Pcidev *p, *head, *tail;
  48. int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
  49. maxubn = bno;
  50. head = nil;
  51. tail = nil;
  52. for(dno = 0; dno <= pcimaxdno; dno++){
  53. maxfno = 0;
  54. for(fno = 0; fno <= maxfno; fno++){
  55. /*
  56. * For this possible device, form the
  57. * bus+device+function triplet needed to address it
  58. * and try to read the vendor and device ID.
  59. * If successful, allocate a device struct and
  60. * start to fill it in with some useful information
  61. * from the device's configuration space.
  62. */
  63. tbdf = MKBUS(BusPCI, bno, dno, fno);
  64. l = pcicfgrw32(tbdf, PciVID, 0, 1);
  65. if(l == 0xFFFFFFFF || l == 0)
  66. continue;
  67. p = malloc(sizeof(*p));
  68. p->tbdf = tbdf;
  69. p->vid = l;
  70. p->did = l>>16;
  71. if(pcilist != nil)
  72. pcitail->list = p;
  73. else
  74. pcilist = p;
  75. pcitail = p;
  76. p->rid = pcicfgr8(p, PciRID);
  77. p->ccrp = pcicfgr8(p, PciCCRp);
  78. p->ccru = pcicfgr8(p, PciCCRu);
  79. p->ccrb = pcicfgr8(p, PciCCRb);
  80. p->pcr = pcicfgr32(p, PciPCR);
  81. p->intl = pcicfgr8(p, PciINTL);
  82. /*
  83. * If the device is a multi-function device adjust the
  84. * loop count so all possible functions are checked.
  85. */
  86. hdt = pcicfgr8(p, PciHDT);
  87. if(hdt & 0x80)
  88. maxfno = MaxFNO;
  89. /*
  90. * If appropriate, read the base address registers
  91. * and work out the sizes.
  92. */
  93. switch(p->ccrb){
  94. case 0x01: /* mass storage controller */
  95. case 0x02: /* network controller */
  96. case 0x03: /* display controller */
  97. case 0x04: /* multimedia device */
  98. case 0x07: /* simple comm. controllers */
  99. case 0x08: /* base system peripherals */
  100. case 0x09: /* input devices */
  101. case 0x0A: /* docking stations */
  102. case 0x0B: /* processors */
  103. case 0x0C: /* serial bus controllers */
  104. if((hdt & 0x7F) != 0)
  105. break;
  106. rno = PciBAR0 - 4;
  107. for(i = 0; i < nelem(p->mem); i++){
  108. rno += 4;
  109. p->mem[i].bar = pcicfgr32(p, rno);
  110. p->mem[i].size = pcibarsize(p, rno);
  111. }
  112. break;
  113. case 0x00:
  114. case 0x05: /* memory controller */
  115. case 0x06: /* bridge device */
  116. default:
  117. break;
  118. }
  119. if(head != nil)
  120. tail->link = p;
  121. else
  122. head = p;
  123. tail = p;
  124. }
  125. }
  126. *list = head;
  127. for(p = head; p != nil; p = p->link){
  128. /*
  129. * Find PCI-PCI and PCI-Cardbus bridges and recursively descend the tree.
  130. */
  131. if(p->ccrb != 0x06 || p->ccru != 0x04)
  132. continue;
  133. /*
  134. * If the secondary or subordinate bus number is not
  135. * initialised try to do what the PCI BIOS should have
  136. * done and fill in the numbers as the tree is descended.
  137. * On the way down the subordinate bus number is set to
  138. * the maximum as it's not known how many buses are behind
  139. * this one; the final value is set on the way back up.
  140. */
  141. ubn = pcicfgr8(p, PciUBN);
  142. sbn = pcicfgr8(p, PciSBN);
  143. if(sbn == 0 || ubn == 0){
  144. sbn = maxubn+1;
  145. /*
  146. * Make sure memory, I/O and master enables are
  147. * off, set the primary, secondary and subordinate
  148. * bus numbers and clear the secondary status before
  149. * attempting to scan the secondary bus.
  150. *
  151. * Initialisation of the bridge should be done here.
  152. */
  153. pcicfgw32(p, PciPCR, 0xFFFF0000);
  154. l = (MaxUBN<<16)|(sbn<<8)|bno;
  155. pcicfgw32(p, PciPBN, l);
  156. pcicfgw16(p, PciSPSR, 0xFFFF);
  157. maxubn = pciscan(sbn, &p->bridge);
  158. l = (maxubn<<16)|(sbn<<8)|bno;
  159. pcicfgw32(p, PciPBN, l);
  160. }
  161. else{
  162. maxubn = ubn;
  163. pciscan(sbn, &p->bridge);
  164. }
  165. }
  166. return maxubn;
  167. }
  168. static uchar
  169. pIIx_link(Pcidev *router, uchar link)
  170. {
  171. uchar pirq;
  172. /* link should be 0x60, 0x61, 0x62, 0x63 */
  173. pirq = pcicfgr8(router, link);
  174. return (pirq < 16)? pirq: 0;
  175. }
  176. static void
  177. pIIx_init(Pcidev *router, uchar link, uchar irq)
  178. {
  179. pcicfgw8(router, link, irq);
  180. }
  181. static uchar
  182. via_link(Pcidev *router, uchar link)
  183. {
  184. uchar pirq;
  185. /* link should be 1, 2, 3, 5 */
  186. pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
  187. return (link & 1)? (pirq >> 4): (pirq & 15);
  188. }
  189. static void
  190. via_init(Pcidev *router, uchar link, uchar irq)
  191. {
  192. uchar pirq;
  193. pirq = pcicfgr8(router, 0x55 + (link >> 1));
  194. pirq &= (link & 1)? 0x0f: 0xf0;
  195. pirq |= (link & 1)? (irq << 4): (irq & 15);
  196. pcicfgw8(router, 0x55 + (link>>1), pirq);
  197. }
  198. static uchar
  199. opti_link(Pcidev *router, uchar link)
  200. {
  201. uchar pirq = 0;
  202. /* link should be 0x02, 0x12, 0x22, 0x32 */
  203. if ((link & 0xcf) == 0x02)
  204. pirq = pcicfgr8(router, 0xb8 + (link >> 5));
  205. return (link & 0x10)? (pirq >> 4): (pirq & 15);
  206. }
  207. static void
  208. opti_init(Pcidev *router, uchar link, uchar irq)
  209. {
  210. uchar pirq;
  211. pirq = pcicfgr8(router, 0xb8 + (link >> 5));
  212. pirq &= (link & 0x10)? 0x0f : 0xf0;
  213. pirq |= (link & 0x10)? (irq << 4): (irq & 15);
  214. pcicfgw8(router, 0xb8 + (link >> 5), pirq);
  215. }
  216. static uchar
  217. ali_link(Pcidev *router, uchar link)
  218. {
  219. /* No, you're not dreaming */
  220. static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
  221. uchar pirq;
  222. /* link should be 0x01..0x08 */
  223. pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
  224. return (link & 1)? map[pirq&15]: map[pirq>>4];
  225. }
  226. static void
  227. ali_init(Pcidev *router, uchar link, uchar irq)
  228. {
  229. /* Inverse of map in ali_link */
  230. static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
  231. uchar pirq;
  232. pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
  233. pirq &= (link & 1)? 0x0f: 0xf0;
  234. pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
  235. pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
  236. }
  237. static uchar
  238. cyrix_link(Pcidev *router, uchar link)
  239. {
  240. uchar pirq;
  241. /* link should be 1, 2, 3, 4 */
  242. pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
  243. return ((link & 1)? pirq >> 4: pirq & 15);
  244. }
  245. static void
  246. cyrix_init(Pcidev *router, uchar link, uchar irq)
  247. {
  248. uchar pirq;
  249. pirq = pcicfgr8(router, 0x5c + (link>>1));
  250. pirq &= (link & 1)? 0x0f: 0xf0;
  251. pirq |= (link & 1)? (irq << 4): (irq & 15);
  252. pcicfgw8(router, 0x5c + (link>>1), pirq);
  253. }
  254. enum {
  255. Intel = 0x8086,
  256. Intel_82371FB_0 = 0x122e,
  257. Intel_82371MX_0 = 0x1234,
  258. Intel_82371SB_0 = 0x7000,
  259. Intel_82371AB_0 = 0x7110,
  260. Intel_82443MX_1 = 0x7198,
  261. Intel_82801AA_0 = 0x2410,
  262. Intel_82801AB_0 = 0x2420,
  263. Intel_82801BA_0 = 0x2440,
  264. Intel_82801BAM_0 = 0x244c,
  265. Intel_82801CAM_0 = 0x248c,
  266. Intel_82801DBM_0 = 0x24cc,
  267. Intel_82801EB_0 = 0x24d0,
  268. Intel_82801FB_0 = 0x2640,
  269. Viatech = 0x1106,
  270. Via_82C586_0 = 0x0586,
  271. Via_82C596 = 0x0596,
  272. Via_82C686 = 0x0686,
  273. Opti = 0x1045,
  274. Opti_82C700 = 0xc700,
  275. Al = 0x10b9,
  276. Al_M1533 = 0x1533,
  277. SI = 0x1039,
  278. SI_503 = 0x0008,
  279. SI_496 = 0x0496,
  280. Cyrix = 0x1078,
  281. Cyrix_5530_Legacy = 0x0100,
  282. };
  283. typedef struct {
  284. ushort sb_vid, sb_did;
  285. uchar (*sb_translate)(Pcidev *, uchar);
  286. void (*sb_initialize)(Pcidev *, uchar, uchar);
  287. } bridge_t;
  288. static bridge_t southbridges[] = {
  289. { Intel, Intel_82371FB_0, pIIx_link, pIIx_init },
  290. { Intel, Intel_82371MX_0, pIIx_link, pIIx_init },
  291. { Intel, Intel_82371SB_0, pIIx_link, pIIx_init },
  292. { Intel, Intel_82371AB_0, pIIx_link, pIIx_init },
  293. { Intel, Intel_82443MX_1, pIIx_link, pIIx_init },
  294. { Intel, Intel_82801AA_0, pIIx_link, pIIx_init },
  295. { Intel, Intel_82801AB_0, pIIx_link, pIIx_init },
  296. { Intel, Intel_82801BA_0, pIIx_link, pIIx_init },
  297. { Intel, Intel_82801BAM_0, pIIx_link, pIIx_init },
  298. { Intel, Intel_82801CAM_0, pIIx_link, pIIx_init },
  299. { Intel, Intel_82801DBM_0, pIIx_link, pIIx_init },
  300. { Intel, Intel_82801EB_0, pIIx_link, pIIx_init },
  301. { Intel, Intel_82801FB_0, pIIx_link, pIIx_init },
  302. { Viatech, Via_82C586_0, via_link, via_init },
  303. { Viatech, Via_82C596, via_link, via_init },
  304. { Viatech, Via_82C686, via_link, via_init },
  305. { Opti, Opti_82C700, opti_link, opti_init },
  306. { Al, Al_M1533, ali_link, ali_init },
  307. { SI, SI_503, pIIx_link, pIIx_init },
  308. { SI, SI_496, pIIx_link, pIIx_init },
  309. { Cyrix, Cyrix_5530_Legacy, cyrix_link, cyrix_init }
  310. };
  311. typedef struct {
  312. uchar e_bus; // Pci bus number
  313. uchar e_dev; // Pci device number
  314. uchar e_maps[12]; // Avoid structs! Link and mask.
  315. uchar e_slot; // Add-in/built-in slot
  316. uchar e_reserved;
  317. } slot_t;
  318. typedef struct {
  319. uchar rt_signature[4]; // Routing table signature
  320. uchar rt_version[2]; // Version number
  321. uchar rt_size[2]; // Total table size
  322. uchar rt_bus; // Interrupt router bus number
  323. uchar rt_devfn; // Router's devfunc
  324. uchar rt_pciirqs[2]; // Exclusive PCI irqs
  325. uchar rt_compat[4]; // Compatible PCI interrupt router
  326. uchar rt_miniport[4]; // Miniport data
  327. uchar rt_reserved[11];
  328. uchar rt_checksum;
  329. } router_t;
  330. static ushort pciirqs; // Exclusive PCI irqs
  331. static bridge_t *southbridge; // Which southbridge to use.
  332. static void
  333. pcirouting(void)
  334. {
  335. uchar *p, pin, irq;
  336. ulong tbdf, vdid;
  337. ushort vid, did;
  338. router_t *r;
  339. slot_t *e;
  340. int size, i, fn;
  341. Pcidev *sbpci, *pci;
  342. // Peek in the BIOS
  343. for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
  344. if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
  345. break;
  346. if (p >= (uchar *)KADDR(0xfffff))
  347. return;
  348. r = (router_t *)p;
  349. // print("PCI interrupt routing table version %d.%d at %.6uX\n",
  350. // r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);
  351. tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
  352. vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
  353. vid = vdid;
  354. did = vdid >> 16;
  355. for (i = 0; i != nelem(southbridges); i++)
  356. if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
  357. break;
  358. if (i == nelem(southbridges)) {
  359. print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
  360. return;
  361. }
  362. southbridge = &southbridges[i];
  363. if ((sbpci = pcimatch(nil, vid, did)) == nil) {
  364. print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
  365. vid, did);
  366. return;
  367. }
  368. pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];
  369. size = (r->rt_size[1] << 8)|r->rt_size[0];
  370. for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
  371. // print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
  372. // for (i = 0; i != 4; i++) {
  373. // uchar *m = &e->e_maps[i * 3];
  374. // print("[%d] %.2uX %.4uX ",
  375. // i, m[0], (m[2] << 8)|m[1]);
  376. // }
  377. // print("\n");
  378. for (fn = 0; fn != 8; fn++) {
  379. uchar *m;
  380. // Retrieve the did and vid through the devfn before
  381. // obtaining the Pcidev structure.
  382. tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
  383. vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
  384. if (vdid == 0xFFFFFFFF || vdid == 0)
  385. continue;
  386. vid = vdid;
  387. did = vdid >> 16;
  388. pci = nil;
  389. while ((pci = pcimatch(pci, vid, did)) != nil) {
  390. if (pci->intl != 0 && pci->intl != 0xFF)
  391. continue;
  392. pin = pcicfgr8(pci, PciINTP);
  393. if (pin == 0 || pin == 0xff)
  394. continue;
  395. m = &e->e_maps[(pin - 1) * 3];
  396. irq = southbridge->sb_translate(sbpci, m[0]);
  397. if (irq) {
  398. print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n",
  399. vid, did, pin, irq);
  400. pcicfgw8(pci, PciINTL, irq);
  401. pci->intl = irq;
  402. }
  403. }
  404. }
  405. }
  406. }
  407. static void
  408. pcicfginit(void)
  409. {
  410. char *p;
  411. int bno, n;
  412. Pcidev **list;
  413. lock(&pcicfginitlock);
  414. if(pcicfgmode != -1)
  415. goto out;
  416. /*
  417. * Try to determine which PCI configuration mode is implemented.
  418. * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
  419. * a DWORD at 0xCF8 and another at 0xCFC and will pass through
  420. * any non-DWORD accesses as normal I/O cycles. There shouldn't be
  421. * a device behind these addresses so if Mode1 accesses fail try
  422. * for Mode2 (Mode2 is deprecated).
  423. */
  424. /*
  425. * Bits [30:24] of PciADDR must be 0,
  426. * according to the spec.
  427. */
  428. n = inl(PciADDR);
  429. if(!(n & 0x7FF00000)){
  430. outl(PciADDR, 0x80000000);
  431. outb(PciADDR+3, 0);
  432. if(inl(PciADDR) & 0x80000000){
  433. pcicfgmode = 1;
  434. pcimaxdno = 31;
  435. }
  436. }
  437. outl(PciADDR, n);
  438. if(pcicfgmode < 0){
  439. /*
  440. * The 'key' part of PciCSE should be 0.
  441. */
  442. n = inb(PciCSE);
  443. if(!(n & 0xF0)){
  444. outb(PciCSE, 0x0E);
  445. if(inb(PciCSE) == 0x0E){
  446. pcicfgmode = 2;
  447. pcimaxdno = 15;
  448. }
  449. }
  450. outb(PciCSE, n);
  451. }
  452. if(pcicfgmode < 0)
  453. goto out;
  454. if(p = getconf("*pcimaxbno"))
  455. pcimaxbno = strtoul(p, 0, 0);
  456. if(p = getconf("*pcimaxdno"))
  457. pcimaxdno = strtoul(p, 0, 0);
  458. list = &pciroot;
  459. for(bno = 0; bno <= pcimaxbno; bno++) {
  460. bno = pciscan(bno, list);
  461. while(*list)
  462. list = &(*list)->link;
  463. }
  464. pcirouting();
  465. out:
  466. unlock(&pcicfginitlock);
  467. if(getconf("*pcihinv"))
  468. pcihinv(nil);
  469. }
  470. static int
  471. pcicfgrw8(int tbdf, int rno, int data, int read)
  472. {
  473. int o, type, x;
  474. if(pcicfgmode == -1)
  475. pcicfginit();
  476. if(BUSBNO(tbdf))
  477. type = 0x01;
  478. else
  479. type = 0x00;
  480. x = -1;
  481. if(BUSDNO(tbdf) > pcimaxdno)
  482. return x;
  483. lock(&pcicfglock);
  484. switch(pcicfgmode){
  485. case 1:
  486. o = rno & 0x03;
  487. rno &= ~0x03;
  488. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  489. if(read)
  490. x = inb(PciDATA+o);
  491. else
  492. outb(PciDATA+o, data);
  493. outl(PciADDR, 0);
  494. break;
  495. case 2:
  496. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  497. outb(PciFORWARD, BUSBNO(tbdf));
  498. if(read)
  499. x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  500. else
  501. outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  502. outb(PciCSE, 0);
  503. break;
  504. }
  505. unlock(&pcicfglock);
  506. return x;
  507. }
  508. int
  509. pcicfgr8(Pcidev* pcidev, int rno)
  510. {
  511. return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  512. }
  513. void
  514. pcicfgw8(Pcidev* pcidev, int rno, int data)
  515. {
  516. pcicfgrw8(pcidev->tbdf, rno, data, 0);
  517. }
  518. static int
  519. pcicfgrw16(int tbdf, int rno, int data, int read)
  520. {
  521. int o, type, x;
  522. if(pcicfgmode == -1)
  523. pcicfginit();
  524. if(BUSBNO(tbdf))
  525. type = 0x01;
  526. else
  527. type = 0x00;
  528. x = -1;
  529. if(BUSDNO(tbdf) > pcimaxdno)
  530. return x;
  531. lock(&pcicfglock);
  532. switch(pcicfgmode){
  533. case 1:
  534. o = rno & 0x02;
  535. rno &= ~0x03;
  536. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  537. if(read)
  538. x = ins(PciDATA+o);
  539. else
  540. outs(PciDATA+o, data);
  541. outl(PciADDR, 0);
  542. break;
  543. case 2:
  544. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  545. outb(PciFORWARD, BUSBNO(tbdf));
  546. if(read)
  547. x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  548. else
  549. outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  550. outb(PciCSE, 0);
  551. break;
  552. }
  553. unlock(&pcicfglock);
  554. return x;
  555. }
  556. int
  557. pcicfgr16(Pcidev* pcidev, int rno)
  558. {
  559. return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  560. }
  561. void
  562. pcicfgw16(Pcidev* pcidev, int rno, int data)
  563. {
  564. pcicfgrw16(pcidev->tbdf, rno, data, 0);
  565. }
  566. static int
  567. pcicfgrw32(int tbdf, int rno, int data, int read)
  568. {
  569. int type, x;
  570. if(pcicfgmode == -1)
  571. pcicfginit();
  572. if(BUSBNO(tbdf))
  573. type = 0x01;
  574. else
  575. type = 0x00;
  576. x = -1;
  577. if(BUSDNO(tbdf) > pcimaxdno)
  578. return x;
  579. lock(&pcicfglock);
  580. switch(pcicfgmode){
  581. case 1:
  582. rno &= ~0x03;
  583. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  584. if(read)
  585. x = inl(PciDATA);
  586. else
  587. outl(PciDATA, data);
  588. outl(PciADDR, 0);
  589. break;
  590. case 2:
  591. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  592. outb(PciFORWARD, BUSBNO(tbdf));
  593. if(read)
  594. x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  595. else
  596. outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  597. outb(PciCSE, 0);
  598. break;
  599. }
  600. unlock(&pcicfglock);
  601. return x;
  602. }
  603. int
  604. pcicfgr32(Pcidev* pcidev, int rno)
  605. {
  606. return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  607. }
  608. void
  609. pcicfgw32(Pcidev* pcidev, int rno, int data)
  610. {
  611. pcicfgrw32(pcidev->tbdf, rno, data, 0);
  612. }
  613. Pcidev*
  614. pcimatch(Pcidev* prev, int vid, int did)
  615. {
  616. if(pcicfgmode == -1)
  617. pcicfginit();
  618. if(prev == nil)
  619. prev = pcilist;
  620. else
  621. prev = prev->list;
  622. while(prev != nil) {
  623. if((vid == 0 || prev->vid == vid)
  624. && (did == 0 || prev->did == did))
  625. break;
  626. prev = prev->list;
  627. }
  628. return prev;
  629. }
  630. uchar
  631. pciipin(Pcidev *pci, uchar pin)
  632. {
  633. if (pci == nil)
  634. pci = pcilist;
  635. while (pci) {
  636. uchar intl;
  637. if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
  638. return pci->intl;
  639. if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
  640. return intl;
  641. pci = pci->list;
  642. }
  643. return 0;
  644. }
  645. static ushort
  646. pciimask(Pcidev *pci)
  647. {
  648. ushort imask;
  649. imask = 0;
  650. while (pci) {
  651. if (pcicfgr8(pci, PciINTP) && pci->intl < 16)
  652. imask |= 1 << pci->intl;
  653. if (pci->bridge)
  654. imask |= pciimask(pci->bridge);
  655. pci = pci->list;
  656. }
  657. return imask;
  658. }
  659. uchar
  660. pciintl(Pcidev *pci)
  661. {
  662. ushort imask;
  663. int i;
  664. if (pci == nil)
  665. pci = pcilist;
  666. imask = pciimask(pci) | 1;
  667. for (i = 0; i != 16; i++)
  668. if ((imask & (1 << i)) == 0)
  669. return i;
  670. return 0;
  671. }
  672. void
  673. pcihinv(Pcidev* p)
  674. {
  675. int i;
  676. Pcidev *t;
  677. if(pcicfgmode == -1)
  678. pcicfginit();
  679. if(p == nil) {
  680. p = pciroot;
  681. print("bus dev type vid did intl memory\n");
  682. }
  683. for(t = p; t != nil; t = t->link) {
  684. print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
  685. BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
  686. t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
  687. for(i = 0; i < nelem(p->mem); i++) {
  688. if(t->mem[i].size == 0)
  689. continue;
  690. print("%d:%.8lux %d ", i,
  691. t->mem[i].bar, t->mem[i].size);
  692. }
  693. print("\n");
  694. }
  695. while(p != nil) {
  696. if(p->bridge != nil)
  697. pcihinv(p->bridge);
  698. p = p->link;
  699. }
  700. }
  701. void
  702. pcireset(void)
  703. {
  704. Pcidev *p;
  705. int pcr;
  706. if(pcicfgmode == -1)
  707. pcicfginit();
  708. for(p = pcilist; p != nil; p = p->list){
  709. pcr = pcicfgr16(p, PciPSR);
  710. pcicfgw16(p, PciPSR, pcr & ~0x04);
  711. }
  712. }
  713. void
  714. pcisetbme(Pcidev* p)
  715. {
  716. int pcr;
  717. pcr = pcicfgr16(p, PciPCR);
  718. pcr |= 0x0004;
  719. pcicfgw16(p, PciPCR, pcr);
  720. }