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/hardwa…
==============================================================================
--- 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/physme…
==============================================================================
--- 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/physme…
==============================================================================
--- 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/usbehc…
==============================================================================
--- 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/usbehc…
==============================================================================
--- 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/usbiff…
==============================================================================
--- 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(a)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;
+}