1 /* uhwcmd.c - pciusb.device by Chris Hodges
4 #include <devices/usb_hub.h>
5 #include <proto/utility.h>
6 #include <proto/exec.h>
7 #include <proto/timer.h>
12 #include "ohciproto.h"
14 #define NewList NEWLIST
16 /* we cannot use AROS_WORD2LE in struct initializer */
18 #define WORD2LE(w) (UWORD)(((w) >> 8) & 0x00FF) | (((w) << 8) & 0xFF00)
20 #define WORD2LE(w) (w)
24 const struct UsbStdDevDesc RHDevDesc
= { sizeof(struct UsbStdDevDesc
), UDT_DEVICE
, WORD2LE(0x0110), HUB_CLASSCODE
, 0, 0, 8, WORD2LE(0x0000), WORD2LE(0x0000), WORD2LE(0x0100), 1, 2, 0, 1 };
26 const struct UsbStdCfgDesc RHCfgDesc
= { 9, UDT_CONFIGURATION
, WORD2LE(9+9+7), 1, 1, 3, USCAF_ONE
|USCAF_SELF_POWERED
, 0 };
27 const struct UsbStdIfDesc RHIfDesc
= { 9, UDT_INTERFACE
, 0, 0, 1, HUB_CLASSCODE
, 0, 0, 4 };
28 const struct UsbStdEPDesc RHEPDesc
= { 7, UDT_ENDPOINT
, URTF_IN
|1, USEAF_INTERRUPT
, WORD2LE(8), 255 };
29 const struct UsbHubDesc RHHubDesc
= { 9, // 0 Number of bytes in this descriptor, including this byte
30 UDT_HUB
, // 1 Descriptor Type, value: 29H for hub descriptor
31 0, // 2 Number of downstream facing ports that this hub supports
32 WORD2LE(UHCF_INDIVID_POWER
|UHCF_INDIVID_OVP
), // 3 wHubCharacteristics
33 0, // 5 bPwrOn2PwrGood
34 1, // 6 bHubContrCurrent
35 1, // 7 DeviceRemovable (size is variable)
36 0 // x PortPwrCtrlMask (size is variable)
38 #ifdef AROS_USB30_CODE
39 const struct UsbSSHubDesc RHSSHubDesc
= { 12, // 0 Number of bytes in this descriptor, including this byte. (12 bytes)
40 UDT_SSHUB
, // 1 Descriptor Type, value: 2AH for SuperSpeed hub descriptor
41 0, // 2 Number of downstream facing ports that this hub supports. The maximum number of ports of ports a hub can support is 15
42 WORD2LE(UHCF_INDIVID_POWER
|UHCF_INDIVID_OVP
), // 3 wHubCharacteristics
43 0, // 5 bPwrOn2PwrGood
44 10, // 6 bHubContrCurrent
47 0 // 10 DeviceRemovable
51 const CONST_STRPTR RHStrings
[] = { "Chris Hodges", "PCI Root Hub Unit x", "Standard Config", "Hub interface" };
53 /* /// "SureCause()" */
54 void SureCause(struct PCIDevice
*base
, struct Interrupt
*interrupt
)
56 /* this is a workaround for the original Cause() function missing tailed calls */
59 if((interrupt
->is_Node
.ln_Type
== NT_SOFTINT
) || (interrupt
->is_Node
.ln_Type
== NT_USER
))
62 interrupt
->is_Node
.ln_Type
= NT_USER
;
66 interrupt
->is_Node
.ln_Type
= NT_SOFTINT
;
67 Forbid(); // make sure code is not interrupted by other tasks
69 (*((void (*)(struct Interrupt
*)) (interrupt
->is_Code
)))(interrupt
->is_Data
);
72 } while(interrupt
->is_Node
.ln_Type
!= NT_SOFTINT
);
73 interrupt
->is_Node
.ln_Type
= NT_INTERRUPT
;
79 /* /// "uhwOpenTimer()" */
80 BOOL
uhwOpenTimer(struct PCIUnit
*unit
, struct PCIDevice
*base
)
82 if((unit
->hu_MsgPort
= CreateMsgPort()))
84 if((unit
->hu_TimerReq
= (struct timerequest
*) CreateIORequest(unit
->hu_MsgPort
, sizeof(struct timerequest
))))
86 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) unit
->hu_TimerReq
, 0))
88 unit
->hu_TimerReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "PCI hardware";
89 unit
->hu_TimerReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
90 KPRINTF(1, ("opened timer device\n"));
93 DeleteIORequest((struct IORequest
*) unit
->hu_TimerReq
);
94 unit
->hu_TimerReq
= NULL
;
96 DeleteMsgPort(unit
->hu_MsgPort
);
97 unit
->hu_MsgPort
= NULL
;
99 KPRINTF(5, ("failed to open timer.device\n"));
104 /* /// "uhwDelayMS()" */
105 void uhwDelayMS(ULONG milli
, struct PCIUnit
*unit
)
107 unit
->hu_TimerReq
->tr_time
.tv_secs
= 0;
108 unit
->hu_TimerReq
->tr_time
.tv_micro
= milli
* 1000;
109 DoIO((struct IORequest
*) unit
->hu_TimerReq
);
113 /* /// "uhwDelayMicro()" */
114 void uhwDelayMicro(ULONG micro
, struct PCIUnit
*unit
)
116 unit
->hu_TimerReq
->tr_time
.tv_secs
= 0;
117 unit
->hu_TimerReq
->tr_time
.tv_micro
= micro
;
118 DoIO((struct IORequest
*) unit
->hu_TimerReq
);
122 /* /// "uhwCloseTimer()" */
123 void uhwCloseTimer(struct PCIUnit
*unit
, struct PCIDevice
*base
)
127 if(unit
->hu_TimerReq
)
129 KPRINTF(1, ("closing timer.device\n"));
130 CloseDevice((APTR
) unit
->hu_TimerReq
);
131 DeleteIORequest((struct IORequest
*) unit
->hu_TimerReq
);
132 unit
->hu_TimerReq
= NULL
;
134 DeleteMsgPort(unit
->hu_MsgPort
);
135 unit
->hu_MsgPort
= NULL
;
140 /* /// "Open_Unit()" */
141 struct Unit
* Open_Unit(struct IOUsbHWReq
*ioreq
,
143 struct PCIDevice
*base
)
145 struct PCIUnit
*unit
= NULL
;
147 if(!base
->hd_ScanDone
)
149 base
->hd_ScanDone
= TRUE
;
155 unit
= (struct PCIUnit
*) base
->hd_Units
.lh_Head
;
156 while(((struct Node
*) unit
)->ln_Succ
)
158 if(unit
->hu_UnitNo
== unitnr
)
162 unit
= (struct PCIUnit
*) ((struct Node
*) unit
)->ln_Succ
;
164 if(!((struct Node
*) unit
)->ln_Succ
)
166 KPRINTF(20, ("Unit %ld does not exist!\n", unitnr
));
169 if(unit
->hu_UnitAllocated
)
171 ioreq
->iouh_Req
.io_Error
= IOERR_UNITBUSY
;
172 KPRINTF(5, ("Unit %ld already open!\n", unitnr
));
176 if(uhwOpenTimer(unit
, base
))
179 if(pciAllocUnit(unit
)) // hardware self test
181 unit
->hu_UnitAllocated
= TRUE
;
182 unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
183 unit
->hu_NakTimeoutInt
.is_Node
.ln_Name
= "PCI NakTimeout";
184 unit
->hu_NakTimeoutInt
.is_Node
.ln_Pri
= -16;
185 unit
->hu_NakTimeoutInt
.is_Data
= unit
;
186 unit
->hu_NakTimeoutInt
.is_Code
= (void (*)(void)) &uhwNakTimeoutInt
;
188 CopyMem(unit
->hu_TimerReq
, &unit
->hu_NakTimeoutReq
, sizeof(struct timerequest
));
189 unit
->hu_NakTimeoutReq
.tr_node
.io_Message
.mn_ReplyPort
= &unit
->hu_NakTimeoutMsgPort
;
190 unit
->hu_NakTimeoutMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
191 unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_SOFTINT
;
192 unit
->hu_NakTimeoutMsgPort
.mp_SigTask
= &unit
->hu_NakTimeoutInt
;
193 NewList(&unit
->hu_NakTimeoutMsgPort
.mp_MsgList
);
194 Cause(&unit
->hu_NakTimeoutInt
);
195 return(&unit
->hu_Unit
);
197 ioreq
->iouh_Req
.io_Error
= IOERR_SELFTEST
;
198 KPRINTF(20, ("Hardware allocation failure!\n"));
200 uhwCloseTimer(unit
, base
);
206 /* /// "Close_Unit()" */
207 void Close_Unit(struct PCIDevice
*base
,
208 struct PCIUnit
*unit
,
209 struct IOUsbHWReq
*ioreq
)
211 /* Disable all interrupts */
212 unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_IGNORE
;
213 unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_SOFTINT
;
214 AbortIO((APTR
) &unit
->hu_NakTimeoutReq
);
218 uhwCloseTimer(unit
, base
);
219 unit
->hu_UnitAllocated
= FALSE
;
223 /* /// "uhwGetUsbState()" */
224 UWORD
uhwGetUsbState(struct IOUsbHWReq
*ioreq
,
225 struct PCIUnit
*unit
,
226 struct PCIDevice
*base
)
228 return(ioreq
->iouh_State
= UHSF_OPERATIONAL
);
232 /* /// "cmdReset()" */
234 *======================================================================
235 * cmdReset(ioreq, unit, base)
236 *======================================================================
238 * This is the device CMD_RESET routine.
240 * Resets the whole USB hardware. Goes into USBOperational mode right
241 * after. Must NOT be called from an interrupt.
245 WORD
cmdReset(struct IOUsbHWReq
*ioreq
,
246 struct PCIUnit
*unit
,
247 struct PCIDevice
*base
)
249 KPRINTF(10, ("CMD_RESET ioreq: 0x%p\n", ioreq
));
252 uhwGetUsbState(ioreq
, unit
, base
);
254 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
258 return UHIOERR_USBOFFLINE
;
262 /* /// "cmdUsbReset()" */
264 *======================================================================
265 * cmdUsbReset(ioreq, unit, base)
266 *======================================================================
268 * This is the device UHCMD_USBRESET routine.
270 * Resets the USB bus. Goes into USBOperational mode right after. Must
271 * NOT be called from an interrupt.
275 WORD
cmdUsbReset(struct IOUsbHWReq
*ioreq
,
276 struct PCIUnit
*unit
,
277 struct PCIDevice
*base
)
279 KPRINTF(10, ("UHCMD_USBRESET ioreq: 0x%p\n", ioreq
));
282 uhwGetUsbState(ioreq
, unit
, base
);
284 unit
->hu_FrameCounter
= 1;
285 unit
->hu_RootHubAddr
= 0;
287 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
291 return UHIOERR_USBOFFLINE
;
295 /* /// "cmdUsbResume()" */
297 *======================================================================
298 * cmdUsbResume(ioreq, unit, base)
299 *======================================================================
301 * This is the device UHCMD_USBRESUME routine.
303 * Tries to resume from USBSuspend mode into USBOperational.
304 * Must NOT be called from an interrupt.
308 WORD
cmdUsbResume(struct IOUsbHWReq
*ioreq
,
309 struct PCIUnit
*unit
,
310 struct PCIDevice
*base
)
312 KPRINTF(10, ("UHCMD_USBRESUME ioreq: 0x%p\n", ioreq
));
315 uhwGetUsbState(ioreq
, unit
, base
);
316 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
320 return UHIOERR_USBOFFLINE
;
324 /* /// "cmdUsbSuspend()" */
326 *======================================================================
327 * cmdUsbSuspend(ioreq, unit, base)
328 *======================================================================
330 * This is the device UHCMD_USBSUSPEND routine.
332 * Sets the USB into USBSuspend mode.
333 * Must NOT be called from an interrupt.
337 WORD
cmdUsbSuspend(struct IOUsbHWReq
*ioreq
,
338 struct PCIUnit
*unit
,
339 struct PCIDevice
*base
)
341 KPRINTF(10, ("UHCMD_USBSUSPEND ioreq: 0x%p\n", ioreq
));
344 uhwGetUsbState(ioreq
, unit
, base
);
345 if(ioreq
->iouh_State
& UHSF_SUSPENDED
)
349 return UHIOERR_USBOFFLINE
;
353 /* /// "cmdUsbOper()" */
355 *======================================================================
356 * cmdUsbOper(ioreq, unit, base)
357 *======================================================================
359 * This is the device UHCMD_USBOPER routine.
361 * Sets the USB into USBOperational mode.
362 * Must NOT be called from an interrupt.
366 WORD
cmdUsbOper(struct IOUsbHWReq
*ioreq
,
367 struct PCIUnit
*unit
,
368 struct PCIDevice
*base
)
370 KPRINTF(10, ("UHCMD_USBOPER ioreq: 0x%p\n", ioreq
));
373 uhwGetUsbState(ioreq
, unit
, base
);
374 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
378 return UHIOERR_USBOFFLINE
;
382 /* /// "cmdQueryDevice()" */
384 *======================================================================
385 * cmdQueryDevice(ioreq, unit, base)
386 *======================================================================
388 * This is the device UHCMD_QUERYDEVICE routine.
390 * Returns information about the hardware.
394 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
,
395 struct PCIUnit
*unit
,
396 struct PCIDevice
*base
)
398 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
402 KPRINTF(10, ("UHCMD_QUERYDEVICE ioreq: 0x%p, taglist: 0x%p\n", ioreq
, taglist
));
404 if((tag
= FindTagItem(UHA_State
, taglist
)))
406 *((ULONG
*) tag
->ti_Data
) = (ULONG
) uhwGetUsbState(ioreq
, unit
, base
);
409 if((tag
= FindTagItem(UHA_Manufacturer
, taglist
)))
411 *((STRPTR
*) tag
->ti_Data
) = "Chris Hodges";
414 if((tag
= FindTagItem(UHA_ProductName
, taglist
)))
416 *((STRPTR
*) tag
->ti_Data
) = unit
->hu_ProductName
;
419 if((tag
= FindTagItem(UHA_Description
, taglist
)))
421 *((STRPTR
*) tag
->ti_Data
) = "Generic adaptive host controller driver for PCI cards";
424 if((tag
= FindTagItem(UHA_Copyright
, taglist
)))
426 *((STRPTR
*) tag
->ti_Data
) ="©2007-2009 Chris Hodges";
429 if((tag
= FindTagItem(UHA_Version
, taglist
)))
431 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
434 if((tag
= FindTagItem(UHA_Revision
, taglist
)))
436 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
439 if((tag
= FindTagItem(UHA_DriverVersion
, taglist
)))
441 *((ULONG
*) tag
->ti_Data
) = 0x220;
444 if((tag
= FindTagItem(UHA_Capabilities
, taglist
)))
446 *((ULONG
*) tag
->ti_Data
) = UHCF_USB20
;
449 ioreq
->iouh_Actual
= count
;
454 /* /// "cmdControlXFerRootHub()" */
455 WORD
cmdControlXFerRootHub(struct IOUsbHWReq
*ioreq
,
456 struct PCIUnit
*unit
,
457 struct PCIDevice
*base
)
459 struct PCIController
*hc
;
460 struct PCIController
*chc
;
461 UWORD rt
= ioreq
->iouh_SetupData
.bmRequestType
;
462 UWORD req
= ioreq
->iouh_SetupData
.bRequest
;
463 UWORD idx
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
);
464 UWORD val
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wValue
);
465 UWORD len
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
467 ULONG numports
= unit
->hu_RootHubPorts
;
471 if(ioreq
->iouh_Endpoint
)
473 return(UHIOERR_STALL
);
476 if(len
!= ioreq
->iouh_Length
)
478 KPRINTF(20, ("RH: Len (%ld != %ld) mismatch!\n", len
!= ioreq
->iouh_Length
));
479 return(UHIOERR_STALL
);
483 case (URTF_STANDARD
|URTF_DEVICE
):
486 case USR_SET_ADDRESS
:
487 KPRINTF(1, ("RH: SetAddress = %ld\n", val
));
488 unit
->hu_RootHubAddr
= val
;
489 ioreq
->iouh_Actual
= len
;
492 case USR_SET_CONFIGURATION
:
493 KPRINTF(1, ("RH: SetConfiguration=%ld\n", val
));
494 ioreq
->iouh_Actual
= len
;
499 case (URTF_IN
|URTF_STANDARD
|URTF_DEVICE
):
502 case USR_GET_DESCRIPTOR
:
506 KPRINTF(1, ("RH: GetDeviceDescriptor (%ld)\n", len
));
507 ioreq
->iouh_Actual
= (len
> sizeof(struct UsbStdDevDesc
)) ? sizeof(struct UsbStdDevDesc
) : len
;
508 CopyMem((APTR
) &RHDevDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
509 if(ioreq
->iouh_Length
>= sizeof(struct UsbStdDevDesc
))
511 if(unit
->hu_RootHub20Ports
)
513 struct UsbStdDevDesc
*usdd
= (struct UsbStdDevDesc
*) ioreq
->iouh_Data
;
514 usdd
->bcdUSB
= AROS_WORD2LE(0x0200); // signal a highspeed root hub
515 usdd
->bDeviceProtocol
= 1; // single TT
517 #ifdef AROS_USB30_CODE
518 if(unit
->hu_RootHub30Ports
)
520 struct UsbStdDevDesc
*usdd
= (struct UsbStdDevDesc
*) ioreq
->iouh_Data
;
521 usdd
->bcdUSB
= AROS_WORD2LE(0x0300); // signal a superspeed root hub
522 usdd
->bDeviceProtocol
= 3;
528 case UDT_CONFIGURATION
:
531 KPRINTF(1, ("RH: GetConfigDescriptor (%ld)\n", len
));
532 CopyMem((APTR
) &RHCfgDesc
, tmpbuf
, 9);
533 CopyMem((APTR
) &RHIfDesc
, &tmpbuf
[9], 9);
534 CopyMem((APTR
) &RHEPDesc
, &tmpbuf
[9+9], 7);
535 if(unit
->hu_RootHub20Ports
)
537 struct UsbStdEPDesc
*usepd
= (struct UsbStdEPDesc
*) &tmpbuf
[9+9];
538 usepd
->bInterval
= 12; // 2048 µFrames
540 ioreq
->iouh_Actual
= (len
> 9+9+7) ? 9+9+7 : len
;
541 CopyMem(tmpbuf
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
546 if(val
& 0xff) /* get lang array */
548 CONST_STRPTR source
= NULL
;
549 UWORD
*mptr
= ioreq
->iouh_Data
;
551 KPRINTF(1, ("RH: GetString %04lx (%ld)\n", val
, len
));
552 if((val
& 0xff) > 4) /* index too high? */
554 return(UHIOERR_STALL
);
556 source
= RHStrings
[(val
& 0xff)-1];
559 ioreq
->iouh_Actual
= 2;
564 source
= RHStrings
[(val
& 0xff)-1];
565 *mptr
++ = AROS_WORD2BE((slen
<<9)|UDT_STRING
);
566 while(ioreq
->iouh_Actual
+1 < len
)
568 // special hack for unit number in root hub string
569 if(((val
& 0xff) == 2) && (source
[1] == 0))
571 *mptr
++ = AROS_WORD2LE('0' + unit
->hu_UnitNo
);
573 *mptr
++ = AROS_WORD2LE(*source
);
576 ioreq
->iouh_Actual
+= 2;
584 UWORD
*mptr
= ioreq
->iouh_Data
;
585 KPRINTF(1, ("RH: GetLangArray %04lx (%ld)\n", val
, len
));
588 ioreq
->iouh_Actual
= 2;
589 mptr
[0] = AROS_WORD2BE((4<<8)|UDT_STRING
);
592 ioreq
->iouh_Actual
+= 2;
593 mptr
[1] = AROS_WORD2LE(0x0409);
600 KPRINTF(1, ("RH: Unsupported Descriptor %04lx\n", idx
));
604 case USR_GET_CONFIGURATION
:
607 KPRINTF(1, ("RH: GetConfiguration\n"));
608 ((UBYTE
*) ioreq
->iouh_Data
)[0] = 1;
609 ioreq
->iouh_Actual
= len
;
616 case (URTF_CLASS
|URTF_OTHER
):
619 case USR_SET_FEATURE
:
620 if((!idx
) && (idx
> numports
))
622 KPRINTF(20, ("Port %ld out of range\n", idx
));
623 return(UHIOERR_STALL
);
625 chc
= unit
->hu_PortMap11
[idx
- 1];
626 if(unit
->hu_EhciOwned
[idx
- 1])
628 hc
= unit
->hu_PortMap20
[idx
- 1];
632 hciport
= unit
->hu_PortNum11
[idx
- 1];
634 KPRINTF(10, ("Set Feature %ld maps from glob. Port %ld to local Port %ld (%s)\n", val
, idx
, hciport
, unit
->hu_EhciOwned
[idx
- 1] ? "EHCI" : "U/OHCI"));
636 switch(hc
->hc_HCIType
)
640 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
641 ULONG oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
); // these are clear-on-write!
642 ULONG newval
= oldval
;
645 /* case UFS_PORT_CONNECTION: not possible */
646 case UFS_PORT_ENABLE
:
647 KPRINTF(10, ("Enabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "already" : "ok"));
648 newval
|= UHPF_PORTENABLE
;
652 case UFS_PORT_SUSPEND
:
653 newval
|= UHPF_PORTSUSPEND
;
654 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
; // manually fake suspend change
658 /* case UFS_PORT_OVER_CURRENT: not possible */
660 KPRINTF(10, ("Resetting Port (%s)\n", newval
& UHPF_PORTRESET
? "already" : "ok"));
662 // this is an ugly blocking workaround to the inability of UHCI to clear reset automatically
663 newval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
664 newval
|= UHPF_PORTRESET
;
665 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
666 uhwDelayMS(25, unit
);
667 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
668 KPRINTF(10, ("Reset=%s\n", newval
& UHPF_PORTRESET
? "GOOD" : "BAD!"));
669 // like windows does it
670 newval
&= ~UHPF_PORTRESET
;
671 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
672 uhwDelayMicro(50, unit
);
673 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
674 KPRINTF(10, ("Reset=%s\n", newval
& UHPF_PORTRESET
? "BAD!" : "GOOD"));
675 newval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTRESET
);
676 newval
|= UHPF_PORTENABLE
;
677 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
678 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
|UPSF_PORT_ENABLE
; // manually fake reset change
684 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
);
685 } while(--cnt
&& (!(newval
& UHPF_PORTENABLE
)));
688 KPRINTF(10, ("Enabled after %ld ticks\n", 100-cnt
));
690 KPRINTF(20, ("Port refuses to be enabled!\n"));
691 return(UHIOERR_HOSTERROR
);
693 // make enumeration possible
694 unit
->hu_DevControllers
[0] = hc
;
699 KPRINTF(10, ("Powering Port\n"));
700 // ignore for UHCI, is always powered
704 /* case UFS_PORT_LOW_SPEED: not possible */
705 /* case UFS_C_PORT_CONNECTION:
706 case UFS_C_PORT_ENABLE:
707 case UFS_C_PORT_SUSPEND:
708 case UFS_C_PORT_OVER_CURRENT:
709 case UFS_C_PORT_RESET: */
713 KPRINTF(5, ("Port %ld SET_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
714 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
722 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
723 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
727 /* case UFS_PORT_CONNECTION: not possible */
728 case UFS_PORT_ENABLE
:
729 KPRINTF(10, ("Enabling Port (%s)\n", oldval
& OHPF_PORTENABLE
? "already" : "ok"));
730 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTENABLE
);
734 case UFS_PORT_SUSPEND
:
735 KPRINTF(10, ("Suspending Port (%s)\n", oldval
& OHPF_PORTSUSPEND
? "already" : "ok"));
736 //hc->hc_PortChangeMap[hciport] |= UPSF_PORT_SUSPEND; // manually fake suspend change
737 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTSUSPEND
);
741 /* case UFS_PORT_OVER_CURRENT: not possible */
743 KPRINTF(10, ("Resetting Port (%s)\n", oldval
& OHPF_PORTRESET
? "already" : "ok"));
744 // make sure we have at least 50ms of reset time here, as required for a root hub port
745 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
746 uhwDelayMS(10, unit
);
747 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
748 uhwDelayMS(10, unit
);
749 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
750 uhwDelayMS(10, unit
);
751 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
752 uhwDelayMS(10, unit
);
753 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
754 uhwDelayMS(15, unit
);
755 oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
756 KPRINTF(10, ("OHCI Reset release (%s %s)\n", oldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
757 oldval
& OHPF_PORTENABLE
? "enabled" : "not enabled"));
758 if(oldval
& OHPF_PORTRESET
)
760 uhwDelayMS(40, unit
);
761 oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
762 KPRINTF(10, ("OHCI Reset 2nd release (%s %s)\n", oldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
763 oldval
& OHPF_PORTENABLE
? "enabled" : "still not enabled"));
765 // make enumeration possible
766 unit
->hu_DevControllers
[0] = hc
;
771 KPRINTF(10, ("Powering Port (%s)\n", oldval
& OHPF_PORTPOWER
? "already" : "ok"));
772 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTPOWER
);
776 /* case UFS_PORT_LOW_SPEED: not possible */
777 /* case UFS_C_PORT_CONNECTION:
778 case UFS_C_PORT_ENABLE:
779 case UFS_C_PORT_SUSPEND:
780 case UFS_C_PORT_OVER_CURRENT:
781 case UFS_C_PORT_RESET: */
792 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
793 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
); // these are clear-on-write!
794 ULONG newval
= oldval
;
797 /* case UFS_PORT_CONNECTION: not possible */
798 case UFS_PORT_ENABLE
:
799 KPRINTF(10, ("Enabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "already" : "ok"));
800 newval
|= EHPF_PORTENABLE
;
804 case UFS_PORT_SUSPEND
:
805 newval
|= EHPF_PORTSUSPEND
;
806 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
; // manually fake suspend change
810 /* case UFS_PORT_OVER_CURRENT: not possible */
812 KPRINTF(10, ("Resetting Port (%s)\n", newval
& EHPF_PORTRESET
? "already" : "ok"));
814 // this is an ugly blocking workaround to the inability of EHCI to clear reset automatically
815 newval
&= ~(EHPF_PORTSUSPEND
|EHPF_PORTENABLE
);
816 newval
|= EHPF_PORTRESET
;
817 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
818 uhwDelayMS(50, unit
);
819 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
|EHPF_PORTENABLE
);
820 KPRINTF(10, ("Reset=%s\n", newval
& EHPF_PORTRESET
? "GOOD" : "BAD!"));
821 newval
&= ~EHPF_PORTRESET
;
822 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
823 uhwDelayMS(10, unit
);
824 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
);
825 KPRINTF(10, ("Reset=%s\n", newval
& EHPF_PORTRESET
? "BAD!" : "GOOD"));
826 KPRINTF(10, ("Highspeed=%s\n", newval
& EHPF_PORTENABLE
? "YES!" : "NO"));
827 KPRINTF(10, ("EHCI Port status=%08lx\n", newval
));
828 if(!(newval
& EHPF_PORTENABLE
))
830 // if not highspeed, release ownership
831 KPRINTF(20, ("Transferring ownership to UHCI/OHCI port %ld\n", unit
->hu_PortNum11
[idx
- 1]));
832 KPRINTF(10, ("Device is %s\n", newval
& EHPF_LINESTATUS_DM
? "LOWSPEED" : "FULLSPEED"));
833 newval
|= EHPF_NOTPORTOWNER
;
836 KPRINTF(20, ("EHCI has no companion controller, can't transfer ownership!\n"));
837 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
838 return(UHIOERR_HOSTERROR
);
840 switch(chc
->hc_HCIType
)
844 UWORD uhcihciport
= unit
->hu_PortNum11
[idx
- 1];
845 UWORD uhciportreg
= uhcihciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
846 ULONG __unused uhcinewval
= READREG16_LE(chc
->hc_RegBase
, uhciportreg
);
848 KPRINTF(10, ("UHCI Port status before handover=%04lx\n", uhcinewval
));
854 UWORD ohcihciport
= unit
->hu_PortNum11
[idx
- 1];
855 UWORD ohciportreg
= OHCI_PORTSTATUS
+ (ohcihciport
<<2);
856 ULONG __unused ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
858 KPRINTF(10, ("OHCI Port status before handover=%08lx\n", ohcioldval
));
859 KPRINTF(10, ("Powering Port (%s)\n", ohcioldval
& OHPF_PORTPOWER
? "already" : "ok"));
860 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTPOWER
);
861 uhwDelayMS(10, unit
);
862 KPRINTF(10, ("OHCI Port status after handover=%08lx\n", READREG32_LE(chc
->hc_RegBase
, ohciportreg
)));
866 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
);
867 KPRINTF(10, ("EHCI Port status (reread)=%08lx\n", newval
));
868 newval
|= EHPF_NOTPORTOWNER
;
869 unit
->hu_EhciOwned
[idx
- 1] = FALSE
;
870 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
871 uhwDelayMS(90, unit
);
872 KPRINTF(10, ("EHCI Port status (after handover)=%08lx\n", READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
)));
873 // enable companion controller port
874 switch(chc
->hc_HCIType
)
878 UWORD uhcihciport
= unit
->hu_PortNum11
[idx
- 1];
879 UWORD uhciportreg
= uhcihciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
882 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
883 KPRINTF(10, ("UHCI Reset=%s\n", uhcinewval
& UHPF_PORTRESET
? "BAD!" : "GOOD"));
884 if((uhcinewval
& UHPF_PORTRESET
))//|| (newval & EHPF_LINESTATUS_DM))
886 // this is an ugly blocking workaround to the inability of UHCI to clear reset automatically
887 KPRINTF(20, ("Uhm, UHCI reset was bad!\n"));
888 uhcinewval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
889 uhcinewval
|= UHPF_PORTRESET
;
890 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
891 uhwDelayMS(50, unit
);
892 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
893 KPRINTF(10, ("ReReset=%s\n", uhcinewval
& UHPF_PORTRESET
? "GOOD" : "BAD!"));
894 uhcinewval
&= ~UHPF_PORTRESET
;
895 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
896 uhwDelayMicro(50, unit
);
897 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
898 KPRINTF(10, ("ReReset=%s\n", uhcinewval
& UHPF_PORTRESET
? "STILL BAD!" : "GOOD"));
900 uhcinewval
&= ~UHPF_PORTRESET
;
901 uhcinewval
|= UHPF_PORTENABLE
;
902 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
903 chc
->hc_PortChangeMap
[uhcihciport
] |= UPSF_PORT_RESET
|UPSF_PORT_ENABLE
; // manually fake reset change
909 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
);
910 } while(--cnt
&& (!(uhcinewval
& UHPF_PORTENABLE
)));
913 KPRINTF(10, ("Enabled after %ld ticks\n", 100-cnt
));
915 KPRINTF(20, ("Port refuses to be enabled!\n"));
916 return(UHIOERR_HOSTERROR
);
923 UWORD ohcihciport
= unit
->hu_PortNum11
[idx
- 1];
924 UWORD ohciportreg
= OHCI_PORTSTATUS
+ (ohcihciport
<<2);
925 ULONG ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
926 KPRINTF(10, ("OHCI Resetting Port (%s)\n", ohcioldval
& OHPF_PORTRESET
? "already" : "ok"));
927 // make sure we have at least 50ms of reset time here, as required for a root hub port
928 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
929 uhwDelayMS(10, unit
);
930 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
931 uhwDelayMS(10, unit
);
932 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
933 uhwDelayMS(10, unit
);
934 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
935 uhwDelayMS(10, unit
);
936 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
937 uhwDelayMS(15, unit
);
938 ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
939 KPRINTF(10, ("OHCI Reset release (%s %s)\n", ohcioldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
940 ohcioldval
& OHPF_PORTENABLE
? "enabled" : "not enabled"));
941 if(ohcioldval
& OHPF_PORTRESET
)
943 uhwDelayMS(40, unit
);
944 ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
945 KPRINTF(10, ("OHCI Reset 2nd release (%s %s)\n", ohcioldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
946 ohcioldval
& OHPF_PORTENABLE
? "enabled" : "still not enabled"));
952 // make enumeration possible
953 unit
->hu_DevControllers
[0] = chc
;
956 newval
&= ~EHPF_PORTRESET
;
957 WRITEREG16_LE(hc
->hc_RegBase
, portreg
, newval
);
958 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
; // manually fake reset change
959 uhwDelayMS(10, unit
);
964 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
965 } while(--cnt
&& (!(newval
& EHPF_PORTENABLE
)));
968 KPRINTF(10, ("Enabled after %ld ticks\n", 100-cnt
));
970 KPRINTF(20, ("Port refuses to be enabled!\n"));
971 return(UHIOERR_HOSTERROR
);
973 // make enumeration possible
974 unit
->hu_DevControllers
[0] = hc
;
980 KPRINTF(10, ("Powering Port\n"));
981 newval
|= EHPF_PORTPOWER
;
985 /* case UFS_PORT_LOW_SPEED: not possible */
986 /* case UFS_C_PORT_CONNECTION:
987 case UFS_C_PORT_ENABLE:
988 case UFS_C_PORT_SUSPEND:
989 case UFS_C_PORT_OVER_CURRENT:
990 case UFS_C_PORT_RESET: */
994 KPRINTF(5, ("Port %ld SET_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
995 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
1001 #ifdef AROS_USB30_CODE
1002 /* (URTF_CLASS|URTF_OTHER) USR_SET_FEATURE */
1008 KPRINTF(1000, ("XHCI (URTF_CLASS|URTF_OTHER) USR_SET_FEATURE\n"));
1018 case USR_CLEAR_FEATURE
:
1019 if((!idx
) && (idx
> numports
))
1021 KPRINTF(20, ("Port %ld out of range\n", idx
));
1022 return(UHIOERR_STALL
);
1024 if(unit
->hu_EhciOwned
[idx
- 1])
1026 hc
= unit
->hu_PortMap20
[idx
- 1];
1029 hc
= unit
->hu_PortMap11
[idx
- 1];
1030 hciport
= unit
->hu_PortNum11
[idx
- 1];
1032 KPRINTF(10, ("Clear Feature %ld maps from glob. Port %ld to local Port %ld (%s)\n", val
, idx
, hciport
, unit
->hu_EhciOwned
[idx
- 1] ? "EHCI" : "U/OHCI"));
1034 switch(hc
->hc_HCIType
)
1038 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
1039 ULONG oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
); // these are clear-on-write!
1040 ULONG newval
= oldval
;
1043 case UFS_PORT_ENABLE
:
1044 KPRINTF(10, ("Disabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "ok" : "already"));
1045 newval
&= ~UHPF_PORTENABLE
;
1047 // disable enumeration
1048 unit
->hu_DevControllers
[0] = NULL
;
1051 case UFS_PORT_SUSPEND
:
1052 newval
&= ~UHPF_PORTSUSPEND
;
1056 case UFS_PORT_POWER
: // ignore for UHCI, there's no power control here
1057 KPRINTF(10, ("Disabling Power\n"));
1058 KPRINTF(10, ("Disabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "ok" : "already"));
1059 newval
&= ~UHPF_PORTENABLE
;
1063 case UFS_C_PORT_CONNECTION
:
1064 newval
|= UHPF_CONNECTCHANGE
; // clear-on-write!
1065 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1069 case UFS_C_PORT_ENABLE
:
1070 newval
|= UHPF_ENABLECHANGE
; // clear-on-write!
1071 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1075 case UFS_C_PORT_SUSPEND
: // ignore for UHCI, there's no bit indicating this
1076 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
; // manually fake suspend change clearing
1080 case UFS_C_PORT_OVER_CURRENT
: // ignore for UHCI, there's no bit indicating this
1081 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
; // manually fake over current clearing
1085 case UFS_C_PORT_RESET
: // ignore for UHCI, there's no bit indicating this
1086 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
; // manually fake reset change clearing
1092 KPRINTF(5, ("Port %ld CLEAR_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
1093 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
1094 if(hc
->hc_PortChangeMap
[hciport
])
1096 unit
->hu_RootPortChanges
|= 1UL<<idx
;
1098 unit
->hu_RootPortChanges
&= ~(1UL<<idx
);
1107 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
1108 ULONG __unused oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1112 case UFS_PORT_ENABLE
:
1113 KPRINTF(10, ("Disabling Port (%s)\n", oldval
& OHPF_PORTENABLE
? "ok" : "already"));
1114 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTDISABLE
);
1118 case UFS_PORT_SUSPEND
:
1119 KPRINTF(10, ("Resuming Port (%s)\n", oldval
& OHPF_PORTSUSPEND
? "ok" : "already"));
1120 //hc->hc_PortChangeMap[hciport] &= ~UPSF_PORT_SUSPEND; // manually fake suspend change
1121 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESUME
);
1125 case UFS_PORT_POWER
:
1126 KPRINTF(10, ("Unpowering Port (%s)\n", oldval
& OHPF_PORTPOWER
? "ok" : "already"));
1127 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTUNPOWER
);
1131 case UFS_C_PORT_CONNECTION
:
1132 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_CONNECTCHANGE
);
1133 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1137 case UFS_C_PORT_ENABLE
:
1138 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_ENABLECHANGE
);
1139 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1143 case UFS_C_PORT_SUSPEND
:
1144 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESUMEDTX
);
1145 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
;
1149 case UFS_C_PORT_OVER_CURRENT
:
1150 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_OVERCURRENTCHG
);
1151 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
;
1155 case UFS_C_PORT_RESET
:
1156 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESETCHANGE
);
1157 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
;
1170 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
1171 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
); // these are clear-on-write!
1172 ULONG newval
= oldval
;
1175 case UFS_PORT_ENABLE
:
1176 KPRINTF(10, ("Disabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "ok" : "already"));
1177 newval
&= ~EHPF_PORTENABLE
;
1179 // disable enumeration
1180 unit
->hu_DevControllers
[0] = NULL
;
1183 case UFS_PORT_SUSPEND
:
1184 newval
&= ~EHPF_PORTSUSPEND
;
1188 case UFS_PORT_POWER
: // ignore for UHCI, there's no power control here
1189 KPRINTF(10, ("Disabling Power (%s)\n", newval
& EHPF_PORTPOWER
? "ok" : "already"));
1190 KPRINTF(10, ("Disabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "ok" : "already"));
1191 newval
&= ~(EHPF_PORTENABLE
|EHPF_PORTPOWER
);
1195 case UFS_C_PORT_CONNECTION
:
1196 newval
|= EHPF_CONNECTCHANGE
; // clear-on-write!
1197 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1201 case UFS_C_PORT_ENABLE
:
1202 newval
|= EHPF_ENABLECHANGE
; // clear-on-write!
1203 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1207 case UFS_C_PORT_SUSPEND
: // ignore for EHCI, there's no bit indicating this
1208 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
; // manually fake suspend change clearing
1212 case UFS_C_PORT_OVER_CURRENT
:
1213 newval
|= EHPF_OVERCURRENTCHG
; // clear-on-write!
1214 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
; // manually fake over current clearing
1218 case UFS_C_PORT_RESET
: // ignore for EHCI, there's no bit indicating this
1219 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
; // manually fake reset change clearing
1225 KPRINTF(5, ("Port %ld CLEAR_FEATURE %08lx->%08lx\n", idx
, oldval
, newval
));
1226 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
1227 if(hc
->hc_PortChangeMap
[hciport
])
1229 unit
->hu_RootPortChanges
|= 1UL<<idx
;
1231 unit
->hu_RootPortChanges
&= ~(1UL<<idx
);
1238 #ifdef AROS_USB30_CODE
1239 /* (URTF_CLASS|URTF_OTHER) USR_CLEAR_FEATURE */
1245 KPRINTF(1000, ("XHCI (URTF_CLASS|URTF_OTHER) USR_CLEAR_FEATURE\n"));
1257 case (URTF_IN
|URTF_CLASS
|URTF_OTHER
):
1260 case USR_GET_STATUS
:
1262 UWORD
*mptr
= ioreq
->iouh_Data
;
1263 if(len
!= sizeof(struct UsbPortStatus
))
1265 return(UHIOERR_STALL
);
1267 if((!idx
) && (idx
> numports
))
1269 KPRINTF(20, ("Port %ld out of range\n", idx
));
1270 return(UHIOERR_STALL
);
1272 if(unit
->hu_EhciOwned
[idx
- 1])
1274 hc
= unit
->hu_PortMap20
[idx
- 1];
1277 hc
= unit
->hu_PortMap11
[idx
- 1];
1278 hciport
= unit
->hu_PortNum11
[idx
- 1];
1280 switch(hc
->hc_HCIType
)
1284 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
1285 UWORD oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
);
1286 *mptr
= AROS_WORD2LE(UPSF_PORT_POWER
);
1287 if(oldval
& UHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1288 if(oldval
& UHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
);
1289 if(oldval
& UHPF_LOWSPEED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1290 if(oldval
& UHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1291 if(oldval
& UHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1293 KPRINTF(5, ("UHCI Port %ld is %s\n", idx
, oldval
& UHPF_LOWSPEED
? "LOWSPEED" : "FULLSPEED"));
1294 KPRINTF(5, ("UHCI Port %ld Status %08lx\n", idx
, *mptr
));
1297 if(oldval
& UHPF_ENABLECHANGE
)
1299 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1301 if(oldval
& UHPF_CONNECTCHANGE
)
1303 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1305 if(oldval
& UHPF_RESUMEDTX
)
1307 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
|UPSF_PORT_ENABLE
;
1309 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1310 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, oldval
);
1311 KPRINTF(5, ("UHCI Port %ld Change %08lx\n", idx
, *mptr
));
1317 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
1318 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1321 if(oldval
& OHPF_PORTPOWER
) *mptr
|= AROS_WORD2LE(UPSF_PORT_POWER
);
1322 if(oldval
& OHPF_OVERCURRENT
) *mptr
|= AROS_WORD2LE(UPSF_PORT_OVER_CURRENT
);
1323 if(oldval
& OHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1324 if(oldval
& OHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
);
1325 if(oldval
& OHPF_LOWSPEED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1326 if(oldval
& OHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1327 if(oldval
& OHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1329 KPRINTF(5, ("OHCI Port %ld (glob. %ld) is %s\n", hciport
, idx
, oldval
& OHPF_LOWSPEED
? "LOWSPEED" : "FULLSPEED"));
1330 KPRINTF(5, ("OHCI Port %ld Status %08lx (%08lx)\n", idx
, *mptr
, oldval
));
1333 if(oldval
& OHPF_OVERCURRENTCHG
)
1335 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_OVER_CURRENT
;
1337 if(oldval
& OHPF_RESETCHANGE
)
1339 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
;
1341 if(oldval
& OHPF_ENABLECHANGE
)
1343 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1345 if(oldval
& OHPF_CONNECTCHANGE
)
1347 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1349 if(oldval
& OHPF_RESUMEDTX
)
1351 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
;
1353 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1354 KPRINTF(5, ("OHCI Port %ld Change %08lx\n", idx
, *mptr
));
1360 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
1361 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1364 if(oldval
& EHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1365 if(oldval
& EHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
|UPSF_PORT_HIGH_SPEED
);
1366 if((oldval
& (EHPF_LINESTATUS_DM
|EHPF_PORTCONNECTED
|EHPF_PORTENABLE
)) ==
1367 (EHPF_LINESTATUS_DM
|EHPF_PORTCONNECTED
))
1369 KPRINTF(10, ("EHCI Port %ld is LOWSPEED\n", idx
));
1370 // we need to detect low speed devices prior to reset
1371 *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1374 if(oldval
& EHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1375 if(oldval
& EHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1376 if(oldval
& EHPF_PORTPOWER
) *mptr
|= AROS_WORD2LE(UPSF_PORT_POWER
);
1377 if(oldval
& EHPM_PORTINDICATOR
) *mptr
|= AROS_WORD2LE(UPSF_PORT_INDICATOR
);
1379 KPRINTF(5, ("EHCI Port %ld Status %08lx\n", idx
, *mptr
));
1382 if(oldval
& EHPF_ENABLECHANGE
)
1384 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1386 if(oldval
& EHPF_CONNECTCHANGE
)
1388 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1390 if(oldval
& EHPF_RESUMEDTX
)
1392 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
|UPSF_PORT_ENABLE
;
1394 if(oldval
& EHPF_OVERCURRENTCHG
)
1396 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_OVER_CURRENT
;
1398 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1399 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, oldval
);
1400 KPRINTF(5, ("EHCI Port %ld Change %08lx\n", idx
, *mptr
));
1404 #ifdef AROS_USB30_CODE
1405 /* (URTF_IN|URTF_CLASS|URTF_OTHER) USR_GET_STATUS */
1408 KPRINTF(1000, ("XHCI (URTF_IN|URTF_CLASS|URTF_OTHER) USR_GET_STATUS\n"));
1420 case (URTF_IN
|URTF_CLASS
|URTF_DEVICE
):
1423 case USR_GET_STATUS
:
1425 UWORD
*mptr
= ioreq
->iouh_Data
;
1426 if(len
< sizeof(struct UsbHubStatus
))
1428 return(UHIOERR_STALL
);
1432 ioreq
->iouh_Actual
= 4;
1436 case USR_GET_DESCRIPTOR
:
1439 //FIXME: Add USB3.0 hub descriptor support
1440 #ifdef AROS_USB30_CODE
1443 ULONG hubdesclen
= 12;
1445 struct UsbSSHubDesc
*uhd
= (struct UsbSSHubDesc
*) ioreq
->iouh_Data
;
1446 KPRINTF(1, ("RH: Get(SS)HubDescriptor (%ld)\n", len
));
1448 ioreq
->iouh_Actual
= (len
> hubdesclen
) ? hubdesclen
: len
;
1449 CopyMem((APTR
) &RHSSHubDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
1451 if(ioreq
->iouh_Length
)
1453 uhd
->bLength
= hubdesclen
;
1456 uhd
->bNbrPorts
= unit
->hu_RootHubPorts
;
1463 ULONG hubdesclen
= 9;
1464 ULONG powergood
= 1;
1466 struct UsbHubDesc
*uhd
= (struct UsbHubDesc
*) ioreq
->iouh_Data
;
1467 KPRINTF(1, ("RH: GetHubDescriptor (%ld)\n", len
));
1469 if(unit
->hu_RootHubPorts
> 7) // needs two bytes for port masks
1474 ioreq
->iouh_Actual
= (len
> hubdesclen
) ? hubdesclen
: len
;
1475 CopyMem((APTR
) &RHHubDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
1477 if(ioreq
->iouh_Length
)
1479 uhd
->bLength
= hubdesclen
;
1482 if(ioreq
->iouh_Length
>= 6)
1484 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1485 while(hc
->hc_Node
.ln_Succ
)
1487 if(hc
->hc_HCIType
== HCITYPE_OHCI
)
1489 ULONG localpwgood
= (READREG32_LE(hc
->hc_RegBase
, OHCI_HUBDESCA
) & OHAM_POWERGOOD
) >> OHAS_POWERGOOD
;
1490 if(localpwgood
> powergood
)
1492 powergood
= localpwgood
;
1493 KPRINTF(10, ("Increasing power good time to %ld\n", powergood
));
1496 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1499 uhd
->bPwrOn2PwrGood
= powergood
;
1501 if(ioreq
->iouh_Length
>= hubdesclen
)
1503 uhd
->bNbrPorts
= unit
->hu_RootHubPorts
;
1506 uhd
->DeviceRemovable
= 0;
1507 uhd
->PortPwrCtrlMask
= (1<<(unit
->hu_RootHubPorts
+2))-2;
1509 // each field is now 16 bits wide
1510 uhd
->DeviceRemovable
= 0;
1511 uhd
->PortPwrCtrlMask
= 0;
1512 ((UBYTE
*) ioreq
->iouh_Data
)[9] = (1<<(unit
->hu_RootHubPorts
+2))-2;
1513 ((UBYTE
*) ioreq
->iouh_Data
)[10] = ((1<<(unit
->hu_RootHubPorts
+2))-2)>>8;
1520 KPRINTF(20, ("RH: Unsupported Descriptor %04lx\n", idx
));
1526 KPRINTF(20, ("RH: Unsupported command %02lx %02lx %04lx %04lx %04lx!\n", rt
, req
, idx
, val
, len
));
1527 return(UHIOERR_STALL
);
1531 /* /// "cmdIntXFerRootHub()" */
1532 WORD
cmdIntXFerRootHub(struct IOUsbHWReq
*ioreq
,
1533 struct PCIUnit
*unit
,
1534 struct PCIDevice
*base
)
1536 if((ioreq
->iouh_Endpoint
!= 1) || (!ioreq
->iouh_Length
))
1538 return(UHIOERR_STALL
);
1541 if(unit
->hu_RootPortChanges
)
1543 KPRINTF(1, ("Immediate Portchange map %04lx\n", unit
->hu_RootPortChanges
));
1544 if((unit
->hu_RootHubPorts
< 8) || (ioreq
->iouh_Length
== 1))
1546 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->hu_RootPortChanges
;
1547 ioreq
->iouh_Actual
= 1;
1549 ((UBYTE
*) ioreq
->iouh_Data
)[0] = unit
->hu_RootPortChanges
;
1550 ((UBYTE
*) ioreq
->iouh_Data
)[1] = unit
->hu_RootPortChanges
>>8;
1551 ioreq
->iouh_Actual
= 2;
1553 unit
->hu_RootPortChanges
= 0;
1556 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1558 AddTail(&unit
->hu_RHIOQueue
, (struct Node
*) ioreq
);
1560 return(RC_DONTREPLY
);
1564 /* /// "cmdControlXFer()" */
1566 *======================================================================
1567 * cmdControlXFer(ioreq, unit, base)
1568 *======================================================================
1570 * This is the device UHCMD_CONTROLXFER routine.
1572 * First it check if the usb is in proper state and if user passed arguments
1573 * are valid. If everything is ok, the request is linked to queue of
1574 * pending transfer requests.
1578 WORD
cmdControlXFer(struct IOUsbHWReq
*ioreq
,
1579 struct PCIUnit
*unit
,
1580 struct PCIDevice
*base
)
1582 struct PCIController
*hc
;
1584 KPRINTF(10, ("UHCMD_CONTROLXFER ioreq: 0x%p\n", ioreq
));
1585 uhwGetUsbState(ioreq
, unit
, base
);
1586 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1588 return(UHIOERR_USBOFFLINE
);
1590 /* Root hub emulation */
1591 if(ioreq
->iouh_DevAddr
== unit
->hu_RootHubAddr
)
1593 return(cmdControlXFerRootHub(ioreq
, unit
, base
));
1596 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1599 KPRINTF(20, ("No Host controller assigned to device address %ld\n", ioreq
->iouh_DevAddr
));
1600 return(UHIOERR_HOSTERROR
);
1603 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1604 ioreq
->iouh_Actual
= 0;
1607 AddTail(&hc
->hc_CtrlXFerQueue
, (struct Node
*) ioreq
);
1609 SureCause(base
, &hc
->hc_CompleteInt
);
1611 KPRINTF(10, ("UHCMD_CONTROLXFER processed ioreq: 0x%p\n", ioreq
));
1612 return(RC_DONTREPLY
);
1616 /* /// "cmdBulkXFer()" */
1618 *======================================================================
1619 * cmdBulkXFer(ioreq, unit, base)
1620 *======================================================================
1622 * This is the device UHCMD_BULKXFER routine.
1624 * First it check if the usb is in proper state and if user passed arguments
1625 * are valid. If everything is ok, the request is linked to queue of
1626 * pending transfer requests.
1630 WORD
cmdBulkXFer(struct IOUsbHWReq
*ioreq
,
1631 struct PCIUnit
*unit
,
1632 struct PCIDevice
*base
)
1634 struct PCIController
*hc
;
1636 KPRINTF(10, ("UHCMD_BULKXFER ioreq: 0x%p\n", ioreq
));
1637 uhwGetUsbState(ioreq
, unit
, base
);
1638 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1640 return(UHIOERR_USBOFFLINE
);
1643 if(ioreq
->iouh_Flags
& UHFF_LOWSPEED
)
1645 return(UHIOERR_BADPARAMS
);
1648 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1651 return(UHIOERR_HOSTERROR
);
1654 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1655 ioreq
->iouh_Actual
= 0;
1658 AddTail(&hc
->hc_BulkXFerQueue
, (struct Node
*) ioreq
);
1660 SureCause(base
, &hc
->hc_CompleteInt
);
1662 KPRINTF(10, ("UHCMD_BULKXFER processed ioreq: 0x%p\n", ioreq
));
1663 return(RC_DONTREPLY
);
1667 /* /// "cmdIsoXFer()" */
1669 *======================================================================
1670 * cmdIsoXFer(ioreq, unit, base)
1671 *======================================================================
1673 * This is the device UHCMD_ISOXFER routine.
1675 * First it check if the usb is in proper state and if user passed arguments
1676 * are valid. If everything is ok, the request is linked to queue of
1677 * pending transfer requests.
1681 WORD
cmdIsoXFer(struct IOUsbHWReq
*ioreq
,
1682 struct PCIUnit
*unit
,
1683 struct PCIDevice
*base
)
1685 struct PCIController
*hc
;
1687 KPRINTF(10, ("UHCMD_ISOXFER ioreq: 0x%p\n", ioreq
));
1688 uhwGetUsbState(ioreq
, unit
, base
);
1689 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1691 return(UHIOERR_USBOFFLINE
);
1694 if(ioreq
->iouh_Flags
& UHFF_LOWSPEED
)
1696 return(UHIOERR_BADPARAMS
);
1699 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1702 return(UHIOERR_HOSTERROR
);
1705 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1706 ioreq
->iouh_Actual
= 0;
1709 AddTail(&hc
->hc_IsoXFerQueue
, (struct Node
*) ioreq
);
1711 SureCause(base
, &hc
->hc_CompleteInt
);
1713 KPRINTF(10, ("UHCMD_ISOXFER processed ioreq: 0x%p\n", ioreq
));
1714 return(RC_DONTREPLY
);
1718 /* /// "cmdIntXFer()" */
1720 *======================================================================
1721 * cmdIntXFer(ioreq, unit, base)
1722 *======================================================================
1724 * This is the device UHCMD_INTXFER routine.
1726 * First it check if the usb is in proper state and if user passed arguments
1727 * are valid. If everything is ok, the request is linked to queue of
1728 * pending transfer requests.
1732 WORD
cmdIntXFer(struct IOUsbHWReq
*ioreq
,
1733 struct PCIUnit
*unit
,
1734 struct PCIDevice
*base
)
1736 struct PCIController
*hc
;
1738 KPRINTF(10, ("UHCMD_INTXFER ioreq: 0x%p\n", ioreq
));
1739 //uhwDelayMS(1000, unit); /* Wait 200 ms */
1740 uhwGetUsbState(ioreq
, unit
, base
);
1741 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1743 return(UHIOERR_USBOFFLINE
);
1746 /* Root Hub Emulation */
1747 if(ioreq
->iouh_DevAddr
== unit
->hu_RootHubAddr
)
1749 return(cmdIntXFerRootHub(ioreq
, unit
, base
));
1752 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1755 return(UHIOERR_HOSTERROR
);
1758 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1759 ioreq
->iouh_Actual
= 0;
1762 AddTail(&hc
->hc_IntXFerQueue
, (struct Node
*) ioreq
);
1764 SureCause(base
, &hc
->hc_CompleteInt
);
1766 KPRINTF(10, ("UHCMD_INTXFER processed ioreq: 0x%p\n", ioreq
));
1767 return(RC_DONTREPLY
);
1771 /* /// "cmdFlush()" */
1773 *======================================================================
1774 * cmdFlush(ioreq, base)
1775 *======================================================================
1777 * This is the device CMD_FLUSH routine.
1779 * This routine abort all pending transfer requests.
1783 WORD
cmdFlush(struct IOUsbHWReq
*ioreq
,
1784 struct PCIUnit
*unit
,
1785 struct PCIDevice
*base
)
1787 struct IOUsbHWReq
*cmpioreq
;
1788 struct PCIController
*hc
;
1791 KPRINTF(10, ("CMD_FLUSH ioreq: 0x%p\n", ioreq
));
1794 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1795 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1797 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1798 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1799 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1800 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1802 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1803 while(hc
->hc_Node
.ln_Succ
)
1805 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1806 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1808 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1809 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1810 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1811 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1813 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1814 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1816 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1817 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1818 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1819 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1821 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1822 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1824 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1825 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1826 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1827 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1829 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1830 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1832 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1833 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1834 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1835 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1837 switch(hc
->hc_HCIType
)
1840 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1841 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1843 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1844 devadrep
= (cmpioreq
->iouh_DevAddr
<<5) + cmpioreq
->iouh_Endpoint
+ ((cmpioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
1845 unit
->hu_DevBusyReq
[devadrep
] = NULL
;
1846 uhciFreeQContext(hc
, (struct UhciQH
*) cmpioreq
->iouh_DriverPrivate1
);
1847 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1848 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1849 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1854 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1855 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1857 ehciFreeAsyncContext(hc
, cmpioreq
);
1858 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1859 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1860 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1862 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
1863 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1865 ehciFreePeriodicContext(hc
, cmpioreq
);
1866 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1867 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1868 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
1871 #ifdef AROS_USB30_CODE
1873 KPRINTF(1000, ("XHCI cmdFlush\n"));
1877 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1886 /* /// "NSD stuff" */
1889 const UWORD NSDSupported
[] =
1891 CMD_FLUSH
, CMD_RESET
,
1892 UHCMD_QUERYDEVICE
, UHCMD_USBRESET
,
1893 UHCMD_USBRESUME
, UHCMD_USBSUSPEND
,
1894 UHCMD_USBOPER
, UHCMD_CONTROLXFER
,
1895 UHCMD_ISOXFER
, UHCMD_INTXFER
,
1897 NSCMD_DEVICEQUERY
, 0
1900 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
1901 struct PCIUnit
*unit
,
1902 struct PCIDevice
*base
)
1904 struct my_NSDeviceQueryResult
*query
;
1906 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
1908 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%p query: 0x%p\n", ioreq
, query
));
1915 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
1916 (query
->DevQueryFormat
!= 0) ||
1917 (query
->SizeAvailable
!= 0))
1919 /* Return error. This is special handling, since iorequest is only
1920 guaranteed to be sizeof(struct IOStdReq). If we'd let our
1921 devBeginIO dispatcher return the error, it would trash some
1922 memory past end of the iorequest (ios2_WireError field).
1924 ioreq
->io_Error
= IOERR_NOCMD
;
1925 TermIO((struct IOUsbHWReq
*) ioreq
, base
);
1927 /* Don't reply, we already did.
1929 return RC_DONTREPLY
;
1932 ioreq
->io_Actual
= query
->SizeAvailable
1933 = sizeof(struct my_NSDeviceQueryResult
);
1934 query
->DeviceType
= NSDEVTYPE_USBHARDWARE
;
1935 query
->DeviceSubType
= 0;
1936 query
->SupportedCommands
= NSDSupported
;
1938 /* Return success (note that this will NOT poke ios2_WireError).
1944 /* /// "TermIO()" */
1946 *===========================================================
1947 * TermIO(ioreq, base)
1948 *===========================================================
1950 * Return completed ioreq to sender.
1954 void TermIO(struct IOUsbHWReq
*ioreq
,
1955 struct PCIDevice
*base
)
1957 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1959 /* If not quick I/O, reply the message
1961 if(!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
))
1963 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
1968 /* /// "cmdAbortIO()" */
1969 BOOL
cmdAbortIO(struct IOUsbHWReq
*ioreq
, struct PCIDevice
*base
)
1971 struct PCIUnit
*unit
= (struct PCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
1972 struct IOUsbHWReq
*cmpioreq
;
1973 struct PCIController
*hc
;
1975 BOOL foundit
= FALSE
;
1977 KPRINTF(10, ("cmdAbort(%p)\n", ioreq
));
1980 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1981 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1983 if(ioreq
== cmpioreq
)
1985 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
1989 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1992 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1993 while(hc
->hc_Node
.ln_Succ
)
1995 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1996 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1998 if(ioreq
== cmpioreq
)
2003 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2007 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
2008 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2010 if(ioreq
== cmpioreq
)
2015 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2020 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
2021 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2023 if(ioreq
== cmpioreq
)
2028 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2033 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
2034 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2036 if(ioreq
== cmpioreq
)
2041 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2046 // IOReq is probably pending in some transfer structure
2047 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2048 switch(hc
->hc_HCIType
)
2051 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2052 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2054 if(ioreq
== cmpioreq
)
2057 unit
->hu_DevBusyReq
[devadrep
] = NULL
;
2058 uhciFreeQContext(hc
, (struct UhciQH
*) ioreq
->iouh_DriverPrivate1
);
2061 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2066 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2067 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2069 if(ioreq
== cmpioreq
)
2072 * Request's ED is in use by the HC, as well as its TDs and
2074 * Schedule abort on the HC driver and reply the request
2075 * only when done. However return success.
2077 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2078 ohciAbortRequest(hc
, ioreq
);
2082 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2087 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2088 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2090 if(ioreq
== cmpioreq
)
2093 * CHECKME: Perhaps immediate freeing can cause issues similar to OHCI.
2094 * Should synchronized abort routine be implemented here too ?
2096 ehciFreeAsyncContext(hc
, ioreq
);
2098 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2099 TermIO(ioreq
, base
);
2102 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2104 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
2105 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2107 if(ioreq
== cmpioreq
)
2109 ehciFreePeriodicContext(hc
, ioreq
);
2111 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2112 TermIO(ioreq
, base
);
2115 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2119 #ifdef AROS_USB30_CODE
2121 KPRINTF(1000, ("XHCI cmdAbortIO\n"));
2129 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
2132 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2138 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2139 TermIO(ioreq
, base
);
2143 KPRINTF(20, ("WARNING, could not abort unknown IOReq %p\n", ioreq
));
2149 /* /// "uhwCheckRootHubChanges()" */
2150 void uhwCheckRootHubChanges(struct PCIUnit
*unit
)
2152 struct IOUsbHWReq
*ioreq
;
2154 if(unit
->hu_RootPortChanges
&& unit
->hu_RHIOQueue
.lh_Head
->ln_Succ
)
2156 KPRINTF(1, ("Portchange map %04lx\n", unit
->hu_RootPortChanges
));
2158 ioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
2159 while(((struct Node
*) ioreq
)->ln_Succ
)
2161 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
2162 if((unit
->hu_RootHubPorts
< 8) || (ioreq
->iouh_Length
== 1))
2164 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->hu_RootPortChanges
;
2165 ioreq
->iouh_Actual
= 1;
2167 ((UBYTE
*) ioreq
->iouh_Data
)[0] = unit
->hu_RootPortChanges
;
2168 ((UBYTE
*) ioreq
->iouh_Data
)[1] = unit
->hu_RootPortChanges
>>8;
2169 ioreq
->iouh_Actual
= 2;
2171 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
2172 ioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
2174 unit
->hu_RootPortChanges
= 0;
2180 /* /// "uhwCheckSpecialCtrlTransfers()" */
2181 void uhwCheckSpecialCtrlTransfers(struct PCIController
*hc
, struct IOUsbHWReq
*ioreq
)
2183 struct PCIUnit
*unit
= hc
->hc_Unit
;
2185 /* Clear Feature(Endpoint halt) */
2186 if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_STANDARD
|URTF_ENDPOINT
)) &&
2187 (ioreq
->iouh_SetupData
.bRequest
== USR_CLEAR_FEATURE
) &&
2188 (ioreq
->iouh_SetupData
.wValue
== AROS_WORD2LE(UFS_ENDPOINT_HALT
)))
2190 KPRINTF(10, ("Resetting toggle bit for endpoint %ld\n", AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0xf));
2191 unit
->hu_DevDataToggle
[(ioreq
->iouh_DevAddr
<<5)|(AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0xf)|((AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0x80)>>3)] = 0;
2193 else if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_STANDARD
|URTF_DEVICE
)) &&
2194 (ioreq
->iouh_SetupData
.bRequest
== USR_SET_ADDRESS
))
2196 /* Set Address -> clear all endpoints */
2198 ULONG adr
= AROS_WORD2BE(ioreq
->iouh_SetupData
.wValue
)>>3;
2199 KPRINTF(10, ("Resetting toggle bits for device address %ld\n", adr
>>5));
2200 for(epnum
= 0; epnum
< 31; epnum
++)
2202 unit
->hu_DevDataToggle
[adr
+epnum
] = 0;
2204 // transfer host controller ownership
2205 unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
] = NULL
;
2206 unit
->hu_DevControllers
[adr
>>5] = hc
;
2208 else if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_CLASS
|URTF_OTHER
)) &&
2209 (ioreq
->iouh_SetupData
.bRequest
== USR_SET_FEATURE
) &&
2210 (ioreq
->iouh_SetupData
.wValue
== AROS_WORD2LE(UFS_PORT_RESET
)))
2212 // a hub will be enumerating a device on this host controller soon!
2213 KPRINTF(10, ("Hub RESET caught, assigning Dev0 to %p!\n", hc
));
2214 unit
->hu_DevControllers
[0] = hc
;
2219 /* /// "uhwNakTimeoutInt()" */
2220 AROS_UFH1(void, uhwNakTimeoutInt
,
2221 AROS_UFHA(struct PCIUnit
*, unit
, A1
))
2225 struct PCIDevice
*base
= unit
->hu_Device
;
2226 struct PCIController
*hc
;
2227 struct IOUsbHWReq
*ioreq
;
2237 KPRINTF(1, ("Enter NakTimeoutInt(0x%p)\n", unit
));
2239 // check for port status change for UHCI and frame rollovers and NAK Timeouts
2240 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
2241 while(hc
->hc_Node
.ln_Succ
)
2243 if (!(hc
->hc_Flags
& HCF_ONLINE
))
2245 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2249 switch(hc
->hc_HCIType
)
2254 uhciUpdateFrameCounter(hc
);
2255 framecnt
= hc
->hc_FrameCounter
;
2258 ioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2259 while(((struct Node
*) ioreq
)->ln_Succ
)
2261 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2263 uqh
= (struct UhciQH
*) ioreq
->iouh_DriverPrivate1
;
2266 KPRINTF(1, ("Examining IOReq=%p with UQH=%p\n", ioreq
, uqh
));
2267 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2268 linkelem
= READMEM32_LE(&uqh
->uqh_Element
);
2269 if(linkelem
& UHCI_TERMINATE
)
2271 KPRINTF(1, ("UQH terminated %08lx\n", linkelem
));
2272 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2274 // give the thing the chance to exit gracefully
2275 KPRINTF(20, ("Terminated? NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2279 utd
= (struct UhciTD
*) (((IPTR
)linkelem
& UHCI_PTRMASK
) - hc
->hc_PCIVirtualAdjust
- 16); // struct UhciTD starts 16 before physical TD
2280 ctrlstatus
= READMEM32_LE(&utd
->utd_CtrlStatus
);
2281 if(ctrlstatus
& UTCF_ACTIVE
)
2283 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2285 // give the thing the chance to exit gracefully
2286 KPRINTF(20, ("NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2287 ctrlstatus
&= ~UTCF_ACTIVE
;
2288 WRITEMEM32_LE(&utd
->utd_CtrlStatus
, ctrlstatus
);
2292 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2294 // give the thing the chance to exit gracefully
2295 KPRINTF(20, ("Terminated? NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2302 ioreq
= (struct IOUsbHWReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
2305 uhciCheckPortStatusChange(hc
);
2312 ohciUpdateFrameCounter(hc
);
2313 framecnt
= hc
->hc_FrameCounter
;
2315 ioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2316 while(((struct Node
*) ioreq
)->ln_Succ
)
2318 // Remember the successor because ohciAbortRequest() will move the request to another list
2319 struct IOUsbHWReq
*succ
= (struct IOUsbHWReq
*)ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2321 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2323 KPRINTF(1, ("Examining IOReq=%p with OED=%p\n", ioreq
, ioreq
->iouh_DriverPrivate1
));
2324 if (ioreq
->iouh_DriverPrivate1
)
2326 KPRINTF(1, ("CTRL=%04lx, CMD=%01lx, F=%ld, hccaDH=%08lx, hcDH=%08lx, CH=%08lx, CCH=%08lx, IntEn=%08lx\n",
2327 READREG32_LE(hc
->hc_RegBase
, OHCI_CONTROL
),
2328 READREG32_LE(hc
->hc_RegBase
, OHCI_CMDSTATUS
),
2329 READREG32_LE(hc
->hc_RegBase
, OHCI_FRAMECOUNT
),
2330 READMEM32_LE(&hc
->hc_OhciHCCA
->oha_DoneHead
),
2331 READREG32_LE(hc
->hc_RegBase
, OHCI_DONEHEAD
),
2332 READREG32_LE(hc
->hc_RegBase
, OHCI_CTRL_HEAD_ED
),
2333 READREG32_LE(hc
->hc_RegBase
, OHCI_CTRL_ED
),
2334 READREG32_LE(hc
->hc_RegBase
, OHCI_INTEN
)));
2336 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2337 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2339 // give the thing the chance to exit gracefully
2340 KPRINTF(200, ("HC 0x%p NAK timeout %ld > %ld, IOReq=%p\n", hc
, framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2341 ioreq
->iouh_Req
.io_Error
= UHIOERR_NAKTIMEOUT
;
2342 ohciAbortRequest(hc
, ioreq
);
2354 ehciUpdateFrameCounter(hc
);
2355 framecnt
= hc
->hc_FrameCounter
;
2357 for(cnt
= 0; cnt
< 1; cnt
++)
2359 ioreq
= (struct IOUsbHWReq
*) (cnt
? hc
->hc_PeriodicTDQueue
.lh_Head
: hc
->hc_TDQueue
.lh_Head
);
2360 while(((struct Node
*) ioreq
)->ln_Succ
)
2362 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2364 eqh
= (struct EhciQH
*) ioreq
->iouh_DriverPrivate1
;
2367 KPRINTF(1, ("Examining IOReq=%p with EQH=%p\n", ioreq
, eqh
));
2368 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2369 ctrlstatus
= READMEM32_LE(&eqh
->eqh_CtrlStatus
);
2370 if(ctrlstatus
& ETCF_ACTIVE
)
2372 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2374 // give the thing the chance to exit gracefully
2375 KPRINTF(20, ("NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2376 ctrlstatus
&= ~ETCF_ACTIVE
;
2377 ctrlstatus
|= ETSF_HALTED
;
2378 WRITEMEM32_LE(&eqh
->eqh_CtrlStatus
, ctrlstatus
);
2382 if(ctrlstatus
& ETCF_READYINTEN
)
2384 KPRINTF(10, ("INT missed?!? Manually causing it! %08lx, IOReq=%p\n",
2385 ctrlstatus
, ioreq
));
2391 ioreq
= (struct IOUsbHWReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
2396 #ifdef AROS_USB30_CODE
2399 //KPRINTF(1000, ("XHCI uhwNakTimeoutInt\n"));
2406 SureCause(base
, &hc
->hc_CompleteInt
);
2409 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2412 uhwCheckRootHubChanges(unit
);
2414 unit
->hu_NakTimeoutReq
.tr_time
.tv_micro
= 150*1000;
2415 SendIO((APTR
) &unit
->hu_NakTimeoutReq
);
2417 KPRINTF(1, ("Exit NakTimeoutInt(0x%p)\n", unit
));