[ros-diffs] [mjmartin] 51326: [USB\USBEHCI] - For common buffer memory, only allocate one page and allocate more as needed. This implementation will most likely be replaced with janderwalds. - Use a safecount ...

mjmartin at svn.reactos.org mjmartin at svn.reactos.org
Wed Apr 13 04:43:25 UTC 2011


Author: mjmartin
Date: Wed Apr 13 04:43:25 2011
New Revision: 51326

URL: http://svn.reactos.org/svn/reactos?rev=51326&view=rev
Log:
[USB\USBEHCI]
- For common buffer memory, only allocate one page and allocate more as needed. This implementation will most likely be replaced with janderwalds.
- Use a safecount while attempting to stop and start the controller, so that an error can be displayed vice doing endless loop for controllers that are misbehaving.
- Reorganize a few structuers and remove members of structures that are not used.
- Add comments for some of the DirectCall Interface Functions.
Change 2 of 3.

Modified:
    trunk/reactos/drivers/usb/usbehci/common.c
    trunk/reactos/drivers/usb/usbehci/hardware.c
    trunk/reactos/drivers/usb/usbehci/physmem.c
    trunk/reactos/drivers/usb/usbehci/physmem.h
    trunk/reactos/drivers/usb/usbehci/usbehci.c
    trunk/reactos/drivers/usb/usbehci/usbehci.h
    trunk/reactos/drivers/usb/usbehci/usbiffn.c

Modified: trunk/reactos/drivers/usb/usbehci/common.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/common.c?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/common.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/common.c [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -98,7 +98,7 @@
     DPRINT1("    PingState %x\n", QueueHead->Token.Bits.PingState);        
     DPRINT1("    SplitTransactionState %x\n", QueueHead->Token.Bits.SplitTransactionState);
     DPRINT1("    ErrorCounter %x\n", QueueHead->Token.Bits.ErrorCounter);
-    DPRINT1("    First TransferDescriptor %x\n", QueueHead->TransferDescriptor);
+    DPRINT1("    First TransferDescriptor %x\n", QueueHead->FirstTransferDescriptor);
 }
 
 VOID

Modified: trunk/reactos/drivers/usb/usbehci/hardware.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/hardware.c?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/hardware.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/hardware.c [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -64,7 +64,7 @@
 {
     ULONG tmp;
     ULONG OpRegisters = hcd->OpRegisters;
-    DPRINT1("Reset Port %x\n", Port);
+    DPRINT("Reset Port %x\n", Port);
 
     tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port)));
     if (tmp & 0x400)
@@ -95,7 +95,9 @@
     if (tmp & 0x100)
     {
         DPRINT1("EHCI ERROR: Port Reset did not complete!\n");
-    }
+        ASSERT(FALSE);
+    }
+    DPRINT("Reset complete\n");
 }
 
 VOID
@@ -107,7 +109,7 @@
     LONG FailSafe;
     LONG tmp;
 
-    DPRINT1("Stopping Ehci controller\n");
+    DPRINT("Stopping Ehci controller\n");
 
     WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBINTR), 0);
 
@@ -117,7 +119,7 @@
     WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBCMD), tmp);
 
     /* Wait for the device to stop */
-    for (FailSafe = 100; FailSafe > 1; FailSafe++)
+    for (FailSafe = 0; FailSafe < 1000; FailSafe++)
     {
         KeStallExecutionProcessor(10);
         tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS));
@@ -129,7 +131,10 @@
         }
     }
     if (!UsbSts->HCHalted)
+    {
         DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n");
+        ASSERT(FALSE);
+    }
 }
 
 VOID
@@ -138,7 +143,7 @@
     ULONG OpRegisters = hcd->OpRegisters;
     PEHCI_USBCMD_CONTENT UsbCmd;
     PEHCI_USBSTS_CONTEXT UsbSts;
-    LONG FailSafe;
+    LONG failSafe;
     LONG tmp;
     LONG tmp2;
 
