[USBUHCI]

- Implement function to retrieve queue head for the specified transfer type
- Pass device speed to IUSBRequest initialization routines
- Implementing inserting the new queue head into the required queue head 
- Implement support for control transfers, not yet used

svn path=/trunk/; revision=55787
This commit is contained in:
Johannes Anderwald 2012-02-21 18:19:24 +00:00
parent a14929eb93
commit d8b2ccec60
6 changed files with 628 additions and 23 deletions

View file

@ -73,8 +73,9 @@ public:
NTSTATUS GetPortStatus(ULONG PortId, OUT USHORT *PortStatus, OUT USHORT *PortChange);
NTSTATUS ClearPortStatus(ULONG PortId, ULONG Status);
NTSTATUS SetPortFeature(ULONG PortId, ULONG Feature);
VOID SetStatusChangeEndpointCallBack(PVOID CallBack, PVOID Context);
VOID GetQueueHead(ULONG QueueHeadIndex, PUHCI_QUEUE_HEAD *OutQueueHead);
KIRQL AcquireDeviceLock(void);
VOID ReleaseDeviceLock(KIRQL OldLevel);
@ -616,7 +617,7 @@ CUSBHardwareDevice::InitializeController()
//
// link queue heads
//
m_QueueHead[Index-1]->LinkPhysical = m_QueueHead[Index]->LinkPhysical | QH_NEXT_IS_QH;
m_QueueHead[Index-1]->LinkPhysical = m_QueueHead[Index]->PhysicalAddress | QH_NEXT_IS_QH;
m_QueueHead[Index-1]->NextLogicalDescriptor = m_QueueHead[Index];
}
}
@ -1218,6 +1219,21 @@ CUSBHardwareDevice::ReadRegister32(
return READ_PORT_ULONG((PULONG)((ULONG)m_Base + Register));
}
VOID
CUSBHardwareDevice::GetQueueHead(
IN ULONG QueueHeadIndex,
OUT PUHCI_QUEUE_HEAD *OutQueueHead)
{
//
// sanity check
//
ASSERT(QueueHeadIndex < 5);
//
// store queue head
//
*OutQueueHead = m_QueueHead[QueueHeadIndex];
}
VOID
NTAPI

View file

@ -163,7 +163,7 @@ UHCI_TRANSFER_DESCRIPTOR_LENGTH(PUHCI_TRANSFER_DESCRIPTOR Descriptor)
}
// Represents a Queue Head (QH)
typedef struct
typedef struct _UHCI_QUEUE_HEAD
{
// hardware part
ULONG LinkPhysical; // address
@ -172,6 +172,8 @@ typedef struct
// Software part
ULONG PhysicalAddress;
PVOID NextLogicalDescriptor;
PVOID Request;
PVOID NextElementDescriptor;
}UHCI_QUEUE_HEAD, *PUHCI_QUEUE_HEAD;
#define QH_TERMINATE 0x01

View file

