usbuhci.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #include "usb.h"
  9. #define XPRINT if(debug)print
  10. #define XXPRINT if(0)print
  11. static int Chatty = 0;
  12. static int debug = 0;
  13. static char Estalled[] = "usb endpoint stalled";
  14. /*
  15. * UHCI interface registers and bits
  16. */
  17. enum
  18. {
  19. /* i/o space */
  20. Cmd = 0,
  21. Status = 2,
  22. Usbintr = 4,
  23. Frnum = 6,
  24. Flbaseadd = 8,
  25. SOFMod = 0xC,
  26. Portsc0 = 0x10,
  27. Portsc1 = 0x12,
  28. /* port status */
  29. Suspend = 1<<12,
  30. PortReset = 1<<9,
  31. SlowDevice = 1<<8,
  32. ResumeDetect = 1<<6,
  33. PortChange = 1<<3, /* write 1 to clear */
  34. PortEnable = 1<<2,
  35. StatusChange = 1<<1, /* write 1 to clear */
  36. DevicePresent = 1<<0,
  37. NFRAME = 1024,
  38. FRAMESIZE= NFRAME*sizeof(ulong), /* fixed by hardware; aligned to same */
  39. Vf = 1<<2, /* TD only */
  40. IsQH = 1<<1,
  41. Terminate = 1<<0,
  42. /* TD.status */
  43. SPD = 1<<29,
  44. ErrLimit0 = 0<<27,
  45. ErrLimit1 = 1<<27,
  46. ErrLimit2 = 2<<27,
  47. ErrLimit3 = 3<<27,
  48. LowSpeed = 1<<26,
  49. IsoSelect = 1<<25,
  50. IOC = 1<<24,
  51. Active = 1<<23,
  52. Stalled = 1<<22,
  53. DataBufferErr = 1<<21,
  54. Babbling = 1<<20,
  55. NAKed = 1<<19,
  56. CRCorTimeout = 1<<18,
  57. BitstuffErr = 1<<17,
  58. AnyError = (Stalled | DataBufferErr | Babbling | NAKed | CRCorTimeout | BitstuffErr),
  59. /* TD.dev */
  60. IsDATA1 = 1<<19,
  61. /* TD.flags (software) */
  62. CancelTD= 1<<0,
  63. IsoClean= 1<<2,
  64. };
  65. static struct
  66. {
  67. int bit;
  68. char *name;
  69. }
  70. portstatus[] =
  71. {
  72. { Suspend, "suspend", },
  73. { PortReset, "reset", },
  74. { SlowDevice, "lowspeed", },
  75. { ResumeDetect, "resume", },
  76. { PortChange, "portchange", },
  77. { PortEnable, "enable", },
  78. { StatusChange, "statuschange", },
  79. { DevicePresent, "present", },
  80. };
  81. typedef struct Ctlr Ctlr;
  82. typedef struct Endptx Endptx;
  83. typedef struct QH QH;
  84. typedef struct TD TD;
  85. /*
  86. * software structures
  87. */
  88. struct Ctlr
  89. {
  90. Lock; /* protects state shared with interrupt (eg, free list) */
  91. Ctlr* next;
  92. Pcidev* pcidev;
  93. int active;
  94. int io;
  95. ulong* frames; /* frame list */
  96. ulong* frameld; /* real time load on each of the frame list entries */
  97. QLock resetl; /* lock controller during USB reset */
  98. TD* tdpool;
  99. TD* freetd;
  100. QH* qhpool;
  101. QH* freeqh;
  102. QH* ctlq; /* queue for control i/o */
  103. QH* bwsop; /* empty bandwidth sop (to PIIX4 errata specifications) */
  104. QH* bulkq; /* queue for bulk i/o (points back to bandwidth sop) */
  105. QH* recvq; /* receive queues for bulk i/o */
  106. Udev* ports[2];
  107. struct {
  108. Lock;
  109. Endpt* f;
  110. } activends;
  111. long usbints; /* debugging */
  112. long framenumber;
  113. long frameptr;
  114. long usbbogus;
  115. };
  116. #define IN(x) ins(ctlr->io+(x))
  117. #define OUT(x, v) outs(ctlr->io+(x), (v))
  118. static Ctlr* ctlrhead;
  119. static Ctlr* ctlrtail;
  120. struct Endptx
  121. {
  122. QH* epq; /* queue of TDs for this endpoint */
  123. /* ISO related: */
  124. void* tdalloc;
  125. void* bpalloc;
  126. uchar* bp0; /* first block in array */
  127. TD* td0; /* first td in array */
  128. TD* etd; /* pointer into circular list of TDs for isochronous ept */
  129. TD* xtd; /* next td to be cleaned */
  130. };
  131. /*
  132. * UHCI hardware structures, aligned on 16-byte boundary
  133. */
  134. struct TD
  135. {
  136. ulong link;
  137. ulong status; /* controller r/w */
  138. ulong dev;
  139. ulong buffer;
  140. /* software */
  141. ulong flags;
  142. union{
  143. Block* bp; /* non-iso */
  144. ulong offset; /* iso */
  145. };
  146. Endpt* ep;
  147. TD* next;
  148. };
  149. #define TFOL(p) ((TD*)KADDR((ulong)(p) & ~(0xF|PCIWINDOW)))
  150. struct QH
  151. {
  152. ulong head;
  153. ulong entries; /* address of next TD or QH to process (updated by controller) */
  154. /* software */
  155. QH* hlink;
  156. TD* first;
  157. QH* next; /* free list */
  158. TD* last;
  159. ulong _d1; /* fillers */
  160. ulong _d2;
  161. };
  162. #define QFOL(p) ((QH*)KADDR((ulong)(p) & ~(0xF|PCIWINDOW)))
  163. static TD *
  164. alloctd(Ctlr *ctlr)
  165. {
  166. TD *t;
  167. ilock(ctlr);
  168. t = ctlr->freetd;
  169. if(t == nil)
  170. panic("alloctd"); /* TO DO */
  171. ctlr->freetd = t->next;
  172. t->next = nil;
  173. iunlock(ctlr);
  174. t->ep = nil;
  175. t->bp = nil;
  176. t->status = 0;
  177. t->link = Terminate;
  178. t->buffer = 0;
  179. t->flags = 0;
  180. return t;
  181. }
  182. static void
  183. freetd(Ctlr *ctlr, TD *t)
  184. {
  185. t->ep = nil;
  186. if(t->bp)
  187. freeb(t->bp);
  188. t->bp = nil;
  189. ilock(ctlr);
  190. t->buffer = 0xdeadbeef;
  191. t->next = ctlr->freetd;
  192. ctlr->freetd = t;
  193. iunlock(ctlr);
  194. }
  195. static void
  196. dumpdata(Block *b, int n)
  197. {
  198. int i;
  199. XPRINT("\tb %8.8lux[%d]: ", (ulong)b->rp, n);
  200. if(n > 16)
  201. n = 16;
  202. for(i=0; i<n; i++)
  203. XPRINT(" %2.2ux", b->rp[i]);
  204. XPRINT("\n");
  205. }
  206. static void
  207. dumptd(TD *t, int follow)
  208. {
  209. int i, n;
  210. char buf[20], *s;
  211. TD *t0;
  212. t0 = t;
  213. while(t){
  214. i = t->dev & 0xFF;
  215. if(i == TokOUT || i == TokSETUP)
  216. n = ((t->dev>>21) + 1) & 0x7FF;
  217. else if((t->status & Active) == 0)
  218. n = (t->status + 1) & 0x7FF;
  219. else
  220. n = 0;
  221. s = buf;
  222. if(t->status & Active)
  223. *s++ = 'A';
  224. if(t->status & Stalled)
  225. *s++ = 'S';
  226. if(t->status & DataBufferErr)
  227. *s++ = 'D';
  228. if(t->status & Babbling)
  229. *s++ = 'B';
  230. if(t->status & NAKed)
  231. *s++ = 'N';
  232. if(t->status & CRCorTimeout)
  233. *s++ = 'T';
  234. if(t->status & BitstuffErr)
  235. *s++ = 'b';
  236. if(t->status & LowSpeed)
  237. *s++ = 'L';
  238. *s = 0;
  239. XPRINT("td %8.8lux: ", t);
  240. XPRINT("l=%8.8lux s=%8.8lux d=%8.8lux b=%8.8lux %8.8lux f=%8.8lux\n",
  241. t->link, t->status, t->dev, t->buffer, t->bp?(ulong)t->bp->rp:0, t->flags);
  242. XPRINT("\ts=%s,ep=%ld,d=%ld,D=%ld\n",
  243. buf, (t->dev>>15)&0xF, (t->dev>>8)&0xFF, (t->dev>>19)&1);
  244. if(debug && t->bp && (t->flags & CancelTD) == 0)
  245. dumpdata(t->bp, n);
  246. if(!follow || t->link & Terminate || t->link & IsQH)
  247. break;
  248. t = TFOL(t->link);
  249. if(t == t0)
  250. break; /* looped */
  251. }
  252. }
  253. static TD *
  254. alloctde(Ctlr *ctlr, Endpt *e, int pid, int n)
  255. {
  256. TD *t;
  257. int tog, id;
  258. t = alloctd(ctlr);
  259. id = (e->x<<7)|(e->dev->x&0x7F);
  260. tog = 0;
  261. if((pid == TokOUT && e->wdata01) || (pid == TokIN && e->rdata01))
  262. tog = IsDATA1;
  263. t->ep = e;
  264. t->status = ErrLimit3 | Active | IOC; /* or put IOC only on last? */
  265. if(e->dev->ls)
  266. t->status |= LowSpeed;
  267. t->dev = ((n-1)<<21) | ((id&0x7FF)<<8) | pid | tog;
  268. return t;
  269. }
  270. static QH *
  271. allocqh(Ctlr *ctlr)
  272. {
  273. QH *qh;
  274. ilock(ctlr);
  275. qh = ctlr->freeqh;
  276. if(qh == nil)
  277. panic("allocqh"); /* TO DO */
  278. ctlr->freeqh = qh->next;
  279. qh->next = nil;
  280. iunlock(ctlr);
  281. qh->head = Terminate;
  282. qh->entries = Terminate;
  283. qh->hlink = nil;
  284. qh->first = nil;
  285. qh->last = nil;
  286. return qh;
  287. }
  288. static void
  289. freeqh(Ctlr *ctlr, QH *qh)
  290. {
  291. ilock(ctlr);
  292. qh->next = ctlr->freeqh;
  293. ctlr->freeqh = qh;
  294. iunlock(ctlr);
  295. }
  296. static void
  297. dumpqh(QH *q)
  298. {
  299. int i;
  300. QH *q0;
  301. q0 = q;
  302. for(i = 0; q != nil && i < 10; i++){
  303. XPRINT("qh %8.8lux: %8.8lux %8.8lux\n", q, q->head, q->entries);
  304. if((q->entries & (IsQH|Terminate)) == 0)
  305. dumptd(TFOL(q->entries), 1);
  306. if(q->head & Terminate)
  307. break;
  308. if((q->head & IsQH) == 0){
  309. XPRINT("head:");
  310. dumptd(TFOL(q->head), 1);
  311. break;
  312. }
  313. q = QFOL(q->head);
  314. if(q == q0)
  315. break; /* looped */
  316. }
  317. }
  318. static void
  319. queuetd(Ctlr *ctlr, QH *q, TD *t, int vf, char *why)
  320. {
  321. TD *lt;
  322. for(lt = t; lt->next != nil; lt = lt->next)
  323. lt->link = PCIWADDR(lt->next) | vf;
  324. lt->link = Terminate;
  325. ilock(ctlr);
  326. XPRINT("queuetd %s: t=%p lt=%p q=%p first=%p last=%p entries=%.8lux\n",
  327. why, t, lt, q, q->first, q->last, q->entries);
  328. if(q->first != nil){
  329. q->last->link = PCIWADDR(t) | vf;
  330. q->last->next = t;
  331. }else{
  332. q->first = t;
  333. q->entries = PCIWADDR(t);
  334. }
  335. q->last = lt;
  336. XPRINT(" t=%p q=%p first=%p last=%p entries=%.8lux\n",
  337. t, q, q->first, q->last, q->entries);
  338. dumpqh(q);
  339. iunlock(ctlr);
  340. }
  341. static void
  342. cleantd(Ctlr *ctlr, TD *t, int discard)
  343. {
  344. Block *b;
  345. int n, err;
  346. XPRINT("cleanTD: %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer);
  347. if(t->ep != nil && t->ep->debug)
  348. dumptd(t, 0);
  349. if(t->status & Active)
  350. panic("cleantd Active");
  351. err = t->status & (AnyError&~NAKed);
  352. /* TO DO: on t->status&AnyError, q->entries will not have advanced */
  353. if (err) {
  354. XPRINT("cleanTD: Error %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer);
  355. // print("cleanTD: Error %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer);
  356. }
  357. switch(t->dev&0xFF){
  358. case TokIN:
  359. if(discard || (t->flags & CancelTD) || t->ep == nil || t->ep->x!=0&&err){
  360. if(t->ep != nil){
  361. if(err != 0)
  362. t->ep->err = err==Stalled? Estalled: Eio;
  363. wakeup(&t->ep->rr); /* in case anyone cares */
  364. }
  365. break;
  366. }
  367. b = t->bp;
  368. n = (t->status + 1) & 0x7FF;
  369. if(n > b->lim - b->wp)
  370. n = 0;
  371. b->wp += n;
  372. if(Chatty)
  373. dumpdata(b, n);
  374. t->bp = nil;
  375. t->ep->nbytes += n;
  376. t->ep->nblocks++;
  377. qpass(t->ep->rq, b); /* TO DO: flow control */
  378. wakeup(&t->ep->rr); /* TO DO */
  379. break;
  380. case TokSETUP:
  381. XPRINT("cleanTD: TokSETUP %lux\n", &t->ep);
  382. /* don't really need to wakeup: subsequent IN or OUT gives status */
  383. if(t->ep != nil) {
  384. wakeup(&t->ep->wr); /* TO DO */
  385. XPRINT("cleanTD: wakeup %lux\n", &t->ep->wr);
  386. }
  387. break;
  388. case TokOUT:
  389. /* TO DO: mark it done somewhere */
  390. XPRINT("cleanTD: TokOut %lux\n", &t->ep);
  391. if(t->ep != nil){
  392. if(t->bp){
  393. n = BLEN(t->bp);
  394. t->ep->nbytes += n;
  395. t->ep->nblocks++;
  396. }
  397. if(t->ep->x!=0 && err != 0)
  398. t->ep->err = err==Stalled? Estalled: Eio;
  399. if(--t->ep->ntd < 0)
  400. panic("cleantd ntd");
  401. wakeup(&t->ep->wr); /* TO DO */
  402. XPRINT("cleanTD: wakeup %lux\n", &t->ep->wr);
  403. }
  404. break;
  405. }
  406. freetd(ctlr, t);
  407. }
  408. static void
  409. cleanq(Ctlr *ctlr, QH *q, int discard, int vf)
  410. {
  411. TD *t, *tp;
  412. ilock(ctlr);
  413. tp = nil;
  414. for(t = q->first; t != nil;){
  415. XPRINT("cleanq: %8.8lux %8.8lux %8.8lux %8.8lux %8.8lux %8.8lux\n", t->link, t->status, t->dev, t->buffer, t->flags, t->next);
  416. if(t->status & Active){
  417. if(t->status & NAKed){
  418. t->status = (t->status & ~NAKed) | IOC; /* ensure interrupt next frame */
  419. tp = t;
  420. t = t->next;
  421. continue;
  422. }
  423. if(t->flags & CancelTD){
  424. XPRINT("cancelTD: %8.8lux\n", (ulong)t);
  425. t->status = (t->status & ~Active) | IOC; /* ensure interrupt next frame */
  426. tp = t;
  427. t = t->next;
  428. continue;
  429. }
  430. tp = t;
  431. t = t->next;
  432. continue;
  433. }
  434. t->status &= ~IOC;
  435. if (tp == nil) {
  436. q->first = t->next;
  437. if(q->first != nil)
  438. q->entries = PCIWADDR(q->first);
  439. else
  440. q->entries = Terminate;
  441. } else {
  442. tp->next = t->next;
  443. if (t->next != nil)
  444. tp->link = PCIWADDR(t->next) | vf;
  445. else
  446. tp->link = Terminate;
  447. }
  448. if (q->last == t)
  449. q->last = tp;
  450. iunlock(ctlr);
  451. cleantd(ctlr, t, discard);
  452. ilock(ctlr);
  453. if (tp)
  454. t = tp->next;
  455. else
  456. t = q->first;
  457. XPRINT("t = %8.8lux\n", t);
  458. dumpqh(q);
  459. }
  460. if(q->first && q->entries != PCIWADDR(q->first)){
  461. ctlr->usbbogus++;
  462. q->entries = PCIWADDR(q->first);
  463. }
  464. iunlock(ctlr);
  465. }
  466. static void
  467. canceltds(Ctlr *ctlr, QH *q, Endpt *e)
  468. {
  469. TD *t;
  470. if(q != nil){
  471. ilock(ctlr);
  472. for(t = q->first; t != nil; t = t->next)
  473. if(t->ep == e)
  474. t->flags |= CancelTD;
  475. iunlock(ctlr);
  476. XPRINT("cancel:\n");
  477. dumpqh(q);
  478. }
  479. }
  480. static void
  481. eptcancel(Ctlr *ctlr, Endpt *e)
  482. {
  483. Endptx *x;
  484. if(e == nil)
  485. return;
  486. x = e->private;
  487. canceltds(ctlr, x->epq, e);
  488. canceltds(ctlr, ctlr->ctlq, e);
  489. canceltds(ctlr, ctlr->bulkq, e);
  490. }
  491. static void
  492. eptactivate(Ctlr *ctlr, Endpt *e)
  493. {
  494. ilock(&ctlr->activends);
  495. if(e->active == 0){
  496. XPRINT("activate 0x%p\n", e);
  497. e->active = 1;
  498. e->activef = ctlr->activends.f;
  499. ctlr->activends.f = e;
  500. }
  501. iunlock(&ctlr->activends);
  502. }
  503. static void
  504. eptdeactivate(Ctlr *ctlr, Endpt *e)
  505. {
  506. Endpt **l;
  507. /* could be O(1) but not worth it yet */
  508. ilock(&ctlr->activends);
  509. if(e->active){
  510. e->active = 0;
  511. XPRINT("deactivate 0x%p\n", e);
  512. for(l = &ctlr->activends.f; *l != e; l = &(*l)->activef)
  513. if(*l == nil){
  514. iunlock(&ctlr->activends);
  515. panic("usb eptdeactivate");
  516. }
  517. *l = e->activef;
  518. }
  519. iunlock(&ctlr->activends);
  520. }
  521. static void
  522. queueqh(Ctlr *ctlr, QH *qh)
  523. {
  524. QH *q;
  525. // See if it's already queued
  526. for (q = ctlr->recvq->next; q; q = q->hlink)
  527. if (q == qh)
  528. return;
  529. if ((qh->hlink = ctlr->recvq->next) == nil)
  530. qh->head = Terminate;
  531. else
  532. qh->head = PCIWADDR(ctlr->recvq->next) | IsQH;
  533. ctlr->recvq->next = qh;
  534. ctlr->recvq->entries = PCIWADDR(qh) | IsQH;
  535. }
  536. static QH*
  537. qxmit(Ctlr *ctlr, Endpt *e, Block *b, int pid)
  538. {
  539. TD *t;
  540. int n, vf;
  541. QH *qh;
  542. Endptx *x;
  543. x = e->private;
  544. if(b != nil){
  545. n = BLEN(b);
  546. t = alloctde(ctlr, e, pid, n);
  547. t->bp = b;
  548. t->buffer = PCIWADDR(b->rp);
  549. }else
  550. t = alloctde(ctlr, e, pid, 0);
  551. ilock(ctlr);
  552. e->ntd++;
  553. iunlock(ctlr);
  554. if(e->debug) pprint("QTD: %8.8lux n=%ld\n", t, b?BLEN(b): 0);
  555. vf = 0;
  556. if(e->x == 0){
  557. qh = ctlr->ctlq;
  558. vf = 0;
  559. }else if((qh = x->epq) == nil || e->mode != OWRITE){
  560. qh = ctlr->bulkq;
  561. vf = Vf;
  562. }
  563. queuetd(ctlr, qh, t, vf, "qxmit");
  564. return qh;
  565. }
  566. static QH*
  567. qrcv(Ctlr *ctlr, Endpt *e)
  568. {
  569. TD *t;
  570. Block *b;
  571. QH *qh;
  572. int vf;
  573. Endptx *x;
  574. x = e->private;
  575. t = alloctde(ctlr, e, TokIN, e->maxpkt);
  576. b = allocb(e->maxpkt);
  577. t->bp = b;
  578. t->buffer = PCIWADDR(b->wp);
  579. vf = 0;
  580. if(e->x == 0){
  581. qh = ctlr->ctlq;
  582. }else if((qh = x->epq) == nil || e->mode != OREAD){
  583. qh = ctlr->bulkq;
  584. vf = Vf;
  585. }
  586. queuetd(ctlr, qh, t, vf, "qrcv");
  587. return qh;
  588. }
  589. static int
  590. usbsched(Ctlr *ctlr, int pollms, ulong load)
  591. {
  592. int i, d, q;
  593. ulong best, worst;
  594. best = 1000000;
  595. q = -1;
  596. for (d = 0; d < pollms; d++){
  597. worst = 0;
  598. for (i = d; i < NFRAME; i++){
  599. if (ctlr->frameld[i] + load > worst)
  600. worst = ctlr->frameld[i] + load;
  601. }
  602. if (worst < best){
  603. best = worst;
  604. q = d;
  605. }
  606. }
  607. return q;
  608. }
  609. static int
  610. schedendpt(Ctlr *ctlr, Endpt *e)
  611. {
  612. TD *td;
  613. Endptx *x;
  614. uchar *bp;
  615. int i, id, ix, size, frnum;
  616. if(!e->iso || e->sched >= 0)
  617. return 0;
  618. if (e->active){
  619. return -1;
  620. }
  621. e->off = 0;
  622. e->sched = usbsched(ctlr, e->pollms, e->maxpkt);
  623. if(e->sched < 0)
  624. return -1;
  625. x = e->private;
  626. if (x->tdalloc || x->bpalloc)
  627. panic("usb: tdalloc/bpalloc");
  628. x->tdalloc = mallocz(0x10 + NFRAME*sizeof(TD), 1);
  629. x->bpalloc = mallocz(0x10 + e->maxpkt*NFRAME/e->pollms, 1);
  630. x->td0 = (TD*)(((ulong)x->tdalloc + 0xf) & ~0xf);
  631. x->bp0 = (uchar *)(((ulong)x->bpalloc + 0xf) & ~0xf);
  632. frnum = (IN(Frnum) + 1) & 0x3ff;
  633. frnum = (frnum & ~(e->pollms - 1)) + e->sched;
  634. x->xtd = &x->td0[(frnum+8)&0x3ff]; /* Next td to finish */
  635. x->etd = nil;
  636. e->remain = 0;
  637. e->nbytes = 0;
  638. td = x->td0;
  639. for(i = e->sched; i < NFRAME; i += e->pollms){
  640. bp = x->bp0 + e->maxpkt*i/e->pollms;
  641. td->buffer = PCIWADDR(bp);
  642. td->ep = e;
  643. td->next = &td[1];
  644. ctlr->frameld[i] += e->maxpkt;
  645. td++;
  646. }
  647. td[-1].next = x->td0;
  648. for(i = e->sched; i < NFRAME; i += e->pollms){
  649. ix = (frnum+i) & 0x3ff;
  650. td = &x->td0[ix];
  651. id = (e->x<<7)|(e->dev->x&0x7F);
  652. if (e->mode == OREAD)
  653. /* enable receive on this entry */
  654. td->dev = ((e->maxpkt-1)<<21) | ((id&0x7FF)<<8) | TokIN;
  655. else{
  656. size = (e->hz + e->remain)*e->pollms/1000;
  657. e->remain = (e->hz + e->remain)*e->pollms%1000;
  658. size *= e->samplesz;
  659. td->dev = ((size-1)<<21) | ((id&0x7FF)<<8) | TokOUT;
  660. }
  661. td->status = ErrLimit1 | Active | IsoSelect | IOC;
  662. td->link = ctlr->frames[ix];
  663. td->flags |= IsoClean;
  664. ctlr->frames[ix] = PCIWADDR(td);
  665. }
  666. return 0;
  667. }
  668. static void
  669. unschedendpt(Ctlr *ctlr, Endpt *e)
  670. {
  671. int q;
  672. TD *td;
  673. Endptx *x;
  674. ulong *addr;
  675. if(!e->iso || e->sched < 0)
  676. return;
  677. x = e->private;
  678. if (x->tdalloc == nil)
  679. panic("tdalloc");
  680. for (q = e->sched; q < NFRAME; q += e->pollms){
  681. td = x->td0++;
  682. addr = &ctlr->frames[q];
  683. while(*addr != PADDR(td)) {
  684. if(*addr & IsQH)
  685. panic("usb: TD expected");
  686. addr = &TFOL(*addr)->link;
  687. }
  688. *addr = td->link;
  689. ctlr->frameld[q] -= e->maxpkt;
  690. }
  691. free(x->tdalloc);
  692. free(x->bpalloc);
  693. x->tdalloc = nil;
  694. x->bpalloc = nil;
  695. x->etd = nil;
  696. x->td0 = nil;
  697. e->sched = -1;
  698. }
  699. static void
  700. epalloc(Usbhost *uh, Endpt *e)
  701. {
  702. Endptx *x;
  703. x = malloc(sizeof(Endptx));
  704. e->private = x;
  705. x->epq = allocqh(uh->ctlr);
  706. if(x->epq == nil)
  707. panic("devendptx");
  708. }
  709. static void
  710. epfree(Usbhost *uh, Endpt *e)
  711. {
  712. Ctlr *ctlr;
  713. Endptx *x;
  714. ctlr = uh->ctlr;
  715. x = e->private;
  716. if(x->epq != nil)
  717. freeqh(ctlr, x->epq);
  718. }
  719. static void
  720. epopen(Usbhost *uh, Endpt *e)
  721. {
  722. Ctlr *ctlr;
  723. ctlr = uh->ctlr;
  724. if(e->iso && e->active)
  725. error("already open");
  726. if(schedendpt(ctlr, e) < 0){
  727. if(e->active)
  728. error("cannot schedule USB endpoint, active");
  729. else
  730. error("cannot schedule USB endpoint");
  731. }
  732. eptactivate(ctlr, e);
  733. }
  734. static void
  735. epclose(Usbhost *uh, Endpt *e)
  736. {
  737. Ctlr *ctlr;
  738. ctlr = uh->ctlr;
  739. eptdeactivate(ctlr, e);
  740. unschedendpt(ctlr, e);
  741. }
  742. static void
  743. epmode(Usbhost *uh, Endpt *e)
  744. {
  745. Ctlr *ctlr;
  746. Endptx *x;
  747. ctlr = uh->ctlr;
  748. x = e->private;
  749. if(e->iso) {
  750. if(x->epq != nil) {
  751. freeqh(ctlr, x->epq);
  752. x->epq = nil;
  753. }
  754. }
  755. else {
  756. /* Each bulk device gets a queue head hanging off the
  757. * bulk queue head
  758. */
  759. if(x->epq == nil) {
  760. x->epq = allocqh(ctlr);
  761. if(x->epq == nil)
  762. panic("epbulk: allocqh");
  763. }
  764. queueqh(ctlr, x->epq);
  765. }
  766. }
  767. static int ioport[] = {-1, Portsc0, Portsc1};
  768. static void
  769. portreset(Usbhost *uh, int port)
  770. {
  771. int i, p;
  772. Ctlr *ctlr;
  773. ctlr = uh->ctlr;
  774. if(port != 1 && port != 2)
  775. error(Ebadarg);
  776. /* should check that device not being configured on other port? */
  777. p = ioport[port];
  778. qlock(&ctlr->resetl);
  779. if(waserror()){
  780. qunlock(&ctlr->resetl);
  781. nexterror();
  782. }
  783. XPRINT("r: %x\n", IN(p));
  784. ilock(ctlr);
  785. OUT(p, PortReset);
  786. delay(12); /* BUG */
  787. XPRINT("r2: %x\n", IN(p));
  788. OUT(p, IN(p) & ~PortReset);
  789. XPRINT("r3: %x\n", IN(p));
  790. OUT(p, IN(p) | PortEnable);
  791. microdelay(64);
  792. for(i=0; i<1000 && (IN(p) & PortEnable) == 0; i++)
  793. ;
  794. XPRINT("r': %x %d\n", IN(p), i);
  795. OUT(p, (IN(p) & ~PortReset)|PortEnable);
  796. iunlock(ctlr);
  797. poperror();
  798. qunlock(&ctlr->resetl);
  799. }
  800. static void
  801. portenable(Usbhost *uh, int port, int on)
  802. {
  803. int w, p;
  804. Ctlr *ctlr;
  805. ctlr = uh->ctlr;
  806. if(port != 1 && port != 2)
  807. error(Ebadarg);
  808. /* should check that device not being configured on other port? */
  809. p = ioport[port];
  810. qlock(&ctlr->resetl);
  811. if(waserror()){
  812. qunlock(&ctlr->resetl);
  813. nexterror();
  814. }
  815. ilock(ctlr);
  816. w = IN(p);
  817. if(on)
  818. w |= PortEnable;
  819. else
  820. w &= ~PortEnable;
  821. OUT(p, w);
  822. microdelay(64);
  823. iunlock(ctlr);
  824. XPRINT("e: %x\n", IN(p));
  825. poperror();
  826. qunlock(&ctlr->resetl);
  827. }
  828. static void
  829. portinfo(Usbhost *uh, char *s, char *se)
  830. {
  831. int x, i, j;
  832. Ctlr *ctlr;
  833. ctlr = uh->ctlr;
  834. for(i = 1; i <= 2; i++) {
  835. ilock(ctlr);
  836. x = IN(ioport[i]);
  837. if((x & (PortChange|StatusChange)) != 0)
  838. OUT(ioport[i], x);
  839. iunlock(ctlr);
  840. s = seprint(s, se, "%d %ux", i, x);
  841. for(j = 0; j < nelem(portstatus); j++) {
  842. if((x & portstatus[j].bit) != 0)
  843. s = seprint(s, se, " %s", portstatus[j].name);
  844. }
  845. s = seprint(s, se, "\n");
  846. }
  847. }
  848. static void
  849. cleaniso(Endpt *e, int frnum)
  850. {
  851. TD *td;
  852. int id, n, i;
  853. Endptx *x;
  854. uchar *bp;
  855. x = e->private;
  856. td = x->xtd;
  857. if (td->status & Active)
  858. return;
  859. id = (e->x<<7)|(e->dev->x&0x7F);
  860. do {
  861. if (td->status & AnyError)
  862. XPRINT("usbisoerror 0x%lux\n", td->status);
  863. n = (td->status + 1) & 0x3ff;
  864. e->nbytes += n;
  865. if ((td->flags & IsoClean) == 0)
  866. e->nblocks++;
  867. if (e->mode == OREAD){
  868. e->buffered += n;
  869. e->poffset += (td->status + 1) & 0x3ff;
  870. td->offset = e->poffset;
  871. td->dev = ((e->maxpkt -1)<<21) | ((id&0x7FF)<<8) | TokIN;
  872. e->toffset = td->offset;
  873. }else{
  874. if ((td->flags & IsoClean) == 0){
  875. e->buffered -= n;
  876. if (e->buffered < 0){
  877. // print("e->buffered %d?\n", e->buffered);
  878. e->buffered = 0;
  879. }
  880. }
  881. e->toffset = td->offset;
  882. n = (e->hz + e->remain)*e->pollms/1000;
  883. e->remain = (e->hz + e->remain)*e->pollms%1000;
  884. n *= e->samplesz;
  885. td->dev = ((n -1)<<21) | ((id&0x7FF)<<8) | TokOUT;
  886. td->offset = e->poffset;
  887. e->poffset += n;
  888. }
  889. td = td->next;
  890. if (x->xtd == td){
  891. XPRINT("@");
  892. break;
  893. }
  894. } while ((td->status & Active) == 0);
  895. e->time = todget(nil);
  896. x->xtd = td;
  897. for (n = 2; n < 4; n++){
  898. i = ((frnum + n)&0x3ff);
  899. td = x->td0 + i;
  900. bp = x->bp0 + e->maxpkt*i/e->pollms;
  901. if (td->status & Active)
  902. continue;
  903. if (e->mode == OWRITE){
  904. if (td == x->etd) {
  905. XPRINT("*");
  906. memset(bp+e->off, 0, e->maxpkt-e->off);
  907. if (e->off == 0)
  908. td->flags |= IsoClean;
  909. else
  910. e->buffered += (((td->dev>>21) +1) & 0x3ff) - e->off;
  911. x->etd = nil;
  912. }else if ((td->flags & IsoClean) == 0){
  913. XPRINT("-");
  914. memset(bp, 0, e->maxpkt);
  915. td->flags |= IsoClean;
  916. }
  917. } else {
  918. /* Unread bytes are now lost */
  919. e->buffered -= (td->status + 1) & 0x3ff;
  920. }
  921. td->status = ErrLimit1 | Active | IsoSelect | IOC;
  922. }
  923. wakeup(&e->wr);
  924. }
  925. static void
  926. interrupt(Ureg*, void *a)
  927. {
  928. QH *q;
  929. Ctlr *ctlr;
  930. Endpt *e;
  931. Endptx *x;
  932. int s, frnum;
  933. Usbhost *uh;
  934. uh = a;
  935. ctlr = uh->ctlr;
  936. s = IN(Status);
  937. ctlr->frameptr = inl(ctlr->io+Flbaseadd);
  938. ctlr->framenumber = IN(Frnum) & 0x3ff;
  939. OUT(Status, s);
  940. if ((s & 0x1f) == 0)
  941. return;
  942. ctlr->usbints++;
  943. frnum = IN(Frnum) & 0x3ff;
  944. if (s & 0x1a) {
  945. XPRINT("cmd #%x sofmod #%x\n", IN(Cmd), inb(ctlr->io+SOFMod));
  946. XPRINT("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1));
  947. }
  948. ilock(&ctlr->activends);
  949. for(e = ctlr->activends.f; e != nil; e = e->activef) {
  950. x = e->private;
  951. if(!e->iso && x->epq != nil) {
  952. XXPRINT("cleanq(ctlr, x->epq, 0, 0)\n");
  953. cleanq(ctlr, x->epq, 0, 0);
  954. }
  955. if(e->iso) {
  956. XXPRINT("cleaniso(e)\n");
  957. cleaniso(e, frnum);
  958. }
  959. }
  960. iunlock(&ctlr->activends);
  961. XXPRINT("cleanq(ctlr, ctlr->ctlq, 0, 0)\n");
  962. cleanq(ctlr, ctlr->ctlq, 0, 0);
  963. XXPRINT("cleanq(ctlr, ctlr->bulkq, 0, Vf)\n");
  964. cleanq(ctlr, ctlr->bulkq, 0, Vf);
  965. XXPRINT("clean recvq\n");
  966. for (q = ctlr->recvq->next; q; q = q->hlink) {
  967. XXPRINT("cleanq(ctlr, q, 0, Vf)\n");
  968. cleanq(ctlr, q, 0, Vf);
  969. }
  970. }
  971. static int
  972. eptinput(void *arg)
  973. {
  974. Endpt *e;
  975. e = arg;
  976. return e->eof || e->err || qcanread(e->rq);
  977. }
  978. static int
  979. isoready(void *a)
  980. {
  981. Endptx *x;
  982. TD *etd;
  983. x = a;
  984. return (etd = x->etd) == nil || (etd != x->xtd && (etd->status & Active) == 0);
  985. }
  986. static long
  987. isoio(Ctlr *ctlr, Endpt *e, void *a, long n, ulong offset, int w)
  988. {
  989. TD *td;
  990. Endptx *x;
  991. int i, frnum;
  992. uchar *p, *q, *bp;
  993. volatile int isolock;
  994. x = e->private;
  995. qlock(&e->rlock);
  996. isolock = 0;
  997. if(waserror()){
  998. if (isolock){
  999. isolock = 0;
  1000. iunlock(&ctlr->activends);
  1001. }
  1002. qunlock(&e->rlock);
  1003. eptcancel(ctlr, e);
  1004. nexterror();
  1005. }
  1006. p = a;
  1007. if (offset != 0 && offset != e->foffset){
  1008. iprint("offset %lud, foffset %lud\n", offset, e->foffset);
  1009. /* Seek to a specific position */
  1010. frnum = (IN(Frnum) + 8) & 0x3ff;
  1011. td = x->td0 +frnum;
  1012. if (offset < td->offset)
  1013. error("ancient history");
  1014. while (offset > e->toffset){
  1015. tsleep(&e->wr, return0, 0, 500);
  1016. }
  1017. while (offset >= td->offset + ((w?(td->dev >> 21):td->status) + 1) & 0x7ff){
  1018. td = td->next;
  1019. if (td == x->xtd)
  1020. iprint("trouble\n");
  1021. }
  1022. ilock(&ctlr->activends);
  1023. isolock = 1;
  1024. e->off = td->offset - offset;
  1025. if (e->off >= e->maxpkt){
  1026. iprint("I can't program: %d\n", e->off);
  1027. e->off = 0;
  1028. }
  1029. x->etd = td;
  1030. e->foffset = offset;
  1031. }
  1032. do {
  1033. if (isolock == 0){
  1034. ilock(&ctlr->activends);
  1035. isolock = 1;
  1036. }
  1037. td = x->etd;
  1038. if (td == nil || e->off == 0){
  1039. if (td == nil){
  1040. XPRINT("0");
  1041. if (w){
  1042. frnum = (IN(Frnum) + 1) & 0x3ff;
  1043. td = x->td0 + frnum;
  1044. while(td->status & Active)
  1045. td = td->next;
  1046. }else{
  1047. frnum = (IN(Frnum) - 4) & 0x3ff;
  1048. td = x->td0 + frnum;
  1049. while(td->next != x->xtd)
  1050. td = td->next;
  1051. }
  1052. x->etd = td;
  1053. e->off = 0;
  1054. }else{
  1055. /* New td, make sure it's ready */
  1056. while (isoready(x) == 0){
  1057. isolock = 0;
  1058. iunlock(&ctlr->activends);
  1059. sleep(&e->wr, isoready, x);
  1060. ilock(&ctlr->activends);
  1061. isolock = 1;
  1062. }
  1063. if (x->etd == nil){
  1064. XPRINT("!");
  1065. continue;
  1066. }
  1067. }
  1068. if (w)
  1069. e->psize = ((td->dev >> 21) + 1) & 0x7ff;
  1070. else
  1071. e->psize = (x->etd->status + 1) & 0x7ff;
  1072. if(e->psize > e->maxpkt)
  1073. panic("packet size > maximum");
  1074. }
  1075. if((i = n) >= e->psize)
  1076. i = e->psize;
  1077. if (w)
  1078. e->buffered += i;
  1079. else{
  1080. e->buffered -= i;
  1081. if (e->buffered < 0)
  1082. e->buffered = 0;
  1083. }
  1084. isolock = 0;
  1085. iunlock(&ctlr->activends);
  1086. td->flags &= ~IsoClean;
  1087. bp = x->bp0 + (td - x->td0) * e->maxpkt / e->pollms;
  1088. q = bp + e->off;
  1089. if (w){
  1090. memmove(q, p, i);
  1091. }else{
  1092. memmove(p, q, i);
  1093. }
  1094. p += i;
  1095. n -= i;
  1096. e->off += i;
  1097. e->psize -= i;
  1098. if (e->psize){
  1099. if (n != 0)
  1100. panic("usb iso: can't happen");
  1101. break;
  1102. }
  1103. if(w)
  1104. td->offset = offset + (p-(uchar*)a) - (((td->dev >> 21) + 1) & 0x7ff);
  1105. td->status = ErrLimit3 | Active | IsoSelect | IOC;
  1106. x->etd = td->next;
  1107. e->off = 0;
  1108. } while(n > 0);
  1109. n = p-(uchar*)a;
  1110. e->foffset += n;
  1111. poperror();
  1112. if (isolock)
  1113. iunlock(&ctlr->activends);
  1114. qunlock(&e->rlock);
  1115. return n;
  1116. }
  1117. static long
  1118. read(Usbhost *uh, Endpt *e, void *a, long n, vlong offset)
  1119. {
  1120. long l, i;
  1121. Block *b;
  1122. Ctlr *ctlr;
  1123. uchar *p;
  1124. ctlr = uh->ctlr;
  1125. if(e->iso)
  1126. return isoio(ctlr, e, a, n, (ulong)offset, 0);
  1127. XPRINT("qlock(%p)\n", &e->rlock);
  1128. qlock(&e->rlock);
  1129. XPRINT("got qlock(%p)\n", &e->rlock);
  1130. if(waserror()){
  1131. qunlock(&e->rlock);
  1132. eptcancel(ctlr, e);
  1133. nexterror();
  1134. }
  1135. p = a;
  1136. do {
  1137. if(e->eof) {
  1138. XPRINT("e->eof\n");
  1139. break;
  1140. }
  1141. if(e->err)
  1142. error(e->err);
  1143. qrcv(ctlr, e);
  1144. if(!e->iso)
  1145. e->rdata01 ^= 1;
  1146. sleep(&e->rr, eptinput, e);
  1147. if(e->err)
  1148. error(e->err);
  1149. b = qget(e->rq); /* TO DO */
  1150. if(b == nil) {
  1151. XPRINT("b == nil\n");
  1152. break;
  1153. }
  1154. if(waserror()){
  1155. freeb(b);
  1156. nexterror();
  1157. }
  1158. l = BLEN(b);
  1159. if((i = l) > n)
  1160. i = n;
  1161. if(i > 0){
  1162. memmove(p, b->rp, i);
  1163. p += i;
  1164. }
  1165. poperror();
  1166. freeb(b);
  1167. n -= i;
  1168. if (l != e->maxpkt)
  1169. break;
  1170. } while (n > 0);
  1171. poperror();
  1172. qunlock(&e->rlock);
  1173. return p-(uchar*)a;
  1174. }
  1175. static int
  1176. qisempty(void *arg)
  1177. {
  1178. return ((QH*)arg)->entries & Terminate;
  1179. }
  1180. static long
  1181. write(Usbhost *uh, Endpt *e, void *a, long n, vlong offset, int tok)
  1182. {
  1183. int i, j;
  1184. QH *qh;
  1185. Block *b;
  1186. Ctlr *ctlr;
  1187. uchar *p;
  1188. ctlr = uh->ctlr;
  1189. if(e->iso)
  1190. return isoio(ctlr, e, a, n, (ulong)offset, 1);
  1191. p = a;
  1192. qlock(&e->wlock);
  1193. if(waserror()){
  1194. qunlock(&e->wlock);
  1195. eptcancel(ctlr, e);
  1196. nexterror();
  1197. }
  1198. do {
  1199. if(e->err)
  1200. error(e->err);
  1201. if((i = n) >= e->maxpkt)
  1202. i = e->maxpkt;
  1203. b = allocb(i);
  1204. if(waserror()){
  1205. freeb(b);
  1206. nexterror();
  1207. }
  1208. XPRINT("out [%d]", i);
  1209. for (j = 0; j < i; j++) XPRINT(" %.2x", p[j]);
  1210. XPRINT("\n");
  1211. memmove(b->wp, p, i);
  1212. b->wp += i;
  1213. p += i;
  1214. n -= i;
  1215. poperror();
  1216. qh = qxmit(ctlr, e, b, tok);
  1217. tok = TokOUT;
  1218. e->wdata01 ^= 1;
  1219. if(e->ntd >= e->nbuf) {
  1220. XPRINT("qh %s: q=%p first=%p last=%p entries=%.8lux\n",
  1221. "writeusb sleep", qh, qh->first, qh->last, qh->entries);
  1222. XPRINT("write: sleep %lux\n", &e->wr);
  1223. sleep(&e->wr, qisempty, qh);
  1224. XPRINT("write: awake\n");
  1225. }
  1226. } while(n > 0);
  1227. poperror();
  1228. qunlock(&e->wlock);
  1229. return p-(uchar*)a;
  1230. }
  1231. static void
  1232. init(Usbhost* uh)
  1233. {
  1234. Ctlr *ctlr;
  1235. ctlr = uh->ctlr;
  1236. ilock(ctlr);
  1237. outl(ctlr->io+Flbaseadd, PCIWADDR(ctlr->frames));
  1238. OUT(Frnum, 0);
  1239. OUT(Usbintr, 0xF); /* enable all interrupts */
  1240. XPRINT("cmd 0x%x sofmod 0x%x\n", IN(Cmd), inb(ctlr->io+SOFMod));
  1241. XPRINT("sc0 0x%x sc1 0x%x\n", IN(Portsc0), IN(Portsc1));
  1242. if((IN(Cmd)&1)==0)
  1243. OUT(Cmd, 1); /* run */
  1244. // pprint("at: c=%x s=%x c0=%x\n", IN(Cmd), IN(Status), IN(Portsc0));
  1245. iunlock(ctlr);
  1246. }
  1247. static void
  1248. scanpci(void)
  1249. {
  1250. int io;
  1251. Ctlr *ctlr;
  1252. Pcidev *p;
  1253. static int already = 0;
  1254. if(already)
  1255. return;
  1256. already = 1;
  1257. p = nil;
  1258. while(p = pcimatch(p, 0, 0)) {
  1259. /*
  1260. * Find UHCI controllers. Class = 12 (serial controller),
  1261. * Sub-class = 3 (USB) and Programming Interface = 0.
  1262. */
  1263. if(p->ccrb != 0x0C || p->ccru != 0x03)
  1264. continue;
  1265. switch(p->ccrp){
  1266. case 0x00:
  1267. io = p->mem[4].bar & ~0x0F;
  1268. break;
  1269. case 0x10:
  1270. case 0x20:
  1271. print("usb%chci: %x/%x %sport 0x%lux size 0x%x irq %d (ignored)\n",
  1272. (p->ccrp == 0x10? 'o': 'e'), p->vid, p->did,
  1273. (p->ccrp == 0x10? "": "USB 2 "),
  1274. p->mem[0].bar & ~0x0F, p->mem[0].size, p->intl);
  1275. /* fallthrough */
  1276. default:
  1277. continue;
  1278. }
  1279. if(io == 0) {
  1280. print("usbuhci: failed to map registers\n");
  1281. continue;
  1282. }
  1283. if(ioalloc(io, p->mem[4].size, 0, "usbuhci") < 0){
  1284. print("usbuhci: port %d in use\n", io);
  1285. continue;
  1286. }
  1287. if(p->intl == 0xFF || p->intl == 0) {
  1288. print("usbuhci: no irq assigned for port %d\n", io);
  1289. continue;
  1290. }
  1291. XPRINT("usbuhci: %x/%x port 0x%ux size 0x%x irq %d\n",
  1292. p->vid, p->did, io, p->mem[4].size, p->intl);
  1293. ctlr = malloc(sizeof(Ctlr));
  1294. ctlr->pcidev = p;
  1295. ctlr->io = io;
  1296. if(ctlrhead != nil)
  1297. ctlrtail->next = ctlr;
  1298. else
  1299. ctlrhead = ctlr;
  1300. ctlrtail = ctlr;
  1301. }
  1302. }
  1303. static int
  1304. reset(Usbhost *uh)
  1305. {
  1306. int i;
  1307. TD *t;
  1308. ulong io;
  1309. Ctlr *ctlr;
  1310. Pcidev *p;
  1311. scanpci();
  1312. /*
  1313. * Any adapter matches if no uh->port is supplied,
  1314. * otherwise the ports must match.
  1315. */
  1316. for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
  1317. if(ctlr->active)
  1318. continue;
  1319. if(uh->port == 0 || uh->port == ctlr->io){
  1320. ctlr->active = 1;
  1321. break;
  1322. }
  1323. }
  1324. if(ctlr == nil)
  1325. return -1;
  1326. io = ctlr->io;
  1327. p = ctlr->pcidev;
  1328. uh->ctlr = ctlr;
  1329. uh->port = io;
  1330. uh->irq = p->intl;
  1331. uh->tbdf = p->tbdf;
  1332. XPRINT("usbcmd\t0x%.4x\nusbsts\t0x%.4x\nusbintr\t0x%.4x\nfrnum\t0x%.2x\n",
  1333. IN(Cmd), IN(Status), IN(Usbintr), inb(io+Frnum));
  1334. XPRINT("frbaseadd\t0x%.4x\nsofmod\t0x%x\nportsc1\t0x%.4x\nportsc2\t0x%.4x\n",
  1335. IN(Flbaseadd), inb(io+SOFMod), IN(Portsc0), IN(Portsc1));
  1336. OUT(Cmd, 0); /* stop */
  1337. while((IN(Status) & (1<<5)) == 0) /* wait for halt */
  1338. ;
  1339. OUT(Status, 0xFF); /* clear pending interrupts */
  1340. pcicfgw16(p, 0xc0, 0x2000); /* legacy support register: turn off lunacy mode */
  1341. if(0){
  1342. i = inb(io+SOFMod);
  1343. OUT(Cmd, 4); /* global reset */
  1344. delay(15);
  1345. OUT(Cmd, 0); /* end reset */
  1346. delay(4);
  1347. outb(io+SOFMod, i);
  1348. }
  1349. ctlr->tdpool = xspanalloc(128*sizeof(TD), 16, 0);
  1350. for(i=128; --i>=0;){
  1351. ctlr->tdpool[i].next = ctlr->freetd;
  1352. ctlr->freetd = &ctlr->tdpool[i];
  1353. }
  1354. ctlr->qhpool = xspanalloc(64*sizeof(QH), 16, 0);
  1355. for(i=64; --i>=0;){
  1356. ctlr->qhpool[i].next = ctlr->freeqh;
  1357. ctlr->freeqh = &ctlr->qhpool[i];
  1358. }
  1359. /*
  1360. * the last entries of the periodic (interrupt & isochronous) scheduling TD entries
  1361. * points to the control queue and the bandwidth sop for bulk traffic.
  1362. * this is looped following the instructions in PIIX4 errata 29773804.pdf:
  1363. * a QH links to a looped but inactive TD as its sole entry,
  1364. * with its head entry leading on to the bulk traffic, the last QH of which
  1365. * links back to the empty QH.
  1366. */
  1367. ctlr->ctlq = allocqh(ctlr);
  1368. ctlr->bwsop = allocqh(ctlr);
  1369. ctlr->bulkq = allocqh(ctlr);
  1370. ctlr->recvq = allocqh(ctlr);
  1371. t = alloctd(ctlr); /* inactive TD, looped */
  1372. t->link = PCIWADDR(t);
  1373. ctlr->bwsop->entries = PCIWADDR(t);
  1374. ctlr->ctlq->head = PCIWADDR(ctlr->bulkq) | IsQH;
  1375. ctlr->bulkq->head = PCIWADDR(ctlr->recvq) | IsQH;
  1376. ctlr->recvq->head = PCIWADDR(ctlr->bwsop) | IsQH;
  1377. if (1) /* don't use loop back */
  1378. ctlr->bwsop->head = Terminate;
  1379. else /* set up loop back */
  1380. ctlr->bwsop->head = PCIWADDR(ctlr->bwsop) | IsQH;
  1381. ctlr->frames = xspanalloc(FRAMESIZE, FRAMESIZE, 0);
  1382. ctlr->frameld = xallocz(FRAMESIZE, 1);
  1383. for (i = 0; i < NFRAME; i++)
  1384. ctlr->frames[i] = PCIWADDR(ctlr->ctlq) | IsQH;
  1385. /*
  1386. * Linkage to the generic USB driver.
  1387. */
  1388. uh->init = init;
  1389. uh->interrupt = interrupt;
  1390. uh->portinfo = portinfo;
  1391. uh->portreset = portreset;
  1392. uh->portenable = portenable;
  1393. uh->epalloc = epalloc;
  1394. uh->epfree = epfree;
  1395. uh->epopen = epopen;
  1396. uh->epclose = epclose;
  1397. uh->epmode = epmode;
  1398. uh->read = read;
  1399. uh->write = write;
  1400. return 0;
  1401. }
  1402. void
  1403. usbuhcilink(void)
  1404. {
  1405. addusbtype("uhci", reset);
  1406. }