Author: mjmartin
Date: Mon Apr 18 11:34:02 2011
New Revision: 51390
URL:
http://svn.reactos.org/svn/reactos?rev=51390&view=rev
Log:
[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.
Modified:
branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp [iso-8859-1] Mon Apr 18
11:34:02 2011
@@ -50,12 +50,16 @@
PDMA_ADAPTER m_Adapter;
PVOID VirtualBase;
PHYSICAL_ADDRESS PhysicalAddress;
- PLIST_ENTRY ExecutingList;
- PLIST_ENTRY PendingList;
+ PQUEUE_HEAD AsyncQueueHead;
+ PQUEUE_HEAD PendingQueueHead;
IDMAMemoryManager *m_MemoryManager;
PQUEUE_HEAD CreateQueueHead();
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 @@
IN OPTIONAL PKSPIN_LOCK Lock)
{
NTSTATUS Status;
- PQUEUE_HEAD HeadQueueHead;
DPRINT1("CUSBQueue::Initialize()\n");
@@ -130,33 +133,28 @@
}
//
- // Create a dead QueueHead for use in Async Register
- //
- HeadQueueHead = CreateQueueHead();
- HeadQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr |
QH_TYPE_QH;
- HeadQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
- HeadQueueHead->Token.Bits.InterruptOnComplete = FALSE;
- HeadQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE;
- HeadQueueHead->Token.Bits.Halted = TRUE;
+ // Create a QueueHead for use in Async Register
+ //
+ AsyncQueueHead = CreateQueueHead();
+ AsyncQueueHead->HorizontalLinkPointer = AsyncQueueHead->PhysicalAddr |
QH_TYPE_QH;
+ AsyncQueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
+ AsyncQueueHead->Token.Bits.InterruptOnComplete = FALSE;
+ AsyncQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE;
+ AsyncQueueHead->Token.Bits.Halted = TRUE;
- Hardware->SetAsyncListRegister(HeadQueueHead->PhysicalAddr);
-
- //
- // Set ExecutingList and create PendingList
- //
- ExecutingList = &HeadQueueHead->LinkedQueueHeads;
- PendingList = (PLIST_ENTRY) ExAllocatePool(NonPagedPool, sizeof(LIST_ENTRY));
- if (!PendingList)
- {
- DPRINT1("Pool allocation failed\n");
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // Initialize ListHeads
- //
- InitializeListHead(ExecutingList);
- InitializeListHead(PendingList);
+ Hardware->SetAsyncListRegister(AsyncQueueHead->PhysicalAddr);
+
+ //
+ // Create a Unused QueueHead to hold pending QueueHeads
+ //
+ PendingQueueHead = CreateQueueHead();
+ PendingQueueHead->Token.Bits.Halted = TRUE;
+
+ //
+ // Initialize ListHead in QueueHeads
+ //
+ InitializeListHead(&AsyncQueueHead->LinkedQueueHeads);
+ InitializeListHead(&PendingQueueHead->LinkedQueueHeads);
return STATUS_SUCCESS;
}
@@ -262,6 +260,9 @@
if (!NT_SUCCESS(Status))
return NULL;
+ //
+ // Set default values
+ //
Descriptor->NextPointer = TERMINATE_POINTER;
Descriptor->AlternateNextPointer = TERMINATE_POINTER;
Descriptor->Token.Bits.DataToggle = TRUE;
@@ -270,7 +271,144 @@
Descriptor->Token.Bits.PIDCode = PIDCode;
Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer;
Descriptor->PhysicalAddr = PhysicalAddress.LowPart;
+
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