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)
39 const CONST_STRPTR RHStrings
[] = { "Chris Hodges", "PCI Root Hub Unit x", "Standard Config", "Hub interface" };
41 /* /// "SureCause()" */
42 void SureCause(struct PCIDevice
*base
, struct Interrupt
*interrupt
)
44 /* this is a workaround for the original Cause() function missing tailed calls */
47 if((interrupt
->is_Node
.ln_Type
== NT_SOFTINT
) || (interrupt
->is_Node
.ln_Type
== NT_USER
))
50 interrupt
->is_Node
.ln_Type
= NT_USER
;
54 interrupt
->is_Node
.ln_Type
= NT_SOFTINT
;
55 Forbid(); // make sure code is not interrupted by other tasks
57 AROS_INTC1(interrupt
->is_Code
, interrupt
->is_Data
);
60 } while(interrupt
->is_Node
.ln_Type
!= NT_SOFTINT
);
61 interrupt
->is_Node
.ln_Type
= NT_INTERRUPT
;
67 /* /// "uhwOpenTimer()" */
68 BOOL
uhwOpenTimer(struct PCIUnit
*unit
, struct PCIDevice
*base
)
70 if((unit
->hu_MsgPort
= CreateMsgPort()))
72 if((unit
->hu_TimerReq
= (struct timerequest
*) CreateIORequest(unit
->hu_MsgPort
, sizeof(struct timerequest
))))
74 if(!OpenDevice("timer.device", UNIT_MICROHZ
, (struct IORequest
*) unit
->hu_TimerReq
, 0))
76 unit
->hu_TimerReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "PCI hardware";
77 unit
->hu_TimerReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
78 KPRINTF(1, ("opened timer device\n"));
81 DeleteIORequest((struct IORequest
*) unit
->hu_TimerReq
);
82 unit
->hu_TimerReq
= NULL
;
84 DeleteMsgPort(unit
->hu_MsgPort
);
85 unit
->hu_MsgPort
= NULL
;
87 KPRINTF(5, ("failed to open timer.device\n"));
92 /* /// "uhwDelayMS()" */
93 void uhwDelayMS(ULONG milli
, struct PCIUnit
*unit
)
95 unit
->hu_TimerReq
->tr_time
.tv_secs
= 0;
96 unit
->hu_TimerReq
->tr_time
.tv_micro
= milli
* 1000;
97 DoIO((struct IORequest
*) unit
->hu_TimerReq
);
101 /* /// "uhwDelayMicro()" */
102 void uhwDelayMicro(ULONG micro
, struct PCIUnit
*unit
)
104 unit
->hu_TimerReq
->tr_time
.tv_secs
= 0;
105 unit
->hu_TimerReq
->tr_time
.tv_micro
= micro
;
106 DoIO((struct IORequest
*) unit
->hu_TimerReq
);
110 /* /// "uhwCloseTimer()" */
111 void uhwCloseTimer(struct PCIUnit
*unit
, struct PCIDevice
*base
)
115 if(unit
->hu_TimerReq
)
117 KPRINTF(1, ("closing timer.device\n"));
118 CloseDevice((APTR
) unit
->hu_TimerReq
);
119 DeleteIORequest((struct IORequest
*) unit
->hu_TimerReq
);
120 unit
->hu_TimerReq
= NULL
;
122 DeleteMsgPort(unit
->hu_MsgPort
);
123 unit
->hu_MsgPort
= NULL
;
128 /* /// "Open_Unit()" */
129 struct Unit
* Open_Unit(struct IOUsbHWReq
*ioreq
,
131 struct PCIDevice
*base
)
133 struct PCIUnit
*unit
= NULL
;
135 if(!base
->hd_ScanDone
)
137 base
->hd_ScanDone
= TRUE
;
143 unit
= (struct PCIUnit
*) base
->hd_Units
.lh_Head
;
144 while(((struct Node
*) unit
)->ln_Succ
)
146 if(unit
->hu_UnitNo
== unitnr
)
150 unit
= (struct PCIUnit
*) ((struct Node
*) unit
)->ln_Succ
;
152 if(!((struct Node
*) unit
)->ln_Succ
)
154 KPRINTF(20, ("Unit %ld does not exist!\n", unitnr
));
157 if(unit
->hu_UnitAllocated
)
159 ioreq
->iouh_Req
.io_Error
= IOERR_UNITBUSY
;
160 KPRINTF(5, ("Unit %ld already open!\n", unitnr
));
164 if(uhwOpenTimer(unit
, base
))
167 if(pciAllocUnit(unit
)) // hardware self test
169 unit
->hu_UnitAllocated
= TRUE
;
170 unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_INTERRUPT
;
171 unit
->hu_NakTimeoutInt
.is_Node
.ln_Name
= "PCI NakTimeout";
172 unit
->hu_NakTimeoutInt
.is_Node
.ln_Pri
= -16;
173 unit
->hu_NakTimeoutInt
.is_Data
= unit
;
174 unit
->hu_NakTimeoutInt
.is_Code
= (VOID_FUNC
)uhwNakTimeoutInt
;
176 CopyMem(unit
->hu_TimerReq
, &unit
->hu_NakTimeoutReq
, sizeof(struct timerequest
));
177 memset( &unit
->hu_NakTimeoutMsgPort
, 0, sizeof( unit
->hu_NakTimeoutMsgPort
) );
178 unit
->hu_NakTimeoutMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
179 unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_SOFTINT
;
180 unit
->hu_NakTimeoutMsgPort
.mp_SigTask
= &unit
->hu_NakTimeoutInt
;
181 NewList(&unit
->hu_NakTimeoutMsgPort
.mp_MsgList
);
182 unit
->hu_NakTimeoutReq
.tr_node
.io_Message
.mn_ReplyPort
= &unit
->hu_NakTimeoutMsgPort
;
183 Cause(&unit
->hu_NakTimeoutInt
);
184 return(&unit
->hu_Unit
);
186 ioreq
->iouh_Req
.io_Error
= IOERR_SELFTEST
;
187 KPRINTF(20, ("Hardware allocation failure!\n"));
189 uhwCloseTimer(unit
, base
);
195 /* /// "Close_Unit()" */
196 void Close_Unit(struct PCIDevice
*base
,
197 struct PCIUnit
*unit
,
198 struct IOUsbHWReq
*ioreq
)
200 /* Disable all interrupts */
201 unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_IGNORE
;
202 unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_SOFTINT
;
203 AbortIO((APTR
) &unit
->hu_NakTimeoutReq
);
207 uhwCloseTimer(unit
, base
);
208 unit
->hu_UnitAllocated
= FALSE
;
212 /* /// "uhwGetUsbState()" */
213 UWORD
uhwGetUsbState(struct IOUsbHWReq
*ioreq
,
214 struct PCIUnit
*unit
,
215 struct PCIDevice
*base
)
217 return(ioreq
->iouh_State
= UHSF_OPERATIONAL
);
221 /* /// "cmdReset()" */
223 *======================================================================
224 * cmdReset(ioreq, unit, base)
225 *======================================================================
227 * This is the device CMD_RESET routine.
229 * Resets the whole USB hardware. Goes into USBOperational mode right
230 * after. Must NOT be called from an interrupt.
234 WORD
cmdReset(struct IOUsbHWReq
*ioreq
,
235 struct PCIUnit
*unit
,
236 struct PCIDevice
*base
)
238 KPRINTF(10, ("CMD_RESET ioreq: 0x%p\n", ioreq
));
241 uhwGetUsbState(ioreq
, unit
, base
);
243 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
247 return UHIOERR_USBOFFLINE
;
251 /* /// "cmdUsbReset()" */
253 *======================================================================
254 * cmdUsbReset(ioreq, unit, base)
255 *======================================================================
257 * This is the device UHCMD_USBRESET routine.
259 * Resets the USB bus. Goes into USBOperational mode right after. Must
260 * NOT be called from an interrupt.
264 WORD
cmdUsbReset(struct IOUsbHWReq
*ioreq
,
265 struct PCIUnit
*unit
,
266 struct PCIDevice
*base
)
268 KPRINTF(10, ("UHCMD_USBRESET ioreq: 0x%p\n", ioreq
));
271 uhwGetUsbState(ioreq
, unit
, base
);
273 unit
->hu_FrameCounter
= 1;
274 unit
->hu_RootHubAddr
= 0;
276 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
280 return UHIOERR_USBOFFLINE
;
284 /* /// "cmdUsbResume()" */
286 *======================================================================
287 * cmdUsbResume(ioreq, unit, base)
288 *======================================================================
290 * This is the device UHCMD_USBRESUME routine.
292 * Tries to resume from USBSuspend mode into USBOperational.
293 * Must NOT be called from an interrupt.
297 WORD
cmdUsbResume(struct IOUsbHWReq
*ioreq
,
298 struct PCIUnit
*unit
,
299 struct PCIDevice
*base
)
301 KPRINTF(10, ("UHCMD_USBRESUME ioreq: 0x%p\n", ioreq
));
304 uhwGetUsbState(ioreq
, unit
, base
);
305 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
309 return UHIOERR_USBOFFLINE
;
313 /* /// "cmdUsbSuspend()" */
315 *======================================================================
316 * cmdUsbSuspend(ioreq, unit, base)
317 *======================================================================
319 * This is the device UHCMD_USBSUSPEND routine.
321 * Sets the USB into USBSuspend mode.
322 * Must NOT be called from an interrupt.
326 WORD
cmdUsbSuspend(struct IOUsbHWReq
*ioreq
,
327 struct PCIUnit
*unit
,
328 struct PCIDevice
*base
)
330 KPRINTF(10, ("UHCMD_USBSUSPEND ioreq: 0x%p\n", ioreq
));
333 uhwGetUsbState(ioreq
, unit
, base
);
334 if(ioreq
->iouh_State
& UHSF_SUSPENDED
)
338 return UHIOERR_USBOFFLINE
;
342 /* /// "cmdUsbOper()" */
344 *======================================================================
345 * cmdUsbOper(ioreq, unit, base)
346 *======================================================================
348 * This is the device UHCMD_USBOPER routine.
350 * Sets the USB into USBOperational mode.
351 * Must NOT be called from an interrupt.
355 WORD
cmdUsbOper(struct IOUsbHWReq
*ioreq
,
356 struct PCIUnit
*unit
,
357 struct PCIDevice
*base
)
359 KPRINTF(10, ("UHCMD_USBOPER ioreq: 0x%p\n", ioreq
));
362 uhwGetUsbState(ioreq
, unit
, base
);
363 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
367 return UHIOERR_USBOFFLINE
;
371 /* /// "cmdQueryDevice()" */
373 *======================================================================
374 * cmdQueryDevice(ioreq, unit, base)
375 *======================================================================
377 * This is the device UHCMD_QUERYDEVICE routine.
379 * Returns information about the hardware.
383 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
,
384 struct PCIUnit
*unit
,
385 struct PCIDevice
*base
)
387 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
391 KPRINTF(10, ("UHCMD_QUERYDEVICE ioreq: 0x%p, taglist: 0x%p\n", ioreq
, taglist
));
393 if((tag
= FindTagItem(UHA_State
, taglist
)))
395 *((ULONG
*) tag
->ti_Data
) = (ULONG
) uhwGetUsbState(ioreq
, unit
, base
);
398 if((tag
= FindTagItem(UHA_Manufacturer
, taglist
)))
400 *((STRPTR
*) tag
->ti_Data
) = "Chris Hodges";
403 if((tag
= FindTagItem(UHA_ProductName
, taglist
)))
405 *((STRPTR
*) tag
->ti_Data
) = unit
->hu_ProductName
;
408 if((tag
= FindTagItem(UHA_Description
, taglist
)))
410 *((STRPTR
*) tag
->ti_Data
) = "Generic adaptive host controller driver for PCI cards";
413 if((tag
= FindTagItem(UHA_Copyright
, taglist
)))
415 *((STRPTR
*) tag
->ti_Data
) ="©2007-2009 Chris Hodges";
418 if((tag
= FindTagItem(UHA_Version
, taglist
)))
420 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
423 if((tag
= FindTagItem(UHA_Revision
, taglist
)))
425 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
428 if((tag
= FindTagItem(UHA_DriverVersion
, taglist
)))
430 *((ULONG
*) tag
->ti_Data
) = 0x220;
433 if((tag
= FindTagItem(UHA_Capabilities
, taglist
)))
435 *((ULONG
*) tag
->ti_Data
) = UHCF_USB20
;
438 ioreq
->iouh_Actual
= count
;
443 /* /// "cmdControlXFerRootHub()" */
444 WORD
cmdControlXFerRootHub(struct IOUsbHWReq
*ioreq
,
445 struct PCIUnit
*unit
,
446 struct PCIDevice
*base
)
448 struct PCIController
*hc
;
449 struct PCIController
*chc
;
450 UWORD rt
= ioreq
->iouh_SetupData
.bmRequestType
;
451 UWORD req
= ioreq
->iouh_SetupData
.bRequest
;
452 UWORD idx
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
);
453 UWORD val
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wValue
);
454 UWORD len
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
456 ULONG numports
= unit
->hu_RootHubPorts
;
460 if(ioreq
->iouh_Endpoint
)
462 return(UHIOERR_STALL
);
465 if(len
!= ioreq
->iouh_Length
)
467 KPRINTF(20, ("RH: Len (%ld != %ld) mismatch!\n", len
!= ioreq
->iouh_Length
));
468 return(UHIOERR_STALL
);
472 case (URTF_STANDARD
|URTF_DEVICE
):
475 case USR_SET_ADDRESS
:
476 KPRINTF(1, ("RH: SetAddress = %ld\n", val
));
477 unit
->hu_RootHubAddr
= val
;
478 ioreq
->iouh_Actual
= len
;
481 case USR_SET_CONFIGURATION
:
482 KPRINTF(1, ("RH: SetConfiguration=%ld\n", val
));
483 ioreq
->iouh_Actual
= len
;
488 case (URTF_IN
|URTF_STANDARD
|URTF_DEVICE
):
491 case USR_GET_DESCRIPTOR
:
495 KPRINTF(1, ("RH: GetDeviceDescriptor (%ld)\n", len
));
496 ioreq
->iouh_Actual
= (len
> sizeof(struct UsbStdDevDesc
)) ? sizeof(struct UsbStdDevDesc
) : len
;
497 CopyMem((APTR
) &RHDevDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
498 if(ioreq
->iouh_Length
>= sizeof(struct UsbStdDevDesc
))
500 if(unit
->hu_RootHub20Ports
)
502 struct UsbStdDevDesc
*usdd
= (struct UsbStdDevDesc
*) ioreq
->iouh_Data
;
503 usdd
->bcdUSB
= AROS_WORD2LE(0x0200); // signal a highspeed root hub
504 usdd
->bDeviceProtocol
= 1; // single TT
510 case UDT_CONFIGURATION
:
513 KPRINTF(1, ("RH: GetConfigDescriptor (%ld)\n", len
));
514 CopyMem((APTR
) &RHCfgDesc
, tmpbuf
, 9);
515 CopyMem((APTR
) &RHIfDesc
, &tmpbuf
[9], 9);
516 CopyMem((APTR
) &RHEPDesc
, &tmpbuf
[9+9], 7);
517 if(unit
->hu_RootHub20Ports
)
519 struct UsbStdEPDesc
*usepd
= (struct UsbStdEPDesc
*) &tmpbuf
[9+9];
520 usepd
->bInterval
= 12; // 2048 µFrames
522 ioreq
->iouh_Actual
= (len
> 9+9+7) ? 9+9+7 : len
;
523 CopyMem(tmpbuf
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
528 if(val
& 0xff) /* get lang array */
530 CONST_STRPTR source
= NULL
;
531 UWORD
*mptr
= ioreq
->iouh_Data
;
533 KPRINTF(1, ("RH: GetString %04lx (%ld)\n", val
, len
));
534 if((val
& 0xff) > 4) /* index too high? */
536 return(UHIOERR_STALL
);
538 source
= RHStrings
[(val
& 0xff)-1];
541 ioreq
->iouh_Actual
= 2;
546 source
= RHStrings
[(val
& 0xff)-1];
547 *mptr
++ = AROS_WORD2BE((slen
<<9)|UDT_STRING
);
548 while(ioreq
->iouh_Actual
+1 < len
)
550 // special hack for unit number in root hub string
551 if(((val
& 0xff) == 2) && (source
[1] == 0))
553 *mptr
++ = AROS_WORD2LE('0' + unit
->hu_UnitNo
);
555 *mptr
++ = AROS_WORD2LE(*source
);
558 ioreq
->iouh_Actual
+= 2;
566 UWORD
*mptr
= ioreq
->iouh_Data
;
567 KPRINTF(1, ("RH: GetLangArray %04lx (%ld)\n", val
, len
));
570 ioreq
->iouh_Actual
= 2;
571 mptr
[0] = AROS_WORD2BE((4<<8)|UDT_STRING
);
574 ioreq
->iouh_Actual
+= 2;
575 mptr
[1] = AROS_WORD2LE(0x0409);
582 KPRINTF(1, ("RH: Unsupported Descriptor %04lx\n", idx
));
586 case USR_GET_CONFIGURATION
:
589 KPRINTF(1, ("RH: GetConfiguration\n"));
590 ((UBYTE
*) ioreq
->iouh_Data
)[0] = 1;
591 ioreq
->iouh_Actual
= len
;
598 case (URTF_CLASS
|URTF_OTHER
):
601 case USR_SET_FEATURE
:
602 if((!idx
) || (idx
> numports
))
604 KPRINTF(20, ("Port %ld out of range\n", idx
));
605 return(UHIOERR_STALL
);
607 chc
= unit
->hu_PortMap11
[idx
- 1];
608 if(unit
->hu_EhciOwned
[idx
- 1])
610 hc
= unit
->hu_PortMap20
[idx
- 1];
614 hciport
= unit
->hu_PortNum11
[idx
- 1];
616 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"));
618 switch(hc
->hc_HCIType
)
622 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
623 ULONG oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
); // these are clear-on-write!
624 ULONG newval
= oldval
;
627 /* case UFS_PORT_CONNECTION: not possible */
628 case UFS_PORT_ENABLE
:
629 KPRINTF(10, ("UHCI: Enabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "already" : "ok"));
630 newval
|= UHPF_PORTENABLE
;
634 case UFS_PORT_SUSPEND
:
635 newval
|= UHPF_PORTSUSPEND
;
636 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
; // manually fake suspend change
640 /* case UFS_PORT_OVER_CURRENT: not possible */
642 KPRINTF(10, ("UHCI: Resetting Port (%s)\n", newval
& UHPF_PORTRESET
? "already" : "ok"));
644 // this is an ugly blocking workaround to the inability of UHCI to clear reset automatically
645 newval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
646 newval
|= UHPF_PORTRESET
;
647 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
648 uhwDelayMS(25, unit
);
649 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
650 KPRINTF(10, ("UHCI: Reset=%s\n", newval
& UHPF_PORTRESET
? "GOOD" : "BAD!"));
651 // like windows does it
652 newval
&= ~UHPF_PORTRESET
;
653 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
654 uhwDelayMicro(50, unit
);
655 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
656 KPRINTF(10, ("UHCI: Reset=%s\n", newval
& UHPF_PORTRESET
? "BAD!" : "GOOD"));
657 newval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTRESET
);
658 newval
|= UHPF_PORTENABLE
;
659 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
660 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
|UPSF_PORT_ENABLE
; // manually fake reset change
666 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
);
667 } while(--cnt
&& (!(newval
& UHPF_PORTENABLE
)));
670 KPRINTF(10, ("UHCI: Enabled after %ld ticks\n", 100-cnt
));
672 KPRINTF(20, ("UHCI: Port refuses to be enabled!\n"));
673 return(UHIOERR_HOSTERROR
);
675 // make enumeration possible
676 unit
->hu_DevControllers
[0] = hc
;
681 KPRINTF(10, ("UHCI: Powering Port\n"));
682 // ignore for UHCI, is always powered
686 /* case UFS_PORT_LOW_SPEED: not possible */
687 /* case UFS_C_PORT_CONNECTION:
688 case UFS_C_PORT_ENABLE:
689 case UFS_C_PORT_SUSPEND:
690 case UFS_C_PORT_OVER_CURRENT:
691 case UFS_C_PORT_RESET: */
695 KPRINTF(5, ("UHCI: Port %ld SET_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
696 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
704 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
705 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
709 /* case UFS_PORT_CONNECTION: not possible */
710 case UFS_PORT_ENABLE
:
711 KPRINTF(10, ("OHCI: Enabling Port (%s)\n", oldval
& OHPF_PORTENABLE
? "already" : "ok"));
712 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTENABLE
);
716 case UFS_PORT_SUSPEND
:
717 KPRINTF(10, ("OHCI: Suspending Port (%s)\n", oldval
& OHPF_PORTSUSPEND
? "already" : "ok"));
718 //hc->hc_PortChangeMap[hciport] |= UPSF_PORT_SUSPEND; // manually fake suspend change
719 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTSUSPEND
);
723 /* case UFS_PORT_OVER_CURRENT: not possible */
725 KPRINTF(10, ("OHCI: Resetting Port (%s)\n", oldval
& OHPF_PORTRESET
? "already" : "ok"));
726 // make sure we have at least 50ms of reset time here, as required for a root hub port
727 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
728 uhwDelayMS(10, unit
);
729 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
730 uhwDelayMS(10, unit
);
731 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
732 uhwDelayMS(10, unit
);
733 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
734 uhwDelayMS(10, unit
);
735 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
736 uhwDelayMS(15, unit
);
737 oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
738 KPRINTF(10, ("OHCI: Reset release (%s %s)\n", oldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
739 oldval
& OHPF_PORTENABLE
? "enabled" : "not enabled"));
740 if(oldval
& OHPF_PORTRESET
)
742 uhwDelayMS(40, unit
);
743 oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
744 KPRINTF(10, ("OHCI: Reset 2nd release (%s %s)\n", oldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
745 oldval
& OHPF_PORTENABLE
? "enabled" : "still not enabled"));
747 // make enumeration possible
748 unit
->hu_DevControllers
[0] = hc
;
753 KPRINTF(10, ("OHCI: Powering Port (%s)\n", oldval
& OHPF_PORTPOWER
? "already" : "ok"));
754 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTPOWER
);
758 /* case UFS_PORT_LOW_SPEED: not possible */
759 /* case UFS_C_PORT_CONNECTION:
760 case UFS_C_PORT_ENABLE:
761 case UFS_C_PORT_SUSPEND:
762 case UFS_C_PORT_OVER_CURRENT:
763 case UFS_C_PORT_RESET: */
774 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
775 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
); // these are clear-on-write!
776 ULONG newval
= oldval
;
779 /* case UFS_PORT_CONNECTION: not possible */
780 case UFS_PORT_ENABLE
:
781 KPRINTF(10, ("EHCI: Enabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "already" : "ok"));
782 newval
|= EHPF_PORTENABLE
;
786 case UFS_PORT_SUSPEND
:
787 newval
|= EHPF_PORTSUSPEND
;
788 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
; // manually fake suspend change
792 /* case UFS_PORT_OVER_CURRENT: not possible */
794 KPRINTF(10, ("EHCI: Resetting Port (%s)\n", newval
& EHPF_PORTRESET
? "already" : "ok"));
796 // this is an ugly blocking workaround to the inability of EHCI to clear reset automatically
797 newval
&= ~(EHPF_PORTSUSPEND
|EHPF_PORTENABLE
);
798 newval
|= EHPF_PORTRESET
;
799 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
800 uhwDelayMS(50, unit
);
801 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
|EHPF_PORTENABLE
);
802 KPRINTF(10, ("EHCI: Reset=%s\n", newval
& EHPF_PORTRESET
? "GOOD" : "BAD!"));
803 newval
&= ~EHPF_PORTRESET
;
804 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
805 uhwDelayMS(10, unit
);
806 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
);
807 KPRINTF(10, ("EHCI: Reset=%s\n", newval
& EHPF_PORTRESET
? "BAD!" : "GOOD"));
808 KPRINTF(10, ("EHCI: Highspeed=%s\n", newval
& EHPF_PORTENABLE
? "YES!" : "NO"));
809 KPRINTF(10, ("EHCI: Port status=%08lx\n", newval
));
810 if(!(newval
& EHPF_PORTENABLE
) && unit
->hu_PortMap11
[idx
- 1] != NULL
)
812 // if not highspeed, release ownership
813 KPRINTF(20, ("EHCI: Transferring ownership to UHCI/OHCI port %ld\n", unit
->hu_PortNum11
[idx
- 1]));
814 KPRINTF(10, ("EHCI: Device is %s\n", newval
& EHPF_LINESTATUS_DM
? "LOWSPEED" : "FULLSPEED"));
815 newval
|= EHPF_NOTPORTOWNER
;
818 KPRINTF(20, ("EHCI has no companion controller, can't transfer ownership!\n"));
819 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
820 return(UHIOERR_HOSTERROR
);
822 switch(chc
->hc_HCIType
)
826 UWORD uhcihciport
= unit
->hu_PortNum11
[idx
- 1];
827 UWORD uhciportreg
= uhcihciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
828 ULONG __unused uhcinewval
= READREG16_LE(chc
->hc_RegBase
, uhciportreg
);
830 KPRINTF(10, ("UHCI Port status before handover=%04lx\n", uhcinewval
));
836 UWORD ohcihciport
= unit
->hu_PortNum11
[idx
- 1];
837 UWORD ohciportreg
= OHCI_PORTSTATUS
+ (ohcihciport
<<2);
838 ULONG __unused ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
840 KPRINTF(10, ("OHCI: Port status before handover=%08lx\n", ohcioldval
));
841 KPRINTF(10, ("OHCI: Powering Port (%s)\n", ohcioldval
& OHPF_PORTPOWER
? "already" : "ok"));
842 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTPOWER
);
843 uhwDelayMS(10, unit
);
844 KPRINTF(10, ("OHCI: Port status after handover=%08lx\n", READREG32_LE(chc
->hc_RegBase
, ohciportreg
)));
848 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
);
849 KPRINTF(10, ("EHCI: Port status (reread)=%08lx\n", newval
));
850 newval
|= EHPF_NOTPORTOWNER
;
851 unit
->hu_EhciOwned
[idx
- 1] = FALSE
;
852 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
853 uhwDelayMS(90, unit
);
854 KPRINTF(10, ("EHCI: Port status (after handover)=%08lx\n", READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
)));
855 // enable companion controller port
856 switch(chc
->hc_HCIType
)
860 UWORD uhcihciport
= unit
->hu_PortNum11
[idx
- 1];
861 UWORD uhciportreg
= uhcihciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
864 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
865 KPRINTF(10, ("UHCI: Reset=%s\n", uhcinewval
& UHPF_PORTRESET
? "BAD!" : "GOOD"));
866 if((uhcinewval
& UHPF_PORTRESET
))//|| (newval & EHPF_LINESTATUS_DM))
868 // this is an ugly blocking workaround to the inability of UHCI to clear reset automatically
869 KPRINTF(20, ("UHCI: Uhm, reset was bad!\n"));
870 uhcinewval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
871 uhcinewval
|= UHPF_PORTRESET
;
872 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
873 uhwDelayMS(50, unit
);
874 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
875 KPRINTF(10, ("UHCI: ReReset=%s\n", uhcinewval
& UHPF_PORTRESET
? "GOOD" : "BAD!"));
876 uhcinewval
&= ~UHPF_PORTRESET
;
877 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
878 uhwDelayMicro(50, unit
);
879 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
880 KPRINTF(10, ("UHCI: ReReset=%s\n", uhcinewval
& UHPF_PORTRESET
? "STILL BAD!" : "GOOD"));
882 uhcinewval
&= ~UHPF_PORTRESET
;
883 uhcinewval
|= UHPF_PORTENABLE
;
884 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
885 chc
->hc_PortChangeMap
[uhcihciport
] |= UPSF_PORT_RESET
|UPSF_PORT_ENABLE
; // manually fake reset change
891 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
);
892 } while(--cnt
&& (!(uhcinewval
& UHPF_PORTENABLE
)));
895 KPRINTF(10, ("UHCI: Enabled after %ld ticks\n", 100-cnt
));
897 KPRINTF(20, ("UHCI: Port refuses to be enabled!\n"));
898 return(UHIOERR_HOSTERROR
);
905 UWORD ohcihciport
= unit
->hu_PortNum11
[idx
- 1];
906 UWORD ohciportreg
= OHCI_PORTSTATUS
+ (ohcihciport
<<2);
907 ULONG ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
908 KPRINTF(10, ("OHCI: Resetting Port (%s)\n", ohcioldval
& OHPF_PORTRESET
? "already" : "ok"));
909 // make sure we have at least 50ms of reset time here, as required for a root hub port
910 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
911 uhwDelayMS(10, unit
);
912 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
913 uhwDelayMS(10, unit
);
914 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
915 uhwDelayMS(10, unit
);
916 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
917 uhwDelayMS(10, unit
);
918 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
919 uhwDelayMS(15, unit
);
920 ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
921 KPRINTF(10, ("OHCI: Reset release (%s %s)\n", ohcioldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
922 ohcioldval
& OHPF_PORTENABLE
? "enabled" : "not enabled"));
923 if(ohcioldval
& OHPF_PORTRESET
)
925 uhwDelayMS(40, unit
);
926 ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
927 KPRINTF(10, ("OHCI: Reset 2nd release (%s %s)\n", ohcioldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
928 ohcioldval
& OHPF_PORTENABLE
? "enabled" : "still not enabled"));
934 // make enumeration possible
935 unit
->hu_DevControllers
[0] = chc
;
938 newval
&= ~EHPF_PORTRESET
;
939 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
940 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
; // manually fake reset change
941 uhwDelayMS(10, unit
);
946 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
947 } while(--cnt
&& (!(newval
& EHPF_PORTENABLE
)));
950 KPRINTF(10, ("EHCI: Enabled after %ld ticks\n", 100-cnt
));
952 KPRINTF(20, ("EHCI: Port refuses to be enabled!\n"));
953 return(UHIOERR_HOSTERROR
);
955 // make enumeration possible
956 unit
->hu_DevControllers
[0] = hc
;
962 KPRINTF(10, ("EHCI: Powering Port\n"));
963 newval
|= EHPF_PORTPOWER
;
967 /* case UFS_PORT_LOW_SPEED: not possible */
968 /* case UFS_C_PORT_CONNECTION:
969 case UFS_C_PORT_ENABLE:
970 case UFS_C_PORT_SUSPEND:
971 case UFS_C_PORT_OVER_CURRENT:
972 case UFS_C_PORT_RESET: */
976 KPRINTF(5, ("EHCI: Port %ld SET_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
977 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
986 case USR_CLEAR_FEATURE
:
987 if((!idx
) || (idx
> numports
))
989 KPRINTF(20, ("Port %ld out of range\n", idx
));
990 return(UHIOERR_STALL
);
992 if(unit
->hu_EhciOwned
[idx
- 1])
994 hc
= unit
->hu_PortMap20
[idx
- 1];
997 hc
= unit
->hu_PortMap11
[idx
- 1];
998 hciport
= unit
->hu_PortNum11
[idx
- 1];
1000 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"));
1002 switch(hc
->hc_HCIType
)
1006 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
1007 ULONG oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
); // these are clear-on-write!
1008 ULONG newval
= oldval
;
1011 case UFS_PORT_ENABLE
:
1012 KPRINTF(10, ("Disabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "ok" : "already"));
1013 newval
&= ~UHPF_PORTENABLE
;
1015 // disable enumeration
1016 unit
->hu_DevControllers
[0] = NULL
;
1019 case UFS_PORT_SUSPEND
:
1020 newval
&= ~UHPF_PORTSUSPEND
;
1024 case UFS_PORT_POWER
: // ignore for UHCI, there's no power control here
1025 KPRINTF(10, ("Disabling Power\n"));
1026 KPRINTF(10, ("Disabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "ok" : "already"));
1027 newval
&= ~UHPF_PORTENABLE
;
1031 case UFS_C_PORT_CONNECTION
:
1032 newval
|= UHPF_CONNECTCHANGE
; // clear-on-write!
1033 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1037 case UFS_C_PORT_ENABLE
:
1038 newval
|= UHPF_ENABLECHANGE
; // clear-on-write!
1039 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1043 case UFS_C_PORT_SUSPEND
: // ignore for UHCI, there's no bit indicating this
1044 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
; // manually fake suspend change clearing
1048 case UFS_C_PORT_OVER_CURRENT
: // ignore for UHCI, there's no bit indicating this
1049 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
; // manually fake over current clearing
1053 case UFS_C_PORT_RESET
: // ignore for UHCI, there's no bit indicating this
1054 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
; // manually fake reset change clearing
1060 KPRINTF(5, ("Port %ld CLEAR_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
1061 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
1062 if(hc
->hc_PortChangeMap
[hciport
])
1064 unit
->hu_RootPortChanges
|= 1UL<<idx
;
1066 unit
->hu_RootPortChanges
&= ~(1UL<<idx
);
1075 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
1076 ULONG __unused oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1080 case UFS_PORT_ENABLE
:
1081 KPRINTF(10, ("Disabling Port (%s)\n", oldval
& OHPF_PORTENABLE
? "ok" : "already"));
1082 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTDISABLE
);
1086 case UFS_PORT_SUSPEND
:
1087 KPRINTF(10, ("Resuming Port (%s)\n", oldval
& OHPF_PORTSUSPEND
? "ok" : "already"));
1088 //hc->hc_PortChangeMap[hciport] &= ~UPSF_PORT_SUSPEND; // manually fake suspend change
1089 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESUME
);
1093 case UFS_PORT_POWER
:
1094 KPRINTF(10, ("Unpowering Port (%s)\n", oldval
& OHPF_PORTPOWER
? "ok" : "already"));
1095 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTUNPOWER
);
1099 case UFS_C_PORT_CONNECTION
:
1100 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_CONNECTCHANGE
);
1101 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1105 case UFS_C_PORT_ENABLE
:
1106 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_ENABLECHANGE
);
1107 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1111 case UFS_C_PORT_SUSPEND
:
1112 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESUMEDTX
);
1113 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
;
1117 case UFS_C_PORT_OVER_CURRENT
:
1118 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_OVERCURRENTCHG
);
1119 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
;
1123 case UFS_C_PORT_RESET
:
1124 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESETCHANGE
);
1125 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
;
1138 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
1139 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
); // these are clear-on-write!
1140 ULONG newval
= oldval
;
1143 case UFS_PORT_ENABLE
:
1144 KPRINTF(10, ("Disabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "ok" : "already"));
1145 newval
&= ~EHPF_PORTENABLE
;
1147 // disable enumeration
1148 unit
->hu_DevControllers
[0] = NULL
;
1151 case UFS_PORT_SUSPEND
:
1152 newval
&= ~EHPF_PORTSUSPEND
;
1156 case UFS_PORT_POWER
: // ignore for UHCI, there's no power control here
1157 KPRINTF(10, ("Disabling Power (%s)\n", newval
& EHPF_PORTPOWER
? "ok" : "already"));
1158 KPRINTF(10, ("Disabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "ok" : "already"));
1159 newval
&= ~(EHPF_PORTENABLE
|EHPF_PORTPOWER
);
1163 case UFS_C_PORT_CONNECTION
:
1164 newval
|= EHPF_CONNECTCHANGE
; // clear-on-write!
1165 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1169 case UFS_C_PORT_ENABLE
:
1170 newval
|= EHPF_ENABLECHANGE
; // clear-on-write!
1171 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1175 case UFS_C_PORT_SUSPEND
: // ignore for EHCI, there's no bit indicating this
1176 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
; // manually fake suspend change clearing
1180 case UFS_C_PORT_OVER_CURRENT
:
1181 newval
|= EHPF_OVERCURRENTCHG
; // clear-on-write!
1182 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
; // manually fake over current clearing
1186 case UFS_C_PORT_RESET
: // ignore for EHCI, there's no bit indicating this
1187 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
; // manually fake reset change clearing
1193 KPRINTF(5, ("Port %ld CLEAR_FEATURE %08lx->%08lx\n", idx
, oldval
, newval
));
1194 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
1195 if(hc
->hc_PortChangeMap
[hciport
])
1197 unit
->hu_RootPortChanges
|= 1UL<<idx
;
1199 unit
->hu_RootPortChanges
&= ~(1UL<<idx
);
1211 case (URTF_IN
|URTF_CLASS
|URTF_OTHER
):
1214 case USR_GET_STATUS
:
1216 UWORD
*mptr
= ioreq
->iouh_Data
;
1217 if(len
!= sizeof(struct UsbPortStatus
))
1219 return(UHIOERR_STALL
);
1221 if((!idx
) || (idx
> numports
))
1223 KPRINTF(20, ("Port %ld out of range\n", idx
));
1224 return(UHIOERR_STALL
);
1226 if(unit
->hu_EhciOwned
[idx
- 1])
1228 hc
= unit
->hu_PortMap20
[idx
- 1];
1231 hc
= unit
->hu_PortMap11
[idx
- 1];
1232 hciport
= unit
->hu_PortNum11
[idx
- 1];
1234 switch(hc
->hc_HCIType
)
1238 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
1239 UWORD oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
);
1240 *mptr
= AROS_WORD2LE(UPSF_PORT_POWER
);
1241 if(oldval
& UHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1242 if(oldval
& UHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
);
1243 if(oldval
& UHPF_LOWSPEED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1244 if(oldval
& UHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1245 if(oldval
& UHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1247 KPRINTF(5, ("UHCI Port %ld is %s\n", idx
, oldval
& UHPF_LOWSPEED
? "LOWSPEED" : "FULLSPEED"));
1248 KPRINTF(5, ("UHCI Port %ld Status %08lx\n", idx
, *mptr
));
1251 if(oldval
& UHPF_ENABLECHANGE
)
1253 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1255 if(oldval
& UHPF_CONNECTCHANGE
)
1257 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1259 if(oldval
& UHPF_RESUMEDTX
)
1261 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
|UPSF_PORT_ENABLE
;
1263 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1264 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, oldval
);
1265 KPRINTF(5, ("UHCI Port %ld Change %08lx\n", idx
, *mptr
));
1271 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
1272 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1275 if(oldval
& OHPF_PORTPOWER
) *mptr
|= AROS_WORD2LE(UPSF_PORT_POWER
);
1276 if(oldval
& OHPF_OVERCURRENT
) *mptr
|= AROS_WORD2LE(UPSF_PORT_OVER_CURRENT
);
1277 if(oldval
& OHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1278 if(oldval
& OHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
);
1279 if(oldval
& OHPF_LOWSPEED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1280 if(oldval
& OHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1281 if(oldval
& OHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1283 KPRINTF(5, ("OHCI Port %ld (glob. %ld) is %s\n", hciport
, idx
, oldval
& OHPF_LOWSPEED
? "LOWSPEED" : "FULLSPEED"));
1284 KPRINTF(5, ("OHCI Port %ld Status %08lx (%08lx)\n", idx
, *mptr
, oldval
));
1287 if(oldval
& OHPF_OVERCURRENTCHG
)
1289 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_OVER_CURRENT
;
1291 if(oldval
& OHPF_RESETCHANGE
)
1293 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
;
1295 if(oldval
& OHPF_ENABLECHANGE
)
1297 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1299 if(oldval
& OHPF_CONNECTCHANGE
)
1301 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1303 if(oldval
& OHPF_RESUMEDTX
)
1305 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
;
1307 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1308 KPRINTF(5, ("OHCI Port %ld Change %08lx\n", idx
, *mptr
));
1314 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
1315 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1318 if(oldval
& EHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1319 if(oldval
& EHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
|UPSF_PORT_HIGH_SPEED
);
1320 if((oldval
& (EHPF_LINESTATUS_DM
|EHPF_PORTCONNECTED
|EHPF_PORTENABLE
)) ==
1321 (EHPF_LINESTATUS_DM
|EHPF_PORTCONNECTED
))
1323 KPRINTF(10, ("EHCI Port %ld is LOWSPEED\n", idx
));
1324 // we need to detect low speed devices prior to reset
1325 *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1328 if(oldval
& EHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1329 if(oldval
& EHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1330 if(oldval
& EHPF_PORTPOWER
) *mptr
|= AROS_WORD2LE(UPSF_PORT_POWER
);
1331 if(oldval
& EHPM_PORTINDICATOR
) *mptr
|= AROS_WORD2LE(UPSF_PORT_INDICATOR
);
1333 KPRINTF(5, ("EHCI Port %ld Status %08lx\n", idx
, *mptr
));
1336 if(oldval
& EHPF_ENABLECHANGE
)
1338 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1340 if(oldval
& EHPF_CONNECTCHANGE
)
1342 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1344 if(oldval
& EHPF_RESUMEDTX
)
1346 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
|UPSF_PORT_ENABLE
;
1348 if(oldval
& EHPF_OVERCURRENTCHG
)
1350 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_OVER_CURRENT
;
1352 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1353 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, oldval
);
1354 KPRINTF(5, ("EHCI Port %ld Change %08lx\n", idx
, *mptr
));
1365 case (URTF_IN
|URTF_CLASS
|URTF_DEVICE
):
1368 case USR_GET_STATUS
:
1370 UWORD
*mptr
= ioreq
->iouh_Data
;
1371 if(len
< sizeof(struct UsbHubStatus
))
1373 return(UHIOERR_STALL
);
1377 ioreq
->iouh_Actual
= 4;
1381 case USR_GET_DESCRIPTOR
:
1386 ULONG hubdesclen
= 9;
1387 ULONG powergood
= 1;
1389 struct UsbHubDesc
*uhd
= (struct UsbHubDesc
*) ioreq
->iouh_Data
;
1390 KPRINTF(1, ("RH: GetHubDescriptor (%ld)\n", len
));
1392 if(unit
->hu_RootHubPorts
> 7) // needs two bytes for port masks
1397 ioreq
->iouh_Actual
= (len
> hubdesclen
) ? hubdesclen
: len
;
1398 CopyMem((APTR
) &RHHubDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
1400 if(ioreq
->iouh_Length
)
1402 uhd
->bLength
= hubdesclen
;
1405 if(ioreq
->iouh_Length
>= 6)
1407 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1408 while(hc
->hc_Node
.ln_Succ
)
1410 if(hc
->hc_HCIType
== HCITYPE_OHCI
)
1412 ULONG localpwgood
= (READREG32_LE(hc
->hc_RegBase
, OHCI_HUBDESCA
) & OHAM_POWERGOOD
) >> OHAS_POWERGOOD
;
1413 if(localpwgood
> powergood
)
1415 powergood
= localpwgood
;
1416 KPRINTF(10, ("Increasing power good time to %ld\n", powergood
));
1419 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1422 uhd
->bPwrOn2PwrGood
= powergood
;
1424 if(ioreq
->iouh_Length
>= hubdesclen
)
1426 uhd
->bNbrPorts
= unit
->hu_RootHubPorts
;
1429 uhd
->DeviceRemovable
= 0;
1430 uhd
->PortPwrCtrlMask
= (1<<(unit
->hu_RootHubPorts
+2))-2;
1432 // each field is now 16 bits wide
1433 uhd
->DeviceRemovable
= 0;
1434 uhd
->PortPwrCtrlMask
= 0;
1435 ((UBYTE
*) ioreq
->iouh_Data
)[9] = (1<<(unit
->hu_RootHubPorts
+2))-2;
1436 ((UBYTE
*) ioreq
->iouh_Data
)[10] = ((1<<(unit
->hu_RootHubPorts
+2))-2)>>8;
1443 KPRINTF(20, ("RH: Unsupported Descriptor %04lx\n", idx
));
1449 KPRINTF(20, ("RH: Unsupported command %02lx %02lx %04lx %04lx %04lx!\n", rt
, req
, idx
, val
, len
));
1450 return(UHIOERR_STALL
);
1454 /* /// "cmdIntXFerRootHub()" */
1455 WORD
cmdIntXFerRootHub(struct IOUsbHWReq
*ioreq
,
1456 struct PCIUnit
*unit
,
1457 struct PCIDevice
*base
)
1459 if((ioreq
->iouh_Endpoint
!= 1) || (!ioreq
->iouh_Length
))
1461 return(UHIOERR_STALL
);
1464 if(unit
->hu_RootPortChanges
)
1466 KPRINTF(1, ("Immediate Portchange map %04lx\n", unit
->hu_RootPortChanges
));
1467 if((unit
->hu_RootHubPorts
< 8) || (ioreq
->iouh_Length
== 1))
1469 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->hu_RootPortChanges
;
1470 ioreq
->iouh_Actual
= 1;
1472 ((UBYTE
*) ioreq
->iouh_Data
)[0] = unit
->hu_RootPortChanges
;
1473 ((UBYTE
*) ioreq
->iouh_Data
)[1] = unit
->hu_RootPortChanges
>>8;
1474 ioreq
->iouh_Actual
= 2;
1476 unit
->hu_RootPortChanges
= 0;
1479 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1481 AddTail(&unit
->hu_RHIOQueue
, (struct Node
*) ioreq
);
1483 return(RC_DONTREPLY
);
1487 /* /// "cmdControlXFer()" */
1489 *======================================================================
1490 * cmdControlXFer(ioreq, unit, base)
1491 *======================================================================
1493 * This is the device UHCMD_CONTROLXFER routine.
1495 * First it check if the usb is in proper state and if user passed arguments
1496 * are valid. If everything is ok, the request is linked to queue of
1497 * pending transfer requests.
1501 WORD
cmdControlXFer(struct IOUsbHWReq
*ioreq
,
1502 struct PCIUnit
*unit
,
1503 struct PCIDevice
*base
)
1505 struct PCIController
*hc
;
1507 KPRINTF(10, ("UHCMD_CONTROLXFER ioreq: 0x%p\n", ioreq
));
1508 uhwGetUsbState(ioreq
, unit
, base
);
1509 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1511 return(UHIOERR_USBOFFLINE
);
1513 /* Root hub emulation */
1514 if(ioreq
->iouh_DevAddr
== unit
->hu_RootHubAddr
)
1516 return(cmdControlXFerRootHub(ioreq
, unit
, base
));
1519 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1522 KPRINTF(20, ("No Host controller assigned to device address %ld\n", ioreq
->iouh_DevAddr
));
1523 return(UHIOERR_HOSTERROR
);
1526 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1527 ioreq
->iouh_Actual
= 0;
1530 AddTail(&hc
->hc_CtrlXFerQueue
, (struct Node
*) ioreq
);
1532 SureCause(base
, &hc
->hc_CompleteInt
);
1534 KPRINTF(10, ("UHCMD_CONTROLXFER processed ioreq: 0x%p\n", ioreq
));
1535 return(RC_DONTREPLY
);
1539 /* /// "cmdBulkXFer()" */
1541 *======================================================================
1542 * cmdBulkXFer(ioreq, unit, base)
1543 *======================================================================
1545 * This is the device UHCMD_BULKXFER routine.
1547 * First it check if the usb is in proper state and if user passed arguments
1548 * are valid. If everything is ok, the request is linked to queue of
1549 * pending transfer requests.
1553 WORD
cmdBulkXFer(struct IOUsbHWReq
*ioreq
,
1554 struct PCIUnit
*unit
,
1555 struct PCIDevice
*base
)
1557 struct PCIController
*hc
;
1559 KPRINTF(10, ("UHCMD_BULKXFER ioreq: 0x%p\n", ioreq
));
1560 uhwGetUsbState(ioreq
, unit
, base
);
1561 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1563 return(UHIOERR_USBOFFLINE
);
1566 if(ioreq
->iouh_Flags
& UHFF_LOWSPEED
)
1568 return(UHIOERR_BADPARAMS
);
1571 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1574 return(UHIOERR_HOSTERROR
);
1577 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1578 ioreq
->iouh_Actual
= 0;
1581 AddTail(&hc
->hc_BulkXFerQueue
, (struct Node
*) ioreq
);
1583 SureCause(base
, &hc
->hc_CompleteInt
);
1585 KPRINTF(10, ("UHCMD_BULKXFER processed ioreq: 0x%p\n", ioreq
));
1586 return(RC_DONTREPLY
);
1590 /* /// "cmdIsoXFer()" */
1592 *======================================================================
1593 * cmdIsoXFer(ioreq, unit, base)
1594 *======================================================================
1596 * This is the device UHCMD_ISOXFER routine.
1598 * First it check if the usb is in proper state and if user passed arguments
1599 * are valid. If everything is ok, the request is linked to queue of
1600 * pending transfer requests.
1604 WORD
cmdIsoXFer(struct IOUsbHWReq
*ioreq
,
1605 struct PCIUnit
*unit
,
1606 struct PCIDevice
*base
)
1608 struct PCIController
*hc
;
1610 KPRINTF(10, ("UHCMD_ISOXFER ioreq: 0x%p\n", ioreq
));
1611 uhwGetUsbState(ioreq
, unit
, base
);
1612 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1614 return(UHIOERR_USBOFFLINE
);
1617 if(ioreq
->iouh_Flags
& UHFF_LOWSPEED
)
1619 return(UHIOERR_BADPARAMS
);
1622 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1625 return(UHIOERR_HOSTERROR
);
1628 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1629 ioreq
->iouh_Actual
= 0;
1632 AddTail(&hc
->hc_IsoXFerQueue
, (struct Node
*) ioreq
);
1634 SureCause(base
, &hc
->hc_CompleteInt
);
1636 KPRINTF(10, ("UHCMD_ISOXFER processed ioreq: 0x%p\n", ioreq
));
1637 return(RC_DONTREPLY
);
1641 /* /// "cmdIntXFer()" */
1643 *======================================================================
1644 * cmdIntXFer(ioreq, unit, base)
1645 *======================================================================
1647 * This is the device UHCMD_INTXFER routine.
1649 * First it check if the usb is in proper state and if user passed arguments
1650 * are valid. If everything is ok, the request is linked to queue of
1651 * pending transfer requests.
1655 WORD
cmdIntXFer(struct IOUsbHWReq
*ioreq
,
1656 struct PCIUnit
*unit
,
1657 struct PCIDevice
*base
)
1659 struct PCIController
*hc
;
1661 KPRINTF(10, ("UHCMD_INTXFER ioreq: 0x%p\n", ioreq
));
1662 //uhwDelayMS(1000, unit); /* Wait 200 ms */
1663 uhwGetUsbState(ioreq
, unit
, base
);
1664 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1666 return(UHIOERR_USBOFFLINE
);
1669 /* Root Hub Emulation */
1670 if(ioreq
->iouh_DevAddr
== unit
->hu_RootHubAddr
)
1672 return(cmdIntXFerRootHub(ioreq
, unit
, base
));
1675 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1678 return(UHIOERR_HOSTERROR
);
1681 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1682 ioreq
->iouh_Actual
= 0;
1685 AddTail(&hc
->hc_IntXFerQueue
, (struct Node
*) ioreq
);
1687 SureCause(base
, &hc
->hc_CompleteInt
);
1689 KPRINTF(10, ("UHCMD_INTXFER processed ioreq: 0x%p\n", ioreq
));
1690 return(RC_DONTREPLY
);
1694 /* /// "cmdFlush()" */
1696 *======================================================================
1697 * cmdFlush(ioreq, base)
1698 *======================================================================
1700 * This is the device CMD_FLUSH routine.
1702 * This routine abort all pending transfer requests.
1706 WORD
cmdFlush(struct IOUsbHWReq
*ioreq
,
1707 struct PCIUnit
*unit
,
1708 struct PCIDevice
*base
)
1710 struct IOUsbHWReq
*cmpioreq
;
1711 struct PCIController
*hc
;
1714 KPRINTF(10, ("CMD_FLUSH ioreq: 0x%p\n", ioreq
));
1717 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1718 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1720 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1721 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1722 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1723 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1725 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1726 while(hc
->hc_Node
.ln_Succ
)
1728 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1729 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1731 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1732 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1733 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1734 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1736 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1737 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1739 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1740 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1741 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1742 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1744 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1745 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1747 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1748 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1749 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1750 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1752 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1753 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1755 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1756 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1757 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1758 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1760 switch(hc
->hc_HCIType
)
1763 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1764 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1766 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1767 devadrep
= (cmpioreq
->iouh_DevAddr
<<5) + cmpioreq
->iouh_Endpoint
+ ((cmpioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
1768 unit
->hu_DevBusyReq
[devadrep
] = NULL
;
1769 uhciFreeQContext(hc
, (struct UhciQH
*) cmpioreq
->iouh_DriverPrivate1
);
1770 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1771 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1772 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1777 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1778 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1780 ehciFreeAsyncContext(hc
, cmpioreq
);
1781 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1782 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1783 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1785 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
1786 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1788 ehciFreePeriodicContext(hc
, cmpioreq
);
1789 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1790 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1791 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
1795 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1804 /* /// "NSD stuff" */
1807 const UWORD NSDSupported
[] =
1809 CMD_FLUSH
, CMD_RESET
,
1810 UHCMD_QUERYDEVICE
, UHCMD_USBRESET
,
1811 UHCMD_USBRESUME
, UHCMD_USBSUSPEND
,
1812 UHCMD_USBOPER
, UHCMD_CONTROLXFER
,
1813 UHCMD_ISOXFER
, UHCMD_INTXFER
,
1815 NSCMD_DEVICEQUERY
, 0
1818 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
1819 struct PCIUnit
*unit
,
1820 struct PCIDevice
*base
)
1822 struct my_NSDeviceQueryResult
*query
;
1824 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
1826 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%p query: 0x%p\n", ioreq
, query
));
1833 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
1834 (query
->DevQueryFormat
!= 0) ||
1835 (query
->SizeAvailable
!= 0))
1837 /* Return error. This is special handling, since iorequest is only
1838 guaranteed to be sizeof(struct IOStdReq). If we'd let our
1839 devBeginIO dispatcher return the error, it would trash some
1840 memory past end of the iorequest (ios2_WireError field).
1842 ioreq
->io_Error
= IOERR_NOCMD
;
1843 TermIO((struct IOUsbHWReq
*) ioreq
, base
);
1845 /* Don't reply, we already did.
1847 return RC_DONTREPLY
;
1850 ioreq
->io_Actual
= query
->SizeAvailable
1851 = sizeof(struct my_NSDeviceQueryResult
);
1852 query
->DeviceType
= NSDEVTYPE_USBHARDWARE
;
1853 query
->DeviceSubType
= 0;
1854 query
->SupportedCommands
= NSDSupported
;
1856 /* Return success (note that this will NOT poke ios2_WireError).
1862 /* /// "TermIO()" */
1864 *===========================================================
1865 * TermIO(ioreq, base)
1866 *===========================================================
1868 * Return completed ioreq to sender.
1872 void TermIO(struct IOUsbHWReq
*ioreq
,
1873 struct PCIDevice
*base
)
1875 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1877 /* If not quick I/O, reply the message
1879 if(!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
))
1881 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
1886 /* /// "cmdAbortIO()" */
1887 BOOL
cmdAbortIO(struct IOUsbHWReq
*ioreq
, struct PCIDevice
*base
)
1889 struct PCIUnit
*unit
= (struct PCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
1890 struct IOUsbHWReq
*cmpioreq
;
1891 struct PCIController
*hc
;
1893 BOOL foundit
= FALSE
;
1895 KPRINTF(10, ("cmdAbort(%p)\n", ioreq
));
1898 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1899 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1901 if(ioreq
== cmpioreq
)
1903 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
1907 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1910 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1911 while(hc
->hc_Node
.ln_Succ
)
1913 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1914 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1916 if(ioreq
== cmpioreq
)
1921 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1925 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1926 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1928 if(ioreq
== cmpioreq
)
1933 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1938 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1939 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1941 if(ioreq
== cmpioreq
)
1946 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1951 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1952 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1954 if(ioreq
== cmpioreq
)
1959 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1964 // IOReq is probably pending in some transfer structure
1965 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
1966 switch(hc
->hc_HCIType
)
1969 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1970 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1972 if(ioreq
== cmpioreq
)
1975 unit
->hu_DevBusyReq
[devadrep
] = NULL
;
1976 uhciFreeQContext(hc
, (struct UhciQH
*) ioreq
->iouh_DriverPrivate1
);
1979 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1984 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1985 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1987 if(ioreq
== cmpioreq
)
1990 * Request's ED is in use by the HC, as well as its TDs and
1992 * Schedule abort on the HC driver and reply the request
1993 * only when done. However return success.
1995 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1996 ohciAbortRequest(hc
, ioreq
);
2000 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2005 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2006 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2008 if(ioreq
== cmpioreq
)
2011 * CHECKME: Perhaps immediate freeing can cause issues similar to OHCI.
2012 * Should synchronized abort routine be implemented here too ?
2014 ehciFreeAsyncContext(hc
, ioreq
);
2016 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2017 TermIO(ioreq
, base
);
2020 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2022 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
2023 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2025 if(ioreq
== cmpioreq
)
2027 ehciFreePeriodicContext(hc
, ioreq
);
2029 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2030 TermIO(ioreq
, base
);
2033 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2041 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
2044 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2050 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2051 TermIO(ioreq
, base
);
2055 KPRINTF(20, ("WARNING, could not abort unknown IOReq %p\n", ioreq
));
2061 /* /// "uhwCheckRootHubChanges()" */
2062 void uhwCheckRootHubChanges(struct PCIUnit
*unit
)
2064 struct IOUsbHWReq
*ioreq
;
2066 if(unit
->hu_RootPortChanges
&& unit
->hu_RHIOQueue
.lh_Head
->ln_Succ
)
2068 KPRINTF(1, ("Portchange map %04lx\n", unit
->hu_RootPortChanges
));
2070 ioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
2071 while(((struct Node
*) ioreq
)->ln_Succ
)
2073 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
2074 if((unit
->hu_RootHubPorts
< 8) || (ioreq
->iouh_Length
== 1))
2076 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->hu_RootPortChanges
;
2077 ioreq
->iouh_Actual
= 1;
2079 ((UBYTE
*) ioreq
->iouh_Data
)[0] = unit
->hu_RootPortChanges
;
2080 ((UBYTE
*) ioreq
->iouh_Data
)[1] = unit
->hu_RootPortChanges
>>8;
2081 ioreq
->iouh_Actual
= 2;
2083 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
2084 ioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
2086 unit
->hu_RootPortChanges
= 0;
2092 /* /// "uhwCheckSpecialCtrlTransfers()" */
2093 void uhwCheckSpecialCtrlTransfers(struct PCIController
*hc
, struct IOUsbHWReq
*ioreq
)
2095 struct PCIUnit
*unit
= hc
->hc_Unit
;
2097 /* Clear Feature(Endpoint halt) */
2098 if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_STANDARD
|URTF_ENDPOINT
)) &&
2099 (ioreq
->iouh_SetupData
.bRequest
== USR_CLEAR_FEATURE
) &&
2100 (ioreq
->iouh_SetupData
.wValue
== AROS_WORD2LE(UFS_ENDPOINT_HALT
)))
2102 KPRINTF(10, ("Resetting toggle bit for endpoint %ld\n", AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0xf));
2103 unit
->hu_DevDataToggle
[(ioreq
->iouh_DevAddr
<<5)|(AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0xf)|((AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0x80)>>3)] = 0;
2105 else if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_STANDARD
|URTF_DEVICE
)) &&
2106 (ioreq
->iouh_SetupData
.bRequest
== USR_SET_ADDRESS
))
2108 /* Set Address -> clear all endpoints */
2110 ULONG adr
= AROS_WORD2BE(ioreq
->iouh_SetupData
.wValue
)>>3;
2111 KPRINTF(10, ("Resetting toggle bits for device address %ld\n", adr
>>5));
2112 for(epnum
= 0; epnum
< 31; epnum
++)
2114 unit
->hu_DevDataToggle
[adr
+epnum
] = 0;
2116 // transfer host controller ownership
2117 unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
] = NULL
;
2118 unit
->hu_DevControllers
[adr
>>5] = hc
;
2120 else if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_CLASS
|URTF_OTHER
)) &&
2121 (ioreq
->iouh_SetupData
.bRequest
== USR_SET_FEATURE
) &&
2122 (ioreq
->iouh_SetupData
.wValue
== AROS_WORD2LE(UFS_PORT_RESET
)))
2124 // a hub will be enumerating a device on this host controller soon!
2125 KPRINTF(10, ("Hub RESET caught, assigning Dev0 to %p!\n", hc
));
2126 unit
->hu_DevControllers
[0] = hc
;
2131 /* /// "uhwNakTimeoutInt()" */
2132 AROS_INTH1(uhwNakTimeoutInt
, struct PCIUnit
*, unit
)
2136 struct PCIDevice
*base
= unit
->hu_Device
;
2137 struct PCIController
*hc
;
2138 struct IOUsbHWReq
*ioreq
;
2148 KPRINTF(1, ("Enter NakTimeoutInt(0x%p)\n", unit
));
2150 // check for port status change for UHCI and frame rollovers and NAK Timeouts
2151 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
2152 while(hc
->hc_Node
.ln_Succ
)
2154 if (!(hc
->hc_Flags
& HCF_ONLINE
))
2156 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2160 switch(hc
->hc_HCIType
)
2165 uhciUpdateFrameCounter(hc
);
2166 framecnt
= hc
->hc_FrameCounter
;
2169 ioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2170 while(((struct Node
*) ioreq
)->ln_Succ
)
2172 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2174 uqh
= (struct UhciQH
*) ioreq
->iouh_DriverPrivate1
;
2177 KPRINTF(1, ("Examining IOReq=%p with UQH=%p\n", ioreq
, uqh
));
2178 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2179 linkelem
= READMEM32_LE(&uqh
->uqh_Element
);
2180 if(linkelem
& UHCI_TERMINATE
)
2182 KPRINTF(1, ("UQH terminated %08lx\n", linkelem
));
2183 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2185 // give the thing the chance to exit gracefully
2186 KPRINTF(20, ("Terminated? NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2190 utd
= (struct UhciTD
*) (((IPTR
)linkelem
& UHCI_PTRMASK
) - hc
->hc_PCIVirtualAdjust
- 16); // struct UhciTD starts 16 before physical TD
2191 ctrlstatus
= READMEM32_LE(&utd
->utd_CtrlStatus
);
2192 if(ctrlstatus
& UTCF_ACTIVE
)
2194 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2196 // give the thing the chance to exit gracefully
2197 KPRINTF(20, ("NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2198 ctrlstatus
&= ~UTCF_ACTIVE
;
2199 WRITEMEM32_LE(&utd
->utd_CtrlStatus
, ctrlstatus
);
2203 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2205 // give the thing the chance to exit gracefully
2206 KPRINTF(20, ("Terminated? NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2213 ioreq
= (struct IOUsbHWReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
2216 uhciCheckPortStatusChange(hc
);
2223 ohciUpdateFrameCounter(hc
);
2224 framecnt
= hc
->hc_FrameCounter
;
2226 ioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2227 while(((struct Node
*) ioreq
)->ln_Succ
)
2229 // Remember the successor because ohciAbortRequest() will move the request to another list
2230 struct IOUsbHWReq
*succ
= (struct IOUsbHWReq
*)ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2232 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2234 KPRINTF(1, ("Examining IOReq=%p with OED=%p\n", ioreq
, ioreq
->iouh_DriverPrivate1
));
2235 if (ioreq
->iouh_DriverPrivate1
)
2237 KPRINTF(1, ("CTRL=%04lx, CMD=%01lx, F=%ld, hccaDH=%08lx, hcDH=%08lx, CH=%08lx, CCH=%08lx, IntEn=%08lx\n",
2238 READREG32_LE(hc
->hc_RegBase
, OHCI_CONTROL
),
2239 READREG32_LE(hc
->hc_RegBase
, OHCI_CMDSTATUS
),
2240 READREG32_LE(hc
->hc_RegBase
, OHCI_FRAMECOUNT
),
2241 READMEM32_LE(&hc
->hc_OhciHCCA
->oha_DoneHead
),
2242 READREG32_LE(hc
->hc_RegBase
, OHCI_DONEHEAD
),
2243 READREG32_LE(hc
->hc_RegBase
, OHCI_CTRL_HEAD_ED
),
2244 READREG32_LE(hc
->hc_RegBase
, OHCI_CTRL_ED
),
2245 READREG32_LE(hc
->hc_RegBase
, OHCI_INTEN
)));
2247 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2248 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2250 // give the thing the chance to exit gracefully
2251 KPRINTF(200, ("HC 0x%p NAK timeout %ld > %ld, IOReq=%p\n", hc
, framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2252 ioreq
->iouh_Req
.io_Error
= UHIOERR_NAKTIMEOUT
;
2253 ohciAbortRequest(hc
, ioreq
);
2265 ehciUpdateFrameCounter(hc
);
2266 framecnt
= hc
->hc_FrameCounter
;
2268 for(cnt
= 0; cnt
< 1; cnt
++)
2270 ioreq
= (struct IOUsbHWReq
*) (cnt
? hc
->hc_PeriodicTDQueue
.lh_Head
: hc
->hc_TDQueue
.lh_Head
);
2271 while(((struct Node
*) ioreq
)->ln_Succ
)
2273 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2275 eqh
= (struct EhciQH
*) ioreq
->iouh_DriverPrivate1
;
2278 KPRINTF(1, ("Examining IOReq=%p with EQH=%p\n", ioreq
, eqh
));
2279 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2280 ctrlstatus
= READMEM32_LE(&eqh
->eqh_CtrlStatus
);
2281 if(ctrlstatus
& ETCF_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
&= ~ETCF_ACTIVE
;
2288 ctrlstatus
|= ETSF_HALTED
;
2289 WRITEMEM32_LE(&eqh
->eqh_CtrlStatus
, ctrlstatus
);
2293 if(ctrlstatus
& ETCF_READYINTEN
)
2295 KPRINTF(10, ("INT missed?!? Manually causing it! %08lx, IOReq=%p\n",
2296 ctrlstatus
, ioreq
));
2302 ioreq
= (struct IOUsbHWReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
2311 SureCause(base
, &hc
->hc_CompleteInt
);
2314 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2317 uhwCheckRootHubChanges(unit
);
2319 unit
->hu_NakTimeoutReq
.tr_time
.tv_micro
= 150*1000;
2320 SendIO((APTR
) &unit
->hu_NakTimeoutReq
);
2322 KPRINTF(1, ("Exit NakTimeoutInt(0x%p)\n", unit
));