pci.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * PCI support code.
  8. * There really should be a driver for this, it's not terribly safe
  9. * without locks or restrictions on what can be poked (e.g. Axil NX801).
  10. */
  11. enum { /* configuration mechanism #1 */
  12. PciADDR = 0xCF8, /* CONFIG_ADDRESS */
  13. PciDATA = 0xCFC, /* CONFIG_DATA */
  14. /* configuration mechanism #2 */
  15. PciCSE = 0xCF8, /* configuration space enable */
  16. PciFORWARD = 0xCFA, /* which bus */
  17. MaxFNO = 7,
  18. MaxUBN = 255,
  19. };
  20. static int pcicfgmode = -1;
  21. static int pcimaxdno;
  22. static Pcidev* pciroot;
  23. static Pcidev* pcilist;
  24. static Pcidev* pcitail;
  25. static int pcicfgrw32(int, int, int, int);
  26. static int
  27. pciscan(int bno, Pcidev** list)
  28. {
  29. ulong v;
  30. Pcidev *p, *head, *tail;
  31. int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
  32. maxubn = bno;
  33. head = nil;
  34. tail = nil;
  35. for(dno = 0; dno <= pcimaxdno; dno++){
  36. maxfno = 0;
  37. for(fno = 0; fno <= maxfno; fno++){
  38. /*
  39. * For this possible device, form the bus+device+function
  40. * triplet needed to address it and try to read the vendor
  41. * and device ID. If successful, allocate a device struct
  42. * and start to fill it in with some useful information from
  43. * the device's configuration space.
  44. */
  45. tbdf = MKBUS(BusPCI, bno, dno, fno);
  46. l = pcicfgrw32(tbdf, PciVID, 0, 1);
  47. if(l == 0xFFFFFFFF || l == 0)
  48. continue;
  49. p = mallocz(sizeof(*p), 1);
  50. p->tbdf = tbdf;
  51. p->vid = l;
  52. p->did = l>>16;
  53. p->rid = pcicfgr8(p, PciRID);
  54. if(pcilist != nil)
  55. pcitail->list = p;
  56. else
  57. pcilist = p;
  58. pcitail = p;
  59. p->intl = pcicfgr8(p, PciINTL);
  60. p->ccru = pcicfgr16(p, PciCCRu);
  61. /*
  62. * If the device is a multi-function device adjust the
  63. * loop count so all possible functions are checked.
  64. */
  65. hdt = pcicfgr8(p, PciHDT);
  66. if(hdt & 0x80)
  67. maxfno = MaxFNO;
  68. /*
  69. * If appropriate, read the base address registers
  70. * and work out the sizes.
  71. */
  72. switch(p->ccru>>8){
  73. case 0x01: /* mass storage controller */
  74. case 0x02: /* network controller */
  75. case 0x03: /* display controller */
  76. case 0x04: /* multimedia device */
  77. case 0x07: /* simple communication controllers */
  78. case 0x08: /* base system peripherals */
  79. case 0x09: /* input devices */
  80. case 0x0A: /* docking stations */
  81. case 0x0B: /* processors */
  82. case 0x0C: /* serial bus controllers */
  83. if((hdt & 0x7F) != 0)
  84. break;
  85. rno = PciBAR0 - 4;
  86. for(i = 0; i < nelem(p->mem); i++){
  87. rno += 4;
  88. p->mem[i].bar = pcicfgr32(p, rno);
  89. pcicfgw32(p, rno, -1);
  90. v = pcicfgr32(p, rno);
  91. pcicfgw32(p, rno, p->mem[i].bar);
  92. p->mem[i].size = -(v & ~0xF);
  93. }
  94. break;
  95. case 0x00:
  96. case 0x05: /* memory controller */
  97. case 0x06: /* bridge device */
  98. default:
  99. break;
  100. }
  101. if(head != nil)
  102. tail->link = p;
  103. else
  104. head = p;
  105. tail = p;
  106. }
  107. }
  108. *list = head;
  109. for(p = head; p != nil; p = p->link){
  110. /*
  111. * Find PCI-PCI bridges and recursively descend the tree.
  112. */
  113. if(p->ccru != ((0x06<<8)|0x04))
  114. continue;
  115. /*
  116. * If the secondary or subordinate bus number is not initialised
  117. * try to do what the PCI BIOS should have done and fill in the
  118. * numbers as the tree is descended. On the way down the subordinate
  119. * bus number is set to the maximum as it's not known how many
  120. * buses are behind this one; the final value is set on the way
  121. * back up.
  122. */
  123. sbn = pcicfgr8(p, PciSBN);
  124. ubn = pcicfgr8(p, PciUBN);
  125. if(sbn == 0 || ubn == 0){
  126. sbn = maxubn+1;
  127. /*
  128. * Make sure memory, I/O and master enables are off,
  129. * set the primary, secondary and subordinate bus numbers
  130. * and clear the secondary status before attempting to
  131. * scan the secondary bus.
  132. *
  133. * Initialisation of the bridge should be done here.
  134. */
  135. pcicfgw32(p, PciPCR, 0xFFFF0000);
  136. l = (MaxUBN<<16)|(sbn<<8)|bno;
  137. pcicfgw32(p, PciPBN, l);
  138. pcicfgw16(p, PciSPSR, 0xFFFF);
  139. maxubn = pciscan(sbn, &p->bridge);
  140. l = (maxubn<<16)|(sbn<<8)|bno;
  141. pcicfgw32(p, PciPBN, l);
  142. }
  143. else{
  144. maxubn = ubn;
  145. pciscan(sbn, &p->bridge);
  146. }
  147. }
  148. return maxubn;
  149. }
  150. static void
  151. pcicfginit(void)
  152. {
  153. #ifdef kernel
  154. char *p;
  155. #endif /* kernel */
  156. int bno;
  157. Pcidev **list;
  158. if(pcicfgmode == -1){
  159. /*
  160. * Try to determine which PCI configuration mode is implemented.
  161. * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
  162. * a DWORD at 0xCF8 and another at 0xCFC and will pass through
  163. * any non-DWORD accesses as normal I/O cycles. There shouldn't be
  164. * a device behind these addresses so if Mode2 accesses fail try
  165. * for Mode1 (which is preferred, Mode2 is deprecated).
  166. */
  167. outportb(PciCSE, 0);
  168. if(inportb(PciCSE) == 0){
  169. pcicfgmode = 2;
  170. pcimaxdno = 15;
  171. }
  172. else{
  173. outportl(PciADDR, 0);
  174. if(inportl(PciADDR) == 0){
  175. pcicfgmode = 1;
  176. pcimaxdno = 31;
  177. }
  178. }
  179. if(pcicfgmode > 0){
  180. list = &pciroot;
  181. for(bno = 0; bno < 256; bno++){
  182. bno = pciscan(bno, list);
  183. while(*list)
  184. list = &(*list)->link;
  185. }
  186. }
  187. }
  188. }
  189. static int
  190. pcicfgrw8(int tbdf, int rno, int data, int read)
  191. {
  192. int o, type, x;
  193. if(pcicfgmode == -1)
  194. pcicfginit();
  195. if(BUSBNO(tbdf))
  196. type = 0x01;
  197. else
  198. type = 0x00;
  199. x = -1;
  200. if(BUSDNO(tbdf) > pcimaxdno)
  201. return x;
  202. switch(pcicfgmode){
  203. case 1:
  204. o = rno & 0x03;
  205. rno &= ~0x03;
  206. outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  207. if(read)
  208. x = inportb(PciDATA+o);
  209. else
  210. outportb(PciDATA+o, data);
  211. outportl(PciADDR, 0);
  212. break;
  213. case 2:
  214. outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  215. outportb(PciFORWARD, BUSBNO(tbdf));
  216. if(read)
  217. x = inportb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  218. else
  219. outportb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  220. outportb(PciCSE, 0);
  221. break;
  222. }
  223. return x;
  224. }
  225. int
  226. pcicfgr8(Pcidev* pcidev, int rno)
  227. {
  228. return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  229. }
  230. void
  231. pcicfgw8(Pcidev* pcidev, int rno, int data)
  232. {
  233. pcicfgrw8(pcidev->tbdf, rno, data, 0);
  234. }
  235. static int
  236. pcicfgrw16(int tbdf, int rno, int data, int read)
  237. {
  238. int o, type, x;
  239. if(pcicfgmode == -1)
  240. pcicfginit();
  241. if(BUSBNO(tbdf))
  242. type = 0x01;
  243. else
  244. type = 0x00;
  245. x = -1;
  246. if(BUSDNO(tbdf) > pcimaxdno)
  247. return x;
  248. switch(pcicfgmode){
  249. case 1:
  250. o = rno & 0x02;
  251. rno &= ~0x03;
  252. outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  253. if(read)
  254. x = inportw(PciDATA+o);
  255. else
  256. outportw(PciDATA+o, data);
  257. outportl(PciADDR, 0);
  258. break;
  259. case 2:
  260. outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  261. outportb(PciFORWARD, BUSBNO(tbdf));
  262. if(read)
  263. x = inportw((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  264. else
  265. outportw((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  266. outportb(PciCSE, 0);
  267. break;
  268. }
  269. return x;
  270. }
  271. int
  272. pcicfgr16(Pcidev* pcidev, int rno)
  273. {
  274. return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  275. }
  276. void
  277. pcicfgw16(Pcidev* pcidev, int rno, int data)
  278. {
  279. pcicfgrw16(pcidev->tbdf, rno, data, 0);
  280. }
  281. static int
  282. pcicfgrw32(int tbdf, int rno, int data, int read)
  283. {
  284. int type, x;
  285. if(pcicfgmode == -1)
  286. pcicfginit();
  287. if(BUSBNO(tbdf))
  288. type = 0x01;
  289. else
  290. type = 0x00;
  291. x = -1;
  292. if(BUSDNO(tbdf) > pcimaxdno)
  293. return x;
  294. switch(pcicfgmode){
  295. case 1:
  296. rno &= ~0x03;
  297. outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  298. if(read)
  299. x = inportl(PciDATA);
  300. else
  301. outportl(PciDATA, data);
  302. outportl(PciADDR, 0);
  303. break;
  304. case 2:
  305. outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  306. outportb(PciFORWARD, BUSBNO(tbdf));
  307. if(read)
  308. x = inportl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  309. else
  310. outportl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  311. outportb(PciCSE, 0);
  312. break;
  313. }
  314. return x;
  315. }
  316. int
  317. pcicfgr32(Pcidev* pcidev, int rno)
  318. {
  319. return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  320. }
  321. void
  322. pcicfgw32(Pcidev* pcidev, int rno, int data)
  323. {
  324. pcicfgrw32(pcidev->tbdf, rno, data, 0);
  325. }
  326. Pcidev*
  327. pcimatch(Pcidev* prev, int vid, int did)
  328. {
  329. if(pcicfgmode == -1)
  330. pcicfginit();
  331. if(prev == nil)
  332. prev = pcilist;
  333. else
  334. prev = prev->list;
  335. while(prev != nil) {
  336. if(prev->vid == vid && (did == 0 || prev->did == did))
  337. break;
  338. prev = prev->list;
  339. }
  340. return prev;
  341. }
  342. void
  343. pcihinv(Pcidev* p)
  344. {
  345. int i;
  346. Pcidev *t;
  347. if(pcicfgmode == -1)
  348. pcicfginit();
  349. if(p == nil) {
  350. p = pciroot;
  351. Bprint(&stdout, "bus dev type vid did intl memory\n");
  352. }
  353. for(t = p; t != nil; t = t->link) {
  354. Bprint(&stdout, "%d %2d/%d %.4ux %.4ux %.4ux %2d ",
  355. BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
  356. t->ccru, t->vid, t->did, t->intl);
  357. for(i = 0; i < nelem(p->mem); i++) {
  358. if(t->mem[i].size == 0)
  359. continue;
  360. Bprint(&stdout, "%d:%.8lux %d ", i,
  361. t->mem[i].bar, t->mem[i].size);
  362. }
  363. Bprint(&stdout, "\n");
  364. }
  365. while(p != nil) {
  366. if(p->bridge != nil)
  367. pcihinv(p->bridge);
  368. p = p->link;
  369. }
  370. }