[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.

svn path=/trunk/; revision=51326
This commit is contained in:
Michael Martin 2011-04-13 04:43:25 +00:00
parent b6256418e9
commit fe97558adf
7 changed files with 321 additions and 102 deletions

View file

@ -98,7 +98,7 @@ DumpQueueHead(PQUEUE_HEAD QueueHead)
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

View file

@ -64,7 +64,7 @@ ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port)
{
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 @@ ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port)
if (tmp & 0x100)
{
DPRINT1("EHCI ERROR: Port Reset did not complete!\n");
ASSERT(FALSE);
}
DPRINT("Reset complete\n");
}
VOID
@ -107,7 +109,7 @@ StopEhci(PEHCI_HOST_CONTROLLER hcd)
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 @@ StopEhci(PEHCI_HOST_CONTROLLER hcd)
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 @@ StopEhci(PEHCI_HOST_CONTROLLER hcd)
}
}
if (!UsbSts->HCHalted)
{
DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n");
ASSERT(FALSE);
}
}
VOID
@ -138,7 +143,7 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd)
ULONG OpRegisters = hcd->OpRegisters;
PEHCI_USBCMD_CONTENT UsbCmd;
PEHCI_USBSTS_CONTEXT UsbSts;
LONG FailSafe;
LONG failSafe;
LONG tmp;
LONG tmp2;
@ -160,7 +165,7 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd)
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 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd)
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 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd)
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,10 +228,95 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd)
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
GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister)
{
@ -241,11 +332,11 @@ GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister)
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");

View file

@ -22,21 +22,32 @@ DumpPages()
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 @@ AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress)
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 @@ AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress)
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 @@ ReleaseMemory(ULONG Address)
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);
}
}

View file

@ -22,5 +22,4 @@ ULONG
AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress);
VOID
ReleaseMemory(ULONG Address);
ReleaseMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Address);

View file

@ -69,7 +69,7 @@ UsbEhciClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
VOID NTAPI
DriverUnload(PDRIVER_OBJECT DriverObject)
{
DPRINT1("Unloading Driver\n");
DPRINT("Unloading Driver\n");
/* FIXME: Clean up */
}
@ -94,7 +94,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
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");

View file

@ -93,14 +93,6 @@ typedef struct _COMMON_DEVICE_EXTENSION
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 @@ typedef struct _FDO_DEVICE_EXTENSION
PDEVICE_OBJECT LowerDevice;
PDEVICE_OBJECT Pdo;
ULONG DeviceState;
PVOID RootHubDeviceHandle;
PDMA_ADAPTER pDmaAdapter;
ULONG Vector;
KIRQL Irql;
@ -125,8 +114,6 @@ typedef struct _FDO_DEVICE_EXTENSION
KAFFINITY Affinity;
ULONG MapRegisters;
ULONG BusNumber;
ULONG BusAddress;
ULONG PCIAddress;
@ -148,8 +135,6 @@ typedef struct _FDO_DEVICE_EXTENSION
BOOLEAN AsyncComplete;
//PULONG ResourceBase;
//ULONG Size;
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct _PDO_DEVICE_EXTENSION
@ -168,8 +153,6 @@ typedef struct _PDO_DEVICE_EXTENSION
RH_INIT_CALLBACK *CallbackRoutine;
USB_IDLE_CALLBACK IdleCallback;
PVOID IdleContext;
ULONG NumberOfPorts;
EHCIPORTS Ports[32];
KTIMER Timer;
KEVENT QueueDrainedEvent;
FAST_MUTEX ListLock;

View file

@ -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 @@ PVOID InternalCreateUsbDevice(UCHAR DeviceNumber, ULONG Port, PUSB_DEVICE Parent
DPRINT1("This is the root hub\n");
}
UsbDevicePointer->Address = 0;//DeviceNumber;
UsbDevicePointer->Port = Port - 1;
UsbDevicePointer->ParentDevice = Parent;
@ -57,6 +59,11 @@ InterfaceDereference(PVOID BusContext)
/* 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
CreateUsbDevice(PVOID BusContext,
@ -65,11 +72,18 @@ CreateUsbDevice(PVOID BusContext,
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;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
DPRINT1("Ehci: CreateUsbDevice: HubDeviceHandle %x, PortStatus %x, PortNumber %x\n", HubDeviceHandle, PortStatus, PortNumber);
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
hcd = &FdoDeviceExtension->hcd;
if (PdoDeviceExtension->UsbDevices[0] != HubDeviceHandle)
{
@ -77,29 +91,62 @@ CreateUsbDevice(PVOID BusContext,
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
InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
@ -107,13 +154,16 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
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 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
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)
for (i=0; i<127; i++)
{
DPRINT1("Failed to get Device Descriptor from device connected on port %d\n", UsbDevice->Port);
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 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
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 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
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 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
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 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle)
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;
UsbDevice->DeviceState = DEVICEINTIALIZED;
DPRINT1("Setting Address to %x\n", UsbDevice->Address);
SubmitControlTransfer(&FdoDeviceExtension->hcd,
&CtrlSetup,
NULL,
0,
NULL);
PdoDeviceExtension->UsbDevices[i]->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 @@ GetUsbDescriptors(PVOID BusContext,
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 @@ RemoveUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle, ULONG Flags)
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 @@ RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVI
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 @@ RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVI
}
}
/* FIXME: Research this */
NTSTATUS
USB_BUSIFFN
GetPortHackFlags(PVOID BusContext, PULONG Flags)
@ -497,6 +596,9 @@ GetControllerInformation(PVOID BusContext,
DPRINT1("Ehci: GetControllerInformation called\n");
if (!LengthReturned)
return STATUS_INVALID_PARAMETER;
ControllerInfo = ControllerInformationBuffer;
if (ControllerInformationBufferLength < sizeof(USB_CONTROLLER_INFORMATION_0))
@ -653,7 +755,7 @@ FlushTransfers(PVOID BusContext, PVOID DeviceHandle)
DPRINT1("Invalid DeviceHandle or device not connected\n");
}
DPRINT1("FlushTransfers\n");
DPRINT1("FlushTransfers not implemented.\n");
}
VOID
@ -725,5 +827,6 @@ USB_BUSIFFN
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;
}