pci.c 11 KB

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