@ -107,7 +107,7 @@ DECLARE_INTERFACE_(IHCDController, IUnknown)
typedef IHCDController *PHCDCONTROLLER;
struct _UHCI_TRANSFER_DESCRIPTOR;
struct _UHCI_QUEUE_HEAD;
//=========================================================================================
//
// class IUSBHardwareDevice
@ -251,6 +251,15 @@ DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown)
//
virtual VOID SetStatusChangeEndpointCallBack(PVOID CallBack,PVOID Context) = 0;
//-----------------------------------------------------------------------------------------
//
// GetQueueHead
//
// Description: gets a queue head with the specified queue head index
//
virtual VOID GetQueueHead(ULONG QueueHeadIndex, struct _UHCI_QUEUE_HEAD **OutQueueHead) = 0;
//-----------------------------------------------------------------------------------------
//
// AcquireDeviceLock
@ -350,6 +359,7 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager,
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
IN UCHAR DeviceAddress,
IN USB_DEVICE_SPEED DeviceSpeed,
IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
IN OUT ULONG TransferBufferLength,
IN OUT PMDL TransferBuffer) = 0;
@ -362,7 +372,8 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
// The irp contains an URB block which contains all necessary information
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager,
IN OUT PIRP Irp) = 0;
IN OUT PIRP Irp,
IN USB_DEVICE_SPEED DeviceSpeed) = 0;
//-----------------------------------------------------------------------------------------
//
@ -390,7 +401,7 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
//
// Description: returns the general transfer descriptor
virtual NTSTATUS GetEndpointDescriptor(struct _UHCI_TRANSFER_DESCRIPTOR ** OutDescriptor) = 0;
virtual NTSTATUS GetEndpointDescriptor(struct _UHCI_QUEUE_HEAD ** OutDescriptor) = 0;
//-----------------------------------------------------------------------------------------
//
@ -418,6 +429,14 @@ DECLARE_INTERFACE_(IUSBRequest, IUnknown)
virtual UCHAR GetInterval() = 0;
//-----------------------------------------------------------------------------------------
//
// GetDeviceSpeed
//
// Description: returns device speed
virtual USB_DEVICE_SPEED GetDeviceSpeed() = 0;
};

View file