@@ -160,7 +165,7 @@
     WRITE_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBCMD), tmp);
 
     /* Wait for the device to reset */
-    for (FailSafe = 100; FailSafe > 1; FailSafe++)
+    for (failSafe = 0; failSafe < 1000; failSafe++)
     {
         KeStallExecutionProcessor(10);
         tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD));
@@ -176,6 +181,7 @@
     if (UsbCmd->HCReset)
     {
         DPRINT1("EHCI ERROR: Controller failed to reset! Will attempt to continue.\n");
+        ASSERT(FALSE);
     }
 
     UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp;
@@ -209,7 +215,7 @@
     WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD), tmp);
 
     /* Wait for the device to start */
-    for (;;)
+    for (failSafe = 0; failSafe < 1000; failSafe++)
     {
         KeStallExecutionProcessor(10);
         tmp2 = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS));
@@ -222,8 +228,93 @@
         DPRINT("Waiting for start, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBSTS)));
     }
 
+    if (UsbSts->HCHalted)
+    {
+        DPRINT1("EHCI ERROR: Controller failed to start!!!\n");
+        ASSERT(FALSE);
+    }
     /* Set all port routing to ECHI controller */
     WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_CONFIGFLAG), 1);
+}
+
+BOOLEAN
+EnumControllerPorts(PEHCI_HOST_CONTROLLER hcd)
+{
+    ULONG tmp, i, OpRegisters, ChildDeviceCount = 0;
+    BOOLEAN PortChange = FALSE;
+
+    OpRegisters = (ULONG)hcd->OpRegisters;
+    /* Loop through the ports */
+    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)
+        {
+            DPRINT1("Port Change\n");
+
+            /* 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);
+            
+            PortChange = TRUE;
+            /* Connect or Disconnect? */
+            if (tmp & 0x01)
+            {
+                DPRINT1("Device connected on port %d\n", i);
+
+                /* Check if a companion host controller exists */
+                if (hcd->ECHICaps.HCSParams.CHCCount)
+                {
+                    tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
+
+                    /* Port should be in disabled state, as per USB 2.0 specs */
+                    if (tmp & 0x04)
+                    {
+                        DPRINT1("Warning: The port the device has just connected to is not disabled!\n");
+                    }
+
+                    /* Is this non high speed device */
+                    if (tmp & 0x400)
+                    {
+                        DPRINT1("Non HighSpeed device connected. Releasing ownership.\n");
+                        /* Release ownership to companion host controller */
+                        WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), 0x2000);
+                        continue;
+                    }
+                }
+
+                KeStallExecutionProcessor(30);
+
+                /* As per USB 2.0 Specs, 9.1.2. Reset the port and clear the status change */
+                //tmp |= 0x100 | 0x02;
+                /* Sanity, Disable port */
+                //tmp &= ~0x04;
+
+                //WRITE_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)), tmp);
+
+                //KeStallExecutionProcessor(20);
+
+                tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i)));
+
+                ChildDeviceCount++;
+                hcd->Ports[i].PortStatus &= ~0x8000;
+                DPRINT1("Removed 0x8000\n");
+                ASSERT(FALSE);
+                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;
+            }
+            else
+            {
+                DPRINT1("Device disconnected on port %d\n", i);
+                ChildDeviceCount--;
+            }
+        }
+    }
+    return PortChange;
 }
 
 VOID
@@ -241,11 +332,11 @@
     PCap->HCSParamsLong = READ_REGISTER_ULONG((PULONG)(CapRegister + 4));
     PCap->HCCParams = READ_REGISTER_ULONG((PULONG)(CapRegister + 8));
 
