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.... ============================================================================== --- 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/hardwar... ============================================================================== --- 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... ============================================================================== --- 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... ============================================================================== --- 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... ============================================================================== --- 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... ============================================================================== --- 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... ============================================================================== --- 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@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; +}