pci.c 20 KB

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