[USBUHCI]

- Silence traces
- Implement abort pipe
- Implement support for interrupt transfers

svn path=/trunk/; revision=55820
This commit is contained in:
Johannes Anderwald 2012-02-22 23:24:53 +00:00
parent 86ebeb35cc
commit 4b02150831
4 changed files with 154 additions and 35 deletions

View file

@ -1053,36 +1053,36 @@ CUSBDevice::GetConfigurationDescriptorsLength()
VOID
CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
{
DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
DPRINT("Dumping Device Descriptor %x\n", DeviceDescriptor);
DPRINT("bLength %x\n", DeviceDescriptor->bLength);
DPRINT("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
DPRINT("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
DPRINT("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
DPRINT("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
DPRINT("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
DPRINT("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
DPRINT("idVendor %x\n", DeviceDescriptor->idVendor);
DPRINT("idProduct %x\n", DeviceDescriptor->idProduct);
DPRINT("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
DPRINT("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
DPRINT("iProduct %x\n", DeviceDescriptor->iProduct);
DPRINT("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
DPRINT("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
}
//----------------------------------------------------------------------------------------
VOID
CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
DPRINT("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
DPRINT("bLength %x\n", ConfigurationDescriptor->bLength);
DPRINT("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
DPRINT("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
DPRINT("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
DPRINT("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
DPRINT("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
DPRINT("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
DPRINT("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
}
//----------------------------------------------------------------------------------------
NTSTATUS

View file

@ -220,8 +220,8 @@ CUSBQueue::AddUSBRequest(
//
// add queue head
//
DPRINT1("AddUSBRequest Request %p\n", Request);
DPRINT1("NewQueueHead %p\n", NewQueueHead);
DPRINT("AddUSBRequest Request %p\n", Request);
DPRINT("NewQueueHead %p\n", NewQueueHead);
return AddQueueHead(NewQueueHead);
}
@ -260,9 +260,49 @@ CUSBQueue::AbortDevicePipe(
IN UCHAR DeviceAddress,
IN struct _USB_ENDPOINT *EndpointDescriptor)
{
UNIMPLEMENTED
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
KIRQL OldLevel;
PUHCI_TRANSFER_DESCRIPTOR Descriptor;
PUHCI_QUEUE_HEAD QueueHead, PreviousQueueHead = NULL;
UCHAR EndpointAddress, EndpointDeviceAddress;
// acquire lock
KeAcquireSpinLock(&m_Lock, &OldLevel);
// get queue head
m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead);
while(QueueHead)
{
// get descriptor
Descriptor = (PUHCI_TRANSFER_DESCRIPTOR)QueueHead->NextElementDescriptor;
if (Descriptor)
{
// extract endpoint address
EndpointAddress = (Descriptor->Token >> TD_TOKEN_ENDPTADDR_SHIFT) & 0x0F;
// extract device address
EndpointDeviceAddress = (Descriptor->Token >> TD_TOKEN_DEVADDR_SHIFT) & 0x7F;
// check if they match
if (EndpointAddress == (EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F) &&
DeviceAddress == EndpointDeviceAddress)
{
// cleanup queue head
QueueHeadCleanup(QueueHead, PreviousQueueHead, &QueueHead);
continue;
}
}
// move to next queue head
PreviousQueueHead = QueueHead;
QueueHead = (PUHCI_QUEUE_HEAD)QueueHead->NextLogicalDescriptor;
}
// release lock
KeReleaseSpinLock(&m_Lock, OldLevel);
return STATUS_SUCCESS;
}
NTSTATUS
@ -295,7 +335,7 @@ CUSBQueue::IsQueueHeadComplete(
//
// empty queue head
//
DPRINT1("QueueHead %p empty element physical\n", QueueHead);
DPRINT("QueueHead %p empty element physical\n", QueueHead);
return FALSE;
}
@ -396,7 +436,7 @@ CUSBQueue::QueueHeadCleanup(
//
// free queue head
//
DPRINT1("Request %p\n", Request);
DPRINT("Request %p\n", Request);
Request->FreeEndpointDescriptor(QueueHead);
//
@ -467,7 +507,7 @@ CUSBQueue::TransferInterrupt(
//
// is queue head complete
//
DPRINT1("QueueHead %p\n", QueueHead);
DPRINT("QueueHead %p\n", QueueHead);
IsComplete = IsQueueHeadComplete(QueueHead);
if (IsComplete)
{

View file

@ -59,6 +59,7 @@ public:
USHORT GetMaxPacketSize();
NTSTATUS CreateDescriptor(PUHCI_TRANSFER_DESCRIPTOR *OutDescriptor, IN UCHAR PidCode, ULONG BufferLength);
NTSTATUS BuildControlTransferDescriptor(IN PUHCI_QUEUE_HEAD * OutQueueHead);
NTSTATUS BuildBulkInterruptTransferDescriptor(IN PUHCI_QUEUE_HEAD * OutQueueHead);
NTSTATUS BuildQueueHead(OUT PUHCI_QUEUE_HEAD *OutQueueHead);
VOID FreeDescriptor(IN PUHCI_TRANSFER_DESCRIPTOR Descriptor);
NTSTATUS BuildTransferDescriptorChain(IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PUHCI_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PUHCI_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PULONG OutTransferBufferOffset, OUT PUCHAR OutDataToggle);
@ -139,6 +140,9 @@ protected:
//
USB_DEVICE_SPEED m_DeviceSpeed;
// base
PVOID m_Base;
};
//----------------------------------------------------------------------------------------
@ -607,14 +611,25 @@ CUSBRequest::GetEndpointDescriptor(
struct _UHCI_QUEUE_HEAD ** OutQueueHead)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG TransferType;
if (InternalGetTransferType() == USB_ENDPOINT_TYPE_CONTROL)
// get transfer type
TransferType = InternalGetTransferType();
if (TransferType == USB_ENDPOINT_TYPE_CONTROL)
{
//
// build queue head
//
Status = BuildControlTransferDescriptor(OutQueueHead);
}
else if (TransferType == USB_ENDPOINT_TYPE_INTERRUPT || TransferType == USB_ENDPOINT_TYPE_BULK)
{
//
// build queue head
//
Status = BuildBulkInterruptTransferDescriptor(OutQueueHead);
}
if (!NT_SUCCESS(Status))
{
@ -783,7 +798,7 @@ CUSBRequest::CreateDescriptor(
// store address & endpoint number
//
Descriptor->Token |= GetEndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT;
Descriptor->Token |= GetDeviceAddress() << 8 | PidCode;
Descriptor->Token |= GetDeviceAddress() << TD_TOKEN_DEVADDR_SHIFT | PidCode;
if (BufferLength)
{
@ -991,6 +1006,70 @@ CUSBRequest::FreeDescriptor(
m_DmaManager->Release(Descriptor, sizeof(UHCI_TRANSFER_DESCRIPTOR));
}
NTSTATUS
CUSBRequest::BuildBulkInterruptTransferDescriptor(
IN PUHCI_QUEUE_HEAD * OutQueueHead)
{
NTSTATUS Status;
PUHCI_QUEUE_HEAD QueueHead;
PUHCI_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor;
ULONG ChainDescriptorLength;
BOOLEAN Direction;
PVOID Buffer;
ULONG BufferSize;
// create queue head
Status = BuildQueueHead(&QueueHead);
if (!NT_SUCCESS(Status))
{
// failed to allocate descriptor
DPRINT1("[UHCI] Failed to create queue head\n");
return Status;
}
// get direction
Direction = InternalGetPidDirection();
if (!m_Base)
{
// get buffer base
m_Base = MmGetMdlVirtualAddress(m_TransferBufferMDL);
}
// get new buffer offset
Buffer = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
// FIXME determine buffer limit
BufferSize = min(m_TransferBufferLength - m_TransferBufferLengthCompleted, PAGE_SIZE);
// create descriptor chain
Status = BuildTransferDescriptorChain(Buffer,
BufferSize,
Direction ? TD_TOKEN_IN : TD_TOKEN_OUT,
m_EndpointDescriptor->DataToggle,
&FirstDescriptor,
&LastDescriptor,
&ChainDescriptorLength,
NULL);
// adjust buffer offset
m_TransferBufferLengthCompleted += ChainDescriptorLength;
// fire interrupt when the last descriptor is complete
LastDescriptor->Status |= TD_CONTROL_IOC;
LastDescriptor->LinkPhysical = TD_TERMINATE;
LastDescriptor->NextLogicalDescriptor = NULL;
// link queue head with first data descriptor descriptor
QueueHead->NextElementDescriptor = (PVOID)FirstDescriptor;
QueueHead->ElementPhysical = FirstDescriptor->PhysicalAddress;
// store result
*OutQueueHead = QueueHead;
return STATUS_SUCCESS;
}
NTSTATUS
CUSBRequest::BuildControlTransferDescriptor(
IN PUHCI_QUEUE_HEAD * OutQueueHead)

View file

@ -2,7 +2,7 @@
#define USBOHCI_H__
#include <ntddk.h>
#define YDEBUG
#define NDEBUG
#include <debug.h>
#include <hubbusif.h>
#include <usbbusif.h>