mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +00:00
[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:
parent
b6256418e9
commit
fe97558adf
7 changed files with 321 additions and 102 deletions
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue