usbuhci.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547
  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((pid == TokOUT && e->wdata01) || (pid == TokIN && e->rdata01))
  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 & (IsQH|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(e->iso && e->active)
  724. error("already open");
  725. if(schedendpt(ctlr, e) < 0){
  726. if(e->active)
  727. error("cannot schedule USB endpoint, active");
  728. else
  729. error("cannot schedule USB endpoint");
  730. }
  731. eptactivate(ctlr, e);
  732. }
  733. static void
  734. epclose(Usbhost *uh, Endpt *e)
  735. {
  736. Ctlr *ctlr;
  737. ctlr = uh->ctlr;
  738. eptdeactivate(ctlr, e);
  739. unschedendpt(ctlr, e);
  740. }
  741. static void
  742. epmode(Usbhost *uh, Endpt *e)
  743. {
  744. Ctlr *ctlr;
  745. Endptx *x;
  746. ctlr = uh->ctlr;
  747. x = e->private;
  748. if(e->iso) {
  749. if(x->epq != nil) {
  750. freeqh(ctlr, x->epq);
  751. x->epq = nil;
  752. }
  753. }
  754. else {
  755. /* Each bulk device gets a queue head hanging off the
  756. * bulk queue head
  757. */
  758. if(x->epq == nil) {
  759. x->epq = allocqh(ctlr);
  760. if(x->epq == nil)
  761. panic("epbulk: allocqh");
  762. }
  763. queueqh(ctlr, x->epq);
  764. }
  765. }
  766. static int ioport[] = {-1, Portsc0, Portsc1};
  767. static void
  768. portreset(Usbhost *uh, int port)
  769. {
  770. int i, p;
  771. Ctlr *ctlr;
  772. ctlr = uh->ctlr;
  773. if(port != 1 && port != 2)
  774. error(Ebadarg);
  775. /* should check that device not being configured on other port? */
  776. p = ioport[port];
  777. qlock(&ctlr->resetl);
  778. if(waserror()){
  779. qunlock(&ctlr->resetl);
  780. nexterror();
  781. }
  782. XPRINT("r: %x\n", IN(p));
  783. ilock(ctlr);
  784. OUT(p, PortReset);
  785. delay(12); /* BUG */
  786. XPRINT("r2: %x\n", IN(p));
  787. OUT(p, IN(p) & ~PortReset);
  788. XPRINT("r3: %x\n", IN(p));
  789. OUT(p, IN(p) | PortEnable);
  790. microdelay(64);
  791. for(i=0; i<1000 && (IN(p) & PortEnable) == 0; i++)
  792. ;
  793. XPRINT("r': %x %d\n", IN(p), i);
  794. OUT(p, (IN(p) & ~PortReset)|PortEnable);
  795. iunlock(ctlr);
  796. poperror();
  797. qunlock(&ctlr->resetl);
  798. }
  799. static void
  800. portenable(Usbhost *uh, int port, int on)
  801. {
  802. int w, p;
  803. Ctlr *ctlr;
  804. ctlr = uh->ctlr;
  805. if(port != 1 && port != 2)
  806. error(Ebadarg);
  807. /* should check that device not being configured on other port? */
  808. p = ioport[port];
  809. qlock(&ctlr->resetl);
  810. if(waserror()){
  811. qunlock(&ctlr->resetl);
  812. nexterror();
  813. }
  814. ilock(ctlr);
  815. w = IN(p);
  816. if(on)
  817. w |= PortEnable;
  818. else
  819. w &= ~PortEnable;
  820. OUT(p, w);
  821. microdelay(64);
  822. iunlock(ctlr);
  823. XPRINT("e: %x\n", IN(p));
  824. poperror();
  825. qunlock(&ctlr->resetl);
  826. }
  827. static void
  828. portinfo(Usbhost *uh, char *s, char *se)
  829. {
  830. int x, i, j;
  831. Ctlr *ctlr;
  832. ctlr = uh->ctlr;
  833. for(i = 1; i <= 2; i++) {
  834. ilock(ctlr);
  835. x = IN(ioport[i]);
  836. if((x & (PortChange|StatusChange)) != 0)
  837. OUT(ioport[i], x);
  838. iunlock(ctlr);
  839. s = seprint(s, se, "%d %ux", i, x);
  840. for(j = 0; j < nelem(portstatus); j++) {
  841. if((x & portstatus[j].bit) != 0)
  842. s = seprint(s, se, " %s", portstatus[j].name);
  843. }
  844. s = seprint(s, se, "\n");
  845. }
  846. }
  847. static void
  848. cleaniso(Endpt *e, int frnum)
  849. {
  850. TD *td;
  851. int id, n, i;
  852. Endptx *x;
  853. uchar *bp;
  854. x = e->private;
  855. td = x->xtd;
  856. if (td->status & Active)
  857. return;
  858. id = (e->x<<7)|(e->dev->x&0x7F);
  859. do {
  860. if (td->status & AnyError)
  861. XPRINT("usbisoerror 0x%lux\n", td->status);
  862. n = (td->status + 1) & 0x3ff;
  863. e->nbytes += n;
  864. if ((td->flags & IsoClean) == 0)
  865. e->nblocks++;
  866. if (e->mode == OREAD){
  867. e->buffered += n;
  868. e->poffset += (td->status + 1) & 0x3ff;
  869. td->offset = e->poffset;
  870. td->dev = ((e->maxpkt -1)<<21) | ((id&0x7FF)<<8) | TokIN;
  871. e->toffset = td->offset;
  872. }else{
  873. if ((td->flags & IsoClean) == 0){
  874. e->buffered -= n;
  875. if (e->buffered < 0){
  876. // print("e->buffered %d?\n", e->buffered);
  877. e->buffered = 0;
  878. }
  879. }
  880. e->toffset = td->offset;
  881. n = (e->hz + e->remain)*e->pollms/1000;
  882. e->remain = (e->hz + e->remain)*e->pollms%1000;
  883. n *= e->samplesz;
  884. td->dev = ((n -1)<<21) | ((id&0x7FF)<<8) | TokOUT;
  885. td->offset = e->poffset;
  886. e->poffset += n;
  887. }
  888. td = td->next;
  889. if (x->xtd == td){
  890. XPRINT("@");
  891. break;
  892. }
  893. } while ((td->status & Active) == 0);
  894. e->time = todget(nil);
  895. x->xtd = td;
  896. for (n = 2; n < 4; n++){
  897. i = ((frnum + n)&0x3ff);
  898. td = x->td0 + i;
  899. bp = x->bp0 + e->maxpkt*i/e->pollms;
  900. if (td->status & Active)
  901. continue;
  902. if (e->mode == OWRITE){
  903. if (td == x->etd) {
  904. XPRINT("*");
  905. memset(bp+e->off, 0, e->maxpkt-e->off);
  906. if (e->off == 0)
  907. td->flags |= IsoClean;
  908. else
  909. e->buffered += (((td->dev>>21) +1) & 0x3ff) - e->off;
  910. x->etd = nil;
  911. }else if ((td->flags & IsoClean) == 0){
  912. XPRINT("-");
  913. memset(bp, 0, e->maxpkt);
  914. td->flags |= IsoClean;
  915. }
  916. } else {
  917. /* Unread bytes are now lost */
  918. e->buffered -= (td->status + 1) & 0x3ff;
  919. }
  920. td->status = ErrLimit1 | Active | IsoSelect | IOC;
  921. }
  922. wakeup(&e->wr);
  923. }
  924. static void
  925. interrupt(Ureg*, void *a)
  926. {
  927. QH *q;
  928. Ctlr *ctlr;
  929. Endpt *e;
  930. Endptx *x;
  931. int s, frnum;
  932. Usbhost *uh;
  933. uh = a;
  934. ctlr = uh->ctlr;
  935. s = IN(Status);
  936. ctlr->frameptr = inl(ctlr->io+Flbaseadd);
  937. ctlr->framenumber = IN(Frnum) & 0x3ff;
  938. OUT(Status, s);
  939. if ((s & 0x1f) == 0)
  940. return;
  941. ctlr->usbints++;
  942. frnum = IN(Frnum) & 0x3ff;
  943. if (s & 0x1a) {
  944. XPRINT("cmd #%x sofmod #%x\n", IN(Cmd), inb(ctlr->io+SOFMod));
  945. XPRINT("sc0 #%x sc1 #%x\n", IN(Portsc0), IN(Portsc1));
  946. }
  947. ilock(&ctlr->activends);
  948. for(e = ctlr->activends.f; e != nil; e = e->activef) {
  949. x = e->private;
  950. if(!e->iso && x->epq != nil) {
  951. XPRINT("cleanq(ctlr, x->epq, 0, 0)\n");
  952. cleanq(ctlr, x->epq, 0, 0);
  953. }
  954. if(e->iso) {
  955. XPRINT("cleaniso(e)\n");
  956. cleaniso(e, frnum);
  957. }
  958. }
  959. iunlock(&ctlr->activends);
  960. XPRINT("cleanq(ctlr, ctlr->ctlq, 0, 0)\n");
  961. cleanq(ctlr, ctlr->ctlq, 0, 0);
  962. XPRINT("cleanq(ctlr, ctlr->bulkq, 0, Vf)\n");
  963. cleanq(ctlr, ctlr->bulkq, 0, Vf);
  964. XPRINT("clean recvq\n");
  965. for (q = ctlr->recvq->next; q; q = q->hlink) {
  966. XPRINT("cleanq(ctlr, q, 0, Vf)\n");
  967. cleanq(ctlr, q, 0, Vf);
  968. }
  969. }
  970. static int
  971. eptinput(void *arg)
  972. {
  973. Endpt *e;
  974. e = arg;
  975. return e->eof || e->err || qcanread(e->rq);
  976. }
  977. static int
  978. isoreadyx(Endptx *x)
  979. {
  980. return x->etd == nil || (x->etd != x->xtd && (x->etd->status & Active) == 0);
  981. }
  982. static int
  983. isoready(void *arg)
  984. {
  985. int ret;
  986. Ctlr *ctlr;
  987. Endpt *e;
  988. Endptx *x;
  989. e = arg;
  990. ctlr = e->dev->uh->ctlr;
  991. x = e->private;
  992. ilock(&ctlr->activends);
  993. ret = isoreadyx(x);
  994. iunlock(&ctlr->activends);
  995. return ret;
  996. }
  997. static long
  998. isoio(Ctlr *ctlr, Endpt *e, void *a, long n, ulong offset, int w)
  999. {
  1000. TD *td;
  1001. Endptx *x;
  1002. int i, frnum;
  1003. uchar *p, *q, *bp;
  1004. volatile int isolock;
  1005. x = e->private;
  1006. qlock(&e->rlock);
  1007. isolock = 0;
  1008. if(waserror()){
  1009. if (isolock){
  1010. isolock = 0;
  1011. iunlock(&ctlr->activends);
  1012. }
  1013. qunlock(&e->rlock);
  1014. eptcancel(ctlr, e);
  1015. nexterror();
  1016. }
  1017. p = a;
  1018. if (offset != 0 && offset != e->foffset){
  1019. iprint("offset %lud, foffset %lud\n", offset, e->foffset);
  1020. /* Seek to a specific position */
  1021. frnum = (IN(Frnum) + 8) & 0x3ff;
  1022. td = x->td0 +frnum;
  1023. if (offset < td->offset)
  1024. error("ancient history");
  1025. while (offset > e->toffset){
  1026. tsleep(&e->wr, return0, 0, 500);
  1027. }
  1028. while (offset >= td->offset + ((w?(td->dev >> 21):td->status) + 1) & 0x7ff){
  1029. td = td->next;
  1030. if (td == x->xtd)
  1031. iprint("trouble\n");
  1032. }
  1033. ilock(&ctlr->activends);
  1034. isolock = 1;
  1035. e->off = td->offset - offset;
  1036. if (e->off >= e->maxpkt){
  1037. iprint("I can't program: %d\n", e->off);
  1038. e->off = 0;
  1039. }
  1040. x->etd = td;
  1041. e->foffset = offset;
  1042. }
  1043. do {
  1044. if (isolock == 0){
  1045. ilock(&ctlr->activends);
  1046. isolock = 1;
  1047. }
  1048. td = x->etd;
  1049. if (td == nil || e->off == 0){
  1050. if (td == nil){
  1051. XPRINT("0");
  1052. if (w){
  1053. frnum = (IN(Frnum) + 1) & 0x3ff;
  1054. td = x->td0 + frnum;
  1055. while(td->status & Active)
  1056. td = td->next;
  1057. }else{
  1058. frnum = (IN(Frnum) - 4) & 0x3ff;
  1059. td = x->td0 + frnum;
  1060. while(td->next != x->xtd)
  1061. td = td->next;
  1062. }
  1063. x->etd = td;
  1064. e->off = 0;
  1065. }else{
  1066. /* New td, make sure it's ready */
  1067. while (isoreadyx(x) == 0){
  1068. isolock = 0;
  1069. iunlock(&ctlr->activends);
  1070. sleep(&e->wr, isoready, e);
  1071. ilock(&ctlr->activends);
  1072. isolock = 1;
  1073. }
  1074. if (x->etd == nil){
  1075. XPRINT("!");
  1076. continue;
  1077. }
  1078. }
  1079. if (w)
  1080. e->psize = ((td->dev >> 21) + 1) & 0x7ff;
  1081. else
  1082. e->psize = (x->etd->status + 1) & 0x7ff;
  1083. if(e->psize > e->maxpkt)
  1084. panic("packet size > maximum");
  1085. }
  1086. if((i = n) >= e->psize)
  1087. i = e->psize;
  1088. if (w)
  1089. e->buffered += i;
  1090. else{
  1091. e->buffered -= i;
  1092. if (e->buffered < 0)
  1093. e->buffered = 0;
  1094. }
  1095. isolock = 0;
  1096. iunlock(&ctlr->activends);
  1097. td->flags &= ~IsoClean;
  1098. bp = x->bp0 + (td - x->td0) * e->maxpkt / e->pollms;
  1099. q = bp + e->off;
  1100. if (w){
  1101. memmove(q, p, i);
  1102. }else{
  1103. memmove(p, q, i);
  1104. }
  1105. p += i;
  1106. n -= i;
  1107. e->off += i;
  1108. e->psize -= i;
  1109. if (e->psize){
  1110. if (n != 0)
  1111. panic("usb iso: can't happen");
  1112. break;
  1113. }
  1114. if(w)
  1115. td->offset = offset + (p-(uchar*)a) - (((td->dev >> 21) + 1) & 0x7ff);
  1116. td->status = ErrLimit3 | Active | IsoSelect | IOC;
  1117. x->etd = td->next;
  1118. e->off = 0;
  1119. } while(n > 0);
  1120. n = p-(uchar*)a;
  1121. e->foffset += n;
  1122. poperror();
  1123. if (isolock)
  1124. iunlock(&ctlr->activends);
  1125. qunlock(&e->rlock);
  1126. return n;
  1127. }
  1128. static long
  1129. read(Usbhost *uh, Endpt *e, void *a, long n, vlong offset)
  1130. {
  1131. long l, i;
  1132. Block *b;
  1133. Ctlr *ctlr;
  1134. uchar *p;
  1135. ctlr = uh->ctlr;
  1136. if(e->iso)
  1137. return isoio(ctlr, e, a, n, (ulong)offset, 0);
  1138. XPRINT("qlock(%p)\n", &e->rlock);
  1139. qlock(&e->rlock);
  1140. XPRINT("got qlock(%p)\n", &e->rlock);
  1141. if(waserror()){
  1142. qunlock(&e->rlock);
  1143. eptcancel(ctlr, e);
  1144. nexterror();
  1145. }
  1146. p = a;
  1147. do {
  1148. if(e->eof) {
  1149. XPRINT("e->eof\n");
  1150. break;
  1151. }
  1152. if(e->err)
  1153. error(e->err);
  1154. qrcv(ctlr, e);
  1155. if(!e->iso)
  1156. e->rdata01 ^= 1;
  1157. sleep(&e->rr, eptinput, e);
  1158. if(e->err)
  1159. error(e->err);
  1160. b = qget(e->rq); /* TO DO */
  1161. if(b == nil) {
  1162. XPRINT("b == nil\n");
  1163. break;
  1164. }
  1165. if(waserror()){
  1166. freeb(b);
  1167. nexterror();
  1168. }
  1169. l = BLEN(b);
  1170. if((i = l) > n)
  1171. i = n;
  1172. if(i > 0){
  1173. memmove(p, b->rp, i);
  1174. p += i;
  1175. }
  1176. poperror();
  1177. freeb(b);
  1178. n -= i;
  1179. if (l != e->maxpkt)
  1180. break;
  1181. } while (n > 0);
  1182. poperror();
  1183. qunlock(&e->rlock);
  1184. return p-(uchar*)a;
  1185. }
  1186. static int
  1187. qisempty(void *arg)
  1188. {
  1189. return ((QH*)arg)->entries & Terminate;
  1190. }
  1191. static long
  1192. write(Usbhost *uh, Endpt *e, void *a, long n, vlong offset, int tok)
  1193. {
  1194. int i, j;
  1195. QH *qh;
  1196. Block *b;
  1197. Ctlr *ctlr;
  1198. uchar *p;
  1199. ctlr = uh->ctlr;
  1200. if(e->iso)
  1201. return isoio(ctlr, e, a, n, (ulong)offset, 1);
  1202. p = a;
  1203. qlock(&e->wlock);
  1204. if(waserror()){
  1205. qunlock(&e->wlock);
  1206. eptcancel(ctlr, e);
  1207. nexterror();
  1208. }
  1209. do {
  1210. if(e->err)
  1211. error(e->err);
  1212. if((i = n) >= e->maxpkt)
  1213. i = e->maxpkt;
  1214. b = allocb(i);
  1215. if(waserror()){
  1216. freeb(b);
  1217. nexterror();
  1218. }
  1219. XPRINT("out [%d]", i);
  1220. for (j = 0; j < i; j++) XPRINT(" %.2x", p[j]);
  1221. XPRINT("\n");
  1222. memmove(b->wp, p, i);
  1223. b->wp += i;
  1224. p += i;
  1225. n -= i;
  1226. poperror();
  1227. qh = qxmit(ctlr, e, b, tok);
  1228. tok = TokOUT;
  1229. e->wdata01 ^= 1;
  1230. if(e->ntd >= e->nbuf) {
  1231. XPRINT("qh %s: q=%p first=%p last=%p entries=%.8lux\n",
  1232. "writeusb sleep", qh, qh->first, qh->last, qh->entries);
  1233. XPRINT("write: sleep %lux\n", &e->wr);
  1234. sleep(&e->wr, qisempty, qh);
  1235. XPRINT("write: awake\n");
  1236. }
  1237. } while(n > 0);
  1238. poperror();
  1239. qunlock(&e->wlock);
  1240. return p-(uchar*)a;
  1241. }
  1242. static void
  1243. init(Usbhost* uh)
  1244. {
  1245. Ctlr *ctlr;
  1246. ctlr = uh->ctlr;
  1247. ilock(ctlr);
  1248. outl(ctlr->io+Flbaseadd, PCIWADDR(ctlr->frames));
  1249. OUT(Frnum, 0);
  1250. OUT(Usbintr, 0xF); /* enable all interrupts */
  1251. XPRINT("cmd 0x%x sofmod 0x%x\n", IN(Cmd), inb(ctlr->io+SOFMod));
  1252. XPRINT("sc0 0x%x sc1 0x%x\n", IN(Portsc0), IN(Portsc1));
  1253. if((IN(Cmd)&1)==0)
  1254. OUT(Cmd, 1); /* run */
  1255. // pprint("at: c=%x s=%x c0=%x\n", IN(Cmd), IN(Status), IN(Portsc0));
  1256. iunlock(ctlr);
  1257. }
  1258. static void
  1259. scanpci(void)
  1260. {
  1261. int io;
  1262. Ctlr *ctlr;
  1263. Pcidev *p;
  1264. static int already = 0;
  1265. if(already)
  1266. return;
  1267. already = 1;
  1268. p = nil;
  1269. while(p = pcimatch(p, 0, 0)) {
  1270. /*
  1271. * Find UHCI controllers. Class = 12 (serial controller),
  1272. * Sub-class = 3 (USB) and Programming Interface = 0.
  1273. */
  1274. if(p->ccrb != 0x0C || p->ccru != 0x03)
  1275. continue;
  1276. switch(p->ccrp){
  1277. case 0x00:
  1278. io = p->mem[4].bar & ~0x0F;
  1279. break;
  1280. case 0x10:
  1281. print("usbohci: %x/%x port 0x%lux size 0x%x irq %d\n",
  1282. p->vid, p->did, p->mem[0].bar & ~0x0F, p->mem[0].size, p->intl);
  1283. default:
  1284. continue;
  1285. }
  1286. if(io == 0) {
  1287. print("usbuhci: failed to map registers\n");
  1288. continue;
  1289. }
  1290. if(ioalloc(io, p->mem[4].size, 0, "usbuhci") < 0){
  1291. print("usbuhci: port %d in use\n", io);
  1292. continue;
  1293. }
  1294. if(p->intl == 0xFF || p->intl == 0) {
  1295. print("usbuhci: no irq assigned for port %d\n", io);
  1296. continue;
  1297. }
  1298. XPRINT("usbuhci: %x/%x port 0x%ux size 0x%x irq %d\n",
  1299. p->vid, p->did, io, p->mem[4].size, p->intl);
  1300. ctlr = malloc(sizeof(Ctlr));
  1301. ctlr->pcidev = p;
  1302. ctlr->io = io;
  1303. if(ctlrhead != nil)
  1304. ctlrtail->next = ctlr;
  1305. else
  1306. ctlrhead = ctlr;
  1307. ctlrtail = ctlr;
  1308. }
  1309. }
  1310. static int
  1311. reset(Usbhost *uh)
  1312. {
  1313. int i;
  1314. TD *t;
  1315. ulong io;
  1316. Ctlr *ctlr;
  1317. Pcidev *p;
  1318. scanpci();
  1319. /*
  1320. * Any adapter matches if no uh->port is supplied,
  1321. * otherwise the ports must match.
  1322. */
  1323. for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
  1324. if(ctlr->active)
  1325. continue;
  1326. if(uh->port == 0 || uh->port == ctlr->io){
  1327. ctlr->active = 1;
  1328. break;
  1329. }
  1330. }
  1331. if(ctlr == nil)
  1332. return -1;
  1333. io = ctlr->io;
  1334. p = ctlr->pcidev;
  1335. uh->ctlr = ctlr;
  1336. uh->port = io;
  1337. uh->irq = p->intl;
  1338. uh->tbdf = p->tbdf;
  1339. XPRINT("usbcmd\t0x%.4x\nusbsts\t0x%.4x\nusbintr\t0x%.4x\nfrnum\t0x%.2x\n",
  1340. IN(Cmd), IN(Status), IN(Usbintr), inb(io+Frnum));
  1341. XPRINT("frbaseadd\t0x%.4x\nsofmod\t0x%x\nportsc1\t0x%.4x\nportsc2\t0x%.4x\n",
  1342. IN(Flbaseadd), inb(io+SOFMod), IN(Portsc0), IN(Portsc1));
  1343. OUT(Cmd, 0); /* stop */
  1344. while((IN(Status) & (1<<5)) == 0) /* wait for halt */
  1345. ;
  1346. OUT(Status, 0xFF); /* clear pending interrupts */
  1347. pcicfgw16(p, 0xc0, 0x2000); /* legacy support register: turn off lunacy mode */
  1348. if(0){
  1349. i = inb(io+SOFMod);
  1350. OUT(Cmd, 4); /* global reset */
  1351. delay(15);
  1352. OUT(Cmd, 0); /* end reset */
  1353. delay(4);
  1354. outb(io+SOFMod, i);
  1355. }
  1356. ctlr->tdpool = xspanalloc(128*sizeof(TD), 16, 0);
  1357. for(i=128; --i>=0;){
  1358. ctlr->tdpool[i].next = ctlr->freetd;
  1359. ctlr->freetd = &ctlr->tdpool[i];
  1360. }
  1361. ctlr->qhpool = xspanalloc(64*sizeof(QH), 16, 0);
  1362. for(i=64; --i>=0;){
  1363. ctlr->qhpool[i].next = ctlr->freeqh;
  1364. ctlr->freeqh = &ctlr->qhpool[i];
  1365. }
  1366. /*
  1367. * the last entries of the periodic (interrupt & isochronous) scheduling TD entries
  1368. * points to the control queue and the bandwidth sop for bulk traffic.
  1369. * this is looped following the instructions in PIIX4 errata 29773804.pdf:
  1370. * a QH links to a looped but inactive TD as its sole entry,
  1371. * with its head entry leading on to the bulk traffic, the last QH of which
  1372. * links back to the empty QH.
  1373. */
  1374. ctlr->ctlq = allocqh(ctlr);
  1375. ctlr->bwsop = allocqh(ctlr);
  1376. ctlr->bulkq = allocqh(ctlr);
  1377. ctlr->recvq = allocqh(ctlr);
  1378. t = alloctd(ctlr); /* inactive TD, looped */
  1379. t->link = PCIWADDR(t);
  1380. ctlr->bwsop->entries = PCIWADDR(t);
  1381. ctlr->ctlq->head = PCIWADDR(ctlr->bulkq) | IsQH;
  1382. ctlr->bulkq->head = PCIWADDR(ctlr->recvq) | IsQH;
  1383. ctlr->recvq->head = PCIWADDR(ctlr->bwsop) | IsQH;
  1384. if (1) /* don't use loop back */
  1385. ctlr->bwsop->head = Terminate;
  1386. else /* set up loop back */
  1387. ctlr->bwsop->head = PCIWADDR(ctlr->bwsop) | IsQH;
  1388. ctlr->frames = xspanalloc(FRAMESIZE, FRAMESIZE, 0);
  1389. ctlr->frameld = xallocz(FRAMESIZE, 1);
  1390. for (i = 0; i < NFRAME; i++)
  1391. ctlr->frames[i] = PCIWADDR(ctlr->ctlq) | IsQH;
  1392. /*
  1393. * Linkage to the generic USB driver.
  1394. */
  1395. uh->init = init;
  1396. uh->interrupt = interrupt;
  1397. uh->portinfo = portinfo;
  1398. uh->portreset = portreset;
  1399. uh->portenable = portenable;
  1400. uh->epalloc = epalloc;
  1401. uh->epfree = epfree;
  1402. uh->epopen = epopen;
  1403. uh->epclose = epclose;
  1404. uh->epmode = epmode;
  1405. uh->read = read;
  1406. uh->write = write;
  1407. return 0;
  1408. }
  1409. void
  1410. usbuhcilink(void)
  1411. {
  1412. addusbtype("uhci", reset);
  1413. }