[USBEHCI_NEW]

- Use PQUEUE_HEAD as the Head of pending list  and Async (Active) list vice using PLIST_ENTRY.
- Implement linking/unlinking a QueueHead to these Head QueueHeads.
- Implement chain linking/unlinking of QueueHeads. Thr plan being to used these functions during DMA operations to pull a number of QueueHeads from the pending list to place into the Async list for execution. 
- Will look for optimization in these functions later.

svn path=/branches/usb-bringup/; revision=51390
This commit is contained in:
Michael Martin 2011-04-18 11:34:02 +00:00
parent 9067f34e6f
commit d3e13a4ada

View file

@ -50,12 +50,16 @@ protected:
PDMA_ADAPTER m_Adapter; PDMA_ADAPTER m_Adapter;
PVOID VirtualBase; PVOID VirtualBase;
PHYSICAL_ADDRESS PhysicalAddress; PHYSICAL_ADDRESS PhysicalAddress;
PLIST_ENTRY ExecutingList; PQUEUE_HEAD AsyncQueueHead;
PLIST_ENTRY PendingList; PQUEUE_HEAD PendingQueueHead;
IDMAMemoryManager *m_MemoryManager; IDMAMemoryManager *m_MemoryManager;
PQUEUE_HEAD CreateQueueHead(); PQUEUE_HEAD CreateQueueHead();
PQUEUE_TRANSFER_DESCRIPTOR CreateDescriptor(UCHAR PIDCode, ULONG TotalBytesToTransfer); PQUEUE_TRANSFER_DESCRIPTOR CreateDescriptor(UCHAR PIDCode, ULONG TotalBytesToTransfer);
VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead);
VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead);
PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count);
}; };
//================================================================================================= //=================================================================================================
@ -84,7 +88,6 @@ CUSBQueue::Initialize(
IN OPTIONAL PKSPIN_LOCK Lock) IN OPTIONAL PKSPIN_LOCK Lock)
{ {
NTSTATUS Status; NTSTATUS Status;
PQUEUE_HEAD HeadQueueHead;
DPRINT1("CUSBQueue::Initialize()\n"); DPRINT1("CUSBQueue::Initialize()\n");
@ -130,33 +133,28 @@ CUSBQueue::Initialize(
} }
// //
// Create a dead QueueHead for use in Async Register // Create a QueueHead for use in Async Register
// //
HeadQueueHead = CreateQueueHead(); AsyncQueueHead = CreateQueueHead();
HeadQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr | QH_TYPE_QH; AsyncQueueHead->HorizontalLinkPointer = AsyncQueueHead->PhysicalAddr | QH_TYPE_QH;
HeadQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE; AsyncQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
HeadQueueHead->Token.Bits.InterruptOnComplete = FALSE; AsyncQueueHead->Token.Bits.InterruptOnComplete = FALSE;
HeadQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE; AsyncQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE;
HeadQueueHead->Token.Bits.Halted = TRUE; AsyncQueueHead->Token.Bits.Halted = TRUE;
Hardware->SetAsyncListRegister(HeadQueueHead->PhysicalAddr); Hardware->SetAsyncListRegister(AsyncQueueHead->PhysicalAddr);
// //
// Set ExecutingList and create PendingList // Create a Unused QueueHead to hold pending QueueHeads
// //
ExecutingList = &HeadQueueHead->LinkedQueueHeads; PendingQueueHead = CreateQueueHead();
PendingList = (PLIST_ENTRY) ExAllocatePool(NonPagedPool, sizeof(LIST_ENTRY)); PendingQueueHead->Token.Bits.Halted = TRUE;
if (!PendingList)
{
DPRINT1("Pool allocation failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
// //
// Initialize ListHeads // Initialize ListHead in QueueHeads
// //
InitializeListHead(ExecutingList); InitializeListHead(&AsyncQueueHead->LinkedQueueHeads);
InitializeListHead(PendingList); InitializeListHead(&PendingQueueHead->LinkedQueueHeads);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -262,6 +260,9 @@ CUSBQueue::CreateDescriptor(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
return NULL; return NULL;
//
// Set default values
//
Descriptor->NextPointer = TERMINATE_POINTER; Descriptor->NextPointer = TERMINATE_POINTER;
Descriptor->AlternateNextPointer = TERMINATE_POINTER; Descriptor->AlternateNextPointer = TERMINATE_POINTER;
Descriptor->Token.Bits.DataToggle = TRUE; Descriptor->Token.Bits.DataToggle = TRUE;
@ -270,9 +271,146 @@ CUSBQueue::CreateDescriptor(
Descriptor->Token.Bits.PIDCode = PIDCode; Descriptor->Token.Bits.PIDCode = PIDCode;
Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer; Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer;
Descriptor->PhysicalAddr = PhysicalAddress.LowPart; Descriptor->PhysicalAddr = PhysicalAddress.LowPart;
return Descriptor; return Descriptor;
} }
//
// LinkQueueHead - Links one QueueHead to the end of HeadQueueHead list, updating HorizontalLinkPointer.
//
VOID
CUSBQueue::LinkQueueHead(
PQUEUE_HEAD HeadQueueHead,
PQUEUE_HEAD NewQueueHead)
{
PQUEUE_HEAD LastQueueHead, NextQueueHead;
PLIST_ENTRY Entry;
ASSERT(HeadQueueHead);
ASSERT(NewQueueHead);
//
// Link the LIST_ENTRYs
//
InsertTailList(&HeadQueueHead->LinkedQueueHeads, &NewQueueHead->LinkedQueueHeads);
//
// Update HLP for Previous QueueHead, which should be the last in list.
//
Entry = NewQueueHead->LinkedQueueHeads.Blink;
LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
LastQueueHead->HorizontalLinkPointer = (NewQueueHead->PhysicalAddr | QH_TYPE_QH);
//
// Update HLP for NewQueueHead to point to next, which should be the HeadQueueHead
//
Entry = NewQueueHead->LinkedQueueHeads.Flink;
NextQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
ASSERT(NextQueueHead == HeadQueueHead);
NewQueueHead->HorizontalLinkPointer = NextQueueHead->PhysicalAddr;
}
//
// UnlinkQueueHead - Unlinks one QueueHead, updating HorizontalLinkPointer.
//
VOID
CUSBQueue::UnlinkQueueHead(
PQUEUE_HEAD QueueHead)
{
PQUEUE_HEAD PreviousQH, NextQH;
PLIST_ENTRY Entry;
Entry = QueueHead->LinkedQueueHeads.Blink;
PreviousQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
Entry = QueueHead->LinkedQueueHeads.Flink;
NextQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
ASSERT(QueueHead->HorizontalLinkPointer == (NextQH->PhysicalAddr | QH_TYPE_QH));
PreviousQH->HorizontalLinkPointer = NextQH->PhysicalAddr | QH_TYPE_QH;
RemoveEntryList(&QueueHead->LinkedQueueHeads);
}
//
// LinkQueueHeadChain - Links a list of QueueHeads to the HeadQueueHead list, updating HorizontalLinkPointer.
//
VOID
CUSBQueue::LinkQueueHeadChain(
PQUEUE_HEAD HeadQueueHead,
PQUEUE_HEAD NewQueueHead)
{
PQUEUE_HEAD LastQueueHead;
PLIST_ENTRY Entry;
ASSERT(HeadQueueHead);
ASSERT(NewQueueHead);
//
// Find the last QueueHead in NewQueueHead
//
Entry = NewQueueHead->LinkedQueueHeads.Blink;
ASSERT(Entry != NewQueueHead->LinkedQueueHeads.Flink);
LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
//
// Set the LinkPointer and Flink
//
LastQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr | QH_TYPE_QH;
LastQueueHead->LinkedQueueHeads.Flink = &HeadQueueHead->LinkedQueueHeads;
//
// Fine the last QueueHead in HeadQueueHead
//
Entry = HeadQueueHead->LinkedQueueHeads.Blink;
HeadQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads;
LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
LastQueueHead->LinkedQueueHeads.Flink = &NewQueueHead->LinkedQueueHeads;
LastQueueHead->HorizontalLinkPointer = NewQueueHead->PhysicalAddr | QH_TYPE_QH;
}
//
// UnlinkQueueHeadChain - Unlinks a list number of QueueHeads from HeadQueueHead list, updating HorizontalLinkPointer.
// returns the chain of QueueHeads removed from HeadQueueHead.
//
PQUEUE_HEAD
CUSBQueue::UnlinkQueueHeadChain(
PQUEUE_HEAD HeadQueueHead,
ULONG Count)
{
PQUEUE_HEAD LastQueueHead, FirstQueueHead;
PLIST_ENTRY Entry;
ULONG Index;
//
// Find the last QueueHead in NewQueueHead
//
Entry = &HeadQueueHead->LinkedQueueHeads;
FirstQueueHead = CONTAINING_RECORD(Entry->Flink, QUEUE_HEAD, LinkedQueueHeads);
for (Index = 0; Index < Count; Index++)
{
Entry = Entry->Flink;
if (Entry == &HeadQueueHead->LinkedQueueHeads)
{
DPRINT1("Warnnig; Only %d QueueHeads in HeadQueueHead\n", Index);
Count = Index + 1;
break;
}
}
LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads);
HeadQueueHead->LinkedQueueHeads.Flink = LastQueueHead->LinkedQueueHeads.Flink;
if (Count + 1 == Index)
{
HeadQueueHead->LinkedQueueHeads.Blink = &HeadQueueHead->LinkedQueueHeads;
}
else
HeadQueueHead->LinkedQueueHeads.Blink = LastQueueHead->LinkedQueueHeads.Flink;
FirstQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads;
LastQueueHead->LinkedQueueHeads.Flink = &FirstQueueHead->LinkedQueueHeads;
LastQueueHead->HorizontalLinkPointer = TERMINATE_POINTER;
return FirstQueueHead;
}
NTSTATUS NTSTATUS
CreateUSBQueue( CreateUSBQueue(
PUSBQUEUE *OutUsbQueue) PUSBQUEUE *OutUsbQueue)