Build version 1 of all catalogs.
[AROS.git] / rom / usb / pciusb / uhcichip.c
blob14bf192c5f0df7ca58cc8e15e321271f538db7cd
1 /*
2 Copyright © 2010-2011, The AROS Development Team. All rights reserved
3 $Id$
4 */
7 #include <proto/exec.h>
8 #include <proto/oop.h>
9 #include <hidd/pci.h>
11 #include <devices/usb_hub.h>
13 #include "uhwcmd.h"
15 #undef HiddPCIDeviceAttrBase
16 #define HiddPCIDeviceAttrBase (hd->hd_HiddPCIDeviceAB)
17 #undef HiddAttrBase
18 #define HiddAttrBase (hd->hd_HiddAB)
20 static AROS_INTH1(UhciResetHandler, struct PCIController *, hc)
22 AROS_INTFUNC_INIT
24 // stop controller and disable all interrupts
25 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, 0);
26 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBINTEN, 0);
28 return FALSE;
30 AROS_INTFUNC_EXIT
33 void uhciFreeQContext(struct PCIController *hc, struct UhciQH *uqh) {
35 struct UhciTD *utd = NULL;
36 struct UhciTD *nextutd;
38 KPRINTF(5, ("Unlinking QContext %08lx\n", uqh));
39 // unlink from schedule
40 uqh->uqh_Pred->uxx_Link = uqh->uqh_Succ->uxx_Self;
41 SYNC;
43 uqh->uqh_Succ->uxx_Pred = uqh->uqh_Pred;
44 uqh->uqh_Pred->uxx_Succ = uqh->uqh_Succ;
45 SYNC;
47 nextutd = uqh->uqh_FirstTD;
48 while(nextutd)
50 KPRINTF(1, ("FreeTD %08lx\n", nextutd));
51 utd = nextutd;
52 nextutd = (struct UhciTD *) utd->utd_Succ;
53 uhciFreeTD(hc, utd);
55 uhciFreeQH(hc, uqh);
58 void uhciUpdateIntTree(struct PCIController *hc) {
60 struct UhciXX *uxx;
61 struct UhciXX *preduxx;
62 struct UhciXX *lastuseduxx;
63 UWORD cnt;
65 // optimize linkage between queue heads
66 preduxx = lastuseduxx = (struct UhciXX *) hc->hc_UhciCtrlQH; //hc->hc_UhciIsoTD;
67 for(cnt = 0; cnt < 9; cnt++)
69 uxx = (struct UhciXX *) hc->hc_UhciIntQH[cnt];
70 if(uxx->uxx_Succ != preduxx)
72 lastuseduxx = uxx->uxx_Succ;
74 uxx->uxx_Link = lastuseduxx->uxx_Self;
75 preduxx = uxx;
79 void uhciCheckPortStatusChange(struct PCIController *hc) {
81 struct PCIUnit *unit = hc->hc_Unit;
82 UWORD oldval;
83 UWORD hciport;
85 // check for port status change for UHCI and frame rollovers
87 for(hciport = 0; hciport < 2; hciport++)
89 UWORD portreg;
90 UWORD idx = hc->hc_PortNum20[hciport];
91 // don't pay attention to UHCI port changes when pwned by EHCI
92 if(!unit->hu_EhciOwned[idx])
94 portreg = hciport ? UHCI_PORT2STSCTRL : UHCI_PORT1STSCTRL;
95 oldval = READIO16_LE(hc->hc_RegBase, portreg);
96 if(oldval & UHPF_ENABLECHANGE)
98 KPRINTF(10, ("Port %ld (%ld) Enable changed\n", idx, hciport));
99 hc->hc_PortChangeMap[hciport] |= UPSF_PORT_ENABLE;
101 if(oldval & UHPF_CONNECTCHANGE)
103 KPRINTF(10, ("Port %ld (%ld) Connect changed\n", idx, hciport));
104 hc->hc_PortChangeMap[hciport] |= UPSF_PORT_CONNECTION;
105 if(!(oldval & UHPF_PORTCONNECTED))
107 if(unit->hu_PortMap20[idx])
109 KPRINTF(20, ("Transferring Port %ld back to EHCI\n", idx));
110 unit->hu_EhciOwned[idx] = TRUE;
114 if(oldval & UHPF_RESUMEDTX)
116 KPRINTF(10, ("Port %ld (%ld) Resume changed\n", idx, hciport));
117 hc->hc_PortChangeMap[hciport] |= UPSF_PORT_SUSPEND|UPSF_PORT_ENABLE;
118 oldval &= ~UHPF_RESUMEDTX;
120 if(hc->hc_PortChangeMap[hciport])
122 unit->hu_RootPortChanges |= 1UL<<(idx+1);
123 /*KPRINTF(10, ("Port %ld (%ld) contributes %04lx to portmap %04lx\n",
124 idx, hciport, hc->hc_PortChangeMap[hciport], unit->hu_RootPortChanges));*/
126 WRITEIO16_LE(hc->hc_RegBase, portreg, oldval);
131 void uhciHandleFinishedTDs(struct PCIController *hc) {
133 struct PCIUnit *unit = hc->hc_Unit;
134 struct IOUsbHWReq *ioreq;
135 struct IOUsbHWReq *nextioreq;
136 struct UhciQH *uqh;
137 struct UhciTD *utd;
138 struct UhciTD *nextutd;
139 UWORD devadrep;
140 ULONG len;
141 ULONG linkelem;
142 UWORD inspect;
143 BOOL shortpkt;
144 ULONG ctrlstatus;
145 ULONG nextctrlstatus = 0;
146 ULONG token = 0;
147 ULONG actual;
148 BOOL updatetree = FALSE;
149 BOOL fixsetupterm = FALSE;
151 KPRINTF(1, ("Checking for work done...\n"));
152 ioreq = (struct IOUsbHWReq *) hc->hc_TDQueue.lh_Head;
153 while((nextioreq = (struct IOUsbHWReq *) ((struct Node *) ioreq)->ln_Succ))
155 uqh = (struct UhciQH *) ioreq->iouh_DriverPrivate1;
156 if(uqh)
158 KPRINTF(1, ("Examining IOReq=%08lx with UQH=%08lx\n", ioreq, uqh));
159 linkelem = READMEM32_LE(&uqh->uqh_Element);
160 inspect = 0;
161 devadrep = (ioreq->iouh_DevAddr<<5) + ioreq->iouh_Endpoint + ((ioreq->iouh_Dir == UHDIR_IN) ? 0x10 : 0);
162 if(linkelem & UHCI_TERMINATE)
164 KPRINTF(1, ("UQH terminated %08lx\n", linkelem));
165 inspect = 2;
166 } else {
167 utd = (struct UhciTD *) ((linkelem & UHCI_PTRMASK) - hc->hc_PCIVirtualAdjust - 16); // struct UhciTD starts 16 bytes before physical TD
168 ctrlstatus = READMEM32_LE(&utd->utd_CtrlStatus);
169 nextutd = (struct UhciTD *)utd->utd_Succ;
170 if(!(ctrlstatus & UTCF_ACTIVE) && nextutd)
172 /* OK, it's not active. Does it look like it's done? Code copied from below.
173 If not done, check the next TD too. */
174 if(ctrlstatus & (UTSF_BABBLE|UTSF_STALLED|UTSF_CRCTIMEOUT|UTSF_DATABUFFERERR|UTSF_BITSTUFFERR))
177 Babble condition can only occur on the last data packet (or on the first if only one data packet is in the queue)
178 When UHCI encounters a babble condition it will halt immediately,
179 we can therefore just accept the data that has come through and resume as if we got interrupt on completition (IOC).
181 THEORETICAL: Possible fix for VIA babble bug
182 VIA chipset also halt the entire controller and sets the controller on stopped state.
183 We can resume the controller by changing the status bits in the queue so that the queue looks like it has ended with a completition or
184 remove the entire queue and act like it succeeded.
185 As VIA stops the controller we can then write a new frame list current index to point to the next item and then set the run bit back on.
187 nextutd = 0;
189 else
191 token = READMEM32_LE(&utd->utd_Token);
192 len = (ctrlstatus & UTSM_ACTUALLENGTH) >> UTSS_ACTUALLENGTH;
193 if((len != (token & UTTM_TRANSLENGTH) >> UTTS_TRANSLENGTH))
195 nextutd = 0;
198 if(nextutd)
200 nextctrlstatus = READMEM32_LE(&nextutd->utd_CtrlStatus);
203 /* Now, did the element link pointer change while we fetched the status for the pointed at TD?
204 If so, disregard the gathered information and assume still active. */
205 if(READMEM32_LE(&uqh->uqh_Element) != linkelem)
207 /* Oh well, probably still active */
208 KPRINTF(1, ("Link Element changed, still active.\n"));
210 else if(!(ctrlstatus & UTCF_ACTIVE) && (nextutd == 0 || !(nextctrlstatus & UTCF_ACTIVE)))
212 KPRINTF(1, ("CtrlStatus inactive %08lx\n", ctrlstatus));
213 inspect = 1;
215 else if(unit->hu_NakTimeoutFrame[devadrep] && (hc->hc_FrameCounter > unit->hu_NakTimeoutFrame[devadrep]))
217 ioreq->iouh_Req.io_Error = UHIOERR_NAKTIMEOUT;
218 inspect = 1;
221 fixsetupterm = FALSE;
222 if(inspect)
224 APTR data = &((UBYTE *)ioreq->iouh_Data)[ioreq->iouh_Actual];
225 shortpkt = FALSE;
226 if(inspect < 2) // if all went okay, don't traverse list, assume all bytes successfully transferred
228 utd = uqh->uqh_FirstTD;
229 actual = 0;
232 ctrlstatus = READMEM32_LE(&utd->utd_CtrlStatus);
233 if(ctrlstatus & UTCF_ACTIVE)
235 KPRINTF(20, ("Internal error! Still active?!\n"));
236 if(ctrlstatus & UTSF_BABBLE)
238 KPRINTF(200, ("HOST CONTROLLER IS DEAD!!!\n"));
239 ioreq->iouh_Req.io_Error = UHIOERR_HOSTERROR;
240 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET|UHCF_MAXPACKET64|UHCF_CONFIGURE|UHCF_RUNSTOP);
241 inspect = 0;
242 break;
244 break;
246 token = READMEM32_LE(&utd->utd_Token);
247 KPRINTF(1, ("TD=%08lx CS=%08lx Token=%08lx\n", utd, ctrlstatus, token));
248 if(ctrlstatus & (UTSF_BABBLE|UTSF_STALLED|UTSF_CRCTIMEOUT|UTSF_DATABUFFERERR|UTSF_BITSTUFFERR))
250 if(ctrlstatus & UTSF_BABBLE)
252 KPRINTF(20, ("Babble error %08lx/%08lx\n", ctrlstatus, token));
253 ctrlstatus &= ~(UTSF_BABBLE);
254 WRITEMEM32_LE(&utd->utd_CtrlStatus, ctrlstatus);
255 SYNC;
256 inspect = 3;
257 break;
259 else if(ctrlstatus & UTSF_CRCTIMEOUT)
261 KPRINTF(20, ("CRC/Timeout error IOReq=%08lx DIR=%ld\n", ioreq, ioreq->iouh_Dir));
262 if(ctrlstatus & UTSF_STALLED)
264 ioreq->iouh_Req.io_Error = UHIOERR_TIMEOUT;
265 } else {
266 ioreq->iouh_Req.io_Error = (ioreq->iouh_Dir == UHDIR_IN) ? UHIOERR_CRCERROR : UHIOERR_TIMEOUT;
269 else if(ctrlstatus & UTSF_STALLED)
271 KPRINTF(20, ("STALLED!\n"));
272 ioreq->iouh_Req.io_Error = UHIOERR_STALL;
274 else if(ctrlstatus & UTSF_BITSTUFFERR)
276 KPRINTF(20, ("Bitstuff error\n"));
277 ioreq->iouh_Req.io_Error = UHIOERR_CRCERROR;
279 else if(ctrlstatus & UTSF_DATABUFFERERR)
281 KPRINTF(20, ("Databuffer error\n"));
282 ioreq->iouh_Req.io_Error = UHIOERR_HOSTERROR;
284 inspect = 0;
285 break;
287 if(unit->hu_NakTimeoutFrame[devadrep] && (hc->hc_FrameCounter > unit->hu_NakTimeoutFrame[devadrep]) && (ctrlstatus & UTSF_NAK))
289 ioreq->iouh_Req.io_Error = UHIOERR_NAKTIMEOUT;
290 inspect = 0;
293 len = (ctrlstatus & UTSM_ACTUALLENGTH)>>UTSS_ACTUALLENGTH;
294 if((len != (token & UTTM_TRANSLENGTH)>>UTTS_TRANSLENGTH))
296 shortpkt = TRUE;
298 len = (len+1) & 0x7ff; // get real length
299 if((token & UTTM_PID)>>UTTS_PID != PID_SETUP) // don't count setup packet
301 actual += len;
302 // due to the VIA babble bug workaround, actually more bytes can
303 // be received than requested, limit the actual value to the upper limit
304 if(actual > uqh->uqh_Actual)
306 actual = uqh->uqh_Actual;
309 if(shortpkt)
311 break;
313 } while((utd = (struct UhciTD *) utd->utd_Succ));
314 if(inspect == 3)
316 /* bail out from babble */
317 actual = uqh->uqh_Actual;
319 if((actual < uqh->uqh_Actual) && (!ioreq->iouh_Req.io_Error) && (!(ioreq->iouh_Flags & UHFF_ALLOWRUNTPKTS)))
321 KPRINTF(10, ("Short packet: %ld < %ld\n", actual, ioreq->iouh_Length));
322 ioreq->iouh_Req.io_Error = UHIOERR_RUNTPACKET;
324 } else {
325 KPRINTF(10, ("all %ld bytes transferred\n", uqh->uqh_Actual));
326 actual = uqh->uqh_Actual;
328 ioreq->iouh_Actual += actual;
329 // due to the short packet, the terminal of a setup packet has not been sent. Please do so.
330 if(shortpkt && (ioreq->iouh_Req.io_Command == UHCMD_CONTROLXFER))
332 fixsetupterm = TRUE;
334 // this is actually no short packet but result of the VIA babble fix
335 if(shortpkt && (ioreq->iouh_Actual == ioreq->iouh_Length))
337 shortpkt = FALSE;
339 unit->hu_DevBusyReq[devadrep] = NULL;
340 Remove(&ioreq->iouh_Req.io_Message.mn_Node);
341 if (uqh->uqh_DataBuffer)
342 usbReleaseBuffer(uqh->uqh_DataBuffer, data, actual, ioreq->iouh_Dir);
343 if (uqh->uqh_SetupBuffer)
344 usbReleaseBuffer(uqh->uqh_SetupBuffer, &ioreq->iouh_SetupData, sizeof(ioreq->iouh_SetupData), (ioreq->iouh_SetupData.bmRequestType & URTF_IN) ? UHDIR_IN : UHDIR_OUT);
345 uhciFreeQContext(hc, uqh);
346 if(ioreq->iouh_Req.io_Command == UHCMD_INTXFER)
348 updatetree = TRUE;
350 if(inspect)
352 if(inspect < 2) // otherwise, toggle will be right already
354 // use next data toggle bit based on last successful transaction
355 unit->hu_DevDataToggle[devadrep] = (token & UTTF_DATA1) ? FALSE : TRUE;
357 if((!shortpkt && (ioreq->iouh_Actual < ioreq->iouh_Length)) || fixsetupterm)
359 // fragmented, do some more work
360 switch(ioreq->iouh_Req.io_Command)
362 case UHCMD_CONTROLXFER:
363 KPRINTF(10, ("Rescheduling CtrlTransfer at %ld of %ld\n", ioreq->iouh_Actual, ioreq->iouh_Length));
364 AddHead(&hc->hc_CtrlXFerQueue, (struct Node *) ioreq);
365 break;
367 case UHCMD_INTXFER:
368 KPRINTF(10, ("Rescheduling IntTransfer at %ld of %ld\n", ioreq->iouh_Actual, ioreq->iouh_Length));
369 AddHead(&hc->hc_IntXFerQueue, (struct Node *) ioreq);
370 break;
372 case UHCMD_BULKXFER:
373 KPRINTF(10, ("Rescheduling BulkTransfer at %ld of %ld\n", ioreq->iouh_Actual, ioreq->iouh_Length));
374 AddHead(&hc->hc_BulkXFerQueue, (struct Node *) ioreq);
375 break;
377 default:
378 KPRINTF(10, ("Uhm, internal error, dunno where to queue this req\n"));
379 ReplyMsg(&ioreq->iouh_Req.io_Message);
381 } else {
382 // check for sucessful clear feature and set address ctrl transfers
383 if(ioreq->iouh_Req.io_Command == UHCMD_CONTROLXFER)
385 uhwCheckSpecialCtrlTransfers(hc, ioreq);
387 ReplyMsg(&ioreq->iouh_Req.io_Message);
389 } else {
390 // be sure to save the data toggle bit where the error occurred
391 unit->hu_DevDataToggle[devadrep] = (token & UTTF_DATA1) ? TRUE : FALSE;
392 ReplyMsg(&ioreq->iouh_Req.io_Message);
395 } else {
396 KPRINTF(20, ("IOReq=%08lx has no UQH!\n", ioreq));
398 ioreq = nextioreq;
400 if(updatetree)
402 KPRINTF(10, ("Updating Tree\n"));
403 uhciUpdateIntTree(hc);
407 void uhciScheduleCtrlTDs(struct PCIController *hc) {
409 struct PCIUnit *unit = hc->hc_Unit;
410 struct IOUsbHWReq *ioreq;
411 UWORD devadrep;
412 struct UhciQH *uqh;
413 struct UhciTD *setuputd;
414 struct UhciTD *datautd;
415 struct UhciTD *termutd;
416 struct UhciTD *predutd;
417 ULONG actual;
418 ULONG ctrlstatus;
419 ULONG token;
420 ULONG len;
421 ULONG phyaddr;
422 BOOL cont;
424 /* *** CTRL Transfers *** */
425 KPRINTF(1, ("Scheduling new CTRL transfers...\n"));
426 ioreq = (struct IOUsbHWReq *) hc->hc_CtrlXFerQueue.lh_Head;
427 while(((struct Node *) ioreq)->ln_Succ)
429 devadrep = (ioreq->iouh_DevAddr<<5) + ioreq->iouh_Endpoint;
430 KPRINTF(10, ("New CTRL transfer to %ld.%ld: %ld bytes\n", ioreq->iouh_DevAddr, ioreq->iouh_Endpoint, ioreq->iouh_Length));
431 /* is endpoint already in use or do we have to wait for next transaction */
432 if(unit->hu_DevBusyReq[devadrep])
434 KPRINTF(5, ("Endpoint %02lx in use!\n", devadrep));
435 ioreq = (struct IOUsbHWReq *) ((struct Node *) ioreq)->ln_Succ;
436 continue;
439 uqh = uhciAllocQH(hc);
440 if(!uqh)
442 break;
445 setuputd = uhciAllocTD(hc);
446 if(!setuputd)
448 uhciFreeQH(hc, uqh);
449 break;
451 termutd = uhciAllocTD(hc);
452 if(!termutd)
454 uhciFreeTD(hc, setuputd);
455 uhciFreeQH(hc, uqh);
456 break;
458 uqh->uqh_IOReq = ioreq;
460 //termutd->utd_QueueHead = setuputd->utd_QueueHead = uqh;
462 KPRINTF(1, ("SetupTD=%08lx, TermTD=%08lx\n", setuputd, termutd));
464 // fill setup td
465 ctrlstatus = UTCF_ACTIVE|UTCF_3ERRORSLIMIT;
466 if(ioreq->iouh_Flags & UHFF_LOWSPEED)
468 KPRINTF(5, ("*** LOW SPEED ***\n"));
469 ctrlstatus |= UTCF_LOWSPEED;
471 token = (ioreq->iouh_DevAddr<<UTTS_DEVADDR)|(ioreq->iouh_Endpoint<<UTTS_ENDPOINT);
472 //setuputd->utd_Pred = NULL;
473 if(ioreq->iouh_Actual)
475 // this is a continuation of a fragmented ctrl transfer!
476 KPRINTF(1, ("Continuing FRAGMENT at %ld of %ld\n", ioreq->iouh_Actual, ioreq->iouh_Length));
477 cont = TRUE;
478 } else {
479 cont = FALSE;
480 uqh->uqh_FirstTD = setuputd;
481 uqh->uqh_Element = setuputd->utd_Self; // start of queue
482 uqh->uqh_SetupBuffer = usbGetBuffer(&ioreq->iouh_SetupData, sizeof(ioreq->iouh_SetupData), (ioreq->iouh_SetupData.bmRequestType & URTF_IN) ? UHDIR_IN : UHDIR_OUT);
483 WRITEMEM32_LE(&setuputd->utd_CtrlStatus, ctrlstatus);
484 WRITEMEM32_LE(&setuputd->utd_Token, (PID_SETUP<<UTTS_PID)|token|(7<<UTTS_TRANSLENGTH)|UTTF_DATA0);
485 WRITEMEM32_LE(&setuputd->utd_BufferPtr, (ULONG) (IPTR) pciGetPhysical(hc, uqh->uqh_SetupBuffer));
488 token |= (ioreq->iouh_SetupData.bmRequestType & URTF_IN) ? PID_IN : PID_OUT;
489 predutd = setuputd;
490 actual = ioreq->iouh_Actual;
492 if(ioreq->iouh_Length - actual)
494 ctrlstatus |= UTCF_SHORTPACKET;
495 if(cont)
497 if(!unit->hu_DevDataToggle[devadrep])
499 // continue with data toggle 0
500 token |= UTTF_DATA1;
502 } else {
503 ioreq->iouh_Actual=0;
505 uqh->uqh_DataBuffer = usbGetBuffer(&(((UBYTE *) ioreq->iouh_Data)[ioreq->iouh_Actual]), ioreq->iouh_Length - actual, ioreq->iouh_Dir);
506 phyaddr = (ULONG)(IPTR)pciGetPhysical(hc, uqh->uqh_DataBuffer);
509 datautd = uhciAllocTD(hc);
510 if(!datautd)
512 break;
514 token ^= UTTF_DATA1; // toggle bit
515 predutd->utd_Link = datautd->utd_Self;
516 predutd->utd_Succ = (struct UhciXX *) datautd;
517 //datautd->utd_Pred = (struct UhciXX *) predutd;
518 //datautd->utd_QueueHead = uqh;
519 len = ioreq->iouh_Length - actual;
520 if(len > ioreq->iouh_MaxPktSize)
522 len = ioreq->iouh_MaxPktSize;
524 WRITEMEM32_LE(&datautd->utd_CtrlStatus, ctrlstatus);
525 WRITEMEM32_LE(&datautd->utd_Token, token|((len-1)<<UTTS_TRANSLENGTH)); // no masking need here as len is always >= 1
526 WRITEMEM32_LE(&datautd->utd_BufferPtr, phyaddr);
527 phyaddr += len;
528 actual += len;
529 predutd = datautd;
530 } while((actual < ioreq->iouh_Length) && (actual - ioreq->iouh_Actual < UHCI_TD_CTRL_LIMIT));
531 if(actual == ioreq->iouh_Actual)
533 // not at least one data TD? try again later
534 uhciFreeTD(hc, setuputd);
535 uhciFreeTD(hc, termutd);
536 uhciFreeQH(hc, uqh);
537 break;
539 if(cont)
541 // free Setup packet
542 KPRINTF(1, ("Freeing setup\n"));
543 uqh->uqh_FirstTD = (struct UhciTD *) setuputd->utd_Succ;
544 //uqh->uqh_FirstTD->utd_Pred = NULL;
545 uqh->uqh_Element = setuputd->utd_Succ->uxx_Self; // start of queue after setup packet
546 uhciFreeTD(hc, setuputd);
547 // set toggle for next batch
548 unit->hu_DevDataToggle[devadrep] = (token & UTTF_DATA1) ? FALSE : TRUE;
550 } else {
551 if(cont)
553 // free Setup packet, assign termination as first packet (no data)
554 KPRINTF(1, ("Freeing setup (term only)\n"));
555 uqh->uqh_FirstTD = (struct UhciTD *) termutd;
556 uqh->uqh_Element = termutd->utd_Self; // start of queue after setup packet
557 uhciFreeTD(hc, setuputd);
558 predutd = NULL;
561 uqh->uqh_Actual = actual - ioreq->iouh_Actual;
562 ctrlstatus |= UTCF_READYINTEN;
563 if(actual == ioreq->iouh_Length)
565 // TERM packet
566 KPRINTF(1, ("Activating TERM\n"));
567 token |= UTTF_DATA1;
568 token ^= (PID_IN^PID_OUT)<<UTTS_PID;
570 if(predutd)
572 predutd->utd_Link = termutd->utd_Self;
573 predutd->utd_Succ = (struct UhciXX *) termutd;
575 //termutd->utd_Pred = (struct UhciXX *) predutd;
576 WRITEMEM32_LE(&termutd->utd_CtrlStatus, ctrlstatus);
577 WRITEMEM32_LE(&termutd->utd_Token, token|(0x7ff<<UTTS_TRANSLENGTH));
578 CONSTWRITEMEM32_LE(&termutd->utd_Link, UHCI_TERMINATE);
579 termutd->utd_Succ = NULL;
580 //uqh->uqh_LastTD = termutd;
581 } else {
582 KPRINTF(1, ("Setup data phase fragmented\n"));
583 // don't create TERM, we don't know the final data toggle bit
584 // but mark the last data TD for interrupt generation
585 WRITEMEM32_LE(&predutd->utd_CtrlStatus, ctrlstatus);
586 uhciFreeTD(hc, termutd);
587 CONSTWRITEMEM32_LE(&predutd->utd_Link, UHCI_TERMINATE);
588 predutd->utd_Succ = NULL;
589 //uqh->uqh_LastTD = predutd;
592 Remove(&ioreq->iouh_Req.io_Message.mn_Node);
593 ioreq->iouh_DriverPrivate1 = uqh;
595 // manage endpoint going busy
596 unit->hu_DevBusyReq[devadrep] = ioreq;
597 unit->hu_NakTimeoutFrame[devadrep] = (ioreq->iouh_Flags & UHFF_NAKTIMEOUT) ? hc->hc_FrameCounter + ioreq->iouh_NakTimeout : 0;
599 Disable();
600 AddTail(&hc->hc_TDQueue, (struct Node *) ioreq);
602 // looks good to me, now enqueue this entry (just behind the CtrlQH)
603 uqh->uqh_Succ = hc->hc_UhciCtrlQH->uqh_Succ;
604 uqh->uqh_Link = uqh->uqh_Succ->uxx_Self;
605 SYNC;
607 uqh->uqh_Pred = (struct UhciXX *) hc->hc_UhciCtrlQH;
608 uqh->uqh_Succ->uxx_Pred = (struct UhciXX *) uqh;
609 hc->hc_UhciCtrlQH->uqh_Succ = (struct UhciXX *) uqh;
610 hc->hc_UhciCtrlQH->uqh_Link = uqh->uqh_Self;
611 SYNC;
612 Enable();
614 ioreq = (struct IOUsbHWReq *) hc->hc_CtrlXFerQueue.lh_Head;
618 void uhciScheduleIntTDs(struct PCIController *hc) {
620 struct PCIUnit *unit = hc->hc_Unit;
621 struct IOUsbHWReq *ioreq;
622 UWORD cnt;
623 UWORD devadrep;
624 struct UhciQH *uqh;
625 struct UhciQH *intuqh;
626 struct UhciTD *utd;
627 struct UhciTD *predutd;
628 ULONG actual;
629 ULONG ctrlstatus;
630 ULONG token;
631 ULONG len;
632 ULONG phyaddr;
634 /* *** INT Transfers *** */
635 KPRINTF(1, ("Scheduling new INT transfers...\n"));
636 ioreq = (struct IOUsbHWReq *) hc->hc_IntXFerQueue.lh_Head;
637 while(((struct Node *) ioreq)->ln_Succ)
639 devadrep = (ioreq->iouh_DevAddr<<5) + ioreq->iouh_Endpoint + ((ioreq->iouh_Dir == UHDIR_IN) ? 0x10 : 0);
640 KPRINTF(10, ("New INT transfer to %ld.%ld: %ld bytes\n", ioreq->iouh_DevAddr, ioreq->iouh_Endpoint, ioreq->iouh_Length));
641 /* is endpoint already in use or do we have to wait for next transaction */
642 if(unit->hu_DevBusyReq[devadrep])
644 KPRINTF(5, ("Endpoint %02lx in use!\n", devadrep));
645 ioreq = (struct IOUsbHWReq *) ((struct Node *) ioreq)->ln_Succ;
646 continue;
649 uqh = uhciAllocQH(hc);
650 if(!uqh)
652 break;
655 uqh->uqh_IOReq = ioreq;
657 ctrlstatus = UTCF_ACTIVE|UTCF_1ERRORLIMIT|UTCF_SHORTPACKET;
658 if(ioreq->iouh_Flags & UHFF_LOWSPEED)
660 KPRINTF(5, ("*** LOW SPEED ***\n"));
661 ctrlstatus |= UTCF_LOWSPEED;
663 token = (ioreq->iouh_DevAddr<<UTTS_DEVADDR)|(ioreq->iouh_Endpoint<<UTTS_ENDPOINT);
664 token |= (ioreq->iouh_Dir == UHDIR_IN) ? PID_IN : PID_OUT;
665 predutd = NULL;
666 actual = ioreq->iouh_Actual;
667 uqh->uqh_DataBuffer = usbGetBuffer(&(((UBYTE *) ioreq->iouh_Data)[ioreq->iouh_Actual]), ioreq->iouh_Length - actual, ioreq->iouh_Dir);
668 phyaddr = (ULONG) (IPTR) pciGetPhysical(hc, uqh->uqh_DataBuffer);
669 if(unit->hu_DevDataToggle[devadrep])
671 // continue with data toggle 1
672 KPRINTF(1, ("Data1\n"));
673 token |= UTTF_DATA1;
674 } else {
675 KPRINTF(1, ("Data0\n"));
679 utd = uhciAllocTD(hc);
680 if(!utd)
682 break;
684 if(predutd)
686 WRITEMEM32_LE(&predutd->utd_Link, READMEM32_LE(&utd->utd_Self)|UHCI_DFS);
687 predutd->utd_Succ = (struct UhciXX *) utd;
688 //utd->utd_Pred = (struct UhciXX *) predutd;
689 } else {
690 uqh->uqh_FirstTD = utd;
691 uqh->uqh_Element = utd->utd_Self;
692 //utd->utd_Pred = NULL;
694 //utd->utd_QueueHead = uqh;
695 len = ioreq->iouh_Length - actual;
696 if(len > ioreq->iouh_MaxPktSize)
698 len = ioreq->iouh_MaxPktSize;
701 WRITEMEM32_LE(&utd->utd_CtrlStatus, ctrlstatus);
702 WRITEMEM32_LE(&utd->utd_Token, token|(((len-1) & 0x7ff)<<UTTS_TRANSLENGTH));
703 WRITEMEM32_LE(&utd->utd_BufferPtr, phyaddr);
704 phyaddr += len;
705 actual += len;
706 predutd = utd;
707 token ^= UTTF_DATA1; // toggle bit
708 } while((actual < ioreq->iouh_Length) && (actual - ioreq->iouh_Actual < UHCI_TD_INT_LIMIT));
710 if(!utd)
712 // not at least one data TD? try again later
713 uhciFreeQH(hc, uqh);
714 break;
717 uqh->uqh_Actual = actual - ioreq->iouh_Actual;
718 // set toggle for next batch / succesful transfer
719 unit->hu_DevDataToggle[devadrep] = (token & UTTF_DATA1) ? TRUE : FALSE;
720 if(unit->hu_DevDataToggle[devadrep])
722 // continue with data toggle 1
723 KPRINTF(1, ("NewData1\n"));
724 } else {
725 KPRINTF(1, ("NewData0\n"));
727 ctrlstatus |= UTCF_READYINTEN;
728 WRITEMEM32_LE(&predutd->utd_CtrlStatus, ctrlstatus);
729 CONSTWRITEMEM32_LE(&utd->utd_Link, UHCI_TERMINATE);
730 utd->utd_Succ = NULL;
731 //uqh->uqh_LastTD = utd;
733 if(ioreq->iouh_Interval >= 255)
735 intuqh = hc->hc_UhciIntQH[8]; // 256ms interval
736 } else {
737 cnt = 0;
740 intuqh = hc->hc_UhciIntQH[cnt++];
741 } while(ioreq->iouh_Interval >= (1<<cnt));
742 KPRINTF(1, ("Scheduled at level %ld\n", cnt));
745 Remove(&ioreq->iouh_Req.io_Message.mn_Node);
746 ioreq->iouh_DriverPrivate1 = uqh;
748 // manage endpoint going busy
749 unit->hu_DevBusyReq[devadrep] = ioreq;
750 unit->hu_NakTimeoutFrame[devadrep] = (ioreq->iouh_Flags & UHFF_NAKTIMEOUT) ? hc->hc_FrameCounter + ioreq->iouh_NakTimeout : 0;
752 Disable();
753 AddTail(&hc->hc_TDQueue, (struct Node *) ioreq);
755 // looks good to me, now enqueue this entry (just behind the right IntQH)
756 uqh->uqh_Succ = intuqh->uqh_Succ;
757 uqh->uqh_Link = uqh->uqh_Succ->uxx_Self;
758 SYNC;
760 uqh->uqh_Pred = (struct UhciXX *) intuqh;
761 uqh->uqh_Succ->uxx_Pred = (struct UhciXX *) uqh;
762 intuqh->uqh_Succ = (struct UhciXX *) uqh;
763 intuqh->uqh_Link = uqh->uqh_Self;
764 SYNC;
765 Enable();
767 uhciUpdateIntTree(hc);
769 ioreq = (struct IOUsbHWReq *) hc->hc_IntXFerQueue.lh_Head;
773 void uhciScheduleBulkTDs(struct PCIController *hc) {
775 struct PCIUnit *unit = hc->hc_Unit;
776 struct IOUsbHWReq *ioreq;
777 UWORD devadrep;
778 struct UhciQH *uqh;
779 struct UhciTD *utd;
780 struct UhciTD *predutd;
781 ULONG actual;
782 ULONG ctrlstatus;
783 ULONG token;
784 ULONG len;
785 ULONG phyaddr;
786 BOOL forcezero;
788 /* *** BULK Transfers *** */
789 KPRINTF(1, ("Scheduling new BULK transfers...\n"));
790 ioreq = (struct IOUsbHWReq *) hc->hc_BulkXFerQueue.lh_Head;
791 while(((struct Node *) ioreq)->ln_Succ)
793 devadrep = (ioreq->iouh_DevAddr<<5) + ioreq->iouh_Endpoint + ((ioreq->iouh_Dir == UHDIR_IN) ? 0x10 : 0);
794 KPRINTF(10, ("New BULK transfer to %ld.%ld: %ld bytes\n", ioreq->iouh_DevAddr, ioreq->iouh_Endpoint, ioreq->iouh_Length));
795 /* is endpoint already in use or do we have to wait for next transaction */
796 if(unit->hu_DevBusyReq[devadrep])
798 KPRINTF(5, ("Endpoint %02lx in use!\n", devadrep));
799 ioreq = (struct IOUsbHWReq *) ((struct Node *) ioreq)->ln_Succ;
800 continue;
803 uqh = uhciAllocQH(hc);
804 if(!uqh)
806 break;
809 uqh->uqh_IOReq = ioreq;
811 // fill setup td
812 ctrlstatus = UTCF_ACTIVE|UTCF_1ERRORLIMIT|UTCF_SHORTPACKET;
813 token = (ioreq->iouh_DevAddr<<UTTS_DEVADDR)|(ioreq->iouh_Endpoint<<UTTS_ENDPOINT);
814 token |= (ioreq->iouh_Dir == UHDIR_IN) ? PID_IN : PID_OUT;
815 predutd = NULL;
816 actual = ioreq->iouh_Actual;
818 // Get a MEMF_31BIT bounce buffer
819 uqh->uqh_DataBuffer = usbGetBuffer(&(((UBYTE *) ioreq->iouh_Data)[ioreq->iouh_Actual]), ioreq->iouh_Length - actual, ioreq->iouh_Dir);
820 phyaddr = (IPTR)pciGetPhysical(hc, uqh->uqh_DataBuffer);
821 if(unit->hu_DevDataToggle[devadrep])
823 // continue with data toggle 1
824 token |= UTTF_DATA1;
828 utd = uhciAllocTD(hc);
829 if(!utd)
831 break;
833 forcezero = FALSE;
834 if(predutd)
836 WRITEMEM32_LE(&predutd->utd_Link, READMEM32_LE(&utd->utd_Self)|UHCI_DFS);
837 predutd->utd_Succ = (struct UhciXX *) utd;
838 //utd->utd_Pred = (struct UhciXX *) predutd;
839 } else {
840 uqh->uqh_FirstTD = utd;
841 uqh->uqh_Element = utd->utd_Self;
842 //utd->utd_Pred = NULL;
844 //utd->utd_QueueHead = uqh;
845 len = ioreq->iouh_Length - actual;
846 if(len > ioreq->iouh_MaxPktSize)
848 len = ioreq->iouh_MaxPktSize;
850 WRITEMEM32_LE(&utd->utd_CtrlStatus, ctrlstatus);
851 WRITEMEM32_LE(&utd->utd_Token, token|(((len-1) & 0x7ff)<<UTTS_TRANSLENGTH));
852 WRITEMEM32_LE(&utd->utd_BufferPtr, phyaddr);
853 phyaddr += len;
854 actual += len;
855 predutd = utd;
856 token ^= UTTF_DATA1; // toggle bit
857 if((actual == ioreq->iouh_Length) && len)
859 if((ioreq->iouh_Flags & UHFF_NOSHORTPKT) || (ioreq->iouh_Dir == UHDIR_IN) || (actual % ioreq->iouh_MaxPktSize))
861 // no last zero byte packet
862 break;
863 } else {
864 // avoid rare case that the zero byte packet is reached on TD_BULK_LIMIT
865 forcezero = TRUE;
868 } while(forcezero || (len && (actual <= ioreq->iouh_Length) && (actual - ioreq->iouh_Actual < UHCI_TD_BULK_LIMIT)));
870 if(!utd)
872 // not at least one data TD? try again later
873 uhciFreeQH(hc, uqh);
874 break;
876 uqh->uqh_Actual = actual - ioreq->iouh_Actual;
877 // set toggle for next batch / succesful transfer
878 unit->hu_DevDataToggle[devadrep] = (token & UTTF_DATA1) ? TRUE : FALSE;
880 ctrlstatus |= UTCF_READYINTEN;
881 WRITEMEM32_LE(&predutd->utd_CtrlStatus, ctrlstatus);
882 CONSTWRITEMEM32_LE(&utd->utd_Link, UHCI_TERMINATE);
883 utd->utd_Succ = NULL;
884 //uqh->uqh_LastTD = utd;
886 Remove(&ioreq->iouh_Req.io_Message.mn_Node);
887 ioreq->iouh_DriverPrivate1 = uqh;
889 // manage endpoint going busy
890 unit->hu_DevBusyReq[devadrep] = ioreq;
891 unit->hu_NakTimeoutFrame[devadrep] = (ioreq->iouh_Flags & UHFF_NAKTIMEOUT) ? hc->hc_FrameCounter + ioreq->iouh_NakTimeout : 0;
893 Disable();
894 AddTail(&hc->hc_TDQueue, (struct Node *) ioreq);
896 // looks good to me, now enqueue this entry (just behind the BulkQH)
897 uqh->uqh_Succ = hc->hc_UhciBulkQH->uqh_Succ;
898 uqh->uqh_Link = uqh->uqh_Succ->uxx_Self;
899 SYNC;
901 uqh->uqh_Pred = (struct UhciXX *) hc->hc_UhciBulkQH;
902 uqh->uqh_Succ->uxx_Pred = (struct UhciXX *) uqh;
903 hc->hc_UhciBulkQH->uqh_Succ = (struct UhciXX *) uqh;
904 hc->hc_UhciBulkQH->uqh_Link = uqh->uqh_Self;
905 SYNC;
906 Enable();
908 ioreq = (struct IOUsbHWReq *) hc->hc_BulkXFerQueue.lh_Head;
912 void uhciUpdateFrameCounter(struct PCIController *hc) {
914 UWORD framecnt;
915 Disable();
916 framecnt = READIO16_LE(hc->hc_RegBase, UHCI_FRAMECOUNT) & 0x07ff;
917 if(framecnt < (hc->hc_FrameCounter & 0x07ff))
919 hc->hc_FrameCounter |= 0x07ff;
920 hc->hc_FrameCounter++;
921 hc->hc_FrameCounter |= framecnt;
922 KPRINTF(10, ("Frame Counter Rollover %ld\n", hc->hc_FrameCounter));
923 } else {
924 hc->hc_FrameCounter = (hc->hc_FrameCounter & 0xfffff800)|framecnt;
926 Enable();
929 static AROS_INTH1(uhciCompleteInt, struct PCIController *,hc)
931 AROS_INTFUNC_INIT
933 KPRINTF(1, ("CompleteInt!\n"));
934 uhciUpdateFrameCounter(hc);
936 /* **************** PROCESS DONE TRANSFERS **************** */
938 uhciCheckPortStatusChange(hc);
939 uhwCheckRootHubChanges(hc->hc_Unit);
941 uhciHandleFinishedTDs(hc);
943 if(hc->hc_CtrlXFerQueue.lh_Head->ln_Succ)
945 uhciScheduleCtrlTDs(hc);
948 if(hc->hc_IntXFerQueue.lh_Head->ln_Succ)
950 uhciScheduleIntTDs(hc);
953 if(hc->hc_BulkXFerQueue.lh_Head->ln_Succ)
955 uhciScheduleBulkTDs(hc);
958 KPRINTF(1, ("CompleteDone\n"));
960 return FALSE;
962 AROS_INTFUNC_EXIT
965 static AROS_INTH1(uhciIntCode, struct PCIController *, hc)
967 AROS_INTFUNC_INIT
969 struct PCIDevice *base = hc->hc_Device;
970 UWORD intr;
972 //KPRINTF(10, ("pciUhciInt()\n"));
973 intr = READIO16_LE(hc->hc_RegBase, UHCI_USBSTATUS);
974 if(intr & (UHSF_USBINT|UHSF_USBERRORINT|UHSF_RESUMEDTX|UHSF_HCSYSERROR|UHSF_HCPROCERROR|UHSF_HCHALTED))
976 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBSTATUS, intr);
977 //KPRINTF(1, ("INT=%04lx\n", intr));
978 if(intr & (UHSF_HCSYSERROR|UHSF_HCPROCERROR|UHSF_HCHALTED))
980 KPRINTF(200, ("Host ERROR!\n"));
981 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET|UHCF_GLOBALRESET|UHCF_MAXPACKET64|UHCF_CONFIGURE);
982 //WRITEIO16_LE(hc->hc_RegBase, UHCI_USBINTEN, 0);
984 if (!(hc->hc_Flags & HCF_ONLINE))
986 return FALSE;
988 if(intr & (UHSF_USBINT|UHSF_USBERRORINT))
990 SureCause(base, &hc->hc_CompleteInt);
994 return FALSE;
996 AROS_INTFUNC_EXIT
999 BOOL uhciInit(struct PCIController *hc, struct PCIUnit *hu) {
1001 struct PCIDevice *hd = hu->hu_Device;
1003 struct UhciQH *uqh;
1004 struct UhciQH *preduqh;
1005 struct UhciTD *utd;
1006 ULONG *tabptr;
1007 UBYTE *memptr;
1008 ULONG bitcnt;
1010 ULONG cnt;
1012 struct TagItem pciActivateIO[] =
1014 { aHidd_PCIDevice_isIO, TRUE },
1015 { TAG_DONE, 0UL },
1018 struct TagItem pciActivateBusmaster[] =
1020 { aHidd_PCIDevice_isMaster, TRUE },
1021 { TAG_DONE, 0UL },
1024 struct TagItem pciDeactivateBusmaster[] =
1026 { aHidd_PCIDevice_isMaster, FALSE },
1027 { TAG_DONE, 0UL },
1030 hc->hc_NumPorts = 2; // UHCI always uses 2 ports per controller
1031 KPRINTF(20, ("Found UHCI Controller %08lx FuncNum=%ld with %ld ports\n", hc->hc_PCIDeviceObject, hc->hc_FunctionNum, hc->hc_NumPorts));
1032 hc->hc_CompleteInt.is_Node.ln_Type = NT_INTERRUPT;
1033 hc->hc_CompleteInt.is_Node.ln_Name = "UHCI CompleteInt";
1034 hc->hc_CompleteInt.is_Node.ln_Pri = 0;
1035 hc->hc_CompleteInt.is_Data = hc;
1036 hc->hc_CompleteInt.is_Code = (VOID_FUNC)uhciCompleteInt;
1038 hc->hc_PCIMemSize = sizeof(ULONG) * UHCI_FRAMELIST_SIZE + UHCI_FRAMELIST_ALIGNMENT + 1;
1039 hc->hc_PCIMemSize += sizeof(struct UhciQH) * UHCI_QH_POOLSIZE;
1040 hc->hc_PCIMemSize += sizeof(struct UhciTD) * UHCI_TD_POOLSIZE;
1042 memptr = HIDD_PCIDriver_AllocPCIMem(hc->hc_PCIDriverObject, hc->hc_PCIMemSize);
1043 /* memptr will be in the MEMF_31BIT type, therefore
1044 * we know that it's *physical address* will be 32 bits or
1045 * less, which is required for UHCI operation
1047 hc->hc_PCIMem = (APTR) memptr;
1048 if(memptr) {
1050 // PhysicalAddress - VirtualAdjust = VirtualAddress
1051 // VirtualAddress + VirtualAdjust = PhysicalAddress
1052 hc->hc_PCIVirtualAdjust = (IPTR)pciGetPhysical(hc, memptr) - (IPTR)memptr;
1053 KPRINTF(10, ("VirtualAdjust 0x%08lx\n", hc->hc_PCIVirtualAdjust));
1055 // align memory
1056 memptr = (UBYTE *) ((((IPTR) hc->hc_PCIMem) + UHCI_FRAMELIST_ALIGNMENT) & (~UHCI_FRAMELIST_ALIGNMENT));
1057 hc->hc_UhciFrameList = (ULONG *) memptr;
1058 KPRINTF(10, ("FrameListBase 0x%08lx\n", hc->hc_UhciFrameList));
1059 memptr += sizeof(APTR) * UHCI_FRAMELIST_SIZE;
1061 // build up QH pool
1062 // Again, all the UQHs are in the MEMF_31BIT hc_PCIMem pool,
1063 // so we can safely treat their physical addresses as 32 bit pointers
1064 uqh = (struct UhciQH *) memptr;
1065 hc->hc_UhciQHPool = uqh;
1066 cnt = UHCI_QH_POOLSIZE - 1;
1067 do {
1068 // minimal initalization
1069 uqh->uqh_Succ = (struct UhciXX *) (uqh + 1);
1070 WRITEMEM32_LE(&uqh->uqh_Self, (ULONG) ((IPTR)(&uqh->uqh_Link) + hc->hc_PCIVirtualAdjust + UHCI_QHSELECT));
1071 uqh++;
1072 } while(--cnt);
1073 uqh->uqh_Succ = NULL;
1074 WRITEMEM32_LE(&uqh->uqh_Self, (ULONG) ((IPTR)(&uqh->uqh_Link) + hc->hc_PCIVirtualAdjust + UHCI_QHSELECT));
1075 memptr += sizeof(struct UhciQH) * UHCI_QH_POOLSIZE;
1077 // build up TD pool
1078 // Again, all the UTDs are in the MEMF_31BIT hc_PCIMem pool,
1079 // so we can safely treat their physical addresses as 32 bit pointers
1080 utd = (struct UhciTD *) memptr;
1081 hc->hc_UhciTDPool = utd;
1082 cnt = UHCI_TD_POOLSIZE - 1;
1083 do {
1084 utd->utd_Succ = (struct UhciXX *) (utd + 1);
1085 WRITEMEM32_LE(&utd->utd_Self, (ULONG) ((IPTR)(&utd->utd_Link) + hc->hc_PCIVirtualAdjust + UHCI_TDSELECT));
1086 utd++;
1087 } while(--cnt);
1088 utd->utd_Succ = NULL;
1089 WRITEMEM32_LE(&utd->utd_Self, (ULONG) ((IPTR)(&utd->utd_Link) + hc->hc_PCIVirtualAdjust + UHCI_TDSELECT));
1090 memptr += sizeof(struct UhciTD) * UHCI_TD_POOLSIZE;
1092 // terminating QH
1093 hc->hc_UhciTermQH = preduqh = uqh = uhciAllocQH(hc);
1094 uqh->uqh_Succ = NULL;
1095 CONSTWRITEMEM32_LE(&uqh->uqh_Link, UHCI_TERMINATE);
1096 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
1098 // dummy Bulk QH
1099 hc->hc_UhciBulkQH = uqh = uhciAllocQH(hc);
1100 uqh->uqh_Succ = (struct UhciXX *) preduqh;
1101 preduqh->uqh_Pred = (struct UhciXX *) uqh;
1102 uqh->uqh_Link = preduqh->uqh_Self; // link to terminating QH
1103 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
1104 preduqh = uqh;
1106 // dummy Ctrl QH
1107 hc->hc_UhciCtrlQH = uqh = uhciAllocQH(hc);
1108 uqh->uqh_Succ = (struct UhciXX *) preduqh;
1109 preduqh->uqh_Pred = (struct UhciXX *) uqh;
1110 uqh->uqh_Link = preduqh->uqh_Self; // link to Bulk QH
1111 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
1113 // dummy ISO TD
1114 hc->hc_UhciIsoTD = utd = uhciAllocTD(hc);
1115 utd->utd_Succ = (struct UhciXX *) uqh;
1116 //utd->utd_Pred = NULL; // no certain linkage above this level
1117 uqh->uqh_Pred = (struct UhciXX *) utd;
1118 utd->utd_Link = uqh->uqh_Self; // link to Ctrl QH
1120 CONSTWRITEMEM32_LE(&utd->utd_CtrlStatus, 0);
1122 // 1 ms INT QH
1123 hc->hc_UhciIntQH[0] = uqh = uhciAllocQH(hc);
1124 uqh->uqh_Succ = (struct UhciXX *) utd;
1125 uqh->uqh_Pred = NULL; // who knows...
1126 //uqh->uqh_Link = utd->utd_Self; // link to ISO
1127 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
1128 preduqh = uqh;
1130 // make 9 levels of QH interrupts
1131 for(cnt = 1; cnt < 9; cnt++) {
1132 hc->hc_UhciIntQH[cnt] = uqh = uhciAllocQH(hc);
1133 uqh->uqh_Succ = (struct UhciXX *) preduqh;
1134 uqh->uqh_Pred = NULL; // who knows...
1135 //uqh->uqh_Link = preduqh->uqh_Self; // link to previous int level
1136 CONSTWRITEMEM32_LE(&uqh->uqh_Element, UHCI_TERMINATE);
1137 preduqh = uqh;
1140 uhciUpdateIntTree(hc);
1142 // fill in framelist with IntQH entry points based on interval
1143 tabptr = hc->hc_UhciFrameList;
1144 for(cnt = 0; cnt < UHCI_FRAMELIST_SIZE; cnt++) {
1145 uqh = hc->hc_UhciIntQH[8];
1146 bitcnt = 0;
1147 do {
1148 if(cnt & (1UL<<bitcnt)) {
1149 uqh = hc->hc_UhciIntQH[bitcnt];
1150 break;
1152 } while(++bitcnt < 9);
1153 *tabptr++ = uqh->uqh_Self;
1156 // this will cause more PCI memory access, but faster USB transfers as well
1157 //WRITEMEM32_LE(&hc->hc_UhciTermQH->uqh_Link, AROS_LONG2LE(hc->hc_UhciBulkQH->uqh_Self));
1159 // time to initialize hardware...
1160 OOP_GetAttr(hc->hc_PCIDeviceObject, aHidd_PCIDevice_Base4, (IPTR *) &hc->hc_RegBase);
1161 hc->hc_RegBase = (APTR) (((IPTR) hc->hc_RegBase) & (~0xf));
1162 KPRINTF(10, ("RegBase = 0x%08lx\n", hc->hc_RegBase));
1163 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateIO);
1165 // disable BIOS legacy support
1166 KPRINTF(10, ("Turning off BIOS legacy support (old value=%04lx)\n", PCIXReadConfigWord(hc, UHCI_USBLEGSUP)));
1167 PCIXWriteConfigWord(hc, UHCI_USBLEGSUP, 0x8f00);
1169 KPRINTF(10, ("Resetting UHCI HC\n"));
1170 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_GLOBALRESET);
1171 uhwDelayMS(15, hu);
1173 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciDeactivateBusmaster); // no busmaster yet
1175 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET);
1176 cnt = 100;
1177 do {
1178 uhwDelayMS(10, hu);
1179 if(!(READIO16_LE(hc->hc_RegBase, UHCI_USBCMD) & UHCF_HCRESET)) {
1180 break;
1182 } while(--cnt);
1184 if(cnt == 0) {
1185 KPRINTF(20, ("Reset Timeout!\n"));
1186 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET);
1187 uhwDelayMS(15, hu);
1188 } else {
1189 KPRINTF(20, ("Reset finished after %ld ticks\n", 100-cnt));
1192 // stop controller and disable all interrupts first
1193 KPRINTF(10, ("Stopping controller and enabling busmaster\n"));
1194 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, 0);
1195 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBINTEN, 0);
1197 OOP_SetAttrs(hc->hc_PCIDeviceObject, (struct TagItem *) pciActivateBusmaster); // enable busmaster
1199 // Fix for VIA Babble problem
1200 cnt = PCIXReadConfigByte(hc, 0x40);
1201 if(!(cnt & 0x40)) {
1202 KPRINTF(20, ("Applying VIA Babble workaround\n"));
1203 PCIXWriteConfigByte(hc, 0x40, cnt|0x40);
1206 KPRINTF(10, ("Configuring UHCI HC\n"));
1207 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_MAXPACKET64|UHCF_CONFIGURE);
1209 WRITEIO16_LE(hc->hc_RegBase, UHCI_FRAMECOUNT, 0);
1211 /* hc->hc_UhciFrameList points to a portion of hc->hc_PciMem,
1212 * which we know is 32 bit
1214 WRITEIO32_LE(hc->hc_RegBase, UHCI_FRAMELISTADDR, (ULONG)(IPTR)pciGetPhysical(hc, hc->hc_UhciFrameList));
1216 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBSTATUS, UHIF_TIMEOUTCRC|UHIF_INTONCOMPLETE|UHIF_SHORTPACKET);
1218 // install reset handler
1219 hc->hc_ResetInt.is_Code = (VOID_FUNC)UhciResetHandler;
1220 hc->hc_ResetInt.is_Data = hc;
1221 AddResetCallback(&hc->hc_ResetInt);
1223 // add interrupt
1224 hc->hc_PCIIntHandler.is_Node.ln_Name = "UHCI PCI (pciusb.device)";
1225 hc->hc_PCIIntHandler.is_Node.ln_Pri = 5;
1226 hc->hc_PCIIntHandler.is_Node.ln_Type = NT_INTERRUPT;
1227 hc->hc_PCIIntHandler.is_Code = (VOID_FUNC)uhciIntCode;
1228 hc->hc_PCIIntHandler.is_Data = hc;
1229 PCIXAddInterrupt(hc, &hc->hc_PCIIntHandler);
1231 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBINTEN, UHIF_TIMEOUTCRC|UHIF_INTONCOMPLETE|UHIF_SHORTPACKET);
1233 // clear all port bits (both ports)
1234 WRITEIO32_LE(hc->hc_RegBase, UHCI_PORT1STSCTRL, 0);
1236 // enable PIRQ
1237 KPRINTF(10, ("Enabling PIRQ (old value=%04lx)\n", PCIXReadConfigWord(hc, UHCI_USBLEGSUP)));
1238 PCIXWriteConfigWord(hc, UHCI_USBLEGSUP, 0x2000);
1240 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_MAXPACKET64|UHCF_CONFIGURE|UHCF_RUNSTOP);
1241 SYNC;
1243 KPRINTF(20, ("HW Init done\n"));
1245 KPRINTF(10, ("HW Regs USBCMD=%04lx\n", READIO16_LE(hc->hc_RegBase, UHCI_USBCMD)));
1246 KPRINTF(10, ("HW Regs USBSTS=%04lx\n", READIO16_LE(hc->hc_RegBase, UHCI_USBSTATUS)));
1247 KPRINTF(10, ("HW Regs FRAMECOUNT=%04lx\n", READIO16_LE(hc->hc_RegBase, UHCI_FRAMECOUNT)));
1249 KPRINTF(20, ("uhciInit returns TRUE...\n"));
1250 return TRUE;
1254 FIXME: What would the appropriate debug level be?
1256 KPRINTF(1000, ("uhciInit returns FALSE...\n"));
1257 return FALSE;
1260 void uhciFree(struct PCIController *hc, struct PCIUnit *hu) {
1262 hc = (struct PCIController *) hu->hu_Controllers.lh_Head;
1263 while(hc->hc_Node.ln_Succ)
1265 switch(hc->hc_HCIType)
1267 case HCITYPE_UHCI:
1269 KPRINTF(20, ("Shutting down UHCI %08lx\n", hc));
1270 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBINTEN, 0);
1271 // disable PIRQ
1272 PCIXWriteConfigWord(hc, UHCI_USBLEGSUP, 0);
1273 // disable all ports
1274 WRITEIO32_LE(hc->hc_RegBase, UHCI_PORT1STSCTRL, 0);
1275 uhwDelayMS(50, hu);
1276 //WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_MAXPACKET64|UHCF_CONFIGURE);
1277 //uhwDelayMS(50, hu);
1278 KPRINTF(20, ("Stopping UHCI %08lx\n", hc));
1279 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, 0);
1280 SYNC;
1282 //KPRINTF(20, ("Reset done UHCI %08lx\n", hc));
1283 uhwDelayMS(10, hu);
1285 KPRINTF(20, ("Resetting UHCI %08lx\n", hc));
1286 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, UHCF_HCRESET);
1287 SYNC;
1289 uhwDelayMS(50, hu);
1290 WRITEIO16_LE(hc->hc_RegBase, UHCI_USBCMD, 0);
1291 SYNC;
1293 KPRINTF(20, ("Shutting down UHCI done.\n"));
1294 break;
1298 hc = (struct PCIController *) hc->hc_Node.ln_Succ;