mirror of
https://github.com/reactos/reactos.git
synced 2024-07-12 07:35:10 +00:00
[USBEHCI_NEW]
- Store number of bytes transferred in the transfer descriptors - Perform queue head completion when the door bell ring has been acknowledged. Fixes race condition between multiple irps in the async list - Fix calculation of transfer length when the request is an bulk in operation - Use EndPointDescriptor member to access transfer type / pid direction - Use MmGetSystemAddressForMdlSafe to retrieve system address for urb buffer - Fix check if first transfer buffer finishes on first size if the size is of page_size - With these changes and little luck and good weather, usb mass storage devices have been seen to work in Windows XP SP3 - Code inspired of mjmartin usbehci driver and Haiku's usb stack svn path=/branches/usb-bringup/; revision=51506
This commit is contained in:
parent
547ea14508
commit
6321f84f30
|
@ -127,6 +127,7 @@ typedef struct _QUEUE_TRANSFER_DESCRIPTOR
|
||||||
//Software
|
//Software
|
||||||
ULONG PhysicalAddr;
|
ULONG PhysicalAddr;
|
||||||
LIST_ENTRY LinkedDescriptors;
|
LIST_ENTRY LinkedDescriptors;
|
||||||
|
ULONG TotalBytesToTransfer;
|
||||||
} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
|
} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -52,6 +52,8 @@ protected:
|
||||||
PDMA_ADAPTER m_Adapter;
|
PDMA_ADAPTER m_Adapter;
|
||||||
PQUEUE_HEAD AsyncListQueueHead;
|
PQUEUE_HEAD AsyncListQueueHead;
|
||||||
LIST_ENTRY m_CompletedRequestAsyncList;
|
LIST_ENTRY m_CompletedRequestAsyncList;
|
||||||
|
LIST_ENTRY m_PendingRequestAsyncList;
|
||||||
|
|
||||||
|
|
||||||
// queue head manipulation functions
|
// queue head manipulation functions
|
||||||
VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
|
VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
|
||||||
|
@ -120,6 +122,11 @@ CUSBQueue::Initialize(
|
||||||
//
|
//
|
||||||
InitializeListHead(&m_CompletedRequestAsyncList);
|
InitializeListHead(&m_CompletedRequestAsyncList);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize pending async list head
|
||||||
|
//
|
||||||
|
InitializeListHead(&m_PendingRequestAsyncList);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,19 +432,157 @@ CUSBQueue::QueueHeadCompletion(
|
||||||
NTSTATUS Status)
|
NTSTATUS Status)
|
||||||
{
|
{
|
||||||
IUSBRequest *Request;
|
IUSBRequest *Request;
|
||||||
USBD_STATUS UrbStatus;
|
|
||||||
PQUEUE_HEAD NewQueueHead;
|
PQUEUE_HEAD NewQueueHead;
|
||||||
|
|
||||||
//
|
//
|
||||||
// this function is called when a queue head has been completed
|
// now unlink the queue head
|
||||||
|
// FIXME: implement chained queue heads
|
||||||
//
|
//
|
||||||
PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
|
UnlinkQueueHead(CurrentQH);
|
||||||
|
|
||||||
//
|
//
|
||||||
// get contained usb request
|
// get contained usb request
|
||||||
//
|
//
|
||||||
Request = (IUSBRequest*)CurrentQH->Request;
|
Request = (IUSBRequest*)CurrentQH->Request;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if the request is complete
|
||||||
|
//
|
||||||
|
if (Request->IsRequestComplete() == FALSE)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// request is still in complete
|
||||||
|
// get new queue head
|
||||||
|
//
|
||||||
|
Status = Request->GetQueueHead(&NewQueueHead);
|
||||||
|
|
||||||
|
//
|
||||||
|
// add to pending list
|
||||||
|
//
|
||||||
|
InsertTailList(&m_PendingRequestAsyncList, &NewQueueHead->LinkedQueueHeads);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// put queue head into completed queue head list
|
||||||
|
//
|
||||||
|
InsertTailList(&m_CompletedRequestAsyncList, &CurrentQH->LinkedQueueHeads);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBQueue::ProcessAsyncList(
|
||||||
|
IN NTSTATUS Status,
|
||||||
|
OUT PULONG ShouldRingDoorBell)
|
||||||
|
{
|
||||||
|
KIRQL OldLevel;
|
||||||
|
PLIST_ENTRY Entry;
|
||||||
|
PQUEUE_HEAD QueueHead;
|
||||||
|
IUSBRequest * Request;
|
||||||
|
BOOLEAN IsQueueHeadComplete;
|
||||||
|
|
||||||
|
//
|
||||||
|
// lock completed async list
|
||||||
|
//
|
||||||
|
KeAcquireSpinLock(&m_Lock, &OldLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// walk async list
|
||||||
|
//
|
||||||
|
Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
|
||||||
|
|
||||||
|
while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// get queue head structure
|
||||||
|
//
|
||||||
|
QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(QueueHead->Request);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get IUSBRequest interface
|
||||||
|
//
|
||||||
|
Request = (IUSBRequest*)QueueHead->Request;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next entry
|
||||||
|
//
|
||||||
|
Entry = Entry->Flink;
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if queue head is complete
|
||||||
|
//
|
||||||
|
IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
|
||||||
|
|
||||||
|
DPRINT1("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if queue head is complete
|
||||||
|
//
|
||||||
|
if (IsQueueHeadComplete)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// current queue head is complete
|
||||||
|
//
|
||||||
|
QueueHeadCompletion(QueueHead, Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// ring door bell is going to be necessary
|
||||||
|
//
|
||||||
|
*ShouldRingDoorBell = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// release lock
|
||||||
|
//
|
||||||
|
KeReleaseSpinLock(&m_Lock, OldLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBQueue::InterruptCallback(
|
||||||
|
IN NTSTATUS Status,
|
||||||
|
OUT PULONG ShouldRingDoorBell)
|
||||||
|
{
|
||||||
|
|
||||||
|
DPRINT1("CUSBQueue::InterruptCallback\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// iterate asynchronous list
|
||||||
|
//
|
||||||
|
*ShouldRingDoorBell = FALSE;
|
||||||
|
ProcessAsyncList(Status, ShouldRingDoorBell);
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: implement periodic schedule processing
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CUSBQueue::QueueHeadCleanup(
|
||||||
|
PQUEUE_HEAD CurrentQH)
|
||||||
|
{
|
||||||
|
IUSBRequest * Request;
|
||||||
|
BOOLEAN ShouldReleaseWhenDone;
|
||||||
|
USBD_STATUS UrbStatus;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
|
||||||
|
PC_ASSERT(CurrentQH->Request);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// get request
|
||||||
|
//
|
||||||
|
Request = (IUSBRequest*)CurrentQH->Request;
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity check
|
// sanity check
|
||||||
//
|
//
|
||||||
|
@ -481,145 +626,7 @@ CUSBQueue::QueueHeadCompletion(
|
||||||
//
|
//
|
||||||
// notify request that a queue head has been completed
|
// notify request that a queue head has been completed
|
||||||
//
|
//
|
||||||
Request->CompletionCallback(Status, UrbStatus, CurrentQH);
|
Request->CompletionCallback(STATUS_SUCCESS /*FIXME*/, UrbStatus, CurrentQH);
|
||||||
|
|
||||||
//
|
|
||||||
// now unlink the queue head
|
|
||||||
// FIXME: implement chained queue heads
|
|
||||||
//
|
|
||||||
UnlinkQueueHead(CurrentQH);
|
|
||||||
|
|
||||||
//
|
|
||||||
// check if the request is complete
|
|
||||||
//
|
|
||||||
if (Request->IsRequestComplete() == FALSE)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// request is still in complete
|
|
||||||
// get new queue head
|
|
||||||
//
|
|
||||||
Status = Request->GetQueueHead(&NewQueueHead);
|
|
||||||
|
|
||||||
//
|
|
||||||
// add to pending list
|
|
||||||
//
|
|
||||||
LinkQueueHead(AsyncListQueueHead, NewQueueHead);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// put queue head into completed queue head list
|
|
||||||
//
|
|
||||||
InsertTailList(&m_CompletedRequestAsyncList, &CurrentQH->LinkedQueueHeads);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CUSBQueue::ProcessAsyncList(
|
|
||||||
IN NTSTATUS Status,
|
|
||||||
OUT PULONG ShouldRingDoorBell)
|
|
||||||
{
|
|
||||||
KIRQL OldLevel;
|
|
||||||
PLIST_ENTRY Entry;
|
|
||||||
PQUEUE_HEAD QueueHead;
|
|
||||||
IUSBRequest * Request;
|
|
||||||
|
|
||||||
//
|
|
||||||
// lock completed async list
|
|
||||||
//
|
|
||||||
KeAcquireSpinLock(&m_Lock, &OldLevel);
|
|
||||||
|
|
||||||
//
|
|
||||||
// walk async list
|
|
||||||
//
|
|
||||||
Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
|
|
||||||
|
|
||||||
while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// get queue head structure
|
|
||||||
//
|
|
||||||
QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity check
|
|
||||||
//
|
|
||||||
PC_ASSERT(QueueHead->Request);
|
|
||||||
|
|
||||||
//
|
|
||||||
// get IUSBRequest interface
|
|
||||||
//
|
|
||||||
Request = (IUSBRequest*)QueueHead->Request;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// move to next entry
|
|
||||||
//
|
|
||||||
Entry = Entry->Flink;
|
|
||||||
|
|
||||||
DPRINT1("Request %p QueueHead %p Complete %d\n", Request, QueueHead, Request->IsQueueHeadComplete(QueueHead));
|
|
||||||
|
|
||||||
//
|
|
||||||
// check if queue head is complete
|
|
||||||
//
|
|
||||||
if (Request->IsQueueHeadComplete(QueueHead))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// current queue head is complete
|
|
||||||
//
|
|
||||||
QueueHeadCompletion(QueueHead, Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// ring door bell is going to be necessary
|
|
||||||
//
|
|
||||||
*ShouldRingDoorBell = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// release lock
|
|
||||||
//
|
|
||||||
KeReleaseSpinLock(&m_Lock, OldLevel);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CUSBQueue::InterruptCallback(
|
|
||||||
IN NTSTATUS Status,
|
|
||||||
OUT PULONG ShouldRingDoorBell)
|
|
||||||
{
|
|
||||||
|
|
||||||
DPRINT1("CUSBQueue::InterruptCallback\n");
|
|
||||||
|
|
||||||
//
|
|
||||||
// iterate asynchronous list
|
|
||||||
//
|
|
||||||
*ShouldRingDoorBell = FALSE;
|
|
||||||
ProcessAsyncList(Status, ShouldRingDoorBell);
|
|
||||||
|
|
||||||
//
|
|
||||||
// TODO: implement periodic schedule processing
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CUSBQueue::QueueHeadCleanup(
|
|
||||||
PQUEUE_HEAD CurrentQH)
|
|
||||||
{
|
|
||||||
IUSBRequest * Request;
|
|
||||||
BOOLEAN ShouldReleaseWhenDone;
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity checks
|
|
||||||
//
|
|
||||||
PC_ASSERT(CurrentQH->Token.Bits.Active == 0);
|
|
||||||
PC_ASSERT(CurrentQH->Request);
|
|
||||||
|
|
||||||
//
|
|
||||||
// get request
|
|
||||||
//
|
|
||||||
Request = (IUSBRequest*)CurrentQH->Request;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// let IUSBRequest free the queue head
|
// let IUSBRequest free the queue head
|
||||||
|
@ -689,6 +696,27 @@ CUSBQueue::CompleteAsyncRequests()
|
||||||
QueueHeadCleanup(CurrentQH);
|
QueueHeadCleanup(CurrentQH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// is there a pending async entry
|
||||||
|
//
|
||||||
|
if (!IsListEmpty(&m_PendingRequestAsyncList))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// remove first entry
|
||||||
|
//
|
||||||
|
Entry = RemoveHeadList(&m_CompletedRequestAsyncList);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get queue head structure
|
||||||
|
//
|
||||||
|
CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add it to the pending list
|
||||||
|
//
|
||||||
|
LinkQueueHead(AsyncListQueueHead, CurrentQH);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// release lock
|
// release lock
|
||||||
//
|
//
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
UCHAR GetDeviceAddress();
|
UCHAR GetDeviceAddress();
|
||||||
NTSTATUS BuildSetupPacket();
|
NTSTATUS BuildSetupPacket();
|
||||||
NTSTATUS BuildSetupPacketFromURB();
|
NTSTATUS BuildSetupPacketFromURB();
|
||||||
|
ULONG InternalCalculateTransferLength();
|
||||||
|
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CUSBRequest(IUnknown *OuterUnknown){}
|
CUSBRequest(IUnknown *OuterUnknown){}
|
||||||
|
@ -252,10 +253,15 @@ CUSBRequest::InitializeWithIrp(
|
||||||
//
|
//
|
||||||
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
|
if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create one using TransferBuffer
|
// Create one using TransferBuffer
|
||||||
//
|
//
|
||||||
DPRINT1("Creating Mdl from Urb Buffer\n");
|
DPRINT1("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
|
||||||
m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
|
m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer,
|
||||||
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
|
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
|
||||||
FALSE,
|
FALSE,
|
||||||
|
@ -370,8 +376,15 @@ CUSBRequest::CompletionCallback(
|
||||||
//
|
//
|
||||||
Urb->UrbHeader.Length = 0;
|
Urb->UrbHeader.Length = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// calculate transfer length
|
||||||
|
//
|
||||||
|
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = InternalCalculateTransferLength();
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT1("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x\n", this, m_Irp, NtStatusCode, UrbStatusCode);
|
DPRINT1("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp, NtStatusCode, UrbStatusCode, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME: check if the transfer was split
|
// FIXME: check if the transfer was split
|
||||||
|
@ -525,9 +538,6 @@ CUSBRequest::GetTransferType()
|
||||||
ULONG
|
ULONG
|
||||||
CUSBRequest::InternalGetTransferType()
|
CUSBRequest::InternalGetTransferType()
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
|
||||||
PURB Urb;
|
|
||||||
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
|
||||||
ULONG TransferType;
|
ULONG TransferType;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -535,38 +545,12 @@ CUSBRequest::InternalGetTransferType()
|
||||||
//
|
//
|
||||||
if (m_Irp)
|
if (m_Irp)
|
||||||
{
|
{
|
||||||
//
|
ASSERT(m_EndpointDescriptor);
|
||||||
// get stack location
|
|
||||||
//
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get urb
|
// end point is defined in the low byte of bmAttributes
|
||||||
//
|
//
|
||||||
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
TransferType = (m_EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
||||||
|
|
||||||
//
|
|
||||||
// check if there is a handle
|
|
||||||
//
|
|
||||||
if (Urb->UrbBulkOrInterruptTransfer.PipeHandle)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// cast to end point
|
|
||||||
//
|
|
||||||
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
|
||||||
|
|
||||||
//
|
|
||||||
// end point is defined in the low byte of bmAttributes
|
|
||||||
//
|
|
||||||
TransferType = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// no pipe handle, assume it is a control transfer
|
|
||||||
//
|
|
||||||
TransferType = USB_ENDPOINT_TYPE_CONTROL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -585,30 +569,13 @@ CUSBRequest::InternalGetTransferType()
|
||||||
UCHAR
|
UCHAR
|
||||||
CUSBRequest::InternalGetPidDirection()
|
CUSBRequest::InternalGetPidDirection()
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION IoStack;
|
|
||||||
PURB Urb;
|
|
||||||
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
|
|
||||||
|
|
||||||
ASSERT(m_Irp);
|
ASSERT(m_Irp);
|
||||||
//
|
ASSERT(m_EndpointDescriptor);
|
||||||
// get stack location
|
|
||||||
//
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(m_Irp);
|
|
||||||
|
|
||||||
//
|
|
||||||
// get urb
|
|
||||||
//
|
|
||||||
Urb = (PURB)IoStack->Parameters.Others.Argument1;
|
|
||||||
|
|
||||||
//
|
|
||||||
// cast to end point
|
|
||||||
//
|
|
||||||
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// end point is defined in the low byte of bEndpointAddress
|
// end point is defined in the low byte of bEndpointAddress
|
||||||
//
|
//
|
||||||
return (EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
|
return (m_EndpointDescriptor->bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -816,16 +783,19 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
//
|
//
|
||||||
// get virtual base of mdl
|
// get virtual base of mdl
|
||||||
//
|
//
|
||||||
Base = MmGetMdlVirtualAddress(m_TransferBufferMDL);
|
Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
||||||
BytesAvailable = m_TransferBufferLength;
|
BytesAvailable = m_TransferBufferLength;
|
||||||
|
|
||||||
PC_ASSERT(m_EndpointDescriptor);
|
PC_ASSERT(m_EndpointDescriptor);
|
||||||
|
PC_ASSERT(Base);
|
||||||
|
|
||||||
|
|
||||||
DPRINT1("EndPointAddress %x\n", m_EndpointDescriptor->bEndpointAddress);
|
DPRINT1("EndPointAddress %x\n", m_EndpointDescriptor->bEndpointAddress);
|
||||||
DPRINT1("EndPointDirection %x\n", USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
|
DPRINT1("EndPointDirection %x\n", USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
|
||||||
|
|
||||||
DPRINT1("Request %p Base Address %p TransferBytesLength %lu\n", this, Base, BytesAvailable);
|
DPRINT1("Request %p Base Address %p TransferBytesLength %lu MDL %p\n", this, Base, BytesAvailable, m_TransferBufferMDL);
|
||||||
DPRINT1("InternalGetPidDirection() %d EndPointAddress %x\n", InternalGetPidDirection(), m_EndpointDescriptor->bEndpointAddress & 0x0F);
|
DPRINT1("InternalGetPidDirection() %d EndPointAddress %x\n", InternalGetPidDirection(), m_EndpointDescriptor->bEndpointAddress & 0x0F);
|
||||||
|
DPRINT1("Irp %p QueueHead %p\n", m_Irp, QueueHead);
|
||||||
|
|
||||||
//PC_ASSERT(InternalGetPidDirection() == USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
|
//PC_ASSERT(InternalGetPidDirection() == USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
|
||||||
|
|
||||||
|
@ -881,7 +851,7 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
//
|
//
|
||||||
// check if request fills another page
|
// check if request fills another page
|
||||||
//
|
//
|
||||||
if (PageOffset + BytesAvailable >= PAGE_SIZE)
|
if (PageOffset + BytesAvailable > PAGE_SIZE)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// move to next page
|
// move to next page
|
||||||
|
@ -976,6 +946,11 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store transfer bytes of descriptor
|
||||||
|
//
|
||||||
|
m_TransferDescriptors[Index]->TotalBytesToTransfer = m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Go ahead and link descriptors
|
// Go ahead and link descriptors
|
||||||
//
|
//
|
||||||
|
@ -1579,6 +1554,36 @@ CUSBRequest::GetTransferBuffer(
|
||||||
*OutMDL = m_TransferBufferMDL;
|
*OutMDL = m_TransferBufferMDL;
|
||||||
*TransferLength = m_TransferBufferLength;
|
*TransferLength = m_TransferBufferLength;
|
||||||
}
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
ULONG
|
||||||
|
CUSBRequest::InternalCalculateTransferLength()
|
||||||
|
{
|
||||||
|
if (!m_Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: get length for control request
|
||||||
|
//
|
||||||
|
return m_TransferBufferLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(m_EndpointDescriptor);
|
||||||
|
|
||||||
|
if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// bulk in request
|
||||||
|
//
|
||||||
|
return m_TransferDescriptors[0]->TotalBytesToTransfer - m_TransferDescriptors[0]->Token.Bits.TotalBytesToTransfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// bulk out transfer
|
||||||
|
//
|
||||||
|
return m_TransferBufferLength;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Reference in a new issue