pci.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. /*
  2. * PCI support code.
  3. * To do:
  4. * initialise bridge mappings if the PCI BIOS didn't.
  5. */
  6. #include "all.h"
  7. #include "io.h"
  8. enum { /* configuration mechanism #1 */
  9. PciADDR = 0xCF8, /* CONFIG_ADDRESS */
  10. PciDATA = 0xCFC, /* CONFIG_DATA */
  11. /* configuration mechanism #2 */
  12. PciCSE = 0xCF8, /* configuration space enable */
  13. PciFORWARD = 0xCFA, /* which bus */
  14. MaxFNO = 7,
  15. MaxUBN = 255,
  16. };
  17. enum
  18. { /* command register */
  19. IOen = (1<<0),
  20. MEMen = (1<<1),
  21. MASen = (1<<2),
  22. MemWrInv = (1<<4),
  23. PErrEn = (1<<6),
  24. SErrEn = (1<<8),
  25. };
  26. static Lock pcicfglock;
  27. static Lock pcicfginitlock;
  28. static int pcicfgmode = -1;
  29. static int pcimaxdno;
  30. static Pcidev* pciroot;
  31. static Pcidev* pcilist;
  32. static Pcidev* pcitail;
  33. static int pcicfgrw32(int, int, int, int);
  34. static int pcicfgrw8(int, int, int, int);
  35. ulong
  36. pcibarsize(Pcidev *p, int rno)
  37. {
  38. ulong v, size;
  39. v = pcicfgrw32(p->tbdf, rno, 0, 1);
  40. pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
  41. size = pcicfgrw32(p->tbdf, rno, 0, 1);
  42. if(v & 1)
  43. size |= 0xFFFF0000;
  44. pcicfgrw32(p->tbdf, rno, v, 0);
  45. return -(size & ~0x0F);
  46. }
  47. static void
  48. cmd_pcihinv(int argc, char *argv[])
  49. {
  50. int i, flags = 0;
  51. for (i = 1; i < argc; i++)
  52. if (strcmp(argv[i], "-v") == 0)
  53. flags |= 1;
  54. else {
  55. print("unknown pcihinv option %s; options are: -v\n", argv[i]);
  56. return;
  57. }
  58. pcihinv(nil, flags); /* print the whole device tree */
  59. }
  60. static int
  61. pciscan(int bno, Pcidev** list)
  62. {
  63. Pcidev *p, *head, *tail;
  64. int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
  65. static int first = 1;
  66. maxubn = bno;
  67. head = nil;
  68. tail = nil;
  69. for(dno = 0; dno <= pcimaxdno; dno++){
  70. maxfno = 0;
  71. for(fno = 0; fno <= maxfno; fno++){
  72. /*
  73. * For this possible device, form the bus+device+function
  74. * triplet needed to address it and try to read the vendor
  75. * and device ID. If successful, allocate a device struct
  76. * and start to fill it in with some useful information from
  77. * the device's configuration space.
  78. */
  79. tbdf = MKBUS(BusPCI, bno, dno, fno);
  80. l = pcicfgrw32(tbdf, PciVID, 0, 1);
  81. if(l == 0xFFFFFFFF || l == 0)
  82. continue;
  83. p = ialloc(sizeof(*p), 0);
  84. p->tbdf = tbdf;
  85. p->vid = l;
  86. p->did = l>>16;
  87. if(pcilist != nil)
  88. pcitail->list = p;
  89. else
  90. pcilist = p;
  91. pcitail = p;
  92. p->rid = pcicfgr8(p, PciRID);
  93. p->ccrp = pcicfgr8(p, PciCCRp);
  94. p->ccrb = pcicfgr8(p, PciCCRb);
  95. p->pcr = pcicfgr32(p, PciPCR);
  96. /* ccru is uchar in cpu kernel */
  97. /* p->ccru = pcicfgr8(p, PciCCRu); */
  98. p->ccru = pcicfgr16(p, PciCCRu);
  99. p->intl = pcicfgr8(p, PciINTL);
  100. /*
  101. * If the device is a multi-function device adjust the
  102. * loop count so all possible functions are checked.
  103. */
  104. hdt = pcicfgr8(p, PciHDT);
  105. if(hdt & 0x80)
  106. maxfno = MaxFNO;
  107. /*
  108. * If appropriate, read the base address registers
  109. * and work out the sizes.
  110. */
  111. switch(p->ccru>>8){
  112. case 0x01: /* mass storage controller */
  113. case 0x02: /* network controller */
  114. case 0x03: /* display controller */
  115. case 0x04: /* multimedia device */
  116. case 0x07: /* simple communication controllers */
  117. case 0x08: /* base system peripherals */
  118. case 0x09: /* input devices */
  119. case 0x0A: /* docking stations */
  120. case 0x0B: /* processors */
  121. case 0x0C: /* serial bus controllers */
  122. if((hdt & 0x7F) != 0)
  123. break;
  124. rno = PciBAR0 - 4;
  125. for(i = 0; i < nelem(p->mem); i++){
  126. rno += 4;
  127. p->mem[i].bar = pcicfgr32(p, rno);
  128. p->mem[i].size = pcibarsize(p, rno);
  129. }
  130. break;
  131. case 0x00:
  132. case 0x05: /* memory controller */
  133. case 0x06: /* bridge device */
  134. default:
  135. break;
  136. }
  137. if(head != nil)
  138. tail->link = p;
  139. else
  140. head = p;
  141. tail = p;
  142. }
  143. }
  144. *list = head;
  145. for(p = head; p != nil; p = p->link){
  146. /*
  147. * Find PCI-PCI bridges and recursively descend the tree.
  148. */
  149. if(p->ccru != ((0x06<<8)|0x04))
  150. continue;
  151. /*
  152. * If the secondary or subordinate bus number is not initialized
  153. * try to do what the PCI BIOS should have done and fill in the
  154. * numbers as the tree is descended. On the way down the subordinate
  155. * bus number is set to the maximum as it's not known how many
  156. * buses are behind this one; the final value is set on the way
  157. * back up.
  158. */
  159. sbn = pcicfgr8(p, PciSBN);
  160. ubn = pcicfgr8(p, PciUBN);
  161. if(sbn == 0 || ubn == 0){
  162. sbn = maxubn+1;
  163. /*
  164. * Make sure memory, I/O and master enables are off,
  165. * set the primary, secondary and subordinate bus numbers
  166. * and clear the secondary status before attempting to
  167. * scan the secondary bus.
  168. *
  169. * Initialisation of the bridge should be done here.
  170. */
  171. pcicfgw32(p, PciPCR, 0xFFFF0000);
  172. l = (MaxUBN<<16)|(sbn<<8)|bno;
  173. pcicfgw32(p, PciPBN, l);
  174. pcicfgw16(p, PciSPSR, 0xFFFF);
  175. maxubn = pciscan(sbn, &p->bridge);
  176. l = (maxubn<<16)|(sbn<<8)|bno;
  177. pcicfgw32(p, PciPBN, l);
  178. }
  179. else{
  180. maxubn = ubn;
  181. pciscan(sbn, &p->bridge);
  182. }
  183. }
  184. if (first) {
  185. first = 0;
  186. cmd_install("pcihinv", "-- print PCI bus device inventory",
  187. cmd_pcihinv);
  188. }
  189. return maxubn;
  190. }
  191. static void
  192. pcicfginit(void)
  193. {
  194. char *p;
  195. int bno;
  196. Pcidev **list;
  197. lock(&pcicfginitlock);
  198. if(pcicfgmode == -1){
  199. /*
  200. * Try to determine which PCI configuration mode is implemented.
  201. * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
  202. * a DWORD at 0xCF8 and another at 0xCFC and will pass through
  203. * any non-DWORD accesses as normal I/O cycles. There shouldn't be
  204. * a device behind these addresses so if Mode2 accesses fail try
  205. * for Mode1 (which is preferred, Mode2 is deprecated).
  206. */
  207. outb(PciCSE, 0);
  208. if(inb(PciCSE) == 0){
  209. pcicfgmode = 2;
  210. pcimaxdno = 15;
  211. }
  212. else{
  213. outl(PciADDR, 0);
  214. if(inl(PciADDR) == 0){
  215. pcicfgmode = 1;
  216. pcimaxdno = 31;
  217. }
  218. }
  219. if(pcicfgmode > 0){
  220. if(p = getconf("*pcimaxdno"))
  221. pcimaxdno = strtoul(p, 0, 0);
  222. list = &pciroot;
  223. for(bno = 0; bno < 256; bno++){
  224. bno = pciscan(bno, list);
  225. while(*list)
  226. list = &(*list)->link;
  227. }
  228. }
  229. }
  230. unlock(&pcicfginitlock);
  231. }
  232. static int
  233. pcicfgrw8(int tbdf, int rno, int data, int read)
  234. {
  235. int o, type, x;
  236. if(pcicfgmode == -1)
  237. pcicfginit();
  238. if(BUSBNO(tbdf))
  239. type = 0x01;
  240. else
  241. type = 0x00;
  242. x = -1;
  243. if(BUSDNO(tbdf) > pcimaxdno)
  244. return x;
  245. lock(&pcicfglock);
  246. switch(pcicfgmode){
  247. case 1:
  248. o = rno & 0x03;
  249. rno &= ~0x03;
  250. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  251. if(read)
  252. x = inb(PciDATA+o);
  253. else
  254. outb(PciDATA+o, data);
  255. outl(PciADDR, 0);
  256. break;
  257. case 2:
  258. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  259. outb(PciFORWARD, BUSBNO(tbdf));
  260. if(read)
  261. x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  262. else
  263. outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  264. outb(PciCSE, 0);
  265. break;
  266. }
  267. unlock(&pcicfglock);
  268. return x;
  269. }
  270. int
  271. pcicfgr8(Pcidev* pcidev, int rno)
  272. {
  273. return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  274. }
  275. void
  276. pcicfgw8(Pcidev* pcidev, int rno, int data)
  277. {
  278. pcicfgrw8(pcidev->tbdf, rno, data, 0);
  279. }
  280. static int
  281. pcicfgrw16(int tbdf, int rno, int data, int read)
  282. {
  283. int o, type, x;
  284. if(pcicfgmode == -1)
  285. pcicfginit();
  286. if(BUSBNO(tbdf))
  287. type = 0x01;
  288. else
  289. type = 0x00;
  290. x = -1;
  291. if(BUSDNO(tbdf) > pcimaxdno)
  292. return x;
  293. lock(&pcicfglock);
  294. switch(pcicfgmode){
  295. case 1:
  296. o = rno & 0x02;
  297. rno &= ~0x03;
  298. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  299. if(read)
  300. x = ins(PciDATA+o);
  301. else
  302. outs(PciDATA+o, data);
  303. outl(PciADDR, 0);
  304. break;
  305. case 2:
  306. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  307. outb(PciFORWARD, BUSBNO(tbdf));
  308. if(read)
  309. x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  310. else
  311. outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  312. outb(PciCSE, 0);
  313. break;
  314. }
  315. unlock(&pcicfglock);
  316. return x;
  317. }
  318. int
  319. pcicfgr16(Pcidev* pcidev, int rno)
  320. {
  321. return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  322. }
  323. void
  324. pcicfgw16(Pcidev* pcidev, int rno, int data)
  325. {
  326. pcicfgrw16(pcidev->tbdf, rno, data, 0);
  327. }
  328. static int
  329. pcicfgrw32(int tbdf, int rno, int data, int read)
  330. {
  331. int type, x;
  332. if(pcicfgmode == -1)
  333. pcicfginit();
  334. if(BUSBNO(tbdf))
  335. type = 0x01;
  336. else
  337. type = 0x00;
  338. x = -1;
  339. if(BUSDNO(tbdf) > pcimaxdno)
  340. return x;
  341. lock(&pcicfglock);
  342. switch(pcicfgmode){
  343. case 1:
  344. rno &= ~0x03;
  345. outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  346. if(read)
  347. x = inl(PciDATA);
  348. else
  349. outl(PciDATA, data);
  350. outl(PciADDR, 0);
  351. break;
  352. case 2:
  353. outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  354. outb(PciFORWARD, BUSBNO(tbdf));
  355. if(read)
  356. x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  357. else
  358. outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  359. outb(PciCSE, 0);
  360. break;
  361. }
  362. unlock(&pcicfglock);
  363. return x;
  364. }
  365. int
  366. pcicfgr32(Pcidev* pcidev, int rno)
  367. {
  368. return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  369. }
  370. void
  371. pcicfgw32(Pcidev* pcidev, int rno, int data)
  372. {
  373. pcicfgrw32(pcidev->tbdf, rno, data, 0);
  374. }
  375. void
  376. pciclrmwi(Pcidev* p)
  377. {
  378. p->pcr &= ~MemWrInv;
  379. pcicfgw16(p, PciPCR, p->pcr);
  380. }
  381. Pcidev*
  382. pcimatch(Pcidev* prev, int vid, int did)
  383. {
  384. if(pcicfgmode == -1)
  385. pcicfginit();
  386. if(prev == nil)
  387. prev = pcilist;
  388. else
  389. prev = prev->list;
  390. while(prev != nil){
  391. if((vid == 0 || prev->vid == vid)
  392. && (did == 0 || prev->did == did))
  393. break;
  394. prev = prev->list;
  395. }
  396. return prev;
  397. }
  398. Pcidev*
  399. pcimatchtbdf(int tbdf)
  400. {
  401. Pcidev *pcidev;
  402. if(pcicfgmode == -1)
  403. pcicfginit();
  404. for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list){
  405. if(pcidev->tbdf == tbdf)
  406. break;
  407. }
  408. return pcidev;
  409. }
  410. static char *
  411. ccru2name(int ccru)
  412. {
  413. switch (ccru>>8) {
  414. case 0x01: /* mass storage controller */
  415. return "disks";
  416. case 0x02: /* network controller */
  417. return "net"; /* probably ether */
  418. case 0x03: /* display controller */
  419. return "video";
  420. case 0x04: /* multimedia device */
  421. return "audio";
  422. case 0x07: /* simple communication controllers */
  423. return "serial";
  424. case 0x08: /* base system peripherals */
  425. return "basic";
  426. case 0x09: /* input devices */
  427. return "input";
  428. case 0x0A: /* docking stations */
  429. return "dock";
  430. case 0x0B: /* processors */
  431. return "cpu";
  432. case 0x0C: /* serial bus controllers */
  433. return "usb";
  434. case 0x00:
  435. case 0x05: /* memory controller */
  436. return "memctl";
  437. case 0x06: /* bridge device */
  438. return "bridge";
  439. default:
  440. return "*GOK*";
  441. }
  442. }
  443. static char *
  444. vid2name(int vid)
  445. {
  446. switch (vid) {
  447. case 0x1000:
  448. return "ncr";
  449. case 0x1002:
  450. return "ati";
  451. case 0x100b:
  452. return "natsemi";
  453. case 0x1011:
  454. return "dec";
  455. case 0x1013:
  456. return "cirrus";
  457. case 0x1022:
  458. return "amd";
  459. case 0x1023:
  460. return "cyber?";
  461. case 0x102b:
  462. return "matrox";
  463. case 0x102c:
  464. return "hiq";
  465. case 0x1039:
  466. return "sis";
  467. case 0x104b:
  468. return "mylex";
  469. case 0x105a:
  470. return "promise";
  471. case 0x105d:
  472. return "number9";
  473. case 0x10a9:
  474. return "sgi";
  475. case 0x10b7:
  476. return "3com";
  477. case 0x10c8:
  478. return "neomagic"; /* or magicgraph */
  479. case 0x10de:
  480. return "nvidia";
  481. case 0x11ab:
  482. return "marvell";
  483. case 0x11ad:
  484. return "(pnic?)";
  485. case 0x121a:
  486. return "voodoo";
  487. case 0x12ae:
  488. return "alteon";
  489. case 0x1385:
  490. return "netgear";
  491. case 0x15ad:
  492. return "vmware";
  493. case 0x16ec:
  494. return "usrobot";
  495. case 0x5333: /* "S" "3". har, har. */
  496. return "s3";
  497. case 0x8086:
  498. return "intel";
  499. default:
  500. return "*GOK*";
  501. }
  502. }
  503. void
  504. pcihinv(Pcidev* p, ulong flags)
  505. {
  506. int i;
  507. Pcidev *t;
  508. if(p == nil) {
  509. p = pciroot;
  510. print("bus dev type ");
  511. if (flags)
  512. print("%7s", "");
  513. print("vid ");
  514. if (flags)
  515. print("%8s", "");
  516. print("did intl memory\n");
  517. }
  518. for(t = p; t != nil; t = t->link) {
  519. print("%d %2d/%d %.4ux", BUSBNO(t->tbdf), BUSDNO(t->tbdf),
  520. BUSFNO(t->tbdf), t->ccru);
  521. if (flags)
  522. print(" %-6s", ccru2name(t->ccru));
  523. print(" %.4ux", t->vid);
  524. if (flags)
  525. print(" %-7s", vid2name(t->vid));
  526. print(" %.4ux %2d ", t->did, t->intl);
  527. for(i = 0; i < nelem(p->mem); i++) {
  528. if(t->mem[i].size == 0)
  529. continue;
  530. print("%d:%.8lux %d ", i,
  531. t->mem[i].bar, t->mem[i].size);
  532. }
  533. print("\n");
  534. }
  535. while(p != nil) {
  536. if(p->bridge != nil)
  537. pcihinv(p->bridge, flags);
  538. p = p->link;
  539. }
  540. }
  541. void
  542. pcireset(void)
  543. {
  544. Pcidev *p;
  545. int pcr;
  546. if(pcicfgmode == -1)
  547. pcicfginit();
  548. for(p = pcilist; p != nil; p = p->list){
  549. pcr = pcicfgr16(p, PciPSR);
  550. pcicfgw16(p, PciPSR, pcr & ~0x04);
  551. }
  552. }
  553. void
  554. pcisetbme(Pcidev* p)
  555. {
  556. int pcr;
  557. pcr = pcicfgr16(p, PciPCR);
  558. pcr |= 0x04;
  559. pcicfgw16(p, PciPCR, pcr);
  560. }
  561. void
  562. pciclrbme(Pcidev* p)
  563. {
  564. p->pcr &= ~MASen;
  565. pcicfgw16(p, PciPCR, p->pcr);
  566. }