-    DPRINT1("Length %d\n", PCap->Length);
-    DPRINT1("Reserved %d\n", PCap->Reserved);
-    DPRINT1("HCIVersion %x\n", PCap->HCIVersion);
-    DPRINT1("HCSParams %x\n", PCap->HCSParamsLong);
-    DPRINT1("HCCParams %x\n", PCap->HCCParams);
+    DPRINT("Length %d\n", PCap->Length);
+    DPRINT("Reserved %d\n", PCap->Reserved);
+    DPRINT("HCIVersion %x\n", PCap->HCIVersion);
+    DPRINT("HCSParams %x\n", PCap->HCSParamsLong);
+    DPRINT("HCCParams %x\n", PCap->HCCParams);
 
     if (PCap->HCCParams & 0x02)
         DPRINT1("Frame list size is configurable\n");

Modified: trunk/reactos/drivers/usb/usbehci/physmem.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/physmem.c?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/physmem.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/physmem.c [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -22,21 +22,32 @@
 ULONG
 AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress)
 {
-    PMEM_HEADER MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA;
+    PMEM_HEADER MemoryPage = NULL;
     ULONG PageCount = 0;
     ULONG NumberOfPages = hcd->CommonBufferSize / PAGE_SIZE;
-    ULONG BlocksNeeded;
+    ULONG BlocksNeeded = 0;
     ULONG i,j, freeCount;
     ULONG RetAddr = 0;
 
+    MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[0];
     Size = ((Size + SMALL_ALLOCATION_SIZE - 1) / SMALL_ALLOCATION_SIZE) * SMALL_ALLOCATION_SIZE;
     BlocksNeeded = Size / SMALL_ALLOCATION_SIZE;
+
     do
     {
         if (MemoryPage->IsFull)
         {
             PageCount++;
-            MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE);
+            
+            if (!(PMEM_HEADER)hcd->CommonBufferVA[PageCount])
+            {
+                hcd->CommonBufferVA[PageCount] =
+                    hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter,
+                                                                          PAGE_SIZE,
+                                                                          &hcd->CommonBufferPA[PageCount],
+                                                                          FALSE);
+            }
+            MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[PageCount];
             continue;
         }
         freeCount = 0;
@@ -54,8 +65,9 @@
             if ((i-freeCount+1 + BlocksNeeded) > sizeof(MemoryPage->Entry))
             {
                 freeCount = 0;
-                continue;
+                break;
             }
+
             if (freeCount == BlocksNeeded)
             {
                 for (j = 0; j < freeCount; j++)
@@ -68,20 +80,35 @@
 
                 RetAddr = (ULONG)MemoryPage + (SMALL_ALLOCATION_SIZE * (i - freeCount + 1)) + sizeof(MEM_HEADER);
 
-                *PhysicalAddress = (ULONG)hcd->CommonBufferPA.LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA);
+                *(ULONG*)PhysicalAddress = (ULONG)hcd->CommonBufferPA[PageCount].LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA[PageCount]);
+
                 return RetAddr;
             }
         }
 
         PageCount++;
-        MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE);
+        if (!(PMEM_HEADER)hcd->CommonBufferVA[PageCount])
+        {
+            
+            hcd->CommonBufferVA[PageCount] =
+                hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter,
+                                                                      PAGE_SIZE,
+                                                                      &hcd->CommonBufferPA[PageCount],
+                                                                      FALSE);
+            DPRINT1("Allocated CommonBuffer VA %x, PA %x\n", hcd->CommonBufferVA[PageCount], hcd->CommonBufferPA[PageCount]);
+        }
+        MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[PageCount];
+
     } while (PageCount < NumberOfPages);
+
+    if (PageCount == NumberOfPages)
+        ASSERT(FALSE);
 
     return 0;
 }
 
 VOID
-ReleaseMemory(ULONG Address)
+ReleaseMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Address)
 {
     PMEM_HEADER MemoryPage;
     ULONG Index, i, BlockSize;
@@ -90,9 +117,25 @@
 
     Index = (Address - ((ULONG)MemoryPage + sizeof(MEM_HEADER))) / SMALL_ALLOCATION_SIZE;
     BlockSize = MemoryPage->Entry[Index].Blocks;
+
     for (i = 0; i < BlockSize; i++)
     {
         MemoryPage->Entry[Index + i].InUse = 0;
         MemoryPage->Entry[Index + i].Blocks = 0;
     }
+
+    if (MemoryPage != (PMEM_HEADER)hcd->CommonBufferVA[0])
+    {
+        for (i=0; i < sizeof(MemoryPage->Entry) / 2; i++)
+        {
+            if ((MemoryPage->Entry[i].InUse) || (MemoryPage->Entry[sizeof(MemoryPage->Entry) - i].InUse))
+                return;
+        }
+        DPRINT1("Freeing CommonBuffer VA %x, PA %x\n", MemoryPage, MmGetPhysicalAddress(MemoryPage));
+        hcd->pDmaAdapter->DmaOperations->FreeCommonBuffer(hcd->pDmaAdapter,
+                                                          PAGE_SIZE,
+                                                          MmGetPhysicalAddress(MemoryPage),
+                                                          MemoryPage,
+                                                          FALSE);
+    }
 }

Modified: trunk/reactos/drivers/usb/usbehci/physmem.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/physmem.h?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/physmem.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/physmem.h [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -22,5 +22,4 @@
 AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress);
 
 VOID
-ReleaseMemory(ULONG Address);
-
+ReleaseMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Address);

Modified: trunk/reactos/drivers/usb/usbehci/usbehci.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/usbehci.c?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/usbehci.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/usbehci.c [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -69,7 +69,7 @@
 VOID NTAPI
 DriverUnload(PDRIVER_OBJECT DriverObject)
 {
-    DPRINT1("Unloading Driver\n");
+    DPRINT("Unloading Driver\n");
     /* FIXME: Clean up */
 }
 
@@ -94,7 +94,7 @@
     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl;
     DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
-
+    
     DriverObject->DriverUnload = DriverUnload;
     DPRINT1("Driver entry done\n");
 

Modified: trunk/reactos/drivers/usb/usbehci/usbehci.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/usbehci.h?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/usbehci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/usbehci.h [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -93,14 +93,6 @@
     PDEVICE_OBJECT DeviceObject;
 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
-typedef struct _EHCIPORTS
-{
-    ULONG PortNumber;
-    ULONG PortType;
-    USHORT PortStatus;
-    USHORT PortChange;
-} EHCIPORTS, *PEHCIPORTS;
-
 typedef struct _FDO_DEVICE_EXTENSION
 {
     COMMON_DEVICE_EXTENSION Common;
@@ -109,10 +101,7 @@
     PDEVICE_OBJECT LowerDevice;
     PDEVICE_OBJECT Pdo;
     ULONG DeviceState;
-
     PVOID RootHubDeviceHandle;
-    PDMA_ADAPTER pDmaAdapter;
-
     ULONG Vector;
     KIRQL Irql;
 
@@ -125,8 +114,6 @@
 
     KAFFINITY Affinity;
 
-    ULONG MapRegisters;
-
     ULONG BusNumber;
     ULONG BusAddress;
     ULONG PCIAddress;
@@ -148,8 +135,6 @@
 
     BOOLEAN AsyncComplete;
 
-    //PULONG ResourceBase;
-    //ULONG Size;
 } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 typedef struct _PDO_DEVICE_EXTENSION
@@ -168,8 +153,6 @@
     RH_INIT_CALLBACK *CallbackRoutine;
     USB_IDLE_CALLBACK IdleCallback;
     PVOID IdleContext;
-    ULONG NumberOfPorts;
-    EHCIPORTS Ports[32];
     KTIMER Timer;
     KEVENT QueueDrainedEvent;
     FAST_MUTEX ListLock;

Modified: trunk/reactos/drivers/usb/usbehci/usbiffn.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/usbehci/usbiffn.c?rev=51326&r1=51325&r2=51326&view=diff
==============================================================================
--- trunk/reactos/drivers/usb/usbehci/usbiffn.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/usb/usbehci/usbiffn.c [iso-8859-1] Wed Apr 13 04:43:25 2011
@@ -7,12 +7,15 @@
  *              Michael Martin (michael.martin at reactos.org)
  */
 
+/* Many of these direct calls are documented on http://www.osronline.com */
+
 #include "usbehci.h"
 #include <hubbusif.h>
 #include <usbbusif.h>
+#include "hardware.h"
 #include "transfer.h"
 
-PVOID InternalCreateUsbDevice(UCHAR DeviceNumber, ULONG Port, PUSB_DEVICE Parent, BOOLEAN Hub)
+PVOID InternalCreateUsbDevice(ULONG Port, PUSB_DEVICE Parent, BOOLEAN Hub)
 {
     PUSB_DEVICE UsbDevicePointer = NULL;
 
@@ -31,7 +34,6 @@
         DPRINT1("This is the root hub\n");
     }
 
-    UsbDevicePointer->Address = 0;//DeviceNumber;
     UsbDevicePointer->Port = Port - 1;
     UsbDevicePointer->ParentDevice = Parent;
 
@@ -56,6 +58,11 @@
 
 /* Bus Interface Hub V5 Functions */
 
+
+/* Hub Driver calls this routine for each new device it is informed about on USB Bus
+   osronline documents that this is where the device address is assigned. It also
+   states the same for InitializeUsbDevice. This function only gets the device descriptor 
+   from the device and checks that the members for device are correct. */
 
 NTSTATUS
 USB_BUSIFFN
@@ -65,11 +72,18 @@
                 USHORT PortStatus, USHORT PortNumber)
 {
     PPDO_DEVICE_EXTENSION PdoDeviceExtension;
+    PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+    USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    PEHCI_HOST_CONTROLLER hcd;
     PUSB_DEVICE UsbDevice;
-    LONG i = 0;
-
+    LONG i;
+
+    DPRINT1("Ehci: CreateUsbDevice: HubDeviceHandle %x, PortStatus %x, PortNumber %x\n", HubDeviceHandle, PortStatus, PortNumber);
+    
     PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
-    DPRINT1("Ehci: CreateUsbDevice: HubDeviceHandle %x, PortStatus %x, PortNumber %x\n", HubDeviceHandle, PortStatus, PortNumber);
+    FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
+
+    hcd = &FdoDeviceExtension->hcd;
 
     if (PdoDeviceExtension->UsbDevices[0] != HubDeviceHandle)
     {
@@ -77,28 +91,61 @@
         return STATUS_DEVICE_NOT_CONNECTED;
     }
 
-    UsbDevice = InternalCreateUsbDevice(PdoDeviceExtension->ChildDeviceCount, PortNumber, HubDeviceHandle, FALSE);
-
-    if (!UsbDevice)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
+    UsbDevice = NULL;
     /* Add it to the list */
-    while (TRUE)
+    for (i=0; i < MAX_USB_DEVICES; i++)
     {
         if (PdoDeviceExtension->UsbDevices[i] == NULL)
         {
-            PdoDeviceExtension->UsbDevices[i] = (PUSB_DEVICE)UsbDevice;
+            PdoDeviceExtension->UsbDevices[i] = InternalCreateUsbDevice(PortNumber, HubDeviceHandle, FALSE);
+            
+            if (!PdoDeviceExtension->UsbDevices[i])
+                return STATUS_INSUFFICIENT_RESOURCES;
+            UsbDevice = PdoDeviceExtension->UsbDevices[i];
             break;
         }
-        i++;
-    }
-
-    PdoDeviceExtension->Ports[PortNumber - 1].PortStatus = PortStatus;
+    }
+
+    /* Check that a device was created */
+    if (!UsbDevice)
+    {
+        DPRINT1("Too many usb devices attached. Max is %d\n", MAX_USB_DEVICES);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    hcd->Ports[PortNumber - 1].PortStatus = PortStatus;
+
+    /* Get the device descriptor */
+    CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+    CtrlSetup.wValue.LowByte = 0;
+    CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
+    CtrlSetup.wIndex.W = 0;
+    CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);    
+    CtrlSetup.bmRequestType.B = 0x80;
+    ExecuteTransfer(FdoDeviceExtension->DeviceObject,
+                    UsbDevice,
+                    0,
+                    &CtrlSetup,
+                    0,
+                    &UsbDevice->DeviceDescriptor,
+                    sizeof(USB_DEVICE_DESCRIPTOR),
+                    NULL);
+
+    /* Check status and bLength and bDescriptor members */
+    if ((UsbDevice->DeviceDescriptor.bLength != 0x12) || (UsbDevice->DeviceDescriptor.bDescriptorType != 0x1))
+    {
+        return STATUS_DEVICE_DATA_ERROR;
+    }
+
+    DumpDeviceDescriptor(&UsbDevice->DeviceDescriptor);
 
     /* Return it */
     *NewDevice = UsbDevice;
     return STATUS_SUCCESS;
 }
+
+/* Assigns the device an address, gets the configuration, interface, and endpoint descriptors
+   from the device. All this data is saved as part of this driver */
 
 NTSTATUS
 USB_BUSIFFN
@@ -107,13 +154,16 @@
     PPDO_DEVICE_EXTENSION PdoDeviceExtension;
     PFDO_DEVICE_EXTENSION FdoDeviceExtension;
     USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
+    USB_DEVICE_DESCRIPTOR DeviceDesc;
     PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc;
     PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
     PUSB_ENDPOINT_DESCRIPTOR EndpointDesc;
     PUSB_DEVICE UsbDevice;
     PVOID Buffer;
     PUCHAR Ptr;
-    LONG i, j, k;
+    UCHAR NewAddress = 0;
+
+    LONG i, j, k, InitAttept;
 
     PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
     FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
@@ -126,30 +176,90 @@
         return STATUS_DEVICE_NOT_CONNECTED;
     }
 
-    CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
-    CtrlSetup.wValue.LowByte = 0;
-    CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
-    CtrlSetup.wIndex.W = 0;
-    CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);    
-    CtrlSetup.bmRequestType.B = 0x80;
-
-    SubmitControlTransfer(&FdoDeviceExtension->hcd,
-                          &CtrlSetup,
-                          &UsbDevice->DeviceDescriptor,
-                          sizeof(USB_DEVICE_DESCRIPTOR),
-                          NULL);
-
-    //DumpDeviceDescriptor(&UsbDevice->DeviceDescriptor);
-
-    if (UsbDevice->DeviceDescriptor.bLength != 0x12)
-    {
-        DPRINT1("Failed to get Device Descriptor from device connected on port %d\n", UsbDevice->Port);
+    for (i=0; i<127; i++)
+    {
+        if (UsbDevice == PdoDeviceExtension->UsbDevices[i])
+        {
+            NewAddress = i;
+            break;
+        }
+    }
+
+    ASSERT(NewAddress);
+
+    /* Linux drivers make 3 attemps to set the device address because of problems with some devices. Do the same */
+    InitAttept = 0;
+    while (InitAttept < 3)
+    {
+        /* Set the device address */
+        CtrlSetup.bmRequestType.B = 0x00;
+        CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
+        CtrlSetup.wValue.W = NewAddress;
+        CtrlSetup.wIndex.W = 0;
+        CtrlSetup.wLength = 0;
+
+        DPRINT1("Setting Address to %x\n", NewAddress);
+        ExecuteTransfer(PdoDeviceExtension->ControllerFdo,
+                        UsbDevice,
+                        0,
+                        &CtrlSetup,
+                        0,
+                        NULL,
+                        0,
+                        NULL);
+
+        KeStallExecutionProcessor(300 * InitAttept);
+
+        /* Send 0 length packet to endpoint 0 for ack */
+/*
+        ExecuteTransfer(PdoDeviceExtension->ControllerFdo,
+                        UsbDevice,
+                        0,
+                        NULL,
+                        0,
+                        NULL,
+                        0,
+                        NULL);
+*/
+
+        CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
+        CtrlSetup.wValue.LowByte = 0;
+        CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE;
+        CtrlSetup.wIndex.W = 0;
+        CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR);    
+        CtrlSetup.bmRequestType.B = 0x80;
+
+        UsbDevice->Address = NewAddress;
+        ExecuteTransfer(FdoDeviceExtension->DeviceObject,
+                        UsbDevice,
+                        0,
+                        &CtrlSetup,
+                        0,
+                        &DeviceDesc,
+                        sizeof(USB_DEVICE_DESCRIPTOR),
+                        NULL);
+
+        DPRINT1("Length %d, DescriptorType %d\n", DeviceDesc.bLength, DeviceDesc.bDescriptorType);
+        if ((DeviceDesc.bLength == 0x12) && (DeviceDesc.bDescriptorType == 0x01))
+            break;
+        
+        /* If the descriptor was not gotten */
+        UsbDevice->Address = 0;
+        InitAttept++;
+    }
+    
+    if (InitAttept == 3)
+    {
+        DPRINT1("Unable to initialize usb device connected on port %d!\n", UsbDevice->Port);
+        /* FIXME: Should the memory allocated for this device be deleted? */
         return STATUS_DEVICE_DATA_ERROR;
     }
+    DumpDeviceDescriptor(&DeviceDesc);
 
     if (UsbDevice->DeviceDescriptor.bNumConfigurations == 0)
     {
         DPRINT1("Device on port %d has no configurations!\n", UsbDevice->Port);
+        /* FIXME: Should the memory allocated for this device be deleted? */
         return STATUS_DEVICE_DATA_ERROR;
     }
     UsbDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
@@ -159,6 +269,7 @@
     if (!UsbDevice->Configs)
     {
         DPRINT1("Out of memory\n");
+        /* FIXME: Should the memory allocated for this device be deleted? */
         return STATUS_NO_MEMORY;
     }
 
@@ -167,6 +278,7 @@
     if (!Buffer)
     {
         DPRINT1("Out of memory\n");
+        /* FIXME: Should the memory allocated for this device be deleted? */
         return STATUS_NO_MEMORY;
     }
 
@@ -184,16 +296,18 @@
         CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
         CtrlSetup.wIndex.W = 0;
         CtrlSetup.wLength = PAGE_SIZE;
-
-        SubmitControlTransfer(&FdoDeviceExtension->hcd,
-                              &CtrlSetup,
-                              Buffer,
-                              PAGE_SIZE,
-                              NULL);
+        ExecuteTransfer(PdoDeviceExtension->ControllerFdo,
+                        UsbDevice,
+                        0,
+                        &CtrlSetup,
+                        0,
+                        Buffer,
+                        PAGE_SIZE,
+                        NULL);
 
         ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)Ptr;
 
-        //DumpFullConfigurationDescriptor(ConfigDesc);
+        DumpFullConfigurationDescriptor(ConfigDesc);
         ASSERT(ConfigDesc->wTotalLength <= PAGE_SIZE);
 
         UsbDevice->Configs[i] = ExAllocatePoolWithTag(NonPagedPool,
@@ -230,30 +344,13 @@
 
     UsbDevice->ActiveConfig = UsbDevice->Configs[0];
     UsbDevice->ActiveInterface = UsbDevice->Configs[0]->Interfaces[0];
-    return STATUS_SUCCESS;
-
-    /* Set the device address */
-    CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE;
-    CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD;
-    CtrlSetup.bmRequestType._BM.Reserved = 0;
-    CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_HOST_TO_DEVICE;
-    CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS;
-    CtrlSetup.wValue.W = UsbDevice->Address;
-    CtrlSetup.wIndex.W = 0;
-    CtrlSetup.wLength = 0;
-
-    DPRINT1("Setting Address to %x\n", UsbDevice->Address);
-
-    SubmitControlTransfer(&FdoDeviceExtension->hcd,
-                          &CtrlSetup,
-                          NULL,
-                          0,
-                          NULL);
-
-    PdoDeviceExtension->UsbDevices[i]->DeviceState = DEVICEINTIALIZED;
-    return STATUS_SUCCESS;
-}
-
+
+    UsbDevice->DeviceState = DEVICEINTIALIZED;
+
+    return STATUS_SUCCESS;
+}
+
+/* Return the descriptors that will fit. Descriptors were saved when the InitializeUsbDevice function was called */
 NTSTATUS
 USB_BUSIFFN
 GetUsbDescriptors(PVOID BusContext,
@@ -290,6 +387,7 @@
     return STATUS_SUCCESS;
 }
 
+/* Documented http://www.osronline.com/ddkx/buses/usbinterkr_1m7m.htm */
 NTSTATUS
 USB_BUSIFFN
 RemoveUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle, ULONG Flags)
@@ -347,15 +445,18 @@
     return STATUS_SUCCESS;
 }
 
+/* Documented at http://www.osronline.com/ddkx/buses/usbinterkr_01te.htm */
 NTSTATUS
 USB_BUSIFFN
 RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVICE_HANDLE NewDeviceHandle)
 {
     PUSB_DEVICE OldUsbDevice;
     PUSB_DEVICE NewUsbDevice;
+    PUSB_CONFIGURATION ConfigToDelete;
+    int i;
 
     DPRINT1("Ehci: RestoreUsbDevice %x, %x, %x\n", BusContext, OldDeviceHandle, NewDeviceHandle);
-
+ASSERT(FALSE);
     OldUsbDevice = DeviceHandleToUsbDevice(BusContext, OldDeviceHandle);
     NewUsbDevice = DeviceHandleToUsbDevice(BusContext, NewDeviceHandle);
 
@@ -380,9 +481,6 @@
     if ((OldUsbDevice->DeviceDescriptor.idVendor == NewUsbDevice->DeviceDescriptor.idVendor) &&
         (OldUsbDevice->DeviceDescriptor.idProduct == NewUsbDevice->DeviceDescriptor.idProduct))
     {
-        PUSB_CONFIGURATION ConfigToDelete;
-        int i;
-
         NewUsbDevice->DeviceState &= ~DEVICEBUSY;
         NewUsbDevice->DeviceState &= ~DEVICEREMOVED;
 
@@ -407,6 +505,7 @@
     }
 }
 
+/* FIXME: Research this */
 NTSTATUS
 USB_BUSIFFN
 GetPortHackFlags(PVOID BusContext, PULONG Flags)
@@ -496,6 +595,9 @@
     PUSB_CONTROLLER_INFORMATION_0 ControllerInfo;
 
     DPRINT1("Ehci: GetControllerInformation called\n");
+
+    if (!LengthReturned)
+        return STATUS_INVALID_PARAMETER;
 
     ControllerInfo = ControllerInformationBuffer;
 
@@ -653,7 +755,7 @@
         DPRINT1("Invalid DeviceHandle or device not connected\n");
     }
 
-    DPRINT1("FlushTransfers\n");
+    DPRINT1("FlushTransfers not implemented.\n");
 }
 
 VOID
@@ -725,5 +827,6 @@
 EnumLogEntry(PVOID BusContext, ULONG DriverTag, ULONG EnumTag, ULONG P1, ULONG P2)
 {
     DPRINT1("Ehci: EnumLogEntry called %x, %x, %x, %x\n", DriverTag, EnumTag, P1, P2);
-    return STATUS_SUCCESS;
-}
+    
+    return STATUS_SUCCESS;
+}




More information about the Ros-diffs mailing list