Author: mjmartin
Date: Mon Apr 18 00:06:37 2011
New Revision: 51388
URL:
http://svn.reactos.org/svn/reactos?rev=51388&view=rev
Log:
[USBEHCI_NEW]
- Use LIST_ENTRY in QueueHeads and Descriptors vice Next and Previous Pointers.
- Add functions to interface for setting AsyncListRegister and PeriodicListRegister.
- USBHardwareDevice: Initialize USBQueue when handling PNPStart.
- USBQueue: Allocate Common Buffer and use it to Create and Initialize DmaMemoryManager
object.
- USBQueue: Implement CreateQueueHead and CreateDescriptor.
Modified:
branches/usb-bringup/drivers/usb/usbehci_new/hardware.cpp
branches/usb-bringup/drivers/usb/usbehci_new/hardware.h
branches/usb-bringup/drivers/usb/usbehci_new/interfaces.h
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] Mon Apr 18
00:06:37 2011
@@ -60,7 +60,7 @@
NTSTATUS ResetController();
NTSTATUS ResetPort(ULONG PortIndex);
- VOID SetAsyncListAddressRegister(ULONG PhysicalAddress);
+ VOID SetAsyncListRegister(ULONG PhysicalAddress);
VOID SetPeriodicListRegister(ULONG PhysicalAddress);
KIRQL AcquireDeviceLock(void);
@@ -132,12 +132,16 @@
DPRINT1("CUSBHardwareDevice::Initialize\n");
+ //
+ // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules
+ //
Status = CreateUSBQueue(&m_UsbQueue);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create UsbQueue!\n");
return Status;
}
+
//
// store device objects
//
@@ -333,8 +337,26 @@
}
//
+ // Stop the controller before modifying schedules
+ //
+ Status = StopController();
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ //
+ // Initialize the UsbQueue now that we have an AdapterObject.
+ //
+ Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to Initialize the UsbQueue\n");
+ return Status;
+ }
+
+ //
// Start the controller
//
+
DPRINT1("Starting Controller\n");
return StartController();
}
@@ -369,7 +391,7 @@
*NumberOfPorts = m_Capabilities.HCSParams.PortCount;
//FIXME: What to returned here?
if (Speed)
- *Speed = 0;
+ *Speed = 0x200;
return STATUS_SUCCESS;
}
@@ -477,6 +499,7 @@
// Set port routing to EHCI controller
//
EHCI_WRITE_REGISTER_ULONG(EHCI_CONFIGFLAG, 1);
+
DPRINT1("EHCI Started!\n");
return STATUS_SUCCESS;
}
@@ -489,6 +512,7 @@
//
// Disable Interrupts and stop execution
+ //
EHCI_WRITE_REGISTER_ULONG (EHCI_USBINTR, 0);
GetCommandRegister(&UsbCmd);
@@ -565,25 +589,11 @@
return STATUS_SUCCESS;
}
-//-----------------------------------------------------------------------------------------
-//
-// SetAsyncListAddressRegister
-//
-// Description: this functions sets the register to a address that is the physical
address of a QueueHead.
-// This is the location at which the controller will start executing the Asynchronous
Schedule.
-//
-VOID CUSBHardwareDevice::SetAsyncListAddressRegister(ULONG PhysicalAddress)
+VOID CUSBHardwareDevice::SetAsyncListRegister(ULONG PhysicalAddress)
{
EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress);
}
-//-----------------------------------------------------------------------------------------
-//
-// SetPeriodicListRegister
-//
-// Description: this functions sets the register to a address that is the physical
address of a ???.
-// This is the location at which the controller will start executing the Periodic
Schedule.
-//
VOID CUSBHardwareDevice::SetPeriodicListRegister(ULONG PhysicalAddress)
{
EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, PhysicalAddress);
Modified: branches/usb-bringup/drivers/usb/usbehci_new/hardware.h
URL:
http://svn.reactos.org/svn/reactos/branches/usb-bringup/drivers/usb/usbehci…
==============================================================================
--- branches/usb-bringup/drivers/usb/usbehci_new/hardware.h [iso-8859-1] (original)
+++ branches/usb-bringup/drivers/usb/usbehci_new/hardware.h [iso-8859-1] Mon Apr 18
00:06:37 2011
@@ -125,8 +125,7 @@
//Software
ULONG PhysicalAddr;
- struct _QUEUE_TRANSFER_DESCRIPTOR *PreviousDescriptor;
- struct _QUEUE_TRANSFER_DESCRIPTOR *NextDescriptor;
+ LIST_ENTRY LinkedDescriptors;
} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR;
//
@@ -190,8 +189,7 @@
//Software
ULONG PhysicalAddr;
- struct _QUEUE_HEAD *PreviousQueueHead;
- struct _QUEUE_HEAD *NextQueueHead;
+ LIST_ENTRY LinkedQueueHeads;
PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor;
PIRP IrpToComplete;
PMDL MdlToFree;
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] Mon Apr 18
00:06:37 2011
@@ -209,6 +209,25 @@
//
virtual NTSTATUS ResetPort(ULONG PortNumber) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetAsyncListRegister
+//
+// Description: this functions sets the register to a address that is the physical
address of a QueueHead.
+// This is the location at which the controller will start executing the Asynchronous
Schedule.
+//
+// FIXME: This is only available for USB 2.0
+ virtual VOID SetAsyncListRegister(ULONG PhysicalAddress) = 0;
+
+//-----------------------------------------------------------------------------------------
+//
+// SetPeriodicListRegister
+//
+// Description: this functions sets the register to a address that is the physical
address of a ???.
+// This is the location at which the controller will start executing the Periodic
Schedule.
+//
+ virtual VOID SetPeriodicListRegister(ULONG PhysicalAddress) = 0;
//-----------------------------------------------------------------------------------------
//
@@ -374,7 +393,7 @@
// Description: initializes the object
virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware,
- PADAPTER_OBJECT AdapterObject,
+ PDMA_ADAPTER AdapterObject,
IN OPTIONAL PKSPIN_LOCK Lock) = 0;
//-----------------------------------------------------------------------------------------
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
00:06:37 2011
@@ -33,7 +33,7 @@
return m_Ref;
}
- NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PADAPTER_OBJECT AdapterObject, IN
OPTIONAL PKSPIN_LOCK Lock);
+ NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Hardware, PDMA_ADAPTER AdapterObject, IN
OPTIONAL PKSPIN_LOCK Lock);
ULONG GetPendingRequestCount();
NTSTATUS AddUSBRequest(PURB Urb);
NTSTATUS AddUSBRequest(IUSBRequest * Request);
@@ -46,10 +46,16 @@
protected:
LONG m_Ref;
+ KSPIN_LOCK m_Lock;
PDMA_ADAPTER m_Adapter;
- PQUEUE_HEAD ExecutingList;
- PQUEUE_HEAD PendingList;
+ PVOID VirtualBase;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PLIST_ENTRY ExecutingList;
+ PLIST_ENTRY PendingList;
IDMAMemoryManager *m_MemoryManager;
+
+ PQUEUE_HEAD CreateQueueHead();
+ PQUEUE_TRANSFER_DESCRIPTOR CreateDescriptor(UCHAR PIDCode, ULONG
TotalBytesToTransfer);
};
//=================================================================================================
@@ -74,14 +80,33 @@
NTSTATUS
CUSBQueue::Initialize(
IN PUSBHARDWAREDEVICE Hardware,
- PADAPTER_OBJECT AdapterObject,
+ PDMA_ADAPTER AdapterObject,
IN OPTIONAL PKSPIN_LOCK Lock)
{
NTSTATUS Status;
+ PQUEUE_HEAD HeadQueueHead;
+
+ DPRINT1("CUSBQueue::Initialize()\n");
ASSERT(Hardware);
ASSERT(AdapterObject);
+ //
+ // Create Common Buffer
+ //
+ VirtualBase = AdapterObject->DmaOperations->AllocateCommonBuffer(AdapterObject,
+ PAGE_SIZE * 4,
+
&PhysicalAddress,
+ FALSE);
+ if (!VirtualBase)
+ {
+ DPRINT1("Failed to allocate a common buffer\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors.
+ //
Status = CreateDMAMemoryManager(&m_MemoryManager);
if (!NT_SUCCESS(Status))
{
@@ -89,6 +114,50 @@
return Status;
}
+ //
+ // initialize device lock
+ //
+ KeInitializeSpinLock(&m_Lock);
+
+ //
+ // Initialize the DMAMemoryManager
+ //
+ Status = m_MemoryManager->Initialize(Hardware, &m_Lock, PAGE_SIZE * 4,
VirtualBase, PhysicalAddress, 32);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to initialize the DMAMemoryManager\n");
+ return Status;
+ }
+
+ //
+ // 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;
+
+ 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);
+
return STATUS_SUCCESS;
}
@@ -128,6 +197,80 @@
{
UNIMPLEMENTED
return STATUS_NOT_IMPLEMENTED;
+}
+
+PQUEUE_HEAD
+CUSBQueue::CreateQueueHead()
+{
+ PQUEUE_HEAD QueueHead;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ NTSTATUS Status;
+ //
+ // Create the QueueHead from Common Buffer
+ //
+ Status = m_MemoryManager->Allocate(sizeof(QUEUE_HEAD),
+ (PVOID*)&QueueHead,
+ &PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+
+ //
+ // Initialize default values
+ //
+
+ QueueHead->PhysicalAddr = PhysicalAddress.LowPart;
+ 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 Queue Element Desriptor
+ QueueHead->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
+
+ QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
+
+ QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x03;
+
+ // Interrupt when QueueHead is processed
+ QueueHead->Token.Bits.InterruptOnComplete = FALSE;
+
+ return QueueHead;
+}
+
+PQUEUE_TRANSFER_DESCRIPTOR
+CUSBQueue::CreateDescriptor(
+ UCHAR PIDCode,
+ ULONG TotalBytesToTransfer)
+{
+ PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ NTSTATUS Status;
+
+ //
+ // Create the Descriptor from Common Buffer
+ //
+ Status = m_MemoryManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR),
+ (PVOID*)&Descriptor,
+ &PhysicalAddress);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+
+ Descriptor->NextPointer = TERMINATE_POINTER;
+ Descriptor->AlternateNextPointer = TERMINATE_POINTER;
+ Descriptor->Token.Bits.DataToggle = TRUE;
+ Descriptor->Token.Bits.ErrorCounter = 0x03;
+ Descriptor->Token.Bits.Active = TRUE;
+ Descriptor->Token.Bits.PIDCode = PIDCode;
+ Descriptor->Token.Bits.TotalBytesToTransfer = TotalBytesToTransfer;
+ Descriptor->PhysicalAddr = PhysicalAddress.LowPart;
+ return Descriptor;
}
NTSTATUS