pci.c 20 KB

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