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_new/hardware.cpp?rev=51388&r1=51387&r2=51388&view=diff
==============================================================================
--- 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_new/hardware.h?rev=51388&r1=51387&r2=51388&view=diff
==============================================================================
--- 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_new/interfaces.h?rev=51388&r1=51387&r2=51388&view=diff
==============================================================================
--- 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_new/usb_queue.cpp?rev=51388&r1=51387&r2=51388&view=diff
==============================================================================
--- 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


Reply via email to