[ros-diffs] [mjmartin] 51325: [USB\USBEHCI] - Fix linking of QueueHeads. Implement LinkQueueHeadToCompletedList and CleanupAsyncList. These functions are used to software link the completed queueheads to a com...

mjmartin at svn.reactos.org mjmartin at svn.reactos.org
Wed Apr 13 04:33:14 UTC 2011


Author: mjmartin
Date: Wed Apr 13 04:33:14 2011
New Revision: 51325

URL: http://svn.reactos.org/svn/reactos?rev=51325&view=rev
Log:
[USB\USBEHCI]
- Fix linking of QueueHeads. Implement LinkQueueHeadToCompletedList and CleanupAsyncList. These functions are used to software link the completed queueheads to a completed list. Only after the driver handshakes with the controller can this memory be freed.
Fix a few incorrect values for QueueHead.
- EhciDefferedRoutine: Implement handling of completed QueueHeads by removing them from the AnsycList and setting any errors for failure.
- Reserved a QueueHead that will always be in the AsyncList Address Register. By setting it as the Head of Reclamation the controller can know when it has reached the end of the QueueHead list.
- Remove all code from FdoDispatchInternalDeviceControl. This should never be called by upper level drivers.
Change 1 of 3.

Modified:
    trunk/reactos/drivers/usb/usbehci/fdo.c
    trunk/reactos/drivers/usb/usbehci/hardware.h
    trunk/reactos/drivers/usb/usbehci/hwiface.c
    trunk/reactos/drivers/usb/usbehci/hwiface.h

Modified: trunk/reactos/drivers/usb/usbehci/fdo.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/fdo.c?rev=51325&r1=51324&r2=51325&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/fdo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/fdo.c [iso-8859-1] Wed Apr 13 04:33:14 2011
@@ -21,10 +21,11 @@
     ULONG tmp;
     ULONG OpRegisters;
     PEHCI_HOST_CONTROLLER hcd;
-    LONG i;
+    int i;
 
     FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeferredContext;
 
