mirror of
https://github.com/reactos/reactos.git
synced 2024-09-12 22:02:18 +00:00
[EHCI]
- Try fix bulk transfers #1 svn path=/branches/usb-bringup-trunk/; revision=55515
This commit is contained in:
parent
42ff9c13c0
commit
08ec4cc76d
|
@ -32,6 +32,11 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
StatusChangeWorkItemRoutine(PVOID Context);
|
StatusChangeWorkItemRoutine(PVOID Context);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
QueueHeadCompletionRoutine(PVOID Context);
|
||||||
|
|
||||||
|
|
||||||
class CUSBHardwareDevice : public IUSBHardwareDevice
|
class CUSBHardwareDevice : public IUSBHardwareDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -94,6 +99,7 @@ public:
|
||||||
friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
|
friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
|
||||||
friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
friend VOID NTAPI EhciDefferedRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||||
friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context);
|
friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context);
|
||||||
|
friend VOID NTAPI QueueHeadCompletionRoutine(PVOID Context);
|
||||||
// constructor / destructor
|
// constructor / destructor
|
||||||
CUSBHardwareDevice(IUnknown *OuterUnknown){}
|
CUSBHardwareDevice(IUnknown *OuterUnknown){}
|
||||||
virtual ~CUSBHardwareDevice(){}
|
virtual ~CUSBHardwareDevice(){}
|
||||||
|
@ -1306,6 +1312,37 @@ InterruptServiceRoutine(
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WORK_QUEUE_ITEM QueueHeadWorkItem;
|
||||||
|
CUSBHardwareDevice * This;
|
||||||
|
|
||||||
|
}QUEUE_HEAD_COMPLETION, *PQUEUE_HEAD_COMPLETION;
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
QueueHeadCompletionRoutine(
|
||||||
|
IN PVOID Ctx)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// cast to hardware object
|
||||||
|
//
|
||||||
|
PQUEUE_HEAD_COMPLETION Context = (PQUEUE_HEAD_COMPLETION)Ctx;
|
||||||
|
|
||||||
|
//
|
||||||
|
// now notify IUSBQueue that it can free completed requests
|
||||||
|
//
|
||||||
|
Context->This->m_UsbQueue->CompleteAsyncRequests();
|
||||||
|
|
||||||
|
//
|
||||||
|
// door ring bell completed
|
||||||
|
//
|
||||||
|
Context->This->m_DoorBellRingInProgress = FALSE;
|
||||||
|
|
||||||
|
ExFreePool(Context);
|
||||||
|
}
|
||||||
|
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
EhciDefferedRoutine(
|
EhciDefferedRoutine(
|
||||||
IN PKDPC Dpc,
|
IN PKDPC Dpc,
|
||||||
|
@ -1317,6 +1354,7 @@ EhciDefferedRoutine(
|
||||||
ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell;
|
ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
EHCI_USBCMD_CONTENT UsbCmd;
|
EHCI_USBCMD_CONTENT UsbCmd;
|
||||||
|
PQUEUE_HEAD_COMPLETION Context;
|
||||||
|
|
||||||
This = (CUSBHardwareDevice*) SystemArgument1;
|
This = (CUSBHardwareDevice*) SystemArgument1;
|
||||||
CStatus = (ULONG) SystemArgument2;
|
CStatus = (ULONG) SystemArgument2;
|
||||||
|
@ -1386,14 +1424,22 @@ EhciDefferedRoutine(
|
||||||
PC_ASSERT(This->m_DoorBellRingInProgress == TRUE);
|
PC_ASSERT(This->m_DoorBellRingInProgress == TRUE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// now notify IUSBQueue that it can free completed requests
|
// get command register
|
||||||
//
|
//
|
||||||
This->m_UsbQueue->CompleteAsyncRequests();
|
This->GetCommandRegister(&UsbCmd);
|
||||||
|
ASSERT(UsbCmd.DoorBell == FALSE);
|
||||||
|
|
||||||
//
|
//
|
||||||
// door ring bell completed
|
// allocate work item context
|
||||||
//
|
//
|
||||||
This->m_DoorBellRingInProgress = FALSE;
|
Context = (PQUEUE_HEAD_COMPLETION)ExAllocatePool(NonPagedPool, sizeof(QUEUE_HEAD_COMPLETION));
|
||||||
|
if (Context)
|
||||||
|
{
|
||||||
|
ExInitializeWorkItem(&Context->QueueHeadWorkItem, QueueHeadCompletionRoutine, Context);
|
||||||
|
Context->This = This;
|
||||||
|
ExQueueWorkItem(&Context->QueueHeadWorkItem, DelayedWorkQueue);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
This->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
|
This->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
|
||||||
|
|
|
@ -220,6 +220,17 @@ typedef struct _QUEUE_HEAD
|
||||||
PVOID Request;
|
PVOID Request;
|
||||||
} QUEUE_HEAD, *PQUEUE_HEAD;
|
} QUEUE_HEAD, *PQUEUE_HEAD;
|
||||||
|
|
||||||
|
C_ASSERT(sizeof(END_POINT_CHARACTERISTICS) == 4);
|
||||||
|
C_ASSERT(sizeof(END_POINT_CAPABILITIES) == 4);
|
||||||
|
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, HorizontalLinkPointer) == 0x00);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCharacteristics) == 0x04);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCapabilities) == 0x08);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, CurrentLinkPointer) == 0xC);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, NextPointer) == 0x10);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, AlternateNextPointer) == 0x14);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, Token) == 0x18);
|
||||||
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, BufferPointer) == 0x1C);
|
||||||
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, PhysicalAddr) == 0x30);
|
C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, PhysicalAddr) == 0x30);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -626,6 +626,7 @@ CUSBQueue::ProcessAsyncList(
|
||||||
//
|
//
|
||||||
// walk async list
|
// walk async list
|
||||||
//
|
//
|
||||||
|
ASSERT(AsyncListQueueHead);
|
||||||
Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
|
Entry = AsyncListQueueHead->LinkedQueueHeads.Flink;
|
||||||
|
|
||||||
while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
|
while(Entry != &AsyncListQueueHead->LinkedQueueHeads)
|
||||||
|
@ -634,6 +635,7 @@ CUSBQueue::ProcessAsyncList(
|
||||||
// get queue head structure
|
// get queue head structure
|
||||||
//
|
//
|
||||||
QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
|
QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
|
||||||
|
ASSERT(QueueHead);
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity check
|
// sanity check
|
||||||
|
@ -655,7 +657,7 @@ CUSBQueue::ProcessAsyncList(
|
||||||
//
|
//
|
||||||
IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
|
IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead);
|
||||||
|
|
||||||
DPRINT1("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
|
DPRINT("Request %p QueueHead %p Complete %d\n", Request, QueueHead, IsQueueHeadComplete);
|
||||||
|
|
||||||
//
|
//
|
||||||
// check if queue head is complete
|
// check if queue head is complete
|
||||||
|
|
|
@ -141,6 +141,8 @@ protected:
|
||||||
NTSTATUS m_NtStatusCode;
|
NTSTATUS m_NtStatusCode;
|
||||||
ULONG m_UrbStatusCode;
|
ULONG m_UrbStatusCode;
|
||||||
|
|
||||||
|
PVOID m_Base;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -660,8 +662,7 @@ CUSBRequest::InitDescriptor(
|
||||||
//
|
//
|
||||||
// Get the offset from page size
|
// Get the offset from page size
|
||||||
//
|
//
|
||||||
PageOffset = BYTE_OFFSET(TransferBuffer);
|
PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]);
|
||||||
|
|
||||||
if (PageOffset != 0)
|
if (PageOffset != 0)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -688,7 +689,7 @@ CUSBRequest::InitDescriptor(
|
||||||
CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength;
|
CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength;
|
||||||
CurrentDescriptor->TotalBytesToTransfer += BufferLength;
|
CurrentDescriptor->TotalBytesToTransfer += BufferLength;
|
||||||
Length += BufferLength;
|
Length += BufferLength;
|
||||||
DPRINT1("Index %lu Length %lu Buffer %p\n", Index, Length, TransferBuffer);
|
DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset, BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer);
|
||||||
|
|
||||||
//
|
//
|
||||||
// decrement available byte count
|
// decrement available byte count
|
||||||
|
@ -757,7 +758,6 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("BuildTransferDescriptorChain TransferBufferLength %lu TransferBufferOffset %lu\n", TransferBufferLength, TransferBufferOffset);
|
|
||||||
//
|
//
|
||||||
// now init the descriptor
|
// now init the descriptor
|
||||||
//
|
//
|
||||||
|
@ -785,6 +785,7 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
//
|
//
|
||||||
LastDescriptor->AlternateNextPointer = CurrentDescriptor->PhysicalAddr;
|
LastDescriptor->AlternateNextPointer = CurrentDescriptor->PhysicalAddr;
|
||||||
LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr;
|
LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr;
|
||||||
|
LastDescriptor = CurrentDescriptor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -794,11 +795,6 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
LastDescriptor = FirstDescriptor = CurrentDescriptor;
|
LastDescriptor = FirstDescriptor = CurrentDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// flip data toggle
|
|
||||||
//
|
|
||||||
InitialDataToggle = !InitialDataToggle;
|
|
||||||
|
|
||||||
if(TransferBufferLength == TransferBufferOffset)
|
if(TransferBufferLength == TransferBufferOffset)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -806,7 +802,6 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
//
|
//
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}while(TRUE);
|
}while(TRUE);
|
||||||
|
|
||||||
if (OutFirstDescriptor)
|
if (OutFirstDescriptor)
|
||||||
|
@ -827,6 +822,11 @@ CUSBRequest::BuildTransferDescriptorChain(
|
||||||
|
|
||||||
if (OutDataToggle)
|
if (OutDataToggle)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// flip data toggle
|
||||||
|
//
|
||||||
|
InitialDataToggle = !InitialDataToggle;
|
||||||
|
|
||||||
//
|
//
|
||||||
// store result data toggle
|
// store result data toggle
|
||||||
//
|
//
|
||||||
|
@ -1090,303 +1090,6 @@ NTSTATUS
|
||||||
CUSBRequest::BuildBulkTransferQueueHead(
|
CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
PQUEUE_HEAD * OutHead)
|
PQUEUE_HEAD * OutHead)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
NTSTATUS Status;
|
|
||||||
PQUEUE_HEAD QueueHead;
|
|
||||||
ULONG TransferDescriptorCount, Index;
|
|
||||||
ULONG BytesAvailable, BufferIndex;
|
|
||||||
PVOID Base;
|
|
||||||
ULONG PageOffset, CurrentTransferBufferLength;
|
|
||||||
PQUEUE_TRANSFER_DESCRIPTOR m_TransferDescriptors[3];
|
|
||||||
|
|
||||||
//
|
|
||||||
// Allocate the queue head
|
|
||||||
//
|
|
||||||
Status = CreateQueueHead(&QueueHead);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// failed to allocate queue heads
|
|
||||||
//
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity checks
|
|
||||||
//
|
|
||||||
PC_ASSERT(QueueHead);
|
|
||||||
PC_ASSERT(m_TransferBufferLength);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Max default of 3 descriptors
|
|
||||||
//
|
|
||||||
TransferDescriptorCount = 3;
|
|
||||||
|
|
||||||
//
|
|
||||||
// get virtual base of mdl
|
|
||||||
//
|
|
||||||
Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Increase the size of last transfer, 0 in case this is the first
|
|
||||||
//
|
|
||||||
Base = (PVOID)((ULONG_PTR)Base + m_TransferBufferLengthCompleted);
|
|
||||||
|
|
||||||
PC_ASSERT(m_EndpointDescriptor);
|
|
||||||
PC_ASSERT(Base);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the offset from page size
|
|
||||||
//
|
|
||||||
PageOffset = BYTE_OFFSET(Base);
|
|
||||||
|
|
||||||
//
|
|
||||||
// PageOffset should only be > 0 if this is the first transfer for this requests
|
|
||||||
//
|
|
||||||
if ((PageOffset != 0) && (m_TransferBufferLengthCompleted != 0))
|
|
||||||
{
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calculate the size of this transfer
|
|
||||||
//
|
|
||||||
if ((PageOffset != 0) && ((m_TransferBufferLength - m_TransferBufferLengthCompleted) >= (PAGE_SIZE * 4) + PageOffset))
|
|
||||||
{
|
|
||||||
CurrentTransferBufferLength = (PAGE_SIZE * 4) + PageOffset;
|
|
||||||
}
|
|
||||||
else if ((m_TransferBufferLength - m_TransferBufferLengthCompleted) >= PAGE_SIZE * 5)
|
|
||||||
{
|
|
||||||
CurrentTransferBufferLength = PAGE_SIZE * 5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
CurrentTransferBufferLength = (m_TransferBufferLength - m_TransferBufferLengthCompleted);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Add current transfer length to transfer length completed
|
|
||||||
//
|
|
||||||
m_TransferBufferLengthCompleted += CurrentTransferBufferLength;
|
|
||||||
BytesAvailable = CurrentTransferBufferLength;
|
|
||||||
DPRINT("CurrentTransferBufferLength %x, m_TransferBufferLengthCompleted %x\n", CurrentTransferBufferLength, m_TransferBufferLengthCompleted);
|
|
||||||
|
|
||||||
DPRINT("EndPointAddress %x\n", m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress);
|
|
||||||
DPRINT("EndPointDirection %x\n", USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress));
|
|
||||||
|
|
||||||
DPRINT("Request %p Base Address %p TransferBytesLength %lu MDL %p\n", this, Base, BytesAvailable, m_TransferBufferMDL);
|
|
||||||
DPRINT("InternalGetPidDirection() %d EndPointAddress %x\n", InternalGetPidDirection(), m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F);
|
|
||||||
DPRINT("Irp %p QueueHead %p\n", m_Irp, QueueHead);
|
|
||||||
|
|
||||||
//PC_ASSERT(InternalGetPidDirection() == USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->bEndpointAddress));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Allocated transfer descriptors
|
|
||||||
//
|
|
||||||
for (Index = 0; Index < TransferDescriptorCount; Index++)
|
|
||||||
{
|
|
||||||
Status = CreateDescriptor(&m_TransferDescriptors[Index]);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Failed to allocate transfer descriptors
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Free QueueHead
|
|
||||||
//
|
|
||||||
FreeQueueHead(QueueHead);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Free Descriptors
|
|
||||||
// FIXME: Implement FreeDescriptors
|
|
||||||
//
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity check
|
|
||||||
//
|
|
||||||
PC_ASSERT(BytesAvailable);
|
|
||||||
|
|
||||||
//
|
|
||||||
// now setup transfer buffers
|
|
||||||
//
|
|
||||||
for(BufferIndex = 0; BufferIndex < 5; BufferIndex++)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// If this is the first buffer of the first descriptor and there is a PageOffset
|
|
||||||
//
|
|
||||||
if ((BufferIndex == 0) && (PageOffset != 0) && (Index == 0))
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// use physical address
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->BufferPointer[0] = MmGetPhysicalAddress(Base).LowPart;
|
|
||||||
|
|
||||||
//
|
|
||||||
// move to next page
|
|
||||||
//
|
|
||||||
Base = (PVOID)ROUND_TO_PAGES(Base);
|
|
||||||
|
|
||||||
//
|
|
||||||
// increment transfer bytes
|
|
||||||
//
|
|
||||||
if (CurrentTransferBufferLength > PAGE_SIZE - PageOffset)
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = PAGE_SIZE - PageOffset;
|
|
||||||
else
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer = CurrentTransferBufferLength;
|
|
||||||
|
|
||||||
//
|
|
||||||
// decrement available byte count
|
|
||||||
//
|
|
||||||
BytesAvailable -= m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer;
|
|
||||||
|
|
||||||
DPRINT("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
|
|
||||||
BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// the following pages always start on byte zero of each page
|
|
||||||
//
|
|
||||||
PC_ASSERT(((ULONG_PTR)Base & (PAGE_SIZE-1)) == 0);
|
|
||||||
|
|
||||||
if (BytesAvailable >= PAGE_SIZE)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// store address
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart;
|
|
||||||
|
|
||||||
//
|
|
||||||
// move to next page
|
|
||||||
//
|
|
||||||
Base = (PVOID)((ULONG_PTR)Base + PAGE_SIZE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// increment transfer descriptor bytes
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += PAGE_SIZE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// decrement available byte count
|
|
||||||
//
|
|
||||||
BytesAvailable -= PAGE_SIZE;
|
|
||||||
|
|
||||||
DPRINT("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
|
|
||||||
BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PC_ASSERT(BytesAvailable);
|
|
||||||
|
|
||||||
//
|
|
||||||
// store address
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->BufferPointer[BufferIndex] = MmGetPhysicalAddress(Base).LowPart;
|
|
||||||
|
|
||||||
//
|
|
||||||
// increment transfer descriptor bytes
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer += BytesAvailable;
|
|
||||||
|
|
||||||
//
|
|
||||||
// decrement available byte count
|
|
||||||
//
|
|
||||||
BytesAvailable -= BytesAvailable;
|
|
||||||
|
|
||||||
//
|
|
||||||
// done as this is the last partial or full page
|
|
||||||
//
|
|
||||||
DPRINT("TransferDescriptor %p BufferPointer %p BufferIndex %lu TotalBytes %lu Remaining %lu\n", m_TransferDescriptors[Index], m_TransferDescriptors[Index]->BufferPointer[BufferIndex],
|
|
||||||
BufferIndex, m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer, BytesAvailable);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check if all bytes have been consumed
|
|
||||||
//
|
|
||||||
if (BytesAvailable == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// store transfer bytes of descriptor
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->TotalBytesToTransfer = m_TransferDescriptors[Index]->Token.Bits.TotalBytesToTransfer;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Go ahead and link descriptors
|
|
||||||
//
|
|
||||||
if (Index > 0)
|
|
||||||
{
|
|
||||||
m_TransferDescriptors[Index - 1]->NextPointer = m_TransferDescriptors[Index]->PhysicalAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// setup direction
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.PIDCode = InternalGetPidDirection();
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME: performance penality?
|
|
||||||
//
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.InterruptOnComplete = TRUE;
|
|
||||||
|
|
||||||
InsertTailList(&QueueHead->TransferDescriptorListHead, &m_TransferDescriptors[Index]->DescriptorEntry);
|
|
||||||
|
|
||||||
m_TransferDescriptors[Index]->Token.Bits.DataToggle = m_EndpointDescriptor->DataToggle;
|
|
||||||
m_EndpointDescriptor->DataToggle = !m_EndpointDescriptor->DataToggle;
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME need dead queue transfer descriptor?
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check if all bytes have been consumed
|
|
||||||
//
|
|
||||||
if (BytesAvailable == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// all bytes should have been consumed
|
|
||||||
//
|
|
||||||
PC_ASSERT(BytesAvailable == 0);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the QueueHead
|
|
||||||
//
|
|
||||||
QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress();
|
|
||||||
|
|
||||||
if (m_EndpointDescriptor)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Set endpoint address and max packet length
|
|
||||||
//
|
|
||||||
QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
|
|
||||||
QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueHead->Token.Bits.DataToggle = TRUE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// link descriptor with queue head
|
|
||||||
//
|
|
||||||
QueueHead->NextPointer = m_TransferDescriptors[0]->PhysicalAddr;
|
|
||||||
|
|
||||||
//
|
|
||||||
// store result
|
|
||||||
//
|
|
||||||
*OutHead = QueueHead;
|
|
||||||
|
|
||||||
//
|
|
||||||
// done
|
|
||||||
//
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
#else
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PQUEUE_HEAD QueueHead;
|
PQUEUE_HEAD QueueHead;
|
||||||
PVOID Base;
|
PVOID Base;
|
||||||
|
@ -1412,15 +1115,18 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
PC_ASSERT(QueueHead);
|
PC_ASSERT(QueueHead);
|
||||||
PC_ASSERT(m_TransferBufferLength);
|
PC_ASSERT(m_TransferBufferLength);
|
||||||
|
|
||||||
|
if (!m_Base)
|
||||||
|
{
|
||||||
//
|
//
|
||||||
// get virtual base of mdl
|
// get virtual base of mdl
|
||||||
//
|
//
|
||||||
Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Increase the size of last transfer, 0 in case this is the first
|
// Increase the size of last transfer, 0 in case this is the first
|
||||||
//
|
//
|
||||||
Base = (PVOID)((ULONG_PTR)Base + m_TransferBufferLengthCompleted);
|
Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted);
|
||||||
|
|
||||||
PC_ASSERT(m_EndpointDescriptor);
|
PC_ASSERT(m_EndpointDescriptor);
|
||||||
PC_ASSERT(Base);
|
PC_ASSERT(Base);
|
||||||
|
@ -1430,8 +1136,6 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
//
|
//
|
||||||
ASSERT(m_EndpointDescriptor);
|
ASSERT(m_EndpointDescriptor);
|
||||||
|
|
||||||
DPRINT1("Before EndPoint %p DataToggle %x\n", m_EndpointDescriptor, m_EndpointDescriptor->DataToggle);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// build bulk transfer descriptor chain
|
// build bulk transfer descriptor chain
|
||||||
//
|
//
|
||||||
|
@ -1448,15 +1152,13 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
//
|
//
|
||||||
// FIXME: handle errors
|
// FIXME: handle errors
|
||||||
//
|
//
|
||||||
//ASSERT(ChainDescriptorLength == m_TransferBufferLength);
|
ASSERT(ChainDescriptorLength == m_TransferBufferLength);
|
||||||
DPRINT1("Afterwards: EndPoint %p DataToggle %x\n", m_EndpointDescriptor, m_EndpointDescriptor->DataToggle);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// move to next offset
|
// move to next offset
|
||||||
//
|
//
|
||||||
m_TransferBufferLengthCompleted += ChainDescriptorLength;
|
m_TransferBufferLengthCompleted += ChainDescriptorLength;
|
||||||
|
|
||||||
|
|
||||||
ASSERT(Status == STATUS_SUCCESS);
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1466,7 +1168,8 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
|
QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F;
|
||||||
QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
|
QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize;
|
||||||
QueueHead->NextPointer = FirstDescriptor->PhysicalAddr;
|
QueueHead->NextPointer = FirstDescriptor->PhysicalAddr;
|
||||||
|
QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr;
|
||||||
|
QueueHead->AlternateNextPointer = TERMINATE_POINTER;
|
||||||
|
|
||||||
ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress);
|
ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress);
|
||||||
ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber);
|
ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber);
|
||||||
|
@ -1486,13 +1189,12 @@ CUSBRequest::BuildBulkTransferQueueHead(
|
||||||
//
|
//
|
||||||
// dump status
|
// dump status
|
||||||
//
|
//
|
||||||
DumpQueueHead(QueueHead);
|
//DumpQueueHead(QueueHead);
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
//
|
//
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------
|
||||||
|
@ -1929,6 +1631,13 @@ CUSBRequest::FreeQueueHead(
|
||||||
PLIST_ENTRY Entry;
|
PLIST_ENTRY Entry;
|
||||||
PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
|
PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(m_DmaManager);
|
||||||
|
ASSERT(QueueHead);
|
||||||
|
ASSERT(!IsListEmpty(&QueueHead->TransferDescriptorListHead));
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -1941,12 +1650,13 @@ CUSBRequest::FreeQueueHead(
|
||||||
// obtain descriptor from entry
|
// obtain descriptor from entry
|
||||||
//
|
//
|
||||||
Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
|
Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
|
||||||
|
ASSERT(Descriptor);
|
||||||
|
|
||||||
//
|
//
|
||||||
// add transfer count
|
// add transfer count
|
||||||
//
|
//
|
||||||
m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
|
m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
|
||||||
DPRINT1("TotalBytes Transferred in Descriptor %p Length %lu\n", Descriptor, Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
|
DPRINT("TotalBytes Transferred in Descriptor %p Phys Addr %x TotalBytesSoftware %lu Length %lu\n", Descriptor, Descriptor->PhysicalAddr, Descriptor->TotalBytesToTransfer, Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer);
|
||||||
|
|
||||||
//
|
//
|
||||||
// release transfer descriptors
|
// release transfer descriptors
|
||||||
|
@ -2015,6 +1725,7 @@ CUSBRequest::IsQueueHeadComplete(
|
||||||
// obtain descriptor from entry
|
// obtain descriptor from entry
|
||||||
//
|
//
|
||||||
Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
|
Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry);
|
||||||
|
ASSERT(Descriptor);
|
||||||
if (Descriptor->Token.Bits.Active)
|
if (Descriptor->Token.Bits.Active)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -2029,6 +1740,8 @@ CUSBRequest::IsQueueHeadComplete(
|
||||||
Entry = Entry->Flink;
|
Entry = Entry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr);
|
||||||
|
|
||||||
//
|
//
|
||||||
// no active descriptors found, queue head is finished
|
// no active descriptors found, queue head is finished
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue