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 unit
->hu_NakTimeoutReq
.tr_node
.io_Message
.mn_ReplyPort
= &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 Cause(&unit
->hu_NakTimeoutInt
);
183 return(&unit
->hu_Unit
);
185 ioreq
->iouh_Req
.io_Error
= IOERR_SELFTEST
;
186 KPRINTF(20, ("Hardware allocation failure!\n"));
188 uhwCloseTimer(unit
, base
);
194 /* /// "Close_Unit()" */
195 void Close_Unit(struct PCIDevice
*base
,
196 struct PCIUnit
*unit
,
197 struct IOUsbHWReq
*ioreq
)
199 /* Disable all interrupts */
200 unit
->hu_NakTimeoutMsgPort
.mp_Flags
= PA_IGNORE
;
201 unit
->hu_NakTimeoutInt
.is_Node
.ln_Type
= NT_SOFTINT
;
202 AbortIO((APTR
) &unit
->hu_NakTimeoutReq
);
206 uhwCloseTimer(unit
, base
);
207 unit
->hu_UnitAllocated
= FALSE
;
211 /* /// "uhwGetUsbState()" */
212 UWORD
uhwGetUsbState(struct IOUsbHWReq
*ioreq
,
213 struct PCIUnit
*unit
,
214 struct PCIDevice
*base
)
216 return(ioreq
->iouh_State
= UHSF_OPERATIONAL
);
220 /* /// "cmdReset()" */
222 *======================================================================
223 * cmdReset(ioreq, unit, base)
224 *======================================================================
226 * This is the device CMD_RESET routine.
228 * Resets the whole USB hardware. Goes into USBOperational mode right
229 * after. Must NOT be called from an interrupt.
233 WORD
cmdReset(struct IOUsbHWReq
*ioreq
,
234 struct PCIUnit
*unit
,
235 struct PCIDevice
*base
)
237 KPRINTF(10, ("CMD_RESET ioreq: 0x%p\n", ioreq
));
240 uhwGetUsbState(ioreq
, unit
, base
);
242 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
246 return UHIOERR_USBOFFLINE
;
250 /* /// "cmdUsbReset()" */
252 *======================================================================
253 * cmdUsbReset(ioreq, unit, base)
254 *======================================================================
256 * This is the device UHCMD_USBRESET routine.
258 * Resets the USB bus. Goes into USBOperational mode right after. Must
259 * NOT be called from an interrupt.
263 WORD
cmdUsbReset(struct IOUsbHWReq
*ioreq
,
264 struct PCIUnit
*unit
,
265 struct PCIDevice
*base
)
267 KPRINTF(10, ("UHCMD_USBRESET ioreq: 0x%p\n", ioreq
));
270 uhwGetUsbState(ioreq
, unit
, base
);
272 unit
->hu_FrameCounter
= 1;
273 unit
->hu_RootHubAddr
= 0;
275 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
279 return UHIOERR_USBOFFLINE
;
283 /* /// "cmdUsbResume()" */
285 *======================================================================
286 * cmdUsbResume(ioreq, unit, base)
287 *======================================================================
289 * This is the device UHCMD_USBRESUME routine.
291 * Tries to resume from USBSuspend mode into USBOperational.
292 * Must NOT be called from an interrupt.
296 WORD
cmdUsbResume(struct IOUsbHWReq
*ioreq
,
297 struct PCIUnit
*unit
,
298 struct PCIDevice
*base
)
300 KPRINTF(10, ("UHCMD_USBRESUME ioreq: 0x%p\n", ioreq
));
303 uhwGetUsbState(ioreq
, unit
, base
);
304 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
308 return UHIOERR_USBOFFLINE
;
312 /* /// "cmdUsbSuspend()" */
314 *======================================================================
315 * cmdUsbSuspend(ioreq, unit, base)
316 *======================================================================
318 * This is the device UHCMD_USBSUSPEND routine.
320 * Sets the USB into USBSuspend mode.
321 * Must NOT be called from an interrupt.
325 WORD
cmdUsbSuspend(struct IOUsbHWReq
*ioreq
,
326 struct PCIUnit
*unit
,
327 struct PCIDevice
*base
)
329 KPRINTF(10, ("UHCMD_USBSUSPEND ioreq: 0x%p\n", ioreq
));
332 uhwGetUsbState(ioreq
, unit
, base
);
333 if(ioreq
->iouh_State
& UHSF_SUSPENDED
)
337 return UHIOERR_USBOFFLINE
;
341 /* /// "cmdUsbOper()" */
343 *======================================================================
344 * cmdUsbOper(ioreq, unit, base)
345 *======================================================================
347 * This is the device UHCMD_USBOPER routine.
349 * Sets the USB into USBOperational mode.
350 * Must NOT be called from an interrupt.
354 WORD
cmdUsbOper(struct IOUsbHWReq
*ioreq
,
355 struct PCIUnit
*unit
,
356 struct PCIDevice
*base
)
358 KPRINTF(10, ("UHCMD_USBOPER ioreq: 0x%p\n", ioreq
));
361 uhwGetUsbState(ioreq
, unit
, base
);
362 if(ioreq
->iouh_State
& UHSF_OPERATIONAL
)
366 return UHIOERR_USBOFFLINE
;
370 /* /// "cmdQueryDevice()" */
372 *======================================================================
373 * cmdQueryDevice(ioreq, unit, base)
374 *======================================================================
376 * This is the device UHCMD_QUERYDEVICE routine.
378 * Returns information about the hardware.
382 WORD
cmdQueryDevice(struct IOUsbHWReq
*ioreq
,
383 struct PCIUnit
*unit
,
384 struct PCIDevice
*base
)
386 struct TagItem
*taglist
= (struct TagItem
*) ioreq
->iouh_Data
;
390 KPRINTF(10, ("UHCMD_QUERYDEVICE ioreq: 0x%p, taglist: 0x%p\n", ioreq
, taglist
));
392 if((tag
= FindTagItem(UHA_State
, taglist
)))
394 *((ULONG
*) tag
->ti_Data
) = (ULONG
) uhwGetUsbState(ioreq
, unit
, base
);
397 if((tag
= FindTagItem(UHA_Manufacturer
, taglist
)))
399 *((STRPTR
*) tag
->ti_Data
) = "Chris Hodges";
402 if((tag
= FindTagItem(UHA_ProductName
, taglist
)))
404 *((STRPTR
*) tag
->ti_Data
) = unit
->hu_ProductName
;
407 if((tag
= FindTagItem(UHA_Description
, taglist
)))
409 *((STRPTR
*) tag
->ti_Data
) = "Generic adaptive host controller driver for PCI cards";
412 if((tag
= FindTagItem(UHA_Copyright
, taglist
)))
414 *((STRPTR
*) tag
->ti_Data
) ="©2007-2009 Chris Hodges";
417 if((tag
= FindTagItem(UHA_Version
, taglist
)))
419 *((ULONG
*) tag
->ti_Data
) = VERSION_NUMBER
;
422 if((tag
= FindTagItem(UHA_Revision
, taglist
)))
424 *((ULONG
*) tag
->ti_Data
) = REVISION_NUMBER
;
427 if((tag
= FindTagItem(UHA_DriverVersion
, taglist
)))
429 *((ULONG
*) tag
->ti_Data
) = 0x220;
432 if((tag
= FindTagItem(UHA_Capabilities
, taglist
)))
434 *((ULONG
*) tag
->ti_Data
) = UHCF_USB20
;
437 ioreq
->iouh_Actual
= count
;
442 /* /// "cmdControlXFerRootHub()" */
443 WORD
cmdControlXFerRootHub(struct IOUsbHWReq
*ioreq
,
444 struct PCIUnit
*unit
,
445 struct PCIDevice
*base
)
447 struct PCIController
*hc
;
448 struct PCIController
*chc
;
449 UWORD rt
= ioreq
->iouh_SetupData
.bmRequestType
;
450 UWORD req
= ioreq
->iouh_SetupData
.bRequest
;
451 UWORD idx
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
);
452 UWORD val
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wValue
);
453 UWORD len
= AROS_WORD2LE(ioreq
->iouh_SetupData
.wLength
);
455 ULONG numports
= unit
->hu_RootHubPorts
;
459 if(ioreq
->iouh_Endpoint
)
461 return(UHIOERR_STALL
);
464 if(len
!= ioreq
->iouh_Length
)
466 KPRINTF(20, ("RH: Len (%ld != %ld) mismatch!\n", len
!= ioreq
->iouh_Length
));
467 return(UHIOERR_STALL
);
471 case (URTF_STANDARD
|URTF_DEVICE
):
474 case USR_SET_ADDRESS
:
475 KPRINTF(1, ("RH: SetAddress = %ld\n", val
));
476 unit
->hu_RootHubAddr
= val
;
477 ioreq
->iouh_Actual
= len
;
480 case USR_SET_CONFIGURATION
:
481 KPRINTF(1, ("RH: SetConfiguration=%ld\n", val
));
482 ioreq
->iouh_Actual
= len
;
487 case (URTF_IN
|URTF_STANDARD
|URTF_DEVICE
):
490 case USR_GET_DESCRIPTOR
:
494 KPRINTF(1, ("RH: GetDeviceDescriptor (%ld)\n", len
));
495 ioreq
->iouh_Actual
= (len
> sizeof(struct UsbStdDevDesc
)) ? sizeof(struct UsbStdDevDesc
) : len
;
496 CopyMem((APTR
) &RHDevDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
497 if(ioreq
->iouh_Length
>= sizeof(struct UsbStdDevDesc
))
499 if(unit
->hu_RootHub20Ports
)
501 struct UsbStdDevDesc
*usdd
= (struct UsbStdDevDesc
*) ioreq
->iouh_Data
;
502 usdd
->bcdUSB
= AROS_WORD2LE(0x0200); // signal a highspeed root hub
503 usdd
->bDeviceProtocol
= 1; // single TT
509 case UDT_CONFIGURATION
:
512 KPRINTF(1, ("RH: GetConfigDescriptor (%ld)\n", len
));
513 CopyMem((APTR
) &RHCfgDesc
, tmpbuf
, 9);
514 CopyMem((APTR
) &RHIfDesc
, &tmpbuf
[9], 9);
515 CopyMem((APTR
) &RHEPDesc
, &tmpbuf
[9+9], 7);
516 if(unit
->hu_RootHub20Ports
)
518 struct UsbStdEPDesc
*usepd
= (struct UsbStdEPDesc
*) &tmpbuf
[9+9];
519 usepd
->bInterval
= 12; // 2048 µFrames
521 ioreq
->iouh_Actual
= (len
> 9+9+7) ? 9+9+7 : len
;
522 CopyMem(tmpbuf
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
527 if(val
& 0xff) /* get lang array */
529 CONST_STRPTR source
= NULL
;
530 UWORD
*mptr
= ioreq
->iouh_Data
;
532 KPRINTF(1, ("RH: GetString %04lx (%ld)\n", val
, len
));
533 if((val
& 0xff) > 4) /* index too high? */
535 return(UHIOERR_STALL
);
537 source
= RHStrings
[(val
& 0xff)-1];
540 ioreq
->iouh_Actual
= 2;
545 source
= RHStrings
[(val
& 0xff)-1];
546 *mptr
++ = AROS_WORD2BE((slen
<<9)|UDT_STRING
);
547 while(ioreq
->iouh_Actual
+1 < len
)
549 // special hack for unit number in root hub string
550 if(((val
& 0xff) == 2) && (source
[1] == 0))
552 *mptr
++ = AROS_WORD2LE('0' + unit
->hu_UnitNo
);
554 *mptr
++ = AROS_WORD2LE(*source
);
557 ioreq
->iouh_Actual
+= 2;
565 UWORD
*mptr
= ioreq
->iouh_Data
;
566 KPRINTF(1, ("RH: GetLangArray %04lx (%ld)\n", val
, len
));
569 ioreq
->iouh_Actual
= 2;
570 mptr
[0] = AROS_WORD2BE((4<<8)|UDT_STRING
);
573 ioreq
->iouh_Actual
+= 2;
574 mptr
[1] = AROS_WORD2LE(0x0409);
581 KPRINTF(1, ("RH: Unsupported Descriptor %04lx\n", idx
));
585 case USR_GET_CONFIGURATION
:
588 KPRINTF(1, ("RH: GetConfiguration\n"));
589 ((UBYTE
*) ioreq
->iouh_Data
)[0] = 1;
590 ioreq
->iouh_Actual
= len
;
597 case (URTF_CLASS
|URTF_OTHER
):
600 case USR_SET_FEATURE
:
601 if((!idx
) || (idx
> numports
))
603 KPRINTF(20, ("Port %ld out of range\n", idx
));
604 return(UHIOERR_STALL
);
606 chc
= unit
->hu_PortMap11
[idx
- 1];
607 if(unit
->hu_EhciOwned
[idx
- 1])
609 hc
= unit
->hu_PortMap20
[idx
- 1];
613 hciport
= unit
->hu_PortNum11
[idx
- 1];
615 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"));
617 switch(hc
->hc_HCIType
)
621 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
622 ULONG oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
); // these are clear-on-write!
623 ULONG newval
= oldval
;
626 /* case UFS_PORT_CONNECTION: not possible */
627 case UFS_PORT_ENABLE
:
628 KPRINTF(10, ("UHCI: Enabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "already" : "ok"));
629 newval
|= UHPF_PORTENABLE
;
633 case UFS_PORT_SUSPEND
:
634 newval
|= UHPF_PORTSUSPEND
;
635 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
; // manually fake suspend change
639 /* case UFS_PORT_OVER_CURRENT: not possible */
641 KPRINTF(10, ("UHCI: Resetting Port (%s)\n", newval
& UHPF_PORTRESET
? "already" : "ok"));
643 // this is an ugly blocking workaround to the inability of UHCI to clear reset automatically
644 newval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
645 newval
|= UHPF_PORTRESET
;
646 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
647 uhwDelayMS(25, unit
);
648 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
649 KPRINTF(10, ("UHCI: Reset=%s\n", newval
& UHPF_PORTRESET
? "GOOD" : "BAD!"));
650 // like windows does it
651 newval
&= ~UHPF_PORTRESET
;
652 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
653 uhwDelayMicro(50, unit
);
654 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
655 KPRINTF(10, ("UHCI: Reset=%s\n", newval
& UHPF_PORTRESET
? "BAD!" : "GOOD"));
656 newval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTRESET
);
657 newval
|= UHPF_PORTENABLE
;
658 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
659 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
|UPSF_PORT_ENABLE
; // manually fake reset change
665 newval
= READIO16_LE(hc
->hc_RegBase
, portreg
);
666 } while(--cnt
&& (!(newval
& UHPF_PORTENABLE
)));
669 KPRINTF(10, ("UHCI: Enabled after %ld ticks\n", 100-cnt
));
671 KPRINTF(20, ("UHCI: Port refuses to be enabled!\n"));
672 return(UHIOERR_HOSTERROR
);
674 // make enumeration possible
675 unit
->hu_DevControllers
[0] = hc
;
680 KPRINTF(10, ("UHCI: Powering Port\n"));
681 // ignore for UHCI, is always powered
685 /* case UFS_PORT_LOW_SPEED: not possible */
686 /* case UFS_C_PORT_CONNECTION:
687 case UFS_C_PORT_ENABLE:
688 case UFS_C_PORT_SUSPEND:
689 case UFS_C_PORT_OVER_CURRENT:
690 case UFS_C_PORT_RESET: */
694 KPRINTF(5, ("UHCI: Port %ld SET_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
695 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
703 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
704 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
708 /* case UFS_PORT_CONNECTION: not possible */
709 case UFS_PORT_ENABLE
:
710 KPRINTF(10, ("OHCI: Enabling Port (%s)\n", oldval
& OHPF_PORTENABLE
? "already" : "ok"));
711 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTENABLE
);
715 case UFS_PORT_SUSPEND
:
716 KPRINTF(10, ("OHCI: Suspending Port (%s)\n", oldval
& OHPF_PORTSUSPEND
? "already" : "ok"));
717 //hc->hc_PortChangeMap[hciport] |= UPSF_PORT_SUSPEND; // manually fake suspend change
718 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTSUSPEND
);
722 /* case UFS_PORT_OVER_CURRENT: not possible */
724 KPRINTF(10, ("OHCI: Resetting Port (%s)\n", oldval
& OHPF_PORTRESET
? "already" : "ok"));
725 // make sure we have at least 50ms of reset time here, as required for a root hub port
726 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
727 uhwDelayMS(10, unit
);
728 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
729 uhwDelayMS(10, unit
);
730 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
731 uhwDelayMS(10, unit
);
732 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
733 uhwDelayMS(10, unit
);
734 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTRESET
);
735 uhwDelayMS(15, unit
);
736 oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
737 KPRINTF(10, ("OHCI: Reset release (%s %s)\n", oldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
738 oldval
& OHPF_PORTENABLE
? "enabled" : "not enabled"));
739 if(oldval
& OHPF_PORTRESET
)
741 uhwDelayMS(40, unit
);
742 oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
743 KPRINTF(10, ("OHCI: Reset 2nd release (%s %s)\n", oldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
744 oldval
& OHPF_PORTENABLE
? "enabled" : "still not enabled"));
746 // make enumeration possible
747 unit
->hu_DevControllers
[0] = hc
;
752 KPRINTF(10, ("OHCI: Powering Port (%s)\n", oldval
& OHPF_PORTPOWER
? "already" : "ok"));
753 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTPOWER
);
757 /* case UFS_PORT_LOW_SPEED: not possible */
758 /* case UFS_C_PORT_CONNECTION:
759 case UFS_C_PORT_ENABLE:
760 case UFS_C_PORT_SUSPEND:
761 case UFS_C_PORT_OVER_CURRENT:
762 case UFS_C_PORT_RESET: */
773 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
774 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
); // these are clear-on-write!
775 ULONG newval
= oldval
;
778 /* case UFS_PORT_CONNECTION: not possible */
779 case UFS_PORT_ENABLE
:
780 KPRINTF(10, ("EHCI: Enabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "already" : "ok"));
781 newval
|= EHPF_PORTENABLE
;
785 case UFS_PORT_SUSPEND
:
786 newval
|= EHPF_PORTSUSPEND
;
787 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
; // manually fake suspend change
791 /* case UFS_PORT_OVER_CURRENT: not possible */
793 KPRINTF(10, ("EHCI: Resetting Port (%s)\n", newval
& EHPF_PORTRESET
? "already" : "ok"));
795 // this is an ugly blocking workaround to the inability of EHCI to clear reset automatically
796 newval
&= ~(EHPF_PORTSUSPEND
|EHPF_PORTENABLE
);
797 newval
|= EHPF_PORTRESET
;
798 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
799 uhwDelayMS(50, unit
);
800 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
|EHPF_PORTENABLE
);
801 KPRINTF(10, ("EHCI: Reset=%s\n", newval
& EHPF_PORTRESET
? "GOOD" : "BAD!"));
802 newval
&= ~EHPF_PORTRESET
;
803 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
804 uhwDelayMS(10, unit
);
805 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
);
806 KPRINTF(10, ("EHCI: Reset=%s\n", newval
& EHPF_PORTRESET
? "BAD!" : "GOOD"));
807 KPRINTF(10, ("EHCI: Highspeed=%s\n", newval
& EHPF_PORTENABLE
? "YES!" : "NO"));
808 KPRINTF(10, ("EHCI: Port status=%08lx\n", newval
));
809 if(!(newval
& EHPF_PORTENABLE
) && unit
->hu_PortMap11
[idx
- 1] != NULL
)
811 // if not highspeed, release ownership
812 KPRINTF(20, ("EHCI: Transferring ownership to UHCI/OHCI port %ld\n", unit
->hu_PortNum11
[idx
- 1]));
813 KPRINTF(10, ("EHCI: Device is %s\n", newval
& EHPF_LINESTATUS_DM
? "LOWSPEED" : "FULLSPEED"));
814 newval
|= EHPF_NOTPORTOWNER
;
817 KPRINTF(20, ("EHCI has no companion controller, can't transfer ownership!\n"));
818 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
819 return(UHIOERR_HOSTERROR
);
821 switch(chc
->hc_HCIType
)
825 UWORD uhcihciport
= unit
->hu_PortNum11
[idx
- 1];
826 UWORD uhciportreg
= uhcihciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
827 ULONG __unused uhcinewval
= READREG16_LE(chc
->hc_RegBase
, uhciportreg
);
829 KPRINTF(10, ("UHCI Port status before handover=%04lx\n", uhcinewval
));
835 UWORD ohcihciport
= unit
->hu_PortNum11
[idx
- 1];
836 UWORD ohciportreg
= OHCI_PORTSTATUS
+ (ohcihciport
<<2);
837 ULONG __unused ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
839 KPRINTF(10, ("OHCI: Port status before handover=%08lx\n", ohcioldval
));
840 KPRINTF(10, ("OHCI: Powering Port (%s)\n", ohcioldval
& OHPF_PORTPOWER
? "already" : "ok"));
841 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTPOWER
);
842 uhwDelayMS(10, unit
);
843 KPRINTF(10, ("OHCI: Port status after handover=%08lx\n", READREG32_LE(chc
->hc_RegBase
, ohciportreg
)));
847 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
);
848 KPRINTF(10, ("EHCI: Port status (reread)=%08lx\n", newval
));
849 newval
|= EHPF_NOTPORTOWNER
;
850 unit
->hu_EhciOwned
[idx
- 1] = FALSE
;
851 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
852 uhwDelayMS(90, unit
);
853 KPRINTF(10, ("EHCI: Port status (after handover)=%08lx\n", READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
|EHPF_PORTSUSPEND
)));
854 // enable companion controller port
855 switch(chc
->hc_HCIType
)
859 UWORD uhcihciport
= unit
->hu_PortNum11
[idx
- 1];
860 UWORD uhciportreg
= uhcihciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
863 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
864 KPRINTF(10, ("UHCI: Reset=%s\n", uhcinewval
& UHPF_PORTRESET
? "BAD!" : "GOOD"));
865 if((uhcinewval
& UHPF_PORTRESET
))//|| (newval & EHPF_LINESTATUS_DM))
867 // this is an ugly blocking workaround to the inability of UHCI to clear reset automatically
868 KPRINTF(20, ("UHCI: Uhm, reset was bad!\n"));
869 uhcinewval
&= ~(UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
870 uhcinewval
|= UHPF_PORTRESET
;
871 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
872 uhwDelayMS(50, unit
);
873 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
|UHPF_PORTENABLE
);
874 KPRINTF(10, ("UHCI: ReReset=%s\n", uhcinewval
& UHPF_PORTRESET
? "GOOD" : "BAD!"));
875 uhcinewval
&= ~UHPF_PORTRESET
;
876 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
877 uhwDelayMicro(50, unit
);
878 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
|UHPF_PORTSUSPEND
);
879 KPRINTF(10, ("UHCI: ReReset=%s\n", uhcinewval
& UHPF_PORTRESET
? "STILL BAD!" : "GOOD"));
881 uhcinewval
&= ~UHPF_PORTRESET
;
882 uhcinewval
|= UHPF_PORTENABLE
;
883 WRITEIO16_LE(chc
->hc_RegBase
, uhciportreg
, uhcinewval
);
884 chc
->hc_PortChangeMap
[uhcihciport
] |= UPSF_PORT_RESET
|UPSF_PORT_ENABLE
; // manually fake reset change
890 uhcinewval
= READIO16_LE(chc
->hc_RegBase
, uhciportreg
);
891 } while(--cnt
&& (!(uhcinewval
& UHPF_PORTENABLE
)));
894 KPRINTF(10, ("UHCI: Enabled after %ld ticks\n", 100-cnt
));
896 KPRINTF(20, ("UHCI: Port refuses to be enabled!\n"));
897 return(UHIOERR_HOSTERROR
);
904 UWORD ohcihciport
= unit
->hu_PortNum11
[idx
- 1];
905 UWORD ohciportreg
= OHCI_PORTSTATUS
+ (ohcihciport
<<2);
906 ULONG ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
907 KPRINTF(10, ("OHCI: Resetting Port (%s)\n", ohcioldval
& OHPF_PORTRESET
? "already" : "ok"));
908 // make sure we have at least 50ms of reset time here, as required for a root hub port
909 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
910 uhwDelayMS(10, unit
);
911 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
912 uhwDelayMS(10, unit
);
913 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
914 uhwDelayMS(10, unit
);
915 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
916 uhwDelayMS(10, unit
);
917 WRITEREG32_LE(chc
->hc_RegBase
, ohciportreg
, OHPF_PORTRESET
);
918 uhwDelayMS(15, unit
);
919 ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
920 KPRINTF(10, ("OHCI: Reset release (%s %s)\n", ohcioldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
921 ohcioldval
& OHPF_PORTENABLE
? "enabled" : "not enabled"));
922 if(ohcioldval
& OHPF_PORTRESET
)
924 uhwDelayMS(40, unit
);
925 ohcioldval
= READREG32_LE(chc
->hc_RegBase
, ohciportreg
);
926 KPRINTF(10, ("OHCI: Reset 2nd release (%s %s)\n", ohcioldval
& OHPF_PORTRESET
? "didn't turn off" : "okay",
927 ohcioldval
& OHPF_PORTENABLE
? "enabled" : "still not enabled"));
933 // make enumeration possible
934 unit
->hu_DevControllers
[0] = chc
;
937 newval
&= ~EHPF_PORTRESET
;
938 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
939 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
; // manually fake reset change
940 uhwDelayMS(10, unit
);
945 newval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
946 } while(--cnt
&& (!(newval
& EHPF_PORTENABLE
)));
949 KPRINTF(10, ("EHCI: Enabled after %ld ticks\n", 100-cnt
));
951 KPRINTF(20, ("EHCI: Port refuses to be enabled!\n"));
952 return(UHIOERR_HOSTERROR
);
954 // make enumeration possible
955 unit
->hu_DevControllers
[0] = hc
;
961 KPRINTF(10, ("EHCI: Powering Port\n"));
962 newval
|= EHPF_PORTPOWER
;
966 /* case UFS_PORT_LOW_SPEED: not possible */
967 /* case UFS_C_PORT_CONNECTION:
968 case UFS_C_PORT_ENABLE:
969 case UFS_C_PORT_SUSPEND:
970 case UFS_C_PORT_OVER_CURRENT:
971 case UFS_C_PORT_RESET: */
975 KPRINTF(5, ("EHCI: Port %ld SET_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
976 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
985 case USR_CLEAR_FEATURE
:
986 if((!idx
) || (idx
> numports
))
988 KPRINTF(20, ("Port %ld out of range\n", idx
));
989 return(UHIOERR_STALL
);
991 if(unit
->hu_EhciOwned
[idx
- 1])
993 hc
= unit
->hu_PortMap20
[idx
- 1];
996 hc
= unit
->hu_PortMap11
[idx
- 1];
997 hciport
= unit
->hu_PortNum11
[idx
- 1];
999 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"));
1001 switch(hc
->hc_HCIType
)
1005 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
1006 ULONG oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
) & ~(UHPF_ENABLECHANGE
|UHPF_CONNECTCHANGE
); // these are clear-on-write!
1007 ULONG newval
= oldval
;
1010 case UFS_PORT_ENABLE
:
1011 KPRINTF(10, ("Disabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "ok" : "already"));
1012 newval
&= ~UHPF_PORTENABLE
;
1014 // disable enumeration
1015 unit
->hu_DevControllers
[0] = NULL
;
1018 case UFS_PORT_SUSPEND
:
1019 newval
&= ~UHPF_PORTSUSPEND
;
1023 case UFS_PORT_POWER
: // ignore for UHCI, there's no power control here
1024 KPRINTF(10, ("Disabling Power\n"));
1025 KPRINTF(10, ("Disabling Port (%s)\n", newval
& UHPF_PORTENABLE
? "ok" : "already"));
1026 newval
&= ~UHPF_PORTENABLE
;
1030 case UFS_C_PORT_CONNECTION
:
1031 newval
|= UHPF_CONNECTCHANGE
; // clear-on-write!
1032 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1036 case UFS_C_PORT_ENABLE
:
1037 newval
|= UHPF_ENABLECHANGE
; // clear-on-write!
1038 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1042 case UFS_C_PORT_SUSPEND
: // ignore for UHCI, there's no bit indicating this
1043 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
; // manually fake suspend change clearing
1047 case UFS_C_PORT_OVER_CURRENT
: // ignore for UHCI, there's no bit indicating this
1048 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
; // manually fake over current clearing
1052 case UFS_C_PORT_RESET
: // ignore for UHCI, there's no bit indicating this
1053 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
; // manually fake reset change clearing
1059 KPRINTF(5, ("Port %ld CLEAR_FEATURE %04lx->%04lx\n", idx
, oldval
, newval
));
1060 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, newval
);
1061 if(hc
->hc_PortChangeMap
[hciport
])
1063 unit
->hu_RootPortChanges
|= 1UL<<idx
;
1065 unit
->hu_RootPortChanges
&= ~(1UL<<idx
);
1074 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
1075 ULONG __unused oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1079 case UFS_PORT_ENABLE
:
1080 KPRINTF(10, ("Disabling Port (%s)\n", oldval
& OHPF_PORTENABLE
? "ok" : "already"));
1081 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTDISABLE
);
1085 case UFS_PORT_SUSPEND
:
1086 KPRINTF(10, ("Resuming Port (%s)\n", oldval
& OHPF_PORTSUSPEND
? "ok" : "already"));
1087 //hc->hc_PortChangeMap[hciport] &= ~UPSF_PORT_SUSPEND; // manually fake suspend change
1088 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESUME
);
1092 case UFS_PORT_POWER
:
1093 KPRINTF(10, ("Unpowering Port (%s)\n", oldval
& OHPF_PORTPOWER
? "ok" : "already"));
1094 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_PORTUNPOWER
);
1098 case UFS_C_PORT_CONNECTION
:
1099 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_CONNECTCHANGE
);
1100 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1104 case UFS_C_PORT_ENABLE
:
1105 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_ENABLECHANGE
);
1106 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1110 case UFS_C_PORT_SUSPEND
:
1111 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESUMEDTX
);
1112 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
;
1116 case UFS_C_PORT_OVER_CURRENT
:
1117 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_OVERCURRENTCHG
);
1118 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
;
1122 case UFS_C_PORT_RESET
:
1123 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, OHPF_RESETCHANGE
);
1124 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
;
1137 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
1138 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
) & ~(EHPF_OVERCURRENTCHG
|EHPF_ENABLECHANGE
|EHPF_CONNECTCHANGE
); // these are clear-on-write!
1139 ULONG newval
= oldval
;
1142 case UFS_PORT_ENABLE
:
1143 KPRINTF(10, ("Disabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "ok" : "already"));
1144 newval
&= ~EHPF_PORTENABLE
;
1146 // disable enumeration
1147 unit
->hu_DevControllers
[0] = NULL
;
1150 case UFS_PORT_SUSPEND
:
1151 newval
&= ~EHPF_PORTSUSPEND
;
1155 case UFS_PORT_POWER
: // ignore for UHCI, there's no power control here
1156 KPRINTF(10, ("Disabling Power (%s)\n", newval
& EHPF_PORTPOWER
? "ok" : "already"));
1157 KPRINTF(10, ("Disabling Port (%s)\n", newval
& EHPF_PORTENABLE
? "ok" : "already"));
1158 newval
&= ~(EHPF_PORTENABLE
|EHPF_PORTPOWER
);
1162 case UFS_C_PORT_CONNECTION
:
1163 newval
|= EHPF_CONNECTCHANGE
; // clear-on-write!
1164 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_CONNECTION
;
1168 case UFS_C_PORT_ENABLE
:
1169 newval
|= EHPF_ENABLECHANGE
; // clear-on-write!
1170 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_ENABLE
;
1174 case UFS_C_PORT_SUSPEND
: // ignore for EHCI, there's no bit indicating this
1175 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_SUSPEND
; // manually fake suspend change clearing
1179 case UFS_C_PORT_OVER_CURRENT
:
1180 newval
|= EHPF_OVERCURRENTCHG
; // clear-on-write!
1181 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_OVER_CURRENT
; // manually fake over current clearing
1185 case UFS_C_PORT_RESET
: // ignore for EHCI, there's no bit indicating this
1186 hc
->hc_PortChangeMap
[hciport
] &= ~UPSF_PORT_RESET
; // manually fake reset change clearing
1192 KPRINTF(5, ("Port %ld CLEAR_FEATURE %08lx->%08lx\n", idx
, oldval
, newval
));
1193 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, newval
);
1194 if(hc
->hc_PortChangeMap
[hciport
])
1196 unit
->hu_RootPortChanges
|= 1UL<<idx
;
1198 unit
->hu_RootPortChanges
&= ~(1UL<<idx
);
1210 case (URTF_IN
|URTF_CLASS
|URTF_OTHER
):
1213 case USR_GET_STATUS
:
1215 UWORD
*mptr
= ioreq
->iouh_Data
;
1216 if(len
!= sizeof(struct UsbPortStatus
))
1218 return(UHIOERR_STALL
);
1220 if((!idx
) || (idx
> numports
))
1222 KPRINTF(20, ("Port %ld out of range\n", idx
));
1223 return(UHIOERR_STALL
);
1225 if(unit
->hu_EhciOwned
[idx
- 1])
1227 hc
= unit
->hu_PortMap20
[idx
- 1];
1230 hc
= unit
->hu_PortMap11
[idx
- 1];
1231 hciport
= unit
->hu_PortNum11
[idx
- 1];
1233 switch(hc
->hc_HCIType
)
1237 UWORD portreg
= hciport
? UHCI_PORT2STSCTRL
: UHCI_PORT1STSCTRL
;
1238 UWORD oldval
= READIO16_LE(hc
->hc_RegBase
, portreg
);
1239 *mptr
= AROS_WORD2LE(UPSF_PORT_POWER
);
1240 if(oldval
& UHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1241 if(oldval
& UHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
);
1242 if(oldval
& UHPF_LOWSPEED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1243 if(oldval
& UHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1244 if(oldval
& UHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1246 KPRINTF(5, ("UHCI Port %ld is %s\n", idx
, oldval
& UHPF_LOWSPEED
? "LOWSPEED" : "FULLSPEED"));
1247 KPRINTF(5, ("UHCI Port %ld Status %08lx\n", idx
, *mptr
));
1250 if(oldval
& UHPF_ENABLECHANGE
)
1252 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1254 if(oldval
& UHPF_CONNECTCHANGE
)
1256 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1258 if(oldval
& UHPF_RESUMEDTX
)
1260 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
|UPSF_PORT_ENABLE
;
1262 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1263 WRITEIO16_LE(hc
->hc_RegBase
, portreg
, oldval
);
1264 KPRINTF(5, ("UHCI Port %ld Change %08lx\n", idx
, *mptr
));
1270 UWORD portreg
= OHCI_PORTSTATUS
+ (hciport
<<2);
1271 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1274 if(oldval
& OHPF_PORTPOWER
) *mptr
|= AROS_WORD2LE(UPSF_PORT_POWER
);
1275 if(oldval
& OHPF_OVERCURRENT
) *mptr
|= AROS_WORD2LE(UPSF_PORT_OVER_CURRENT
);
1276 if(oldval
& OHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1277 if(oldval
& OHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
);
1278 if(oldval
& OHPF_LOWSPEED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1279 if(oldval
& OHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1280 if(oldval
& OHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1282 KPRINTF(5, ("OHCI Port %ld (glob. %ld) is %s\n", hciport
, idx
, oldval
& OHPF_LOWSPEED
? "LOWSPEED" : "FULLSPEED"));
1283 KPRINTF(5, ("OHCI Port %ld Status %08lx (%08lx)\n", idx
, *mptr
, oldval
));
1286 if(oldval
& OHPF_OVERCURRENTCHG
)
1288 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_OVER_CURRENT
;
1290 if(oldval
& OHPF_RESETCHANGE
)
1292 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_RESET
;
1294 if(oldval
& OHPF_ENABLECHANGE
)
1296 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1298 if(oldval
& OHPF_CONNECTCHANGE
)
1300 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1302 if(oldval
& OHPF_RESUMEDTX
)
1304 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
;
1306 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1307 KPRINTF(5, ("OHCI Port %ld Change %08lx\n", idx
, *mptr
));
1313 UWORD portreg
= EHCI_PORTSC1
+ (hciport
<<2);
1314 ULONG oldval
= READREG32_LE(hc
->hc_RegBase
, portreg
);
1317 if(oldval
& EHPF_PORTCONNECTED
) *mptr
|= AROS_WORD2LE(UPSF_PORT_CONNECTION
);
1318 if(oldval
& EHPF_PORTENABLE
) *mptr
|= AROS_WORD2LE(UPSF_PORT_ENABLE
|UPSF_PORT_HIGH_SPEED
);
1319 if((oldval
& (EHPF_LINESTATUS_DM
|EHPF_PORTCONNECTED
|EHPF_PORTENABLE
)) ==
1320 (EHPF_LINESTATUS_DM
|EHPF_PORTCONNECTED
))
1322 KPRINTF(10, ("EHCI Port %ld is LOWSPEED\n", idx
));
1323 // we need to detect low speed devices prior to reset
1324 *mptr
|= AROS_WORD2LE(UPSF_PORT_LOW_SPEED
);
1327 if(oldval
& EHPF_PORTRESET
) *mptr
|= AROS_WORD2LE(UPSF_PORT_RESET
);
1328 if(oldval
& EHPF_PORTSUSPEND
) *mptr
|= AROS_WORD2LE(UPSF_PORT_SUSPEND
);
1329 if(oldval
& EHPF_PORTPOWER
) *mptr
|= AROS_WORD2LE(UPSF_PORT_POWER
);
1330 if(oldval
& EHPM_PORTINDICATOR
) *mptr
|= AROS_WORD2LE(UPSF_PORT_INDICATOR
);
1332 KPRINTF(5, ("EHCI Port %ld Status %08lx\n", idx
, *mptr
));
1335 if(oldval
& EHPF_ENABLECHANGE
)
1337 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_ENABLE
;
1339 if(oldval
& EHPF_CONNECTCHANGE
)
1341 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_CONNECTION
;
1343 if(oldval
& EHPF_RESUMEDTX
)
1345 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_SUSPEND
|UPSF_PORT_ENABLE
;
1347 if(oldval
& EHPF_OVERCURRENTCHG
)
1349 hc
->hc_PortChangeMap
[hciport
] |= UPSF_PORT_OVER_CURRENT
;
1351 *mptr
= AROS_WORD2LE(hc
->hc_PortChangeMap
[hciport
]);
1352 WRITEREG32_LE(hc
->hc_RegBase
, portreg
, oldval
);
1353 KPRINTF(5, ("EHCI Port %ld Change %08lx\n", idx
, *mptr
));
1364 case (URTF_IN
|URTF_CLASS
|URTF_DEVICE
):
1367 case USR_GET_STATUS
:
1369 UWORD
*mptr
= ioreq
->iouh_Data
;
1370 if(len
< sizeof(struct UsbHubStatus
))
1372 return(UHIOERR_STALL
);
1376 ioreq
->iouh_Actual
= 4;
1380 case USR_GET_DESCRIPTOR
:
1385 ULONG hubdesclen
= 9;
1386 ULONG powergood
= 1;
1388 struct UsbHubDesc
*uhd
= (struct UsbHubDesc
*) ioreq
->iouh_Data
;
1389 KPRINTF(1, ("RH: GetHubDescriptor (%ld)\n", len
));
1391 if(unit
->hu_RootHubPorts
> 7) // needs two bytes for port masks
1396 ioreq
->iouh_Actual
= (len
> hubdesclen
) ? hubdesclen
: len
;
1397 CopyMem((APTR
) &RHHubDesc
, ioreq
->iouh_Data
, ioreq
->iouh_Actual
);
1399 if(ioreq
->iouh_Length
)
1401 uhd
->bLength
= hubdesclen
;
1404 if(ioreq
->iouh_Length
>= 6)
1406 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1407 while(hc
->hc_Node
.ln_Succ
)
1409 if(hc
->hc_HCIType
== HCITYPE_OHCI
)
1411 ULONG localpwgood
= (READREG32_LE(hc
->hc_RegBase
, OHCI_HUBDESCA
) & OHAM_POWERGOOD
) >> OHAS_POWERGOOD
;
1412 if(localpwgood
> powergood
)
1414 powergood
= localpwgood
;
1415 KPRINTF(10, ("Increasing power good time to %ld\n", powergood
));
1418 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1421 uhd
->bPwrOn2PwrGood
= powergood
;
1423 if(ioreq
->iouh_Length
>= hubdesclen
)
1425 uhd
->bNbrPorts
= unit
->hu_RootHubPorts
;
1428 uhd
->DeviceRemovable
= 0;
1429 uhd
->PortPwrCtrlMask
= (1<<(unit
->hu_RootHubPorts
+2))-2;
1431 // each field is now 16 bits wide
1432 uhd
->DeviceRemovable
= 0;
1433 uhd
->PortPwrCtrlMask
= 0;
1434 ((UBYTE
*) ioreq
->iouh_Data
)[9] = (1<<(unit
->hu_RootHubPorts
+2))-2;
1435 ((UBYTE
*) ioreq
->iouh_Data
)[10] = ((1<<(unit
->hu_RootHubPorts
+2))-2)>>8;
1442 KPRINTF(20, ("RH: Unsupported Descriptor %04lx\n", idx
));
1448 KPRINTF(20, ("RH: Unsupported command %02lx %02lx %04lx %04lx %04lx!\n", rt
, req
, idx
, val
, len
));
1449 return(UHIOERR_STALL
);
1453 /* /// "cmdIntXFerRootHub()" */
1454 WORD
cmdIntXFerRootHub(struct IOUsbHWReq
*ioreq
,
1455 struct PCIUnit
*unit
,
1456 struct PCIDevice
*base
)
1458 if((ioreq
->iouh_Endpoint
!= 1) || (!ioreq
->iouh_Length
))
1460 return(UHIOERR_STALL
);
1463 if(unit
->hu_RootPortChanges
)
1465 KPRINTF(1, ("Immediate Portchange map %04lx\n", unit
->hu_RootPortChanges
));
1466 if((unit
->hu_RootHubPorts
< 8) || (ioreq
->iouh_Length
== 1))
1468 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->hu_RootPortChanges
;
1469 ioreq
->iouh_Actual
= 1;
1471 ((UBYTE
*) ioreq
->iouh_Data
)[0] = unit
->hu_RootPortChanges
;
1472 ((UBYTE
*) ioreq
->iouh_Data
)[1] = unit
->hu_RootPortChanges
>>8;
1473 ioreq
->iouh_Actual
= 2;
1475 unit
->hu_RootPortChanges
= 0;
1478 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1480 AddTail(&unit
->hu_RHIOQueue
, (struct Node
*) ioreq
);
1482 return(RC_DONTREPLY
);
1486 /* /// "cmdControlXFer()" */
1488 *======================================================================
1489 * cmdControlXFer(ioreq, unit, base)
1490 *======================================================================
1492 * This is the device UHCMD_CONTROLXFER routine.
1494 * First it check if the usb is in proper state and if user passed arguments
1495 * are valid. If everything is ok, the request is linked to queue of
1496 * pending transfer requests.
1500 WORD
cmdControlXFer(struct IOUsbHWReq
*ioreq
,
1501 struct PCIUnit
*unit
,
1502 struct PCIDevice
*base
)
1504 struct PCIController
*hc
;
1506 KPRINTF(10, ("UHCMD_CONTROLXFER ioreq: 0x%p\n", ioreq
));
1507 uhwGetUsbState(ioreq
, unit
, base
);
1508 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1510 return(UHIOERR_USBOFFLINE
);
1512 /* Root hub emulation */
1513 if(ioreq
->iouh_DevAddr
== unit
->hu_RootHubAddr
)
1515 return(cmdControlXFerRootHub(ioreq
, unit
, base
));
1518 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1521 KPRINTF(20, ("No Host controller assigned to device address %ld\n", ioreq
->iouh_DevAddr
));
1522 return(UHIOERR_HOSTERROR
);
1525 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1526 ioreq
->iouh_Actual
= 0;
1529 AddTail(&hc
->hc_CtrlXFerQueue
, (struct Node
*) ioreq
);
1531 SureCause(base
, &hc
->hc_CompleteInt
);
1533 KPRINTF(10, ("UHCMD_CONTROLXFER processed ioreq: 0x%p\n", ioreq
));
1534 return(RC_DONTREPLY
);
1538 /* /// "cmdBulkXFer()" */
1540 *======================================================================
1541 * cmdBulkXFer(ioreq, unit, base)
1542 *======================================================================
1544 * This is the device UHCMD_BULKXFER routine.
1546 * First it check if the usb is in proper state and if user passed arguments
1547 * are valid. If everything is ok, the request is linked to queue of
1548 * pending transfer requests.
1552 WORD
cmdBulkXFer(struct IOUsbHWReq
*ioreq
,
1553 struct PCIUnit
*unit
,
1554 struct PCIDevice
*base
)
1556 struct PCIController
*hc
;
1558 KPRINTF(10, ("UHCMD_BULKXFER ioreq: 0x%p\n", ioreq
));
1559 uhwGetUsbState(ioreq
, unit
, base
);
1560 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1562 return(UHIOERR_USBOFFLINE
);
1565 if(ioreq
->iouh_Flags
& UHFF_LOWSPEED
)
1567 return(UHIOERR_BADPARAMS
);
1570 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1573 return(UHIOERR_HOSTERROR
);
1576 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1577 ioreq
->iouh_Actual
= 0;
1580 AddTail(&hc
->hc_BulkXFerQueue
, (struct Node
*) ioreq
);
1582 SureCause(base
, &hc
->hc_CompleteInt
);
1584 KPRINTF(10, ("UHCMD_BULKXFER processed ioreq: 0x%p\n", ioreq
));
1585 return(RC_DONTREPLY
);
1589 /* /// "cmdIsoXFer()" */
1591 *======================================================================
1592 * cmdIsoXFer(ioreq, unit, base)
1593 *======================================================================
1595 * This is the device UHCMD_ISOXFER routine.
1597 * First it check if the usb is in proper state and if user passed arguments
1598 * are valid. If everything is ok, the request is linked to queue of
1599 * pending transfer requests.
1603 WORD
cmdIsoXFer(struct IOUsbHWReq
*ioreq
,
1604 struct PCIUnit
*unit
,
1605 struct PCIDevice
*base
)
1607 struct PCIController
*hc
;
1609 KPRINTF(10, ("UHCMD_ISOXFER ioreq: 0x%p\n", ioreq
));
1610 uhwGetUsbState(ioreq
, unit
, base
);
1611 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1613 return(UHIOERR_USBOFFLINE
);
1616 if(ioreq
->iouh_Flags
& UHFF_LOWSPEED
)
1618 return(UHIOERR_BADPARAMS
);
1621 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1624 return(UHIOERR_HOSTERROR
);
1627 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1628 ioreq
->iouh_Actual
= 0;
1631 AddTail(&hc
->hc_IsoXFerQueue
, (struct Node
*) ioreq
);
1633 SureCause(base
, &hc
->hc_CompleteInt
);
1635 KPRINTF(10, ("UHCMD_ISOXFER processed ioreq: 0x%p\n", ioreq
));
1636 return(RC_DONTREPLY
);
1640 /* /// "cmdIntXFer()" */
1642 *======================================================================
1643 * cmdIntXFer(ioreq, unit, base)
1644 *======================================================================
1646 * This is the device UHCMD_INTXFER routine.
1648 * First it check if the usb is in proper state and if user passed arguments
1649 * are valid. If everything is ok, the request is linked to queue of
1650 * pending transfer requests.
1654 WORD
cmdIntXFer(struct IOUsbHWReq
*ioreq
,
1655 struct PCIUnit
*unit
,
1656 struct PCIDevice
*base
)
1658 struct PCIController
*hc
;
1660 KPRINTF(10, ("UHCMD_INTXFER ioreq: 0x%p\n", ioreq
));
1661 //uhwDelayMS(1000, unit); /* Wait 200 ms */
1662 uhwGetUsbState(ioreq
, unit
, base
);
1663 if(!(ioreq
->iouh_State
& UHSF_OPERATIONAL
))
1665 return(UHIOERR_USBOFFLINE
);
1668 /* Root Hub Emulation */
1669 if(ioreq
->iouh_DevAddr
== unit
->hu_RootHubAddr
)
1671 return(cmdIntXFerRootHub(ioreq
, unit
, base
));
1674 hc
= unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
];
1677 return(UHIOERR_HOSTERROR
);
1680 ioreq
->iouh_Req
.io_Flags
&= ~IOF_QUICK
;
1681 ioreq
->iouh_Actual
= 0;
1684 AddTail(&hc
->hc_IntXFerQueue
, (struct Node
*) ioreq
);
1686 SureCause(base
, &hc
->hc_CompleteInt
);
1688 KPRINTF(10, ("UHCMD_INTXFER processed ioreq: 0x%p\n", ioreq
));
1689 return(RC_DONTREPLY
);
1693 /* /// "cmdFlush()" */
1695 *======================================================================
1696 * cmdFlush(ioreq, base)
1697 *======================================================================
1699 * This is the device CMD_FLUSH routine.
1701 * This routine abort all pending transfer requests.
1705 WORD
cmdFlush(struct IOUsbHWReq
*ioreq
,
1706 struct PCIUnit
*unit
,
1707 struct PCIDevice
*base
)
1709 struct IOUsbHWReq
*cmpioreq
;
1710 struct PCIController
*hc
;
1713 KPRINTF(10, ("CMD_FLUSH ioreq: 0x%p\n", ioreq
));
1716 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1717 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1719 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1720 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1721 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1722 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1724 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1725 while(hc
->hc_Node
.ln_Succ
)
1727 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1728 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1730 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1731 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1732 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1733 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1735 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1736 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1738 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1739 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1740 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1741 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1743 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1744 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1746 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1747 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1748 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1749 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1751 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1752 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1754 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1755 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1756 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1757 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1759 switch(hc
->hc_HCIType
)
1762 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1763 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1765 Remove(&cmpioreq
->iouh_Req
.io_Message
.mn_Node
);
1766 devadrep
= (cmpioreq
->iouh_DevAddr
<<5) + cmpioreq
->iouh_Endpoint
+ ((cmpioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
1767 unit
->hu_DevBusyReq
[devadrep
] = NULL
;
1768 uhciFreeQContext(hc
, (struct UhciQH
*) cmpioreq
->iouh_DriverPrivate1
);
1769 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1770 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1771 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1776 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1777 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1779 ehciFreeAsyncContext(hc
, cmpioreq
);
1780 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1781 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1782 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1784 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
1785 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1787 ehciFreePeriodicContext(hc
, cmpioreq
);
1788 cmpioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1789 ReplyMsg(&cmpioreq
->iouh_Req
.io_Message
);
1790 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
1794 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
1803 /* /// "NSD stuff" */
1806 const UWORD NSDSupported
[] =
1808 CMD_FLUSH
, CMD_RESET
,
1809 UHCMD_QUERYDEVICE
, UHCMD_USBRESET
,
1810 UHCMD_USBRESUME
, UHCMD_USBSUSPEND
,
1811 UHCMD_USBOPER
, UHCMD_CONTROLXFER
,
1812 UHCMD_ISOXFER
, UHCMD_INTXFER
,
1814 NSCMD_DEVICEQUERY
, 0
1817 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
1818 struct PCIUnit
*unit
,
1819 struct PCIDevice
*base
)
1821 struct my_NSDeviceQueryResult
*query
;
1823 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
1825 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%p query: 0x%p\n", ioreq
, query
));
1832 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
1833 (query
->DevQueryFormat
!= 0) ||
1834 (query
->SizeAvailable
!= 0))
1836 /* Return error. This is special handling, since iorequest is only
1837 guaranteed to be sizeof(struct IOStdReq). If we'd let our
1838 devBeginIO dispatcher return the error, it would trash some
1839 memory past end of the iorequest (ios2_WireError field).
1841 ioreq
->io_Error
= IOERR_NOCMD
;
1842 TermIO((struct IOUsbHWReq
*) ioreq
, base
);
1844 /* Don't reply, we already did.
1846 return RC_DONTREPLY
;
1849 ioreq
->io_Actual
= query
->SizeAvailable
1850 = sizeof(struct my_NSDeviceQueryResult
);
1851 query
->DeviceType
= NSDEVTYPE_USBHARDWARE
;
1852 query
->DeviceSubType
= 0;
1853 query
->SupportedCommands
= NSDSupported
;
1855 /* Return success (note that this will NOT poke ios2_WireError).
1861 /* /// "TermIO()" */
1863 *===========================================================
1864 * TermIO(ioreq, base)
1865 *===========================================================
1867 * Return completed ioreq to sender.
1871 void TermIO(struct IOUsbHWReq
*ioreq
,
1872 struct PCIDevice
*base
)
1874 ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
1876 /* If not quick I/O, reply the message
1878 if(!(ioreq
->iouh_Req
.io_Flags
& IOF_QUICK
))
1880 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
1885 /* /// "cmdAbortIO()" */
1886 BOOL
cmdAbortIO(struct IOUsbHWReq
*ioreq
, struct PCIDevice
*base
)
1888 struct PCIUnit
*unit
= (struct PCIUnit
*) ioreq
->iouh_Req
.io_Unit
;
1889 struct IOUsbHWReq
*cmpioreq
;
1890 struct PCIController
*hc
;
1892 BOOL foundit
= FALSE
;
1894 KPRINTF(10, ("cmdAbort(%p)\n", ioreq
));
1897 cmpioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
1898 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1900 if(ioreq
== cmpioreq
)
1902 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
1906 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1909 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
1910 while(hc
->hc_Node
.ln_Succ
)
1912 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_CtrlXFerQueue
.lh_Head
;
1913 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1915 if(ioreq
== cmpioreq
)
1920 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1924 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IntXFerQueue
.lh_Head
;
1925 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1927 if(ioreq
== cmpioreq
)
1932 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1937 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_IsoXFerQueue
.lh_Head
;
1938 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1940 if(ioreq
== cmpioreq
)
1945 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1950 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_BulkXFerQueue
.lh_Head
;
1951 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1953 if(ioreq
== cmpioreq
)
1958 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1963 // IOReq is probably pending in some transfer structure
1964 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
1965 switch(hc
->hc_HCIType
)
1968 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1969 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1971 if(ioreq
== cmpioreq
)
1974 unit
->hu_DevBusyReq
[devadrep
] = NULL
;
1975 uhciFreeQContext(hc
, (struct UhciQH
*) ioreq
->iouh_DriverPrivate1
);
1978 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
1983 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
1984 while(((struct Node
*) cmpioreq
)->ln_Succ
)
1986 if(ioreq
== cmpioreq
)
1989 * Request's ED is in use by the HC, as well as its TDs and
1991 * Schedule abort on the HC driver and reply the request
1992 * only when done. However return success.
1994 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
1995 ohciAbortRequest(hc
, ioreq
);
1999 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2004 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2005 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2007 if(ioreq
== cmpioreq
)
2010 * CHECKME: Perhaps immediate freeing can cause issues similar to OHCI.
2011 * Should synchronized abort routine be implemented here too ?
2013 ehciFreeAsyncContext(hc
, ioreq
);
2015 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2016 TermIO(ioreq
, base
);
2019 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2021 cmpioreq
= (struct IOUsbHWReq
*) hc
->hc_PeriodicTDQueue
.lh_Head
;
2022 while(((struct Node
*) cmpioreq
)->ln_Succ
)
2024 if(ioreq
== cmpioreq
)
2026 ehciFreePeriodicContext(hc
, ioreq
);
2028 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2029 TermIO(ioreq
, base
);
2032 cmpioreq
= (struct IOUsbHWReq
*) cmpioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2040 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
2043 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2049 ioreq
->iouh_Req
.io_Error
= IOERR_ABORTED
;
2050 TermIO(ioreq
, base
);
2054 KPRINTF(20, ("WARNING, could not abort unknown IOReq %p\n", ioreq
));
2060 /* /// "uhwCheckRootHubChanges()" */
2061 void uhwCheckRootHubChanges(struct PCIUnit
*unit
)
2063 struct IOUsbHWReq
*ioreq
;
2065 if(unit
->hu_RootPortChanges
&& unit
->hu_RHIOQueue
.lh_Head
->ln_Succ
)
2067 KPRINTF(1, ("Portchange map %04lx\n", unit
->hu_RootPortChanges
));
2069 ioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
2070 while(((struct Node
*) ioreq
)->ln_Succ
)
2072 Remove(&ioreq
->iouh_Req
.io_Message
.mn_Node
);
2073 if((unit
->hu_RootHubPorts
< 8) || (ioreq
->iouh_Length
== 1))
2075 *((UBYTE
*) ioreq
->iouh_Data
) = unit
->hu_RootPortChanges
;
2076 ioreq
->iouh_Actual
= 1;
2078 ((UBYTE
*) ioreq
->iouh_Data
)[0] = unit
->hu_RootPortChanges
;
2079 ((UBYTE
*) ioreq
->iouh_Data
)[1] = unit
->hu_RootPortChanges
>>8;
2080 ioreq
->iouh_Actual
= 2;
2082 ReplyMsg(&ioreq
->iouh_Req
.io_Message
);
2083 ioreq
= (struct IOUsbHWReq
*) unit
->hu_RHIOQueue
.lh_Head
;
2085 unit
->hu_RootPortChanges
= 0;
2091 /* /// "uhwCheckSpecialCtrlTransfers()" */
2092 void uhwCheckSpecialCtrlTransfers(struct PCIController
*hc
, struct IOUsbHWReq
*ioreq
)
2094 struct PCIUnit
*unit
= hc
->hc_Unit
;
2096 /* Clear Feature(Endpoint halt) */
2097 if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_STANDARD
|URTF_ENDPOINT
)) &&
2098 (ioreq
->iouh_SetupData
.bRequest
== USR_CLEAR_FEATURE
) &&
2099 (ioreq
->iouh_SetupData
.wValue
== AROS_WORD2LE(UFS_ENDPOINT_HALT
)))
2101 KPRINTF(10, ("Resetting toggle bit for endpoint %ld\n", AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0xf));
2102 unit
->hu_DevDataToggle
[(ioreq
->iouh_DevAddr
<<5)|(AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0xf)|((AROS_WORD2LE(ioreq
->iouh_SetupData
.wIndex
) & 0x80)>>3)] = 0;
2104 else if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_STANDARD
|URTF_DEVICE
)) &&
2105 (ioreq
->iouh_SetupData
.bRequest
== USR_SET_ADDRESS
))
2107 /* Set Address -> clear all endpoints */
2109 ULONG adr
= AROS_WORD2BE(ioreq
->iouh_SetupData
.wValue
)>>3;
2110 KPRINTF(10, ("Resetting toggle bits for device address %ld\n", adr
>>5));
2111 for(epnum
= 0; epnum
< 31; epnum
++)
2113 unit
->hu_DevDataToggle
[adr
+epnum
] = 0;
2115 // transfer host controller ownership
2116 unit
->hu_DevControllers
[ioreq
->iouh_DevAddr
] = NULL
;
2117 unit
->hu_DevControllers
[adr
>>5] = hc
;
2119 else if((ioreq
->iouh_SetupData
.bmRequestType
== (URTF_CLASS
|URTF_OTHER
)) &&
2120 (ioreq
->iouh_SetupData
.bRequest
== USR_SET_FEATURE
) &&
2121 (ioreq
->iouh_SetupData
.wValue
== AROS_WORD2LE(UFS_PORT_RESET
)))
2123 // a hub will be enumerating a device on this host controller soon!
2124 KPRINTF(10, ("Hub RESET caught, assigning Dev0 to %p!\n", hc
));
2125 unit
->hu_DevControllers
[0] = hc
;
2130 /* /// "uhwNakTimeoutInt()" */
2131 AROS_INTH1(uhwNakTimeoutInt
, struct PCIUnit
*, unit
)
2135 struct PCIDevice
*base
= unit
->hu_Device
;
2136 struct PCIController
*hc
;
2137 struct IOUsbHWReq
*ioreq
;
2147 KPRINTF(1, ("Enter NakTimeoutInt(0x%p)\n", unit
));
2149 // check for port status change for UHCI and frame rollovers and NAK Timeouts
2150 hc
= (struct PCIController
*) unit
->hu_Controllers
.lh_Head
;
2151 while(hc
->hc_Node
.ln_Succ
)
2153 if (!(hc
->hc_Flags
& HCF_ONLINE
))
2155 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2159 switch(hc
->hc_HCIType
)
2164 uhciUpdateFrameCounter(hc
);
2165 framecnt
= hc
->hc_FrameCounter
;
2168 ioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2169 while(((struct Node
*) ioreq
)->ln_Succ
)
2171 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2173 uqh
= (struct UhciQH
*) ioreq
->iouh_DriverPrivate1
;
2176 KPRINTF(1, ("Examining IOReq=%p with UQH=%p\n", ioreq
, uqh
));
2177 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2178 linkelem
= READMEM32_LE(&uqh
->uqh_Element
);
2179 if(linkelem
& UHCI_TERMINATE
)
2181 KPRINTF(1, ("UQH terminated %08lx\n", linkelem
));
2182 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2184 // give the thing the chance to exit gracefully
2185 KPRINTF(20, ("Terminated? NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2189 utd
= (struct UhciTD
*) (((IPTR
)linkelem
& UHCI_PTRMASK
) - hc
->hc_PCIVirtualAdjust
- 16); // struct UhciTD starts 16 before physical TD
2190 ctrlstatus
= READMEM32_LE(&utd
->utd_CtrlStatus
);
2191 if(ctrlstatus
& UTCF_ACTIVE
)
2193 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2195 // give the thing the chance to exit gracefully
2196 KPRINTF(20, ("NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2197 ctrlstatus
&= ~UTCF_ACTIVE
;
2198 WRITEMEM32_LE(&utd
->utd_CtrlStatus
, ctrlstatus
);
2202 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2204 // give the thing the chance to exit gracefully
2205 KPRINTF(20, ("Terminated? NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2212 ioreq
= (struct IOUsbHWReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
2215 uhciCheckPortStatusChange(hc
);
2222 ohciUpdateFrameCounter(hc
);
2223 framecnt
= hc
->hc_FrameCounter
;
2225 ioreq
= (struct IOUsbHWReq
*) hc
->hc_TDQueue
.lh_Head
;
2226 while(((struct Node
*) ioreq
)->ln_Succ
)
2228 // Remember the successor because ohciAbortRequest() will move the request to another list
2229 struct IOUsbHWReq
*succ
= (struct IOUsbHWReq
*)ioreq
->iouh_Req
.io_Message
.mn_Node
.ln_Succ
;
2231 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2233 KPRINTF(1, ("Examining IOReq=%p with OED=%p\n", ioreq
, ioreq
->iouh_DriverPrivate1
));
2234 if (ioreq
->iouh_DriverPrivate1
)
2236 KPRINTF(1, ("CTRL=%04lx, CMD=%01lx, F=%ld, hccaDH=%08lx, hcDH=%08lx, CH=%08lx, CCH=%08lx, IntEn=%08lx\n",
2237 READREG32_LE(hc
->hc_RegBase
, OHCI_CONTROL
),
2238 READREG32_LE(hc
->hc_RegBase
, OHCI_CMDSTATUS
),
2239 READREG32_LE(hc
->hc_RegBase
, OHCI_FRAMECOUNT
),
2240 READMEM32_LE(&hc
->hc_OhciHCCA
->oha_DoneHead
),
2241 READREG32_LE(hc
->hc_RegBase
, OHCI_DONEHEAD
),
2242 READREG32_LE(hc
->hc_RegBase
, OHCI_CTRL_HEAD_ED
),
2243 READREG32_LE(hc
->hc_RegBase
, OHCI_CTRL_ED
),
2244 READREG32_LE(hc
->hc_RegBase
, OHCI_INTEN
)));
2246 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2247 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2249 // give the thing the chance to exit gracefully
2250 KPRINTF(200, ("HC 0x%p NAK timeout %ld > %ld, IOReq=%p\n", hc
, framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2251 ioreq
->iouh_Req
.io_Error
= UHIOERR_NAKTIMEOUT
;
2252 ohciAbortRequest(hc
, ioreq
);
2264 ehciUpdateFrameCounter(hc
);
2265 framecnt
= hc
->hc_FrameCounter
;
2267 for(cnt
= 0; cnt
< 1; cnt
++)
2269 ioreq
= (struct IOUsbHWReq
*) (cnt
? hc
->hc_PeriodicTDQueue
.lh_Head
: hc
->hc_TDQueue
.lh_Head
);
2270 while(((struct Node
*) ioreq
)->ln_Succ
)
2272 if(ioreq
->iouh_Flags
& UHFF_NAKTIMEOUT
)
2274 eqh
= (struct EhciQH
*) ioreq
->iouh_DriverPrivate1
;
2277 KPRINTF(1, ("Examining IOReq=%p with EQH=%p\n", ioreq
, eqh
));
2278 devadrep
= (ioreq
->iouh_DevAddr
<<5) + ioreq
->iouh_Endpoint
+ ((ioreq
->iouh_Dir
== UHDIR_IN
) ? 0x10 : 0);
2279 ctrlstatus
= READMEM32_LE(&eqh
->eqh_CtrlStatus
);
2280 if(ctrlstatus
& ETCF_ACTIVE
)
2282 if(framecnt
> unit
->hu_NakTimeoutFrame
[devadrep
])
2284 // give the thing the chance to exit gracefully
2285 KPRINTF(20, ("NAK timeout %ld > %ld, IOReq=%p\n", framecnt
, unit
->hu_NakTimeoutFrame
[devadrep
], ioreq
));
2286 ctrlstatus
&= ~ETCF_ACTIVE
;
2287 ctrlstatus
|= ETSF_HALTED
;
2288 WRITEMEM32_LE(&eqh
->eqh_CtrlStatus
, ctrlstatus
);
2292 if(ctrlstatus
& ETCF_READYINTEN
)
2294 KPRINTF(10, ("INT missed?!? Manually causing it! %08lx, IOReq=%p\n",
2295 ctrlstatus
, ioreq
));
2301 ioreq
= (struct IOUsbHWReq
*) ((struct Node
*) ioreq
)->ln_Succ
;
2310 SureCause(base
, &hc
->hc_CompleteInt
);
2313 hc
= (struct PCIController
*) hc
->hc_Node
.ln_Succ
;
2316 uhwCheckRootHubChanges(unit
);
2318 unit
->hu_NakTimeoutReq
.tr_time
.tv_micro
= 150*1000;
2319 SendIO((APTR
) &unit
->hu_NakTimeoutReq
);
2321 KPRINTF(1, ("Exit NakTimeoutInt(0x%p)\n", unit
));