+    /* Nothing is valid if the Pdo is NULL */
     if (!FdoDeviceExtension->Pdo)
     {
         DPRINT1("PDO not set yet!\n");
@@ -36,127 +37,183 @@
     OpRegisters = (ULONG)FdoDeviceExtension->hcd.OpRegisters;
 
     hcd = &FdoDeviceExtension->hcd;
-    
+
     CStatus = (ULONG) SystemArgument2;
 
-    
-    /* TD retired or Error */
-    if (CStatus & (EHCI_STS_INT | EHCI_ERROR_INT))
-    {
-        DPRINT("Asyn Complete!\n");
-        ULONG CurrentAddr, OffSet;
-        PQUEUE_HEAD CompletedQH, NextQH;
-        PQUEUE_TRANSFER_DESCRIPTOR CompletedTD, NextTD;
-        
-        /* AsyncListAddr Register will have the next QueueHead to execute */
-        CurrentAddr = GetAsyncListQueueRegister(hcd);
-
-        /* Calculate the VA for the next QueueHead */
-        OffSet = CurrentAddr - (ULONG)FdoDeviceExtension->hcd.CommonBufferPA.LowPart;
-        NextQH = (PQUEUE_HEAD)((ULONG)FdoDeviceExtension->hcd.CommonBufferVA + OffSet);
-
-        /* Get the previous QueueHead which is the QueueHead just completed */
-        CompletedQH = NextQH->PreviousQueueHead;
-        ASSERT(CompletedQH);
-        DPRINT("CompletedQH %x\n", CompletedQH);
-
-        //DumpQueueHead(CompletedQH);
-
-        /* Free memory for the Descriptors */
-        CompletedTD = CompletedQH->TransferDescriptor;
-        NextTD = CompletedTD;
-        while (NextTD)
-        {
-            CompletedTD = NextTD;
-            NextTD = NextTD->NextDescriptor;
-            FreeDescriptor(CompletedTD);
-        }
-        
-        /* If the Event is set then release waiter */
-        if (CompletedQH->Event)
-        {
-            KeSetEvent(CompletedQH->Event, IO_NO_INCREMENT, FALSE);
-        }
-
-        /* Free the Mdl if there was one */
-        if(CompletedQH->MdlToFree)
-            IoFreeMdl(CompletedQH->MdlToFree);
-
-        /* Is there an IRP that needs to be completed */
-        if (CompletedQH->IrpToComplete)
-        {
-            PIRP Irp;     
-            PIO_STACK_LOCATION Stack;
-            PURB Urb;
-
-            Irp = CompletedQH->IrpToComplete;            
-            Stack = IoGetCurrentIrpStackLocation(Irp);
-            ASSERT(Stack);
-            Urb = (PURB) Stack->Parameters.Others.Argument1;
-
-            /* Check for error */
-            if (CStatus & EHCI_ERROR_INT)
+    /* If Reclamation (The QueueHead list has been transveresed twice),
+       look through the queuehead list and find queue heads that have been 
+       1. Halted due to error
+       2. Transfer completion.
+       Move these QueueHeads to a temporary list that is used to pend memory release.
+       Either an Event is signalled or an Irp is completed depending on what was set during transfer request
+       setup. Next software issue a "DoorBell" that informs the controller the Asynchronous List is about to 
+       be modified.
+       After the controller acks this with interrupt, the memory for queueheads are released. */
+
+    if (CStatus & (EHCI_STS_RECL| EHCI_STS_INT | EHCI_ERROR_INT))
+    {
+        PQUEUE_HEAD CurrentQH;
+        PQUEUE_TRANSFER_DESCRIPTOR CurrentTD;
+        BOOLEAN QueueHeadCompleted;
+
+        /* Go through the list and delink completed (not active) QueueHeads */
+        CurrentQH = hcd->AsyncListQueue;
+        CurrentQH = CurrentQH->NextQueueHead;
+
+        while ((CurrentQH) && (CurrentQH != hcd->AsyncListQueue))
+        {
+            DPRINT1("Checking QueueHead %x, Next %x\n", CurrentQH, CurrentQH->NextQueueHead);
+            DPRINT1("Active %d, Halted %d\n", CurrentQH->Token.Bits.Active, CurrentQH->Token.Bits.Halted);
+
+            /* if the QueueHead has completed */
+            if (!CurrentQH->Token.Bits.Active)
             {
-                /* Haled bit should be set */
-                if (CompletedQH->Token.Bits.Halted)
+                /* Assume success */
+                USBD_STATUS UrbStatus = USBD_STATUS_SUCCESS;
+
+                QueueHeadCompleted = TRUE;
+
+                /* Check the Status of the QueueHead */
+                if (CurrentQH->Token.Bits.Halted)
                 {
-                    if (CompletedQH->Token.Bits.DataBufferError)
+                    if (CurrentQH->Token.Bits.DataBufferError)
                     {
                         DPRINT1("Data buffer error\n");
-                        Urb->UrbHeader.Status = USBD_STATUS_DATA_BUFFER_ERROR;
-                        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-                        Irp->IoStatus.Information = 0;
+                        UrbStatus = USBD_STATUS_DATA_BUFFER_ERROR;
                     }
-                    else if (CompletedQH->Token.Bits.BabbleDetected)
+                    else if (CurrentQH->Token.Bits.BabbleDetected)
                     {
                         DPRINT1("Babble Detected\n");
-                        Urb->UrbHeader.Status = USBD_STATUS_BABBLE_DETECTED;
-                        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-                        Irp->IoStatus.Information = 0;
+                        UrbStatus = USBD_STATUS_BABBLE_DETECTED;
                     }
                     else
                     {
                         DPRINT1("Stall PID\n");
-                        Urb->UrbHeader.Status = USBD_STATUS_STALL_PID;
-                        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-                        Irp->IoStatus.Information = 0;
+                        UrbStatus = USBD_STATUS_STALL_PID;
                     }
                 }
+                
+                /* Check the Descriptors */
+                CurrentTD = CurrentQH->FirstTransferDescriptor;
+                while (CurrentTD)
+                {
+                    /* FIXME: What needs to happen if the QueueHead was marked as complete but descriptors was not */
+                    if ((CurrentTD->Token.Bits.Active) || (CurrentTD->Token.Bits.Halted))
+                    {
+                        /* The descriptor was not completed */
+                        QueueHeadCompleted = FALSE;
+                        DPRINT1("QueueHead was marked as completed but contains descriptors that were not completed\n");
+                        ASSERT(FALSE);
+                        break;
+                    }
+                    CurrentTD = CurrentTD->NextDescriptor;
+                }
+
+                if ((QueueHeadCompleted) || (CurrentQH->Token.Bits.Halted))
+                {
+                    PQUEUE_HEAD FreeQH;
+                    
+                    FreeQH = CurrentQH;
+                    CurrentQH = CurrentQH->NextQueueHead;
+                    DPRINT1("QueueHead %x has completed. Removing\n", FreeQH);
+                    /* Move it into the completed list */
+                    UnlinkQueueHead(hcd, FreeQH);
+                    LinkQueueHeadToCompletedList(hcd, FreeQH);
+                    DPRINT1("Remove done\n");
+
+                    /* If the Event is set then the caller is waiting on completion */
+                    if (FreeQH->Event)
+                    {
+                        KeSetEvent(FreeQH->Event, IO_NO_INCREMENT, FALSE);
+                    }
+
+                    /* If there is an IrpToComplete then the caller did not wait on completion
+                       and the IRP was marked as PENDING. Complete it now. */
+                    if (FreeQH->IrpToComplete)
+                    {
+                        PIRP Irp;
+                        PIO_STACK_LOCATION Stack;
+                        PURB Urb;
+
+                        Irp = FreeQH->IrpToComplete;
+                        Stack = IoGetCurrentIrpStackLocation(Irp);
+                        ASSERT(Stack);
+                        Urb = (PURB) Stack->Parameters.Others.Argument1;
+                        ASSERT(Urb);
+
+                        /* Check for error */
+                        if (CStatus & EHCI_ERROR_INT)
+                        {
+                            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+                            Irp->IoStatus.Information = 0;
+                            /* Set BufferLength to 0 as there was error */
+                            if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
+                            {
+                                Urb->UrbControlDescriptorRequest.TransferBufferLength = 0;
+                            }
+                            DPRINT1("There was an Error, TransferBufferLength set to 0\n");
+                        }
+                        else
+                        {
+                            if (Urb->UrbHeader.Function == URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE)
+                            {
+                                if (Urb->UrbControlDescriptorRequest.TransferBufferLength >=
+                                    ((PUSB_COMMON_DESCRIPTOR)(Urb->UrbControlDescriptorRequest.TransferBuffer))->bLength)
+                                {
+                                    Urb->UrbControlDescriptorRequest.TransferBufferLength =
+                                        ((PUSB_COMMON_DESCRIPTOR)(Urb->UrbControlDescriptorRequest.TransferBuffer))->bLength;
+                                }
+                            }
+
+                            Irp->IoStatus.Status = STATUS_SUCCESS;
+                            Irp->IoStatus.Information = 0;
+                            DPRINT1("Completing Irp\n");
+                        }
+                        Urb->UrbHeader.Status = UrbStatus;
+                        IoCompleteRequest(Irp,  IO_NO_INCREMENT);
+                    }
+
+                    /* FIXME: Move to static function */
+                    PEHCI_USBCMD_CONTENT UsbCmd;
+                    /* Ring the DoorBell so that host controller knows a QueueHead was removed */
+                    DPRINT1("Ringing Doorbell\n");
+                    tmp = READ_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBCMD));
+                    UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
+                    UsbCmd->DoorBell = TRUE;
+                    WRITE_REGISTER_ULONG((PULONG) (OpRegisters +  EHCI_USBCMD), tmp);
+                    continue;
+                }
             }
-            else
-            {
-                Irp->IoStatus.Status = STATUS_SUCCESS;
-                Irp->IoStatus.Information = 0;              
-                DPRINT1("Completing Irp\n");
-
-            }
-            IoCompleteRequest(Irp,  IO_NO_INCREMENT);
-        }
-
-        /* Unlink QueueHead */
-        UnlinkQueueHead(hcd, CompletedQH);
-        /* Wait for a complete AsnycList tranversal before deleting? */
-        DeleteQueueHead(CompletedQH);
-    }
-
-    /* Port Change */
+
+            CurrentQH = CurrentQH->NextQueueHead;
+        }
+    }
+
+    
+    /* Port Change. */
+    /* FIXME: Use EnumControllerPorts instead */
     if (CStatus & EHCI_STS_PCD)
     {
         /* Loop through the ports */
-        for (i = 0; i < FdoDeviceExtension->hcd.ECHICaps.HCSParams.PortCount; i++)
+        for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
         {
             tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)));
 
             /* Check for port change on this port */
             if (tmp & 0x02)
             {
+                /* Clear status change */
+                tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
+                tmp |= 0x02;
+                WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), tmp);
+                
                 /* Connect or Disconnect? */
                 if (tmp & 0x01)
                 {
                     DPRINT1("Device connected on port %d\n", i);
 
                     /* Check if a companion host controller exists */
-                    if (FdoDeviceExtension->hcd.ECHICaps.HCSParams.CHCCount)
+                    if (hcd->ECHICaps.HCSParams.CHCCount)
                     {
                         tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
 
@@ -178,6 +235,7 @@
 
                     KeStallExecutionProcessor(30);
 
+                    /* FIXME: Hub driver does this also, is it needed here? */
                     /* As per USB 2.0 Specs, 9.1.2. Reset the port and clear the status change */
                     //tmp |= 0x100 | 0x02;
                     /* Sanity, Disable port */
@@ -190,21 +248,16 @@
                     tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
 
                     PdoDeviceExtension->ChildDeviceCount++;
-                    PdoDeviceExtension->Ports[i].PortStatus &= ~0x8000;
-                    PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED;
-                    PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_CONNECT;
-                    PdoDeviceExtension->Ports[i].PortChange |= USB_PORT_STATUS_CONNECT;
+                    hcd->Ports[i].PortStatus &= ~0x8000;
+                    hcd->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED;
+                    hcd->Ports[i].PortStatus |= USB_PORT_STATUS_CONNECT;
+                    hcd->Ports[i].PortChange |= USB_PORT_STATUS_CONNECT;
                     DPRINT1("Completing URB\n");
                     CompletePendingURBRequest(PdoDeviceExtension);
                 }
                 else
                 {
                     DPRINT1("Device disconnected on port %d\n", i);
-
-                    /* Clear status change */
-                    tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
-                    tmp |= 0x02;
-                    WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), tmp);
                 }
             }
         }
@@ -214,6 +267,7 @@
     if (CStatus & EHCI_STS_IAA)
     {
         DPRINT1("Async Advance!\n");
+        CleanupAsyncList(hcd);
     }
 }
 
@@ -232,7 +286,7 @@
     /* Read device status */
     CStatus = ReadControllerStatus(hcd);
 
-    CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD | EHCI_STS_FLR);
+    CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD | EHCI_STS_FLR | EHCI_STS_RECL);
 
     if ((!CStatus) || (FdoDeviceExtension->DeviceState == 0))
     {
@@ -243,9 +297,22 @@
     /* Clear status */
     ClearControllerStatus(hcd, CStatus);
 
+    if (CStatus & EHCI_STS_RECL)
+    {
+        DPRINT("Reclamation\n");
+    }
+
     if (CStatus & EHCI_ERROR_INT)
     {
         DPRINT1("EHCI Status=0x%x\n", CStatus);
+        /* This check added in case the NT USB Driver is still loading.
+           It will cause this error condition at every device connect. */
+        if(CStatus & EHCI_STS_PCD)
+        {
+            DPRINT1("EHCI Error: Another driver may be interfering with proper operation of this driver\n");
+            DPRINT1("  Hint: Ensure that the old NT Usb Driver has been removed!\n");
+            ASSERT(FALSE);
+        }
     }
 
     if (CStatus & EHCI_STS_FATAL)
@@ -270,6 +337,7 @@
     PFDO_DEVICE_EXTENSION FdoDeviceExtension;
     PCM_PARTIAL_RESOURCE_DESCRIPTOR resource;
     DEVICE_DESCRIPTION DeviceDescription;
+    PEHCI_HOST_CONTROLLER hcd;
     ULONG NumberResources;
     ULONG iCount;
     ULONG DeviceAddress;
@@ -278,26 +346,21 @@
     NTSTATUS Status;
 
     FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
+    hcd = &FdoDeviceExtension->hcd;
+
+    /* Sanity Checks */
     Status = IoGetDeviceProperty(FdoDeviceExtension->LowerDevice,
                                  DevicePropertyAddress,
                                  sizeof(ULONG),
                                  &DeviceAddress,
                                  &PropertySize);
-    if (NT_SUCCESS(Status))
-    {
-        DPRINT1("--->DeviceAddress: %x\n", DeviceAddress);
-    }
 
     Status = IoGetDeviceProperty(FdoDeviceExtension->LowerDevice,
                                  DevicePropertyBusNumber,
                                  sizeof(ULONG),
                                  &BusNumber,
                                  &PropertySize);
-    if (NT_SUCCESS(Status))
-    {
-        DPRINT1("--->BusNumber: %x\n", BusNumber);
-    }
+
 
     /* Get the resources the PNP Manager gave */
     NumberResources = translated->Count;
@@ -364,11 +427,21 @@
         }
     }
 
