devpci.c 6.6 KB

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