Optimizing a USB Function Driver Stack (Windows Embedded CE 6.0)
1/6/2010
When a USB function client driver issues a transfer, the USB function client driver passes a customizable parameter to the USB function client driver PDD. The USB function client driver can use this variable for intensive operations or for optimizing your USB function driver stack. Using this parameter may force you to make hardware platform specific modifications to your USB function client driver. After making these modifications, your USB function client driver may only operate with the hardware platform specific USB function controller driver PDD. None of the USB function client drivers provided by Microsoft use this customizable parameter. For more information, see the STransfer structure in %_WINCEROOT%\Public\Common\OAK\Inc\Usbfn.h.
Configuring DMA Transfers between a Client Driver and a PDD
When the USB function client driver issues a transfer, the client driver can pass DMA addresses to the PDD. This can allow the PDD to perform DMA transfers directly to the disk, instead of performing DMA transfers to memory, and then having the USB function client driver perform the DMA transfer to the disk after the transfer completes.
Typically, the USB function controller driver PDD can implement DMA using an internal physical buffer. For example, in the case of an OUT transfer, the PDD can DMA one or more USB packets to its own physical buffer and then use memcpy, see Alphabetical Function Reference (CRT), to copy the packets to the client buffer. This memcpy is extra additional overhead and it would be ideal to remove it.
In order to remove this memcpy, the USB function client driver and the USB function controller driver PDD must both be modified to allow for DMA directly to the client buffer.
The client must create its buffer using HalAllocateCommonBuffer. It gets the hardware-specific parameters for this routine by calling into the MDD/PDD with IOCTL_UFN_GET_PDD_INFO. If IOCTL_UFN_GET_PDD_INFO fails, then the PDD does not support DMA directly to the client's buffer and it is better to not use HalAllocateCommonBuffer, because HalAllocateCommonBuffer always creates an uncached buffer. If the client is using HalAllocateCommonBuffer, it should pass the physical buffer address in addition to its corresponding virtual address to the lpIssueTransfer function.
The USB function controller driver PDD must implement IOCTL_UFN_GET_PDD_INFO in UfnPdd_IOControl.
If the USB function controller client driver passes a physical address in its call to lpIssueTransfer, the PDD will see it in the dwBufferPhysicalAddress field of the STransfer structure passed to UfnPdd_IssueTransfer. It should use this contiguous physical buffer for DMA.
The following code samples shows how to check if the USB function controller driver PDD can handle DMA transfers.
HANDLE hBus = CreateBusAccessHandle(lpActiveRegPath); // path from driver's Init call
if (hBus == NULL) {
// fail somehow
}
UFN_PDD_INFO PddInfo;
BOOL fSuccess = BusIoControl(hBus, IOCTL_UFN_GET_PDD_INFO, 0, NULL, &PddInfo, sizeof(PddInfo), NULL, NULL);
if (!fSuccess) {
// PDD cannot do DMA directly to the client buffer
}
CloseBusAccessHandle(hBus);
See Also
Other Resources
USB Function Drivers
USB Function Controller Driver Migration