+    for (iCount = 0; iCount < hcd->ECHICaps.HCSParams.PortCount; iCount++)
+    {
+        hcd->Ports[iCount].PortStatus = 0x8000;
+        hcd->Ports[iCount].PortChange = 0;
+        
+        if (hcd->ECHICaps.HCSParams.PortPowerControl)
+            hcd->Ports[iCount].PortStatus |= USB_PORT_STATUS_POWER;
+    }
+
     KeInitializeDpc(&FdoDeviceExtension->DpcObject,
                     EhciDefferedRoutine,
                     FdoDeviceExtension);
 
     RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
+
     DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
     DeviceDescription.Master = TRUE;
     DeviceDescription.ScatterGather = TRUE;
@@ -377,20 +450,24 @@
     DeviceDescription.InterfaceType = PCIBus;
     DeviceDescription.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
 
-    FdoDeviceExtension->pDmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->LowerDevice,
-                                                      &DeviceDescription,
-                                                      &FdoDeviceExtension->MapRegisters);
-
-    if (FdoDeviceExtension->pDmaAdapter == NULL)
+    hcd->pDmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->LowerDevice,
+                                       &DeviceDescription,
+                                       &hcd->MapRegisters);
+
+    if (hcd->pDmaAdapter == NULL)
     {
         DPRINT1("Ehci: IoGetDmaAdapter failed!\n");
         ASSERT(FALSE);
     }
 
+    DPRINT1("MapRegisters %x\n", hcd->MapRegisters);
+
     /* Allocate Common Buffer for Periodic Frame List */
     FdoDeviceExtension->PeriodicFrameList.VirtualAddr =
-        FdoDeviceExtension->pDmaAdapter->DmaOperations->AllocateCommonBuffer(FdoDeviceExtension->pDmaAdapter,
-        sizeof(ULONG) * 1024, &FdoDeviceExtension->PeriodicFrameList.PhysicalAddr, FALSE);
+        hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter,
+                                                              sizeof(ULONG) * 1024,
+                                                              &FdoDeviceExtension->PeriodicFrameList.PhysicalAddr,
+                                                              FALSE);
 
     if (FdoDeviceExtension->PeriodicFrameList.VirtualAddr == NULL)
     {
@@ -403,36 +480,53 @@
 
     ExInitializeFastMutex(&FdoDeviceExtension->FrameListMutex);
 
-    /* Allocate pages for queueheads and descriptors */
-    FdoDeviceExtension->hcd.CommonBufferVA =
-        FdoDeviceExtension->pDmaAdapter->DmaOperations->AllocateCommonBuffer(FdoDeviceExtension->pDmaAdapter,
-                                                                             PAGE_SIZE * 16,
-                                                                             &FdoDeviceExtension->hcd.CommonBufferPA,
-                                                                             FALSE);
-
-    if (FdoDeviceExtension->hcd.CommonBufferVA == 0)
+    /* Allocate initial page for queueheads and descriptors */
+    FdoDeviceExtension->hcd.CommonBufferVA[0] =
+        hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter,
+                                                              PAGE_SIZE,
+                                                              &FdoDeviceExtension->hcd.CommonBufferPA[0],
+                                                              FALSE);
+
+    if (FdoDeviceExtension->hcd.CommonBufferVA[0] == 0)
     {
         DPRINT1("Ehci: Failed to allocate common buffer!\n");
         return STATUS_UNSUCCESSFUL;
     }
 
-    FdoDeviceExtension->hcd.CommonBufferSize = PAGE_SIZE * 16;
+    hcd->CommonBufferSize = PAGE_SIZE * 16;
 
     /* Zeroize it */
-    RtlZeroMemory(FdoDeviceExtension->hcd.CommonBufferVA,
-                  PAGE_SIZE * 16);
+    RtlZeroMemory(FdoDeviceExtension->hcd.CommonBufferVA[0],
+                  PAGE_SIZE);
 
     /* Init SpinLock for host controller device lock */
-    KeInitializeSpinLock(&FdoDeviceExtension->hcd.Lock);
-
-    /* Reserved a Queue Head that will always be in the AsyncList Address Register */
-    FdoDeviceExtension->hcd.AsyncListQueue = CreateQueueHead(&FdoDeviceExtension->hcd);
-    FdoDeviceExtension->hcd.AsyncListQueue->HorizontalLinkPointer = FdoDeviceExtension->hcd.AsyncListQueue->PhysicalAddr | QH_TYPE_QH;
-    FdoDeviceExtension->hcd.AsyncListQueue->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
-    FdoDeviceExtension->hcd.AsyncListQueue->Token.Bits.InterruptOnComplete = FALSE;
-
+    KeInitializeSpinLock(&hcd->Lock);
+
+    /* Reserved a Queue Head that will always be in the AsyncList Address Register. By setting it as the Head of Reclamation
+       the controller can know when it has reached the end of the QueueHead list */
+    hcd->AsyncListQueue = CreateQueueHead(hcd);
+
+    hcd->AsyncListQueue->HorizontalLinkPointer = hcd->AsyncListQueue->PhysicalAddr | QH_TYPE_QH;
+    hcd->AsyncListQueue->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
+    hcd->AsyncListQueue->Token.Bits.InterruptOnComplete = FALSE;
+    hcd->AsyncListQueue->EndPointCharacteristics.HeadOfReclamation = TRUE;
+    hcd->AsyncListQueue->Token.Bits.Halted = TRUE;
+    hcd->AsyncListQueue->NextQueueHead = hcd->AsyncListQueue;
+    hcd->AsyncListQueue->PreviousQueueHead = hcd->AsyncListQueue;
+    
+    /* Reserve a Queue Head thats only purpose is for linking completed Queue Heads.
+       Completed QueueHeads are moved to this temporary. As the memory must still be valid
+       up until the controllers doorbell is rang to let it know info has been removed from QueueHead list */
+    hcd->CompletedListQueue = CreateQueueHead(hcd);
+    hcd->CompletedListQueue->NextQueueHead = hcd->CompletedListQueue;
+    hcd->CompletedListQueue->PreviousQueueHead = hcd->CompletedListQueue;
+    
     /* Ensure the controller is stopped */
