Author: janderwald Date: Fri May 20 14:47:15 2011 New Revision: 51826
URL: http://svn.reactos.org/svn/reactos?rev=51826&view=rev Log: [USBEHCI] - Pass memory manager to USBQueue object - Fix bug in memory manager which did not check if an allocation equals page size - Implement interrupt queue head array with frequencys of 1ms up to 32ms - Store queue heads in the sync schedule array - WIP
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h branches/usb-bringup/drivers/usb/usbehci_new/memory_manager.cpp branches/usb-bringup/drivers/usb/usbehci_new/usb_queue.cpp
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp [iso-8859-1] Fri May 20 14:47:15 2011 @@ -437,7 +437,7 @@ // // Initialize the UsbQueue now that we have an AdapterObject. // - Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, NULL); + Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Initialize the UsbQueue\n");
Modified: branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h [iso-8859-1] Fri May 20 14:47:15 2011 @@ -525,7 +525,8 @@ // Description: initializes the object
virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, - PDMA_ADAPTER AdapterObject, + IN PDMA_ADAPTER AdapterObject, + IN PDMAMEMORYMANAGER MemManager, IN OPTIONAL PKSPIN_LOCK Lock) = 0;
//-----------------------------------------------------------------------------------------
Modified: branches/usb-bringup/drivers/usb/usbehci_new/memory_manager.cpp URL: http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci_... ============================================================================== --- branches/usb-bringup/drivers/usb/usbehci_new/memory_manager.cpp [iso-8859-1] (original) +++ branches/usb-bringup/drivers/usb/usbehci_new/memory_manager.cpp [iso-8859-1] Fri May 20 14:47:15 2011 @@ -131,11 +131,12 @@ { ULONG Length, BlockCount, FreeIndex, StartPage, EndPage; KIRQL OldLevel; + ULONG BlocksPerPage;
// // sanity checks // - ASSERT(Size < PAGE_SIZE); + ASSERT(Size <= PAGE_SIZE); //ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
// @@ -157,6 +158,11 @@ // acquire lock // KeAcquireSpinLock(m_Lock, &OldLevel); + + // + // helper variable + // + BlocksPerPage = PAGE_SIZE / m_BlockSize;
// // start search @@ -202,6 +208,19 @@ // break; } + else if ((BlockCount == BlocksPerPage) && (FreeIndex % BlocksPerPage == 0)) + { + // + // the request equals PAGE_SIZE and is aligned at page boundary + // reserve block + // + RtlSetBits(&m_Bitmap, FreeIndex, BlockCount); + + // + // reserve block + // + break; + } else { //
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] Fri May 20 14:47:15 2011 @@ -33,7 +33,7 @@ return m_Ref; }
- virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER AdapterObject, IN OPTIONAL PKSPIN_LOCK Lock); + virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER AdapterObject, IN PDMAMEMORYMANAGER MemManager, IN OPTIONAL PKSPIN_LOCK Lock); virtual ULONG GetPendingRequestCount(); virtual NTSTATUS AddUSBRequest(PURB Urb); virtual NTSTATUS AddUSBRequest(IUSBRequest * Request); @@ -47,13 +47,18 @@ virtual ~CUSBQueue(){}
protected: - LONG m_Ref; - KSPIN_LOCK m_Lock; - PDMA_ADAPTER m_Adapter; - PQUEUE_HEAD AsyncListQueueHead; - LIST_ENTRY m_CompletedRequestAsyncList; - LIST_ENTRY m_PendingRequestAsyncList; - + LONG m_Ref; // reference count + KSPIN_LOCK m_Lock; // list lock + PDMA_ADAPTER m_Adapter; // dma adapter + PUSBHARDWAREDEVICE m_Hardware; // stores hardware object + PQUEUE_HEAD AsyncListQueueHead; // async queue head + LIST_ENTRY m_CompletedRequestAsyncList; // completed async request list + LIST_ENTRY m_PendingRequestAsyncList; // pending async request list + ULONG m_MaxPeriodicListEntries; // max perdiodic list entries + ULONG m_MaxPollingInterval; // max polling interval + PHYSICAL_ADDRESS m_SyncFrameListAddr; // physical address of sync frame list + PULONG m_SyncFrameList; // virtual address of sync frame list + PQUEUE_HEAD * m_SyncFrameListQueueHeads; // stores the frame list of queue head
// queue head manipulation functions VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); @@ -69,6 +74,9 @@
// called when the completion queue is cleaned up VOID QueueHeadCleanup(PQUEUE_HEAD QueueHead); + + // intializes the sync schedule + NTSTATUS InitializeSyncSchedule(IN PUSBHARDWAREDEVICE Hardware, IN PDMAMEMORYMANAGER MemManager); };
//================================================================================================= @@ -93,7 +101,8 @@ NTSTATUS CUSBQueue::Initialize( IN PUSBHARDWAREDEVICE Hardware, - PDMA_ADAPTER AdapterObject, + IN PDMA_ADAPTER AdapterObject, + IN PDMAMEMORYMANAGER MemManager, IN OPTIONAL PKSPIN_LOCK Lock) { NTSTATUS Status = STATUS_SUCCESS; @@ -127,7 +136,139 @@ // InitializeListHead(&m_PendingRequestAsyncList);
+ // + // now initialize sync schedule + // + Status = InitializeSyncSchedule(Hardware, MemManager); + return Status; +} + +NTSTATUS +CUSBQueue::InitializeSyncSchedule( + IN PUSBHARDWAREDEVICE Hardware, + IN PDMAMEMORYMANAGER MemManager) +{ + PHYSICAL_ADDRESS QueueHeadPhysAddr; + NTSTATUS Status; + ULONG Index; + PQUEUE_HEAD QueueHead; + + // + // FIXME: check if smaller list sizes are supported + // + m_MaxPeriodicListEntries = 1024; + + // + // use polling scheme of 32ms + // + m_MaxPollingInterval = 32; + + // + // allocate dummy frame list array + // + m_SyncFrameListQueueHeads = (PQUEUE_HEAD*)ExAllocatePool(NonPagedPool, m_MaxPollingInterval * sizeof(PQUEUE_HEAD)); + if (!m_SyncFrameListQueueHeads) + { + // + // no memory + // + return STATUS_INSUFFICIENT_RESOURCES; + } + + + // + // first allocate a page to hold the queue array + // + Status = MemManager->Allocate(m_MaxPeriodicListEntries * sizeof(PVOID), (PVOID*)&m_SyncFrameList, &m_SyncFrameListAddr); + if (!NT_SUCCESS(Status)) + { + // + // failed to allocate sync frame list array + // + DPRINT1("Failed to allocate sync frame list\n"); + ExFreePool(m_SyncFrameListQueueHeads); + ASSERT(FALSE); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // now allocate queue head descriptors for the polling interval + // + for(Index = 0; Index < m_MaxPeriodicListEntries; Index++) + { + // + // check if is inside our polling interrupt frequency window + // + if (Index < m_MaxPollingInterval) + { + // + // allocate queue head + // + Status = MemManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysAddr); + + // + // initialize queue head + // + QueueHead->HorizontalLinkPointer = TERMINATE_POINTER; + QueueHead->AlternateNextPointer = TERMINATE_POINTER; + QueueHead->NextPointer = TERMINATE_POINTER; + + // + // 1 for non high speed, 0 for high speed device + // + QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0; + QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE; + QueueHead->EndPointCharacteristics.MaximumPacketLength = 64; + + // + // Set NakCountReload to max value possible + // + QueueHead->EndPointCharacteristics.NakCountReload = 0xF; + + // + // Get the Initial Data Toggle from the QEDT + // + QueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE; + + // + // FIXME: check if High Speed Device + // + QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; + QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03; + QueueHead->Token.DWord = 0; + QueueHead->Token.Bits.InterruptOnComplete = FALSE; + QueueHead->PhysicalAddr = QueueHeadPhysAddr.LowPart; + + + // + // store in queue head array + // + m_SyncFrameListQueueHeads[Index] = QueueHead; + } + else + { + // + // get cached entry + // + QueueHead = m_SyncFrameListQueueHeads[m_MaxPeriodicListEntries % m_MaxPollingInterval]; + } + + // + // store entry + // + m_SyncFrameList[Index] = (QueueHead->PhysicalAddr | 0x2); + } + + // + // now set the sync base + // + Hardware->SetPeriodicListRegister(m_SyncFrameListAddr.LowPart); + + // + // sync frame list initialized + // + return STATUS_SUCCESS; }
ULONG