@ -462,7 +462,7 @@ CUSBDevice::CommitIrp(
//
// initialize request
//
Status = Request->InitializeWithIrp(m_DmaManager, Irp);
Status = Request->InitializeWithIrp(m_DmaManager, Irp, GetSpeed());
//
// mark irp as pending
@ -550,7 +550,7 @@ CUSBDevice::CommitSetupPacket(
//
// initialize request
//
Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, m_DeviceAddress, EndpointDescriptor, BufferLength, Mdl);
Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, m_DeviceAddress, GetSpeed(), EndpointDescriptor, BufferLength, Mdl);
if (!NT_SUCCESS(Status))
{
//

View file

@ -40,6 +40,9 @@ public:
virtual NTSTATUS CancelRequests();
virtual NTSTATUS CreateUSBRequest(IUSBRequest **OutRequest);
// local
VOID LinkQueueHead(PUHCI_QUEUE_HEAD QueueHead, PUHCI_QUEUE_HEAD NextQueueHead);
// constructor / destructor
CUSBQueue(IUnknown *OuterUnknown){}
virtual ~CUSBQueue(){}
@ -104,11 +107,95 @@ NTSTATUS
CUSBQueue::AddUSBRequest(
IUSBRequest * Request)
{
PUHCI_QUEUE_HEAD NewQueueHead, QueueHead = NULL;
NTSTATUS Status;
DPRINT("CUSBQueue::AddUSBRequest\n");
ASSERT(FALSE);
//
// get queue head
//
Status = Request->GetEndpointDescriptor(&NewQueueHead);
if (!NT_SUCCESS(Status))
{
//
// failed to create queue head
//
DPRINT1("[USBUHCI] Failed to create queue head %x\n", Status);
return Status;
}
if (Request->GetTransferType() == USB_ENDPOINT_TYPE_CONTROL)
{
//
// get device speed
//
if (Request->GetDeviceSpeed() == UsbLowSpeed)
{
//
// use low speed queue
//
m_Hardware->GetQueueHead(UHCI_LOW_SPEED_CONTROL_QUEUE, &QueueHead);
}
else
{
//
// use full speed queue
//
m_Hardware->GetQueueHead(UHCI_FULL_SPEED_CONTROL_QUEUE, &QueueHead);
}
}
else if (Request->GetTransferType() == USB_ENDPOINT_TYPE_BULK)
{
//
// use full speed queue
//
m_Hardware->GetQueueHead(UHCI_BULK_QUEUE, &QueueHead);
}
else if (Request->GetTransferType() == USB_ENDPOINT_TYPE_INTERRUPT)
{
//
// use full speed queue
//
m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead);
}
else if (Request->GetTransferType() == USB_ENDPOINT_TYPE_INTERRUPT)
{
//
// use full speed queue
//
m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead);
}
//
// FIXME support isochronous
//
ASSERT(QueueHead);
//
// add reference
//
Request->AddRef();
//
// now link the new queue head
//
LinkQueueHead(QueueHead, NewQueueHead);
return STATUS_SUCCESS;
}
VOID
CUSBQueue::LinkQueueHead(
IN PUHCI_QUEUE_HEAD QueueHead,
IN PUHCI_QUEUE_HEAD NextQueueHead)
{
NextQueueHead->LinkPhysical = QueueHead->LinkPhysical;
NextQueueHead->NextLogicalDescriptor = QueueHead->NextLogicalDescriptor;
QueueHead->LinkPhysical = NextQueueHead->PhysicalAddress | QH_NEXT_IS_QH;
QueueHead->NextLogicalDescriptor = (PVOID)NextQueueHead;
}
NTSTATUS
CUSBQueue::CancelRequests()
{

View file

@ -36,15 +36,16 @@ public:
}
// IUSBRequest interface functions
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp);
virtual NTSTATUS InitializeWithSetupPacket(IN PDMAMEMORYMANAGER DmaManager, IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, IN UCHAR DeviceAddress, IN USB_DEVICE_SPEED DeviceSpeed, IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN OUT ULONG TransferBufferLength, IN OUT PMDL TransferBuffer);
virtual NTSTATUS InitializeWithIrp(IN PDMAMEMORYMANAGER DmaManager, IN OUT PIRP Irp, IN USB_DEVICE_SPEED DeviceSpeed);
virtual BOOLEAN IsRequestComplete();
virtual ULONG GetTransferType();
virtual NTSTATUS GetEndpointDescriptor(struct _UHCI_TRANSFER_DESCRIPTOR ** OutEndpointDescriptor);
virtual NTSTATUS GetEndpointDescriptor(struct _UHCI_QUEUE_HEAD ** OutQueueHead);
virtual VOID GetResultStatus(OUT OPTIONAL NTSTATUS *NtStatusCode, OUT OPTIONAL PULONG UrbStatusCode);
virtual BOOLEAN IsRequestInitialized();
virtual BOOLEAN IsQueueHeadComplete(struct _QUEUE_HEAD * QueueHead);
virtual UCHAR GetInterval();
virtual USB_DEVICE_SPEED GetDeviceSpeed();
// local functions
@ -55,6 +56,13 @@ public:
NTSTATUS BuildSetupPacketFromURB();
UCHAR GetEndpointAddress();
USHORT GetMaxPacketSize();
NTSTATUS CreateDescriptor(PUHCI_TRANSFER_DESCRIPTOR *OutDescriptor, IN UCHAR PidCode, ULONG BufferLength);
NTSTATUS BuildControlTransferDescriptor(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);
// constructor / destructor
CUSBRequest(IUnknown *OuterUnknown){}
@ -125,6 +133,11 @@ protected:
NTSTATUS m_NtStatusCode;
ULONG m_UrbStatusCode;
//
// store device speed
//
USB_DEVICE_SPEED m_DeviceSpeed;
};
//----------------------------------------------------------------------------------------
@ -143,6 +156,7 @@ CUSBRequest::InitializeWithSetupPacket(
IN PDMAMEMORYMANAGER DmaManager,
IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket,
IN UCHAR DeviceAddress,
IN USB_DEVICE_SPEED DeviceSpeed,
IN OPTIONAL PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor,
IN OUT ULONG TransferBufferLength,
IN OUT PMDL TransferBuffer)
@ -163,6 +177,7 @@ CUSBRequest::InitializeWithSetupPacket(
m_DeviceAddress = DeviceAddress;
m_EndpointDescriptor = EndpointDescriptor;
m_TotalBytesTransferred = 0;
m_DeviceSpeed = DeviceSpeed;
//
// Set Length Completed to 0
@ -195,7 +210,8 @@ CUSBRequest::InitializeWithSetupPacket(
NTSTATUS
CUSBRequest::InitializeWithIrp(
IN PDMAMEMORYMANAGER DmaManager,
IN OUT PIRP Irp)
IN OUT PIRP Irp,
IN USB_DEVICE_SPEED DeviceSpeed)
{
PIO_STACK_LOCATION IoStack;
PURB Urb;
@ -208,6 +224,7 @@ CUSBRequest::InitializeWithIrp(
m_DmaManager = DmaManager;
m_TotalBytesTransferred = 0;
m_DeviceSpeed = DeviceSpeed;
//
// get current irp stack location
@ -514,13 +531,21 @@ CUSBRequest::InternalGetTransferType()
UCHAR
CUSBRequest::InternalGetPidDirection()
{
ASSERT(m_Irp);
ASSERT(m_EndpointDescriptor);
//
// end point is defined in the low byte of bEndpointAddress
//
return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
if (m_EndpointDescriptor)
{
//
// end point direction is highest bit in bEndpointAddress
//
return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
}
else
{
//
// request arrives on the control pipe, extract direction from setup packet
//
ASSERT(m_SetupPacket);
return (m_SetupPacket->bmRequestType.B >> 7);
}
}
@ -578,13 +603,35 @@ CUSBRequest::GetDeviceAddress()
//----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::GetEndpointDescriptor(
struct _UHCI_TRANSFER_DESCRIPTOR ** OutDescriptor)
struct _UHCI_QUEUE_HEAD ** OutQueueHead)
{
ASSERT(FALSE);
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (InternalGetTransferType() == USB_ENDPOINT_TYPE_CONTROL)
{
//
// build queue head
//
Status = BuildControlTransferDescriptor(OutQueueHead);
}
if (!NT_SUCCESS(Status))
{
//
// failed
//
return Status;
}
//
// store result
//
(*OutQueueHead)->Request = PVOID(this);
//
// done
//
return STATUS_NOT_IMPLEMENTED;
return STATUS_SUCCESS;
}
//----------------------------------------------------------------------------------------
@ -647,8 +694,442 @@ CUSBRequest::IsQueueHeadComplete(
UNIMPLEMENTED
return TRUE;
}
//-----------------------------------------------------------------------------------------
NTSTATUS
CUSBRequest::CreateDescriptor(
OUT PUHCI_TRANSFER_DESCRIPTOR *OutDescriptor,
IN UCHAR PidCode,
ULONG BufferLength)
{
PUHCI_TRANSFER_DESCRIPTOR Descriptor;
PHYSICAL_ADDRESS Address;
NTSTATUS Status;
//
// allocate descriptor
//
Status = m_DmaManager->Allocate(sizeof(UHCI_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &Address);
if (!NT_SUCCESS(Status))
{
DPRINT1("[USBUHCI] Failed to allocate descriptor\n");
return Status;
}
//
// init descriptor
//
Descriptor->PhysicalAddress = Address;
Descriptor->Status = TD_STATUS_ACTIVE;
if (InternalGetTransferType() == USB_ENDPOINT_TYPE_ISOCHRONOUS)
{
//
// isochronous transfer descriptor
//
Descriptor->Status |= TD_CONTROL_ISOCHRONOUS;
}
else
{
//
// error count
//
Descriptor->Status |= TD_CONTROL_3_ERRORS;
if (PidCode == TD_TOKEN_IN && (InternalGetTransferType() != USB_ENDPOINT_TYPE_CONTROL))
{
//
// enable short packet detect for bulk & interrupt
//
Descriptor->Status |= TD_CONTROL_SPD;
}
}
//
// is it low speed device
//
if (m_DeviceSpeed == UsbLowSpeed)
{
//
// low speed device
//
Descriptor->Status |= TD_CONTROL_LOWSPEED;
}
//
// store buffer size
//
Descriptor->BufferSize = BufferLength;
//
// is there a buffer
//
if(BufferLength)
{
//
// store buffer length
//
Descriptor->Token = (BufferLength - 1) << TD_TOKEN_MAXLEN_SHIFT;
}
else
{
//
// no buffer magic constant
//
Descriptor->Token = TD_TOKEN_NULL_DATA;
}
//
// store address & endpoint number
//
Descriptor->Token |= GetEndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT;
Descriptor->Token |= GetDeviceAddress() << 8 | PidCode;
if (BufferLength)
{
//
// allocate buffer for descriptor
//
Status = m_DmaManager->Allocate(BufferLength, (PVOID*)&Descriptor->BufferLogical, &Address);
if (!NT_SUCCESS(Status))
{
DPRINT1("[USBUHCI] Failed to allocate descriptor buffer length %lu\n", BufferLength);
m_DmaManager->Release(Descriptor, sizeof(UHCI_TRANSFER_DESCRIPTOR));
return Status;
}
//
// store address
//
Descriptor->BufferPhysical = Address.LowPart;
}
//
// done
//
*OutDescriptor = Descriptor;
return STATUS_SUCCESS;
}
NTSTATUS
CUSBRequest::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)
{
PUHCI_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL;
UCHAR TransferBufferOffset = 0;
NTSTATUS Status;
ULONG MaxPacketSize, CurrentBufferSize;
//
// FIXME FIXME FIXME FIXME FIXME
//
MaxPacketSize = 64;
do
{
//
// determine current packet size
//
CurrentBufferSize = min(MaxPacketSize, TransferBufferLength - TransferBufferOffset);
//
// allocate descriptor
//
Status = CreateDescriptor(&CurrentDescriptor, PidCode, CurrentBufferSize);
if (!NT_SUCCESS(Status))
{
//
// failed to allocate queue head
//
DPRINT1("[UHCI] Failed to create descriptor\n");
ASSERT(FALSE);
return Status;
}
if (PidCode == TD_TOKEN_OUT)
{
//
// copy buffer
//
RtlCopyMemory(CurrentDescriptor->BufferLogical, TransferBuffer, CurrentBufferSize);
}
if (!FirstDescriptor)
{
//
// first descriptor
//
FirstDescriptor = CurrentDescriptor;
}
else
{
//
// link descriptor
//
LastDescriptor->LinkPhysical = CurrentDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor;
}
if (InitialDataToggle)
{
//
// apply data toggle
//
CurrentDescriptor->Token |= TD_TOKEN_DATA1;
}
//
// re-run
//
LastDescriptor = CurrentDescriptor;
TransferBufferOffset += CurrentBufferSize;
InitialDataToggle = !InitialDataToggle;
}while(TransferBufferOffset < TransferBufferLength);
if (OutTransferBufferOffset)
{
//
// store transfer buffer length
//
*OutTransferBufferOffset = TransferBufferOffset;
}
if (OutFirstDescriptor)
{
//
// store first descriptor
//
*OutFirstDescriptor = FirstDescriptor;
}
if (OutLastDescriptor)
{
//
// store last descriptor
//
*OutLastDescriptor = CurrentDescriptor;
}
if (OutDataToggle)
{
//
// store data toggle
//
*OutDataToggle = InitialDataToggle;
}
//
// done
//
return STATUS_SUCCESS;
}
NTSTATUS
CUSBRequest::BuildQueueHead(
OUT PUHCI_QUEUE_HEAD *OutQueueHead)
{
PUHCI_QUEUE_HEAD QueueHead;
NTSTATUS Status;
PHYSICAL_ADDRESS Address;
//
// allocate queue head
//
Status = m_DmaManager->Allocate(sizeof(UHCI_QUEUE_HEAD), (PVOID*)&QueueHead, &Address);
if (!NT_SUCCESS(Status))
{
//
// failed to allocate queue head
//
DPRINT1("[UHCI] Failed to create queue head\n");
return Status;
}
//
// store address
//
QueueHead->PhysicalAddress = Address.LowPart;
QueueHead->ElementPhysical = Address.LowPart;
//
// store result
//
*OutQueueHead = QueueHead;
return STATUS_SUCCESS;
}
VOID
CUSBRequest::FreeDescriptor(
IN PUHCI_TRANSFER_DESCRIPTOR Descriptor)
{
if (Descriptor->BufferLogical)
{
//
// free buffer
//
m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize);
}
//
// free descriptors
//
m_DmaManager->Release(Descriptor, sizeof(UHCI_TRANSFER_DESCRIPTOR));
}
NTSTATUS
CUSBRequest::BuildControlTransferDescriptor(
IN PUHCI_QUEUE_HEAD * OutQueueHead)
{
PUHCI_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor;
PUHCI_QUEUE_HEAD QueueHead;
BOOLEAN Direction;
NTSTATUS Status;
ULONG ChainDescriptorLength;
//
// 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();
//
// build setup descriptor
//
Status = CreateDescriptor(&SetupDescriptor,
TD_TOKEN_SETUP,
sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
if (!NT_SUCCESS(Status))
{
//
// failed to allocate descriptor
//
DPRINT1("[UHCI] Failed to create setup descriptor\n");
m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD));
return Status;
}
//
// build status descriptor
//
Status = CreateDescriptor(&StatusDescriptor,
Direction ? TD_TOKEN_OUT : TD_TOKEN_IN,
0);
if (!NT_SUCCESS(Status))
{
//
// failed to allocate descriptor
//
DPRINT1("[UHCI] Failed to create setup descriptor\n");
FreeDescriptor(SetupDescriptor);
m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD));
return Status;
}
if (m_SetupPacket)
{
//
// copy setup packet
//
RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
}
else
{
//
// generate setup packet from urb
//
ASSERT(FALSE);
}
//
// init status descriptor
//
StatusDescriptor->Status |= TD_CONTROL_IOC;
StatusDescriptor->Token |= TD_TOKEN_DATA1;
StatusDescriptor->LinkPhysical = TD_TERMINATE;
StatusDescriptor->NextLogicalDescriptor = NULL;
if (m_TransferBufferLength)
{
//
// create descriptor chain
//
Status = BuildTransferDescriptorChain(MmGetMdlVirtualAddress(m_TransferBufferMDL),
m_TransferBufferLength,
Direction ? TD_TOKEN_IN : TD_TOKEN_OUT,
FALSE,
&FirstDescriptor,
&LastDescriptor,
&ChainDescriptorLength,
NULL);
if (!NT_SUCCESS(Status))
{
//
// failed to allocate descriptor
//
DPRINT1("[UHCI] Failed to create descriptor chain\n");
FreeDescriptor(SetupDescriptor);
FreeDescriptor(StatusDescriptor);
m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD));
return Status;
}
//
// link setup descriptor to first data descriptor
//
SetupDescriptor->LinkPhysical = FirstDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
SetupDescriptor->NextLogicalDescriptor = (PVOID)FirstDescriptor;
//
// link last data descriptor to status descriptor
//
LastDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
LastDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor;
}
else
{
//
// directly link setup to status descriptor
//
SetupDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress.LowPart | TD_DEPTH_FIRST;
SetupDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor;
}
//
// link queue head with setup descriptor
//
QueueHead->NextElementDescriptor = (PVOID)SetupDescriptor;
QueueHead->ElementPhysical = SetupDescriptor->PhysicalAddress.LowPart;
//
// store result
//
*OutQueueHead = QueueHead;
return STATUS_SUCCESS;
}
USB_DEVICE_SPEED
CUSBRequest::GetDeviceSpeed()
{
return m_DeviceSpeed;
}
//-----------------------------------------------------------------------------------------
NTSTATUS