-    StopEhci(&FdoDeviceExtension->hcd);
+    StopEhci(hcd);
+    
+    SetAsyncListQueueRegister(hcd, hcd->AsyncListQueue->PhysicalAddr);
+
+    /* FIXME: Implement Periodic Frame List */
 
     Status = IoConnectInterrupt(&FdoDeviceExtension->EhciInterrupt,
                                 InterruptService,
@@ -446,10 +540,8 @@
                                 FdoDeviceExtension->Affinity,
                                 FALSE);
 
-    StartEhci(&FdoDeviceExtension->hcd);
-    DPRINT1("AsycnAddr %x\n", GetAsyncListQueueRegister(&FdoDeviceExtension->hcd));
+    StartEhci(hcd);
     FdoDeviceExtension->DeviceState = DEVICESTARTED;
-
     return STATUS_SUCCESS;
 }
 
@@ -472,6 +564,10 @@
 
     DPRINT1("Ehci: QueryBusRelations\n");
 
+    /* FIXME: Currently only support for one ehci controller */
+    if (DeviceExtension->Pdo)
+        goto Done;
+
     /* Create the PDO with the next available number */
     while (TRUE)
     {
@@ -513,9 +609,10 @@
 
     PdoDeviceExtension->ControllerFdo = DeviceObject;
     PdoDeviceExtension->DeviceObject = Pdo;
-    PdoDeviceExtension->NumberOfPorts = DeviceExtension->hcd.ECHICaps.HCSParams.PortCount;
+    //PdoDeviceExtension->NumberOfPorts = DeviceExtension->hcd.ECHICaps.HCSParams.PortCount;
 
     InitializeListHead(&PdoDeviceExtension->IrpQueue);
+    
     KeInitializeSpinLock(&PdoDeviceExtension->IrpQueueLock);
 
     KeInitializeEvent(&PdoDeviceExtension->QueueDrainedEvent, SynchronizationEvent, TRUE);
@@ -525,7 +622,7 @@
     Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
     DeviceExtension->Pdo = Pdo;
-
+Done:
     DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
 
     if (!DeviceRelations)
@@ -534,8 +631,8 @@
     }
 
     DeviceRelations->Count = 1;
-    DeviceRelations->Objects[0] = Pdo;
-    ObReferenceObject(Pdo);
+    DeviceRelations->Objects[0] = DeviceExtension->Pdo;
+    ObReferenceObject(DeviceExtension->Pdo);
 
     *pDeviceRelations = DeviceRelations;
     return STATUS_SUCCESS;
@@ -705,6 +802,7 @@
 
     ASSERT(FdoDeviceExtension->LowerDevice == Pdo);
 
+    /* Get the EHCI Device ID and Vendor ID */
     Status = GetBusInterface(FdoDeviceExtension->LowerDevice, &FdoDeviceExtension->BusInterface);
 
     if (!NT_SUCCESS(Status))
@@ -772,270 +870,8 @@
 NTSTATUS NTAPI
 FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
