devpci.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "../port/error.h"
  16. // Include the definitions from VIRTIO spec v1.0
  17. // http://docs.oasis-open.org/virtio/virtio/v1.0/csprd02/listings/virtio_ring.h
  18. #include "virtio_ring.h"
  19. enum {
  20. Qtopdir = 0,
  21. Qpcidir,
  22. Qpcictl,
  23. Qpciraw,
  24. Qpcicap,
  25. };
  26. #define TYPE(q) ((uint32_t)(q).path & 0x0F)
  27. #define QID(c, t) (((c)<<4)|(t))
  28. static Dirtab topdir[] = {
  29. ".", { Qtopdir, 0, QTDIR }, 0, 0555,
  30. "pci", { Qpcidir, 0, QTDIR }, 0, 0555,
  31. };
  32. extern Dev pcidevtab;
  33. static int
  34. pcidirgen(Chan *c, int t, int tbdf, Dir *dp)
  35. {
  36. Pcidev *p;
  37. Proc *up = externup();
  38. Qid q;
  39. q = (Qid){BUSBDF(tbdf)|t, 0, 0};
  40. switch(t) {
  41. case Qpcictl:
  42. snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%dctl",
  43. BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  44. devdir(c, q, up->genbuf, 0, eve, 0444, dp);
  45. return 1;
  46. case Qpciraw:
  47. snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%draw",
  48. BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  49. devdir(c, q, up->genbuf, 128, eve, 0664, dp);
  50. return 1;
  51. // Display device capabilities as a directory,
  52. // each capability has an entry as a file.
  53. case Qpcicap:
  54. p = pcimatchtbdf(tbdf);
  55. if((p == nil) || (p->capcnt == 0))
  56. return 0;
  57. snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%dcap",
  58. BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  59. q.type = QTDIR;
  60. devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp);
  61. return 1;
  62. }
  63. return -1;
  64. }
  65. static int
  66. pcigen(Chan *c, char *d, Dirtab* dir, int i, int s, Dir *dp)
  67. {
  68. Proc *up = externup();
  69. int tbdf;
  70. Pcidev *p;
  71. Qid q;
  72. switch(TYPE(c->qid)){
  73. case Qtopdir:
  74. if(s == DEVDOTDOT){
  75. q = (Qid){QID(0, Qtopdir), 0, QTDIR};
  76. snprint(up->genbuf, sizeof up->genbuf, "#%C", pcidevtab.dc);
  77. devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  78. return 1;
  79. }
  80. return devgen(c, nil, topdir, nelem(topdir), s, dp);
  81. case Qpcidir:
  82. if(s == DEVDOTDOT){
  83. q = (Qid){QID(0, Qtopdir), 0, QTDIR};
  84. snprint(up->genbuf, sizeof up->genbuf, "#%C", pcidevtab.dc);
  85. devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  86. return 1;
  87. }
  88. p = pcimatch(nil, 0, 0);
  89. while(s >= 3 && p != nil) {
  90. p = pcimatch(p, 0, 0);
  91. s -= 3;
  92. }
  93. if(p == nil)
  94. return -1;
  95. return pcidirgen(c, s+Qpcictl, p->tbdf, dp);
  96. case Qpcicap:
  97. case Qpcictl:
  98. case Qpciraw:
  99. tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
  100. p = pcimatchtbdf(tbdf);
  101. if(p == nil)
  102. return -1;
  103. // Generate a directory entry for each PCI device capability
  104. // gathered during the PCI bus scan.
  105. // Each capability is displayed as a file of length equal to the length
  106. // of the capability in the memory, and the file name is formatted as
  107. // capN.vV.lL.tT.bB.oO where N is capability index as collected during
  108. // the PCI bus scan, V is capability vendor code (cap_vndr), L is
  109. // capability length in the PCI config space (cap_len), T is capability
  110. // config type (cfg_type), B is BAR number, and O is offset within BAR.
  111. // The capabilities files cannot be read or written. They are displayed
  112. // for exploratory purposes only.
  113. if(TYPE(c->qid) == Qpcicap) {
  114. if(s >= p->capcnt)
  115. return -1;
  116. q = (Qid){BUSBDF(tbdf)|(Qpcicap + s + 1), 0, 0};
  117. Pcicap *pcp = p->capidx[s];
  118. snprint(up->genbuf, sizeof up->genbuf, "cap%d.v%d.l%d.t%d.b%d.o%d",
  119. s, pcp->vndr, pcp->caplen, pcp->type, pcp->bar, pcp->offset);
  120. devdir(c, q, up->genbuf, pcp->length, eve, 0444, dp);
  121. return 1;
  122. } else {
  123. return pcidirgen(c, TYPE(c->qid), tbdf, dp);
  124. }
  125. default:
  126. break;
  127. }
  128. return -1;
  129. }
  130. static Chan*
  131. pciattach(char *spec)
  132. {
  133. return devattach(pcidevtab.dc, spec);
  134. }
  135. Walkqid*
  136. pciwalk(Chan* c, Chan *nc, char** name, int nname)
  137. {
  138. return devwalk(c, nc, name, nname, (Dirtab *)0, 0, pcigen);
  139. }
  140. static int32_t
  141. pcistat(Chan* c, uint8_t* dp, int32_t n)
  142. {
  143. return devstat(c, dp, n, (Dirtab *)0, 0L, pcigen);
  144. }
  145. static Chan*
  146. pciopen(Chan *c, int omode)
  147. {
  148. c = devopen(c, omode, (Dirtab*)0, 0, pcigen);
  149. switch(TYPE(c->qid)){
  150. default:
  151. break;
  152. }
  153. return c;
  154. }
  155. static void
  156. pciclose(Chan* c)
  157. {
  158. }
  159. static int32_t
  160. pciread(Chan *c, void *va, int32_t n, int64_t offset)
  161. {
  162. char buf[256], *ebuf, *w, *a;
  163. int i, tbdf, r;
  164. uint32_t x;
  165. Pcidev *p;
  166. a = va;
  167. switch(TYPE(c->qid)){
  168. case Qtopdir:
  169. case Qpcidir:
  170. case Qpcicap:
  171. return devdirread(c, a, n, (Dirtab *)0, 0L, pcigen);
  172. case Qpcictl:
  173. tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
  174. p = pcimatchtbdf(tbdf);
  175. if(p == nil)
  176. error(Egreg);
  177. ebuf = buf+sizeof buf-1; /* -1 for newline */
  178. w = seprint(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d",
  179. p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl);
  180. for(i=0; i<nelem(p->mem); i++){
  181. if(p->mem[i].size == 0)
  182. continue;
  183. w = seprint(w, ebuf, " %d:%.8lux %d", i, p->mem[i].bar, p->mem[i].size);
  184. }
  185. *w++ = '\n';
  186. *w = '\0';
  187. return readstr(offset, a, n, buf);
  188. case Qpciraw:
  189. tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
  190. p = pcimatchtbdf(tbdf);
  191. if(p == nil)
  192. error(Egreg);
  193. if(n+offset > 256)
  194. n = 256-offset;
  195. if(n < 0)
  196. return 0;
  197. r = offset;
  198. if(!(r & 3) && n == 4){
  199. x = pcicfgr32(p, r);
  200. PBIT32(a, x);
  201. return 4;
  202. }
  203. if(!(r & 1) && n == 2){
  204. x = pcicfgr16(p, r);
  205. PBIT16(a, x);
  206. return 2;
  207. }
  208. for(i = 0; i < n; i++){
  209. x = pcicfgr8(p, r);
  210. PBIT8(a, x);
  211. a++;
  212. r++;
  213. }
  214. return i;
  215. default:
  216. error(Egreg);
  217. }
  218. return n;
  219. }
  220. static int32_t
  221. pciwrite(Chan *c, void *va, int32_t n, int64_t offset)
  222. {
  223. char buf[256];
  224. uint8_t *a;
  225. int i, r, tbdf;
  226. uint32_t x;
  227. Pcidev *p;
  228. if(n >= sizeof(buf))
  229. n = sizeof(buf)-1;
  230. a = va;
  231. strncpy(buf, (char*)a, n);
  232. buf[n] = 0;
  233. switch(TYPE(c->qid)){
  234. case Qpciraw:
  235. tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
  236. p = pcimatchtbdf(tbdf);
  237. if(p == nil)
  238. error(Egreg);
  239. if(offset > 256)
  240. return 0;
  241. if(n+offset > 256)
  242. n = 256-offset;
  243. r = offset;
  244. if(!(r & 3) && n == 4){
  245. x = GBIT32(a);
  246. pcicfgw32(p, r, x);
  247. return 4;
  248. }
  249. if(!(r & 1) && n == 2){
  250. x = GBIT16(a);
  251. pcicfgw16(p, r, x);
  252. return 2;
  253. }
  254. for(i = 0; i < n; i++){
  255. x = GBIT8(a);
  256. pcicfgw8(p, r, x);
  257. a++;
  258. r++;
  259. }
  260. return i;
  261. default:
  262. error(Egreg);
  263. }
  264. return n;
  265. }
  266. Dev pcidevtab = {
  267. .dc = '$',
  268. .name = "pci",
  269. .reset = devreset,
  270. .init = devinit,
  271. .shutdown = devshutdown,
  272. .attach = pciattach,
  273. .walk = pciwalk,
  274. .stat = pcistat,
  275. .open = pciopen,
  276. .create = devcreate,
  277. .close = pciclose,
  278. .read = pciread,
  279. .bread = devbread,
  280. .write = pciwrite,
  281. .bwrite = devbwrite,
  282. .remove = devremove,
  283. .wstat = devwstat,
  284. };