VxWorks API Reference : USB libraries

usbHcdUhciLib [USB]

NAME

usbHcdUhciLib [USB] - Defines entry point for UHCI HCD

ROUTINES

usbHcdUhciExec( ) - HCD_EXEC_FUNC entry point for UHCI HCD

DESCRIPTION

This is the HCD (host controller driver) for UHCI. This file implements low-level functions required by the client (typically the USBD) to talk to the underlying USB host controller hardware.

The param to the HRB_ATTACH request should be a pointer to a PCI_CFG_HEADER which contains the PCI configuration header for the universal host controller to be managed. Each invocation of the HRB_ATTACH function will return an HCD_CLIENT_HANDLE for which a single host controller will be exposed.

NOTE

This HCD implementation assumes that the caller has already initialized the osServices and handleFuncs libraries by calling ossInitialize( ) and usbHandleInitialize( ), respectively. The USBD implementation guarantees that these libraries have been initialized prior to invoking the HCD.

Regarding IRP callbacks...

There are two callback function pointers in each IRP, usbdCallback and userCallback. By convention, if a non-NULL usbdCallback is supplied, then the HCD invokes only the usbdCallback upon IRP completion - and it is the USBD's responsibility to invoke the userCallback. If no usbdCallback is provided, then the HCD invokes the userCallback directly. Typically, all IRPs are delivered to the HCD through the USBD and a non-NULL usbdCallback will in fact be provided.

Regarding UHCI frame lists...

We use the UHCI frame list in a way anticipated by, but not directly described by the UHCI specfication. As anticipated, we create an array of 1024 frame list entries. We also create an array of 1024 "interrupt anchor" QHs, one "control anchor" QH and one "bulk anchor" QH. Each frame list entry is initialized to point to a corresponding interrupt anchor. Each interrupt anchor points to the single control anchor, and the control anchor initially points to the bulk anchor.

When one or more interrupt transfers are pending, QHs for these transfers will be inserted after the interrupt anchor QHs corresponding to the frames dictated by the interrupt scheduling interval. The last pending interrupt QH in each list points to the common control anchor QH. While clients can request any interrupt service interval they like, the algorithms here always choose an interval which is the largest power of 2 less than or equal to the client's desired interval. For example, if a client requests an interval of 20msec, the HCD will select a real interval of 16msec. In each frame work list, the least frequently scheduled QHs appear ahead of more frequently scheduled QHs. Since only a single QH is actually created for each interrupt transfer, the individual frame lists actually "merge" at each interrupt QH. Now, using the preceding example of 16msec, suppose that there is a second interrupt QH with an interval of 8 msec. In half of the frame lists for which the 8msec interval transfer is scheduled, the "interrupt anchor" QH will point to it directly. In the other half, the 16msec interval transfer will point to it.

When control transfer QHs are scheduled, they are always placed in the list following the "control anchor" QH. Similarly, bulk transfer QHs are always placed after the "bulk anchor" QH. When low speed control transfers are pending, they are always inserted after the "control anchor" QH before any high-speed control transfers.

The anchors themselves never describe work. Instead, they are just placeholders in the work lists to facilitate clean QH and TD list updates. For example, when queuing a new control or bulk transfer, it is only necessary to modify the work list after the single "control" or "bulk" anchor. Similiarly, when queuing interrupt transfers, it is only necessary to modify the work list after the QH anchor in which the interrupt is to be scheduled. Finally, isochronous transfers can be added cleanly at the beginning of each frame's work list; and the last isoch transfer TD in each frame always points to the QH anchor corresponding to that frame.

In effect, this scheme decouples isoch, interrupt, control, and bulk transfers in the TD/QH work lists.

Regarding bus time calculations...

The host controller driver is responsible for ensuring that certain kinds of scheduled transfers never exceed the time available in a USB frame. The HCD and the USBD work cooperatively to ensure this. For its part, the USBD never allows isochronous and interrupt transfers to be scheduled which would exceed 90% of the bus bandwidth. However, the USBD will freely allow control and bulk pipes to be created, as these types of transfers take whatever bus time is left over after isochronous and interrupt transfers have been schedule - and the HCD gives priority to control transfers.

The HCD keeps a running total of the worst case amount of bus time alloted to active isochronous and interrupt transfers. As for control and bulk transfers, the UHC theoretically allows us to schedule as many of them as we desire, and it keeps track of how much time remains in each frame, executing only as many of these transfers as will fit. However, the UHC requires that the driver schedule only as many low speed control transfers (as opposed to full speed control transfers) as can actually fit within the frame. Therefore, after taking into account the time already allotted to isochronous and interrupt transfers, the HCD only schedules as many low speed control transfers as can fit within the current frame - and full speed control and bulk transfers follow.


USB libraries : Routines

usbHcdUhciExec( )

NAME

usbHcdUhciExec( ) - HCD_EXEC_FUNC entry point for UHCI HCD

SYNOPSIS

STATUS usbHcdUhciExec
    (
    pVOID pHrb                /* HRB to be executed */
    )

DESCRIPTION

RETURNS

OK or ERROR

ERRNO

 S_usbHcdLib_BAD_PARAM
 S_usbHcdLib_BAD_HANDLE
 S_usbHcdLib_SHUTDOWN

SEE ALSO

usbHcdUhciLib