-    PFDO_DEVICE_EXTENSION FdoDeviceExtension;
-    PPDO_DEVICE_EXTENSION PdoDeviceExtension;
-    PIO_STACK_LOCATION Stack = NULL;
-    NTSTATUS Status = STATUS_UNSUCCESSFUL;
-    ULONG_PTR Information = 0;
-    PUSB_DEVICE UsbDevice = NULL;
-    URB *Urb;
-
-    /*FIXME: This should never be called by upper drivers as they should only be dealing with the pdo */
-
-    FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
-    PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) FdoDeviceExtension->Pdo->DeviceExtension;
-
-    ASSERT(FdoDeviceExtension->Common.IsFdo == TRUE);
-
-    Stack =  IoGetCurrentIrpStackLocation(Irp);
-
-    ASSERT(Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB);
-
-    Urb = (PURB) Stack->Parameters.Others.Argument1;
-    DPRINT("Header Length %d\n", Urb->UrbHeader.Length);
-    DPRINT("Header Function %d\n", Urb->UrbHeader.Function);
-
-    UsbDevice = DeviceHandleToUsbDevice(PdoDeviceExtension, Urb->UrbHeader.UsbdDeviceHandle);
-
-    if (!UsbDevice)
-    {
-        DPRINT1("Ehci: Invalid DeviceHandle or device not connected\n");
-        return STATUS_DEVICE_NOT_CONNECTED;
-    }
-    switch (Urb->UrbHeader.Function)
-    {
-        case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
-        {
-            DPRINT1("Ehci: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n");
-            break;
-        }
-        case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
-        {
-            DPRINT1("Ehci: URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
-            break;
-        }
-        case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
-        {
-            DPRINT1("Ehci: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
-            switch(Urb->UrbControlDescriptorRequest.DescriptorType)
-            {
-                case USB_DEVICE_DESCRIPTOR_TYPE:
-                {
-                    DPRINT1("USB DEVICE DESC\n");
-                    break;
-                }
-                case USB_CONFIGURATION_DESCRIPTOR_TYPE:
-                    DPRINT1("USB CONFIG DESC\n");
-                    //break;
-                case USB_STRING_DESCRIPTOR_TYPE:
-                {
-                    DPRINT1("Usb String Descriptor\n");
-                    break;
-                }
-                default:
-                {
-                    DPRINT1("Ehci: Descriptor Type %x not supported!\n", Urb->UrbControlDescriptorRequest.DescriptorType);
-                }
-            }
-            break;
-        }
-        case URB_FUNCTION_SELECT_CONFIGURATION:
-        {
-            DPRINT1("Ehci: URB_FUNCTION_SELECT_CONFIGURATION\n");
-            DPRINT1("Urb->UrbSelectConfiguration.ConfigurationHandle %x\n",Urb->UrbSelectConfiguration.ConfigurationHandle);
-            break;
-        }
-        case URB_FUNCTION_CLASS_DEVICE:
-        {
-            DPRINT1("Ehci: URB_FUNCTION_CLASS_DEVICE %x\n",Urb->UrbControlVendorClassRequest.Request);
-            switch (Urb->UrbControlVendorClassRequest.Request)
-            {
-                case USB_REQUEST_GET_DESCRIPTOR:
-                {
-                    DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
-                    DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value);
-
-                    switch (Urb->UrbControlVendorClassRequest.Value >> 8)
-                    {
-                        case USB_DEVICE_CLASS_AUDIO:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_AUDIO\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_COMMUNICATIONS:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_COMMUNICATIONS\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_HUMAN_INTERFACE:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_HUMAN_INTERFACE\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_MONITOR:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_MONITOR\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_PHYSICAL_INTERFACE:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_PHYSICAL_INTERFACE\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_POWER:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_POWER\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_PRINTER:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_PRINTER\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_STORAGE:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_STORAGE\n");
-                            break;
-                        }
-                        case USB_DEVICE_CLASS_RESERVED:
-                            DPRINT1("Reserved!!!\n");
-                        case USB_DEVICE_CLASS_HUB:
-                        {
-                            DPRINT1("USB_DEVICE_CLASS_HUB request\n");
-                            break;
-                        }
-                        default:
-                        {
-                            DPRINT1("Unknown UrbControlVendorClassRequest Value\n");
-                        }
-                    }
-                    break;
-                }
-                case USB_REQUEST_GET_STATUS:
-                {
-                    DPRINT1("DEVICE: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
-                    break;
-                }
-                default:
-                {
-                    DPRINT1("Unhandled URB request for class device\n");
-                    //Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
-                }
-            }
-            break;
-        }
-        case URB_FUNCTION_CLASS_OTHER:
-        {
-            DPRINT1("Ehci: URB_FUNCTION_CLASS_OTHER\n");
-            switch (Urb->UrbControlVendorClassRequest.Request)
-            {
-                case USB_REQUEST_GET_STATUS:
-                {
-                    DPRINT1("OTHER: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
-                    break;
-                }
-                case USB_REQUEST_CLEAR_FEATURE:
-                {
-                    DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
-                        Urb->UrbControlVendorClassRequest.Value);
-                    switch (Urb->UrbControlVendorClassRequest.Value)
-                    {
-                        case C_PORT_CONNECTION:
-                            DPRINT1("Clearing Connect\n");
-                            break;
-                        case C_PORT_RESET:
-                            DPRINT1("Clearing Reset\n");
-                            break;
-                        default:
-                            DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
-                            break;
-                    }
-                    break;
-                }
-                case USB_REQUEST_SET_FEATURE:
-                {
-                    DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
-                        Urb->UrbControlVendorClassRequest.Value);
-
-                    switch(Urb->UrbControlVendorClassRequest.Value)
-                    {
-                        case PORT_RESET:
-                        {
-                            DPRINT1("Port reset\n");
-                            break;
-                        }
-                        case PORT_ENABLE:
-                        {
-                            DPRINT1("Unhandled Set Feature\n");
-                            break;
-                        }
-                        default:
-                        {
-                            DPRINT1("Unknown Set Feature!\n");
-                            break;
-                        }
-                    }
-                    break;
-                }
-                case USB_REQUEST_SET_ADDRESS:
-                {
-                    DPRINT1("USB_REQUEST_SET_ADDRESS\n");
-                    break;
-                }
-                case USB_REQUEST_GET_DESCRIPTOR:
-                {
-                    DPRINT1("USB_REQUEST_GET_DESCRIPTOR\n");
-                    break;
-                }
-                case USB_REQUEST_SET_DESCRIPTOR:
-                {
-                    DPRINT1("USB_REQUEST_SET_DESCRIPTOR\n");
-                    break;
-                }
-                case USB_REQUEST_GET_CONFIGURATION:
-                {
-                    DPRINT1("USB_REQUEST_GET_CONFIGURATION\n");
-                    break;
-                }
-                case USB_REQUEST_SET_CONFIGURATION:
-                {
-                    DPRINT1("USB_REQUEST_SET_CONFIGURATION\n");
-                    break;
-                }
-                case USB_REQUEST_GET_INTERFACE:
-                {
-                    DPRINT1("USB_REQUEST_GET_INTERFACE\n");
-                    break;
-                }
-                case USB_REQUEST_SET_INTERFACE:
-                {
-                    DPRINT1("USB_REQUEST_SET_INTERFACE\n");
-                    break;
-                }
-                case USB_REQUEST_SYNC_FRAME:
-                {
-                    DPRINT1("USB_REQUEST_SYNC_FRAME\n");
-                    break;
-                }
-                default:
-                {
-                    DPRINT1("Unknown Function Class Unknown request\n");
-                    break;
-                }
-            }
-            break;
-        }
-        default:
-        {
-            DPRINT1("Ehci: Unhandled URB %x\n", Urb->UrbHeader.Function);
-            //Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
-        }
-    }
-
-    Irp->IoStatus.Information = Information;
-
-    if (Status != STATUS_PENDING)
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return Status;
+    /*FIXME: This should never be called by upper drivers as they should only be dealing with the pdo. */
+    DPRINT1("Upper Level Device Object shouldnt be calling this!!!!!!!!!!!!\n");
+    ASSERT(FALSE);
+    return STATUS_UNSUCCESSFUL;
 }

Modified: trunk/reactos/drivers/usb/usbehci/hardware.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hardware.h?rev=51325&r1=51324&r2=51325&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hardware.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/hardware.h [iso-8859-1] Wed Apr 13 04:33:14 2011
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <ntddk.h>
+#include <usb.h>
 
 /* USB Command Register */
 #define EHCI_USBCMD         0x00
@@ -98,8 +99,9 @@
         ULONG DWord;
     } Token;
     ULONG BufferPointer[5];
