usbuhci.c 30 KB

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