pci.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  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. null_link(Pcidev *, uchar )
  189. {
  190. return 0;
  191. }
  192. static void
  193. null_init(Pcidev *, uchar , uchar )
  194. {
  195. }
  196. static uchar
  197. pIIx_link(Pcidev *router, uchar link)
  198. {
  199. uchar pirq;
  200. /* link should be 0x60, 0x61, 0x62, 0x63 */
  201. pirq = pcicfgr8(router, link);
  202. return (pirq < 16)? pirq: 0;
  203. }
  204. static void
  205. pIIx_init(Pcidev *router, uchar link, uchar irq)
  206. {
  207. pcicfgw8(router, link, irq);
  208. }
  209. static uchar
  210. via_link(Pcidev *router, uchar link)
  211. {
  212. uchar pirq;
  213. /* link should be 1, 2, 3, 5 */
  214. pirq = (link < 6)? pcicfgr8(router, 0x55 + (link>>1)): 0;
  215. return (link & 1)? (pirq >> 4): (pirq & 15);
  216. }
  217. static void
  218. via_init(Pcidev *router, uchar link, uchar irq)
  219. {
  220. uchar pirq;
  221. pirq = pcicfgr8(router, 0x55 + (link >> 1));
  222. pirq &= (link & 1)? 0x0f: 0xf0;
  223. pirq |= (link & 1)? (irq << 4): (irq & 15);
  224. pcicfgw8(router, 0x55 + (link>>1), pirq);
  225. }
  226. static uchar
  227. opti_link(Pcidev *router, uchar link)
  228. {
  229. uchar pirq = 0;
  230. /* link should be 0x02, 0x12, 0x22, 0x32 */
  231. if ((link & 0xcf) == 0x02)
  232. pirq = pcicfgr8(router, 0xb8 + (link >> 5));
  233. return (link & 0x10)? (pirq >> 4): (pirq & 15);
  234. }
  235. static void
  236. opti_init(Pcidev *router, uchar link, uchar irq)
  237. {
  238. uchar pirq;
  239. pirq = pcicfgr8(router, 0xb8 + (link >> 5));
  240. pirq &= (link & 0x10)? 0x0f : 0xf0;
  241. pirq |= (link & 0x10)? (irq << 4): (irq & 15);
  242. pcicfgw8(router, 0xb8 + (link >> 5), pirq);
  243. }
  244. static uchar
  245. ali_link(Pcidev *router, uchar link)
  246. {
  247. /* No, you're not dreaming */
  248. static const uchar map[] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
  249. uchar pirq;
  250. /* link should be 0x01..0x08 */
  251. pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
  252. return (link & 1)? map[pirq&15]: map[pirq>>4];
  253. }
  254. static void
  255. ali_init(Pcidev *router, uchar link, uchar irq)
  256. {
  257. /* Inverse of map in ali_link */
  258. static const uchar map[] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
  259. uchar pirq;
  260. pirq = pcicfgr8(router, 0x48 + ((link-1)>>1));
  261. pirq &= (link & 1)? 0x0f: 0xf0;
  262. pirq |= (link & 1)? (map[irq] << 4): (map[irq] & 15);
  263. pcicfgw8(router, 0x48 + ((link-1)>>1), pirq);
  264. }
  265. static uchar
  266. cyrix_link(Pcidev *router, uchar link)
  267. {
  268. uchar pirq;
  269. /* link should be 1, 2, 3, 4 */
  270. pirq = pcicfgr8(router, 0x5c + ((link-1)>>1));
  271. return ((link & 1)? pirq >> 4: pirq & 15);
  272. }
  273. static void
  274. cyrix_init(Pcidev *router, uchar link, uchar irq)
  275. {
  276. uchar pirq;
  277. pirq = pcicfgr8(router, 0x5c + (link>>1));
  278. pirq &= (link & 1)? 0x0f: 0xf0;
  279. pirq |= (link & 1)? (irq << 4): (irq & 15);
  280. pcicfgw8(router, 0x5c + (link>>1), pirq);
  281. }
  282. typedef struct {
  283. ushort sb_vid, sb_did;
  284. uchar (*sb_translate)(Pcidev *, uchar);
  285. void (*sb_initialize)(Pcidev *, uchar, uchar);
  286. } bridge_t;
  287. static bridge_t southbridges[] = {
  288. { 0x8086, 0x122e, pIIx_link, pIIx_init }, // Intel 82371FB
  289. { 0x8086, 0x1234, pIIx_link, pIIx_init }, // Intel 82371MX
  290. { 0x8086, 0x7000, pIIx_link, pIIx_init }, // Intel 82371SB
  291. { 0x8086, 0x7110, pIIx_link, pIIx_init }, // Intel 82371AB
  292. { 0x8086, 0x7198, pIIx_link, pIIx_init }, // Intel 82443MX (fn 1)
  293. { 0x8086, 0x2410, pIIx_link, pIIx_init }, // Intel 82801AA
  294. { 0x8086, 0x2420, pIIx_link, pIIx_init }, // Intel 82801AB
  295. { 0x8086, 0x2440, pIIx_link, pIIx_init }, // Intel 82801BA
  296. { 0x8086, 0x244c, pIIx_link, pIIx_init }, // Intel 82801BAM
  297. { 0x8086, 0x2480, pIIx_link, pIIx_init }, // Intel 82801CA
  298. { 0x8086, 0x248c, pIIx_link, pIIx_init }, // Intel 82801CAM
  299. { 0x8086, 0x24c0, pIIx_link, pIIx_init }, // Intel 82801DBL
  300. { 0x8086, 0x24cc, pIIx_link, pIIx_init }, // Intel 82801DBM
  301. { 0x8086, 0x24d0, pIIx_link, pIIx_init }, // Intel 82801EB
  302. { 0x8086, 0x2640, pIIx_link, pIIx_init }, // Intel 82801FB
  303. { 0x8086, 0x27b8, pIIx_link, pIIx_init }, // Intel 82801GB
  304. { 0x8086, 0x27b9, pIIx_link, pIIx_init }, // Intel 82801GBM
  305. { 0x1106, 0x0586, via_link, via_init }, // Viatech 82C586
  306. { 0x1106, 0x0596, via_link, via_init }, // Viatech 82C596
  307. { 0x1106, 0x0686, via_link, via_init }, // Viatech 82C686
  308. { 0x1106, 0x3227, via_link, via_init }, // Viatech VT8237
  309. { 0x1045, 0xc700, opti_link, opti_init }, // Opti 82C700
  310. { 0x10b9, 0x1533, ali_link, ali_init }, // Al M1533
  311. { 0x1039, 0x0008, pIIx_link, pIIx_init }, // SI 503
  312. { 0x1039, 0x0496, pIIx_link, pIIx_init }, // SI 496
  313. { 0x1078, 0x0100, cyrix_link, cyrix_init }, // Cyrix 5530 Legacy
  314. { 0x1002, 0x4377, nil, nil }, // ATI Radeon Xpress 200M
  315. { 0x1002, 0x4372, nil, nil }, // ATI SB400
  316. { 0x1022, 0x746B, nil, nil }, // AMD 8111
  317. { 0x10DE, 0x00D1, nil, nil }, // NVIDIA nForce 3
  318. { 0x10DE, 0x00E0, nil, nil }, // NVIDIA nForce 3 250 Series
  319. { 0x1166, 0x0200, nil, nil }, // ServerWorks ServerSet III LE
  320. };
  321. typedef struct {
  322. uchar e_bus; // Pci bus number
  323. uchar e_dev; // Pci device number
  324. uchar e_maps[12]; // Avoid structs! Link and mask.
  325. uchar e_slot; // Add-in/built-in slot
  326. uchar e_reserved;
  327. } slot_t;
  328. typedef struct {
  329. uchar rt_signature[4]; // Routing table signature
  330. uchar rt_version[2]; // Version number
  331. uchar rt_size[2]; // Total table size
  332. uchar rt_bus; // Interrupt router bus number
  333. uchar rt_devfn; // Router's devfunc
  334. uchar rt_pciirqs[2]; // Exclusive PCI irqs
  335. uchar rt_compat[4]; // Compatible PCI interrupt router
  336. uchar rt_miniport[4]; // Miniport data
  337. uchar rt_reserved[11];
  338. uchar rt_checksum;
  339. } router_t;
  340. static ushort pciirqs; // Exclusive PCI irqs
  341. static bridge_t *southbridge; // Which southbridge to use.
  342. static void
  343. pcirouting(void)
  344. {
  345. uchar *p, pin, irq;
  346. ulong tbdf, vdid;
  347. ushort vid, did;
  348. router_t *r;
  349. slot_t *e;
  350. int size, i, fn;
  351. Pcidev *sbpci, *pci;
  352. // Peek in the BIOS
  353. for (p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
  354. if (p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
  355. break;
  356. if (p >= (uchar *)KADDR(0xfffff))
  357. return;
  358. r = (router_t *)p;
  359. // print("PCI interrupt routing table version %d.%d at %.6uX\n",
  360. // r->rt_version[0], r->rt_version[1], (ulong)r & 0xfffff);
  361. tbdf = (BusPCI << 24)|(r->rt_bus << 16)|(r->rt_devfn << 8);
  362. vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
  363. vid = vdid;
  364. did = vdid >> 16;
  365. for (i = 0; i != nelem(southbridges); i++)
  366. if (vid == southbridges[i].sb_vid && did == southbridges[i].sb_did)
  367. break;
  368. if (i == nelem(southbridges)) {
  369. print("pcirouting: South bridge %.4uX, %.4uX not found\n", vid, did);
  370. return;
  371. }
  372. southbridge = &southbridges[i];
  373. if ((sbpci = pcimatch(nil, vid, did)) == nil) {
  374. print("pcirouting: Cannot match south bridge %.4uX, %.4uX\n",
  375. vid, did);
  376. return;
  377. }
  378. pciirqs = (r->rt_pciirqs[1] << 8)|r->rt_pciirqs[0];
  379. size = (r->rt_size[1] << 8)|r->rt_size[0];
  380. for (e = (slot_t *)&r[1]; (uchar *)e < p + size; e++) {
  381. // print("%.2uX/%.2uX %.2uX: ", e->e_bus, e->e_dev, e->e_slot);
  382. // for (i = 0; i != 4; i++) {
  383. // uchar *m = &e->e_maps[i * 3];
  384. // print("[%d] %.2uX %.4uX ",
  385. // i, m[0], (m[2] << 8)|m[1]);
  386. // }
  387. // print("\n");
  388. for (fn = 0; fn != 8; fn++) {
  389. uchar *m;
  390. // Retrieve the did and vid through the devfn before
  391. // obtaining the Pcidev structure.
  392. tbdf = (BusPCI << 24)|(e->e_bus << 16)|((e->e_dev | fn) << 8);
  393. vdid = pcicfgrw32(tbdf, PciVID, 0, 1);
  394. if (vdid == 0xFFFFFFFF || vdid == 0)
  395. continue;
  396. vid = vdid;
  397. did = vdid >> 16;
  398. pci = nil;
  399. while ((pci = pcimatch(pci, vid, did)) != nil) {
  400. if (pci->intl != 0 && pci->intl != 0xFF)
  401. continue;
  402. pin = pcicfgr8(pci, PciINTP);
  403. if (pin == 0 || pin == 0xff)
  404. continue;
  405. m = &e->e_maps[(pin - 1) * 3];
  406. irq = southbridge->sb_translate(sbpci, m[0]);
  407. if (irq) {
  408. print("pcirouting: %.4uX/%.4uX at pin %d irq %d\n",
  409. vid, did, pin, irq);
  410. pcicfgw8(pci, PciINTL, irq);
  411. pci->intl = irq;
  412. }
  413. }
  414. }
  415. }
  416. }
  417. static void
  418. pcicfginit(void)
  419. {
  420. char *p;
  421. int bno, n;
  422. Pcidev **list;
  423. lock(&pcicfginitlock);
  424. if(pcicfgmode != -1)
  425. goto out;
  426. /*
  427. * Try to determine which PCI configuration mode is implemented.
  428. * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
  429. * a DWORD at 0xCF8 and another at 0xCFC and will pass through
  430. * any non-DWORD accesses as normal I/O cycles. There shouldn't be
  431. * a device behind these addresses so if Mode1 accesses fail try
  432. * for Mode2 (Mode2 is deprecated).
  433. */
  434. /*
  435. * Bits [30:24] of PciADDR must be 0,
  436. * according to the spec.
  437. */
  438. n = inl(PciADDR);
  439. if(!(n & 0x7FF00000)){
  440. outl(PciADDR, 0x80000000);
  441. outb(PciADDR+3, 0);
  442. if(inl(PciADDR) & 0x80000000){
  443. pcicfgmode = 1;
  444. pcimaxdno = 31;
  445. }
  446. }
  447. outl(PciADDR, n);
  448. if(pcicfgmode < 0){
  449. /*
  450. * The 'key' part of PciCSE should be 0.
  451. */
  452. n = inb(PciCSE);
  453. if(!(n & 0xF0)){
  454. outb(PciCSE, 0x0E);
  455. if(inb(PciCSE) == 0x0E){
  456. pcicfgmode = 2;
  457. pcimaxdno = 15;
  458. }
  459. }
  460. outb(PciCSE, n);
  461. }
  462. if(pcicfgmode < 0)
  463. goto out;
  464. if(p = getconf("*pcimaxbno"))
  465. pcimaxbno = strtoul(p, 0, 0);
  466. if(p = getconf("*pcimaxdno"))
  467. pcimaxdno = strtoul(p, 0, 0);
  468. list = &pciroot;
  469. for(bno = 0; bno <= pcimaxbno; bno++) {
  470. bno = pciscan(bno, list);
  471. while(*list)
  472. list = &(*list)->link;
  473. }
  474. pcirouting();
  475. out:
  476. unlock(&pcicfginitlock);
  477. if(getconf("*pcihinv"))
  478. pcihinv(nil);
  479. }
  480. static int
  481. pcicfgrw8(int tbdf, int rno, int data, int read)
  482. {
  483. int o, type, x;
  484. if(pcicfgmode == -1)
  485. pcicfginit();
  486. if(BUSBNO(tbdf))
  487. type = 0x01;
  488. else
  489. type = 0x00;
  490. x = -1;
  491. if(BUSDNO(tbdf) > pcimaxdno)
  492. return x;
  493. lock(&pcicfglock);
  494. switch(pcicfgmode){
  495. case 1:
  496. o = rno & 0x03;
  497. rno &= ~0x03;
  498. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  499. if(read)
  500. x = inb(PciDATA+o);
  501. else
  502. outb(PciDATA+o, data);
  503. outl(PciADDR, 0);
  504. break;
  505. case 2:
  506. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  507. outb(PciFORWARD, BUSBNO(tbdf));
  508. if(read)
  509. x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  510. else
  511. outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  512. outb(PciCSE, 0);
  513. break;
  514. }
  515. unlock(&pcicfglock);
  516. return x;
  517. }
  518. int
  519. pcicfgr8(Pcidev* pcidev, int rno)
  520. {
  521. return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  522. }
  523. void
  524. pcicfgw8(Pcidev* pcidev, int rno, int data)
  525. {
  526. pcicfgrw8(pcidev->tbdf, rno, data, 0);
  527. }
  528. static int
  529. pcicfgrw16(int tbdf, int rno, int data, int read)
  530. {
  531. int o, type, x;
  532. if(pcicfgmode == -1)
  533. pcicfginit();
  534. if(BUSBNO(tbdf))
  535. type = 0x01;
  536. else
  537. type = 0x00;
  538. x = -1;
  539. if(BUSDNO(tbdf) > pcimaxdno)
  540. return x;
  541. lock(&pcicfglock);
  542. switch(pcicfgmode){
  543. case 1:
  544. o = rno & 0x02;
  545. rno &= ~0x03;
  546. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  547. if(read)
  548. x = ins(PciDATA+o);
  549. else
  550. outs(PciDATA+o, data);
  551. outl(PciADDR, 0);
  552. break;
  553. case 2:
  554. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  555. outb(PciFORWARD, BUSBNO(tbdf));
  556. if(read)
  557. x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  558. else
  559. outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  560. outb(PciCSE, 0);
  561. break;
  562. }
  563. unlock(&pcicfglock);
  564. return x;
  565. }
  566. int
  567. pcicfgr16(Pcidev* pcidev, int rno)
  568. {
  569. return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  570. }
  571. void
  572. pcicfgw16(Pcidev* pcidev, int rno, int data)
  573. {
  574. pcicfgrw16(pcidev->tbdf, rno, data, 0);
  575. }
  576. static int
  577. pcicfgrw32(int tbdf, int rno, int data, int read)
  578. {
  579. int type, x;
  580. if(pcicfgmode == -1)
  581. pcicfginit();
  582. if(BUSBNO(tbdf))
  583. type = 0x01;
  584. else
  585. type = 0x00;
  586. x = -1;
  587. if(BUSDNO(tbdf) > pcimaxdno)
  588. return x;
  589. lock(&pcicfglock);
  590. switch(pcicfgmode){
  591. case 1:
  592. rno &= ~0x03;
  593. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  594. if(read)
  595. x = inl(PciDATA);
  596. else
  597. outl(PciDATA, data);
  598. outl(PciADDR, 0);
  599. break;
  600. case 2:
  601. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  602. outb(PciFORWARD, BUSBNO(tbdf));
  603. if(read)
  604. x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  605. else
  606. outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  607. outb(PciCSE, 0);
  608. break;
  609. }
  610. unlock(&pcicfglock);
  611. return x;
  612. }
  613. int
  614. pcicfgr32(Pcidev* pcidev, int rno)
  615. {
  616. return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  617. }
  618. void
  619. pcicfgw32(Pcidev* pcidev, int rno, int data)
  620. {
  621. pcicfgrw32(pcidev->tbdf, rno, data, 0);
  622. }
  623. Pcidev*
  624. pcimatch(Pcidev* prev, int vid, int did)
  625. {
  626. if(pcicfgmode == -1)
  627. pcicfginit();
  628. if(prev == nil)
  629. prev = pcilist;
  630. else
  631. prev = prev->list;
  632. while(prev != nil) {
  633. if((vid == 0 || prev->vid == vid)
  634. && (did == 0 || prev->did == did))
  635. break;
  636. prev = prev->list;
  637. }
  638. return prev;
  639. }
  640. uchar
  641. pciipin(Pcidev *pci, uchar pin)
  642. {
  643. if (pci == nil)
  644. pci = pcilist;
  645. while (pci) {
  646. uchar intl;
  647. if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
  648. return pci->intl;
  649. if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
  650. return intl;
  651. pci = pci->list;
  652. }
  653. return 0;
  654. }
  655. static ushort
  656. pciimask(Pcidev *pci)
  657. {
  658. ushort imask;
  659. imask = 0;
  660. while (pci) {
  661. if (pcicfgr8(pci, PciINTP) && pci->intl < 16)
  662. imask |= 1 << pci->intl;
  663. if (pci->bridge)
  664. imask |= pciimask(pci->bridge);
  665. pci = pci->list;
  666. }
  667. return imask;
  668. }
  669. uchar
  670. pciintl(Pcidev *pci)
  671. {
  672. ushort imask;
  673. int i;
  674. if (pci == nil)
  675. pci = pcilist;
  676. imask = pciimask(pci) | 1;
  677. for (i = 0; i != 16; i++)
  678. if ((imask & (1 << i)) == 0)
  679. return i;
  680. return 0;
  681. }
  682. void
  683. pcihinv(Pcidev* p)
  684. {
  685. int i;
  686. Pcidev *t;
  687. if(pcicfgmode == -1)
  688. pcicfginit();
  689. if(p == nil) {
  690. p = pciroot;
  691. print("bus dev type vid did intl memory\n");
  692. }
  693. for(t = p; t != nil; t = t->link) {
  694. print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d ",
  695. BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
  696. t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
  697. for(i = 0; i < nelem(p->mem); i++) {
  698. if(t->mem[i].size == 0)
  699. continue;
  700. print("%d:%.8lux %d ", i,
  701. t->mem[i].bar, t->mem[i].size);
  702. }
  703. print("\n");
  704. }
  705. while(p != nil) {
  706. if(p->bridge != nil)
  707. pcihinv(p->bridge);
  708. p = p->link;
  709. }
  710. }
  711. void
  712. pcireset(void)
  713. {
  714. Pcidev *p;
  715. int pcr;
  716. if(pcicfgmode == -1)
  717. pcicfginit();
  718. for(p = pcilist; p != nil; p = p->list){
  719. pcr = pcicfgr16(p, PciPSR);
  720. pcicfgw16(p, PciPSR, pcr & ~0x04);
  721. }
  722. }
  723. void
  724. pcisetioe(Pcidev* p)
  725. {
  726. p->pcr |= IOen;
  727. pcicfgw16(p, PciPCR, p->pcr);
  728. }
  729. void
  730. pciclrioe(Pcidev* p)
  731. {
  732. p->pcr &= ~IOen;
  733. pcicfgw16(p, PciPCR, p->pcr);
  734. }
  735. void
  736. pcisetbme(Pcidev* p)
  737. {
  738. p->pcr |= MASen;
  739. pcicfgw16(p, PciPCR, p->pcr);
  740. }
  741. void
  742. pciclrbme(Pcidev* p)
  743. {
  744. p->pcr &= ~MASen;
  745. pcicfgw16(p, PciPCR, p->pcr);
  746. }
  747. void
  748. pcisetmwi(Pcidev* p)
  749. {
  750. p->pcr |= MemWrInv;
  751. pcicfgw16(p, PciPCR, p->pcr);
  752. }
  753. void
  754. pciclrmwi(Pcidev* p)
  755. {
  756. p->pcr &= ~MemWrInv;
  757. pcicfgw16(p, PciPCR, p->pcr);
  758. }
  759. static int
  760. pcigetpmrb(Pcidev* p)
  761. {
  762. int ptr;
  763. if(p->pmrb != 0)
  764. return p->pmrb;
  765. p->pmrb = -1;
  766. /*
  767. * If there are no extended capabilities implemented,
  768. * (bit 4 in the status register) assume there's no standard
  769. * power management method.
  770. * Find the capabilities pointer based on PCI header type.
  771. */
  772. if(!(pcicfgr16(p, PciPSR) & 0x0010))
  773. return -1;
  774. switch(pcicfgr8(p, PciHDT)){
  775. default:
  776. return -1;
  777. case 0: /* all other */
  778. case 1: /* PCI to PCI bridge */
  779. ptr = 0x34;
  780. break;
  781. case 2: /* CardBus bridge */
  782. ptr = 0x14;
  783. break;
  784. }
  785. ptr = pcicfgr32(p, ptr);
  786. while(ptr != 0){
  787. /*
  788. * Check for validity.
  789. * Can't be in standard header and must be double
  790. * word aligned.
  791. */
  792. if(ptr < 0x40 || (ptr & ~0xFC))
  793. return -1;
  794. if(pcicfgr8(p, ptr) == 0x01){
  795. p->pmrb = ptr;
  796. return ptr;
  797. }
  798. ptr = pcicfgr8(p, ptr+1);
  799. }
  800. return -1;
  801. }
  802. int
  803. pcigetpms(Pcidev* p)
  804. {
  805. int pmcsr, ptr;
  806. if((ptr = pcigetpmrb(p)) == -1)
  807. return -1;
  808. /*
  809. * Power Management Register Block:
  810. * offset 0: Capability ID
  811. * 1: next item pointer
  812. * 2: capabilities
  813. * 4: control/status
  814. * 6: bridge support extensions
  815. * 7: data
  816. */
  817. pmcsr = pcicfgr16(p, ptr+4);
  818. return pmcsr & 0x0003;
  819. }
  820. int
  821. pcisetpms(Pcidev* p, int state)
  822. {
  823. int ostate, pmc, pmcsr, ptr;
  824. if((ptr = pcigetpmrb(p)) == -1)
  825. return -1;
  826. pmc = pcicfgr16(p, ptr+2);
  827. pmcsr = pcicfgr16(p, ptr+4);
  828. ostate = pmcsr & 0x0003;
  829. pmcsr &= ~0x0003;
  830. switch(state){
  831. default:
  832. return -1;
  833. case 0:
  834. break;
  835. case 1:
  836. if(!(pmc & 0x0200))
  837. return -1;
  838. break;
  839. case 2:
  840. if(!(pmc & 0x0400))
  841. return -1;
  842. break;
  843. case 3:
  844. break;
  845. }
  846. pmcsr |= state;
  847. pcicfgw16(p, ptr+4, pmcsr);
  848. return ostate;
  849. }