-    
+
     //Software
+    ULONG BufferPointerVA[5];
     ULONG PhysicalAddr;
     struct _QUEUE_TRANSFER_DESCRIPTOR *PreviousDescriptor;
     struct _QUEUE_TRANSFER_DESCRIPTOR *NextDescriptor;
@@ -167,10 +169,13 @@
     ULONG PhysicalAddr;
     struct _QUEUE_HEAD *PreviousQueueHead;
     struct _QUEUE_HEAD *NextQueueHead;
-    PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor;
+    ULONG NumberOfTransferDescriptors;
+    PQUEUE_TRANSFER_DESCRIPTOR FirstTransferDescriptor;
+    PQUEUE_TRANSFER_DESCRIPTOR DeadDescriptor;
     PIRP IrpToComplete;
-	PMDL MdlToFree;
     PKEVENT Event;
+    PMDL Mdl;
+    BOOLEAN FreeMdl;    
 } QUEUE_HEAD, *PQUEUE_HEAD;
 
 /* USBCMD register 32 bits */
@@ -264,14 +269,27 @@
     UCHAR PortRoute [8];
 } EHCI_CAPS, *PEHCI_CAPS;
 
+typedef struct _EHCIPORTS
+{
+    ULONG PortNumber;
+    ULONG PortType;
+    USHORT PortStatus;
+    USHORT PortChange;
+} EHCIPORTS, *PEHCIPORTS;
+
 typedef struct _EHCI_HOST_CONTROLLER
 {
+    PDMA_ADAPTER pDmaAdapter;
+    ULONG MapRegisters;
     ULONG OpRegisters;
     EHCI_CAPS ECHICaps;
-    PVOID CommonBufferVA;
-    PHYSICAL_ADDRESS CommonBufferPA;
+    ULONG NumberOfPorts;
+    EHCIPORTS Ports[127];
+    PVOID CommonBufferVA[16];
+    PHYSICAL_ADDRESS CommonBufferPA[16];
     ULONG CommonBufferSize;
     PQUEUE_HEAD AsyncListQueue;
+    PQUEUE_HEAD CompletedListQueue;
     KSPIN_LOCK Lock;
 } EHCI_HOST_CONTROLLER, *PEHCI_HOST_CONTROLLER;
 
@@ -305,3 +323,5 @@
 ULONG
 GetPeriodicFrameListRegister(PEHCI_HOST_CONTROLLER hcd);
 
+BOOLEAN
+EnumControllerPorts(PEHCI_HOST_CONTROLLER hcd);

Modified: trunk/reactos/drivers/usb/usbehci/hwiface.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hwiface.c?rev=51325&r1=51324&r2=51325&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hwiface.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/hwiface.c [iso-8859-1] Wed Apr 13 04:33:14 2011
@@ -32,7 +32,6 @@
     Descriptor->NextPointer = TERMINATE_POINTER;
     Descriptor->AlternateNextPointer = TERMINATE_POINTER;
     Descriptor->Token.Bits.DataToggle = TRUE;
-    Descriptor->Token.Bits.InterruptOnComplete = TRUE;
     Descriptor->Token.Bits.ErrorCounter = 0x03;
     Descriptor->Token.Bits.Active = TRUE;
     Descriptor->Token.Bits.PIDCode = PIDCode;
@@ -47,9 +46,9 @@
 }
 
 VOID
-FreeDescriptor(PQUEUE_TRANSFER_DESCRIPTOR Descriptor)
-{
-    ReleaseMemory((ULONG)Descriptor);
+FreeDescriptor(PEHCI_HOST_CONTROLLER hcd, PQUEUE_TRANSFER_DESCRIPTOR Descriptor)
+{
+    ReleaseMemory(hcd, (ULONG)Descriptor);
 }
 
 /* Queue Head */
@@ -87,14 +86,12 @@
     KIRQL OldIrql;
 
     KeAcquireSpinLock(&hcd->Lock, &OldIrql);
-
     CurrentQH = (PQUEUE_HEAD)AllocateMemory(hcd, sizeof(QUEUE_HEAD), &PhysicalAddress);
     RtlZeroMemory(CurrentQH, sizeof(QUEUE_HEAD));
 
     ASSERT(CurrentQH);
     CurrentQH->PhysicalAddr = PhysicalAddress;
     CurrentQH->HorizontalLinkPointer = TERMINATE_POINTER;
-    CurrentQH->CurrentLinkPointer = TERMINATE_POINTER;
     CurrentQH->AlternateNextPointer = TERMINATE_POINTER;
     CurrentQH->NextPointer = TERMINATE_POINTER;
 
@@ -107,7 +104,7 @@
     CurrentQH->EndPointCharacteristics.NakCountReload = 0xF;
 
     /* Get the Initial Data Toggle from the QEDT */
-    CurrentQH->EndPointCharacteristics.QEDTDataToggleControl = TRUE;
+    CurrentQH->EndPointCharacteristics.QEDTDataToggleControl = FALSE;
 
     /* High Speed Device */
     CurrentQH->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED;
@@ -120,7 +117,7 @@
     for (i=0; i<5; i++)
         CurrentQH->BufferPointer[i] = 0;
 
-    CurrentQH->Token.Bits.InterruptOnComplete = TRUE;
+    CurrentQH->Token.Bits.InterruptOnComplete = FALSE;
 
     KeReleaseSpinLock(&hcd->Lock, OldIrql);
     return CurrentQH;
@@ -131,19 +128,17 @@
 {
     KIRQL OldIrql;
     PQUEUE_HEAD CurrentHead  = (PQUEUE_HEAD)hcd->AsyncListQueue;
-    PQUEUE_HEAD PreviousHead = CurrentHead->PreviousQueueHead;
-
-    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
-
-    QueueHead->HorizontalLinkPointer = (CurrentHead->HorizontalLinkPointer | QH_TYPE_QH) & ~TERMINATE_POINTER;
+    PQUEUE_HEAD PreviousHead;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+    PreviousHead = CurrentHead->PreviousQueueHead;
     QueueHead->NextQueueHead = CurrentHead;
     QueueHead->PreviousQueueHead = PreviousHead;
-
+    PreviousHead->NextQueueHead = QueueHead;
     CurrentHead->PreviousQueueHead = QueueHead;
-    if (PreviousHead)
-        PreviousHead->NextQueueHead = QueueHead;
-
-    CurrentHead->HorizontalLinkPointer = QueueHead->PhysicalAddr | QH_TYPE_QH;
+    
+    QueueHead->HorizontalLinkPointer = (CurrentHead->HorizontalLinkPointer | QH_TYPE_QH) & ~TERMINATE_POINTER;
+    PreviousHead->HorizontalLinkPointer = QueueHead->PhysicalAddr| QH_TYPE_QH;
 
     KeReleaseSpinLock(&hcd->Lock, OldIrql);
 }
@@ -152,24 +147,80 @@
 UnlinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead)
 {
     KIRQL OldIrql;
-    PQUEUE_HEAD PreviousHead = QueueHead->PreviousQueueHead;
-    PQUEUE_HEAD NextHead = QueueHead->NextQueueHead;
-    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
-
-    if (PreviousHead)
+    PQUEUE_HEAD PreviousHead;
+    PQUEUE_HEAD NextHead;
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    PreviousHead = QueueHead->PreviousQueueHead;
+    NextHead = QueueHead->NextQueueHead;
+
+    PreviousHead->NextQueueHead = NextHead;
+    NextHead->PreviousQueueHead = PreviousHead;
+
+    PreviousHead->HorizontalLinkPointer = NextHead->HorizontalLinkPointer;
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+}
+
+VOID
+LinkQueueHeadToCompletedList(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead)
+{
+    KIRQL OldIrql;
+    PQUEUE_HEAD CurrentHead  = (PQUEUE_HEAD)hcd->CompletedListQueue;
+    PQUEUE_HEAD PreviousHead;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+        
+    PreviousHead = CurrentHead->PreviousQueueHead;
+    QueueHead->NextQueueHead = CurrentHead;
+    QueueHead->PreviousQueueHead = PreviousHead;
+    PreviousHead->NextQueueHead = QueueHead;
+    CurrentHead->PreviousQueueHead = QueueHead;
+
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+
+}
+
+VOID
+DeleteQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead)
+{
+    ReleaseMemory(hcd, (ULONG)QueueHead);
+}
+
+VOID
+CleanupAsyncList(PEHCI_HOST_CONTROLLER hcd)
+{
+    PQUEUE_TRANSFER_DESCRIPTOR Descriptor;
+    PQUEUE_HEAD QueueHead;
+    KIRQL OldIrql;
+
+    KeAcquireSpinLock(&hcd->Lock, &OldIrql);
+
+    QueueHead = hcd->CompletedListQueue;
+    QueueHead = QueueHead->NextQueueHead;
+
+    while (QueueHead != hcd->CompletedListQueue)
     {
-        PreviousHead->NextQueueHead = NextHead;
-        PreviousHead->HorizontalLinkPointer = QueueHead->HorizontalLinkPointer;
+        Descriptor = QueueHead->FirstTransferDescriptor;
+        while (Descriptor)
+        {
+            if (Descriptor->Token.Bits.PIDCode == PID_CODE_SETUP_TOKEN)
+                ReleaseMemory(hcd, Descriptor->BufferPointerVA[0]);
+            FreeDescriptor(hcd, Descriptor);
+            Descriptor = Descriptor->NextDescriptor;
+        }
+
+        if (QueueHead->FreeMdl)
+        {
+            DPRINT("Freeing Mdl %x, StartVA %x\n", QueueHead->Mdl, QueueHead->Mdl->StartVa);
+            IoFreeMdl(QueueHead->Mdl);
+        }
+        
+        QueueHead = QueueHead->NextQueueHead;
     }
-    if (NextHead)
-        NextHead->PreviousQueueHead = PreviousHead;
-
-    KeReleaseSpinLock(&hcd->Lock, OldIrql);
-}
-
-VOID
-DeleteQueueHead(PQUEUE_HEAD QueueHead)
-{
-    ReleaseMemory((ULONG)QueueHead);
-}
-
+    
+    hcd->CompletedListQueue->NextQueueHead = hcd->CompletedListQueue;
+    hcd->CompletedListQueue->PreviousQueueHead = hcd->CompletedListQueue;
+    
+    KeReleaseSpinLock(&hcd->Lock, OldIrql);
+}
+

Modified: trunk/reactos/drivers/usb/usbehci/hwiface.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hwiface.h?rev=51325&r1=51324&r2=51325&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hwiface.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/hwiface.h [iso-8859-1] Wed Apr 13 04:33:14 2011
@@ -5,7 +5,7 @@
 CreateDescriptor(PEHCI_HOST_CONTROLLER hcd, UCHAR PIDCode, ULONG TotalBytesToTransfer);
 
 VOID
-FreeDescriptor(PQUEUE_TRANSFER_DESCRIPTOR Descriptor);
+FreeDescriptor(PEHCI_HOST_CONTROLLER hcd, PQUEUE_TRANSFER_DESCRIPTOR Descriptor);
 
 VOID
 DumpQueueHeadList(PEHCI_HOST_CONTROLLER hcd);
@@ -20,5 +20,10 @@
 UnlinkQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);
 
 VOID
-DeleteQueueHead(PQUEUE_HEAD QueueHead);
+DeleteQueueHead(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);
 
+VOID
+LinkQueueHeadToCompletedList(PEHCI_HOST_CONTROLLER hcd, PQUEUE_HEAD QueueHead);
+
+VOID
+CleanupAsyncList(PEHCI_HOST_CONTROLLER hcd);




More information about the Ros-diffs mailing list