From 80b680b6ae24bd35a8d9bbbd829bf7671ccc1a2e Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Wed, 2 May 2007 11:37:29 +0000 Subject: [PATCH] - Delete cromwell-based usb drivers since they don't work with modern reactos kernel. - Remove usbhub from the build. svn path=/trunk/; revision=26625 --- reactos/drivers/usb/directory.rbuild | 10 +- .../drivers/usb/miniport/common/common.rbuild | 9 - reactos/drivers/usb/miniport/common/fdo.c | 445 --- reactos/drivers/usb/miniport/common/main.c | 453 --- reactos/drivers/usb/miniport/common/misc.c | 167 -- reactos/drivers/usb/miniport/common/pdo.c | 624 ---- .../drivers/usb/miniport/common/usbcommon.h | 114 - .../usb/miniport/common/usbcommon_types.h | 62 - reactos/drivers/usb/miniport/directory.rbuild | 15 - .../drivers/usb/miniport/linux/asm/bitops.h | 384 --- reactos/drivers/usb/miniport/linux/bitops.h | 72 - reactos/drivers/usb/miniport/linux/boot.h | 337 --- reactos/drivers/usb/miniport/linux/consts.h | 70 - .../usb/miniport/linux/cromwell_types.h | 27 - reactos/drivers/usb/miniport/linux/errno.h | 132 - .../usb/miniport/linux/linux_wrapper.h | 856 ------ reactos/drivers/usb/miniport/linux/list.h | 224 -- reactos/drivers/usb/miniport/linux/pci_hal.c | 162 - reactos/drivers/usb/miniport/linux/pci_ids.h | 16 - reactos/drivers/usb/miniport/linux/usb.h | 1037 ------- reactos/drivers/usb/miniport/linux/usb_ch9.h | 315 -- reactos/drivers/usb/miniport/sys/BootUSB.c | 90 - .../drivers/usb/miniport/sys/linuxwrapper.c | 906 ------ reactos/drivers/usb/miniport/sys/risefall.c | 138 - .../drivers/usb/miniport/sys/ros_wrapper.c | 24 - reactos/drivers/usb/miniport/sys/sys.rbuild | 7 - reactos/drivers/usb/miniport/sys/usbkey.c | 124 - reactos/drivers/usb/miniport/sys/usbwrapper.c | 65 - reactos/drivers/usb/miniport/sys/xpad.c | 183 -- reactos/drivers/usb/miniport/sys/xremote.c | 142 - reactos/drivers/usb/miniport/usb_wrapper.h | 48 - .../usb/miniport/usbohci/makefile.crom | 3 - .../drivers/usb/miniport/usbohci/ohci-dbg.c | 666 ----- .../drivers/usb/miniport/usbohci/ohci-hcd.c | 722 ----- .../drivers/usb/miniport/usbohci/ohci-hub.c | 271 -- .../drivers/usb/miniport/usbohci/ohci-mem.c | 146 - .../drivers/usb/miniport/usbohci/ohci-pci.c | 412 --- reactos/drivers/usb/miniport/usbohci/ohci-q.c | 1014 ------- reactos/drivers/usb/miniport/usbohci/ohci.c | 76 - reactos/drivers/usb/miniport/usbohci/ohci.h | 415 --- reactos/drivers/usb/miniport/usbohci/ohci.rc | 5 - .../usb/miniport/usbohci/ohci_config.h | 5 - .../usb/miniport/usbohci/usbohci.rbuild | 13 - .../drivers/usb/miniport/usbuhci/uhci-debug.c | 616 ---- .../drivers/usb/miniport/usbuhci/uhci-hcd.c | 2624 ----------------- .../drivers/usb/miniport/usbuhci/uhci-hcd.h | 419 --- .../drivers/usb/miniport/usbuhci/uhci-hub.c | 184 -- reactos/drivers/usb/miniport/usbuhci/uhci.c | 81 - reactos/drivers/usb/miniport/usbuhci/uhci.h | 9 - reactos/drivers/usb/miniport/usbuhci/uhci.rc | 5 - .../usb/miniport/usbuhci/uhci_config.h | 5 - .../usb/miniport/usbuhci/usbuhci.rbuild | 13 - reactos/drivers/usb/usbport/buffer_simple.c | 42 - reactos/drivers/usb/usbport/config.c | 509 ---- .../drivers/usb/usbport/core_drivers/usbkey.c | 236 -- .../usb/usbport/core_drivers/usbmouse.c | 279 -- reactos/drivers/usb/usbport/hcd-pci.c | 374 --- reactos/drivers/usb/usbport/hcd.c | 1503 ---------- reactos/drivers/usb/usbport/hcd.h | 491 --- reactos/drivers/usb/usbport/hub.c | 1494 ---------- reactos/drivers/usb/usbport/hub.h | 195 -- reactos/drivers/usb/usbport/makefile.crom | 6 - reactos/drivers/usb/usbport/message.c | 1059 ------- reactos/drivers/usb/usbport/urb.c | 398 --- reactos/drivers/usb/usbport/usb-debug.c | 206 -- reactos/drivers/usb/usbport/usb.c | 1627 ---------- reactos/drivers/usb/usbport/usb.h | 5 - reactos/drivers/usb/usbport/usbcore.c | 78 - reactos/drivers/usb/usbport/usbcore.rc | 5 - reactos/drivers/usb/usbport/usbport.def | 34 - reactos/drivers/usb/usbport/usbport.rbuild | 21 - 71 files changed, 2 insertions(+), 23522 deletions(-) delete mode 100644 reactos/drivers/usb/miniport/common/common.rbuild delete mode 100644 reactos/drivers/usb/miniport/common/fdo.c delete mode 100644 reactos/drivers/usb/miniport/common/main.c delete mode 100644 reactos/drivers/usb/miniport/common/misc.c delete mode 100644 reactos/drivers/usb/miniport/common/pdo.c delete mode 100644 reactos/drivers/usb/miniport/common/usbcommon.h delete mode 100644 reactos/drivers/usb/miniport/common/usbcommon_types.h delete mode 100644 reactos/drivers/usb/miniport/directory.rbuild delete mode 100644 reactos/drivers/usb/miniport/linux/asm/bitops.h delete mode 100644 reactos/drivers/usb/miniport/linux/bitops.h delete mode 100644 reactos/drivers/usb/miniport/linux/boot.h delete mode 100644 reactos/drivers/usb/miniport/linux/consts.h delete mode 100644 reactos/drivers/usb/miniport/linux/cromwell_types.h delete mode 100644 reactos/drivers/usb/miniport/linux/errno.h delete mode 100644 reactos/drivers/usb/miniport/linux/linux_wrapper.h delete mode 100644 reactos/drivers/usb/miniport/linux/list.h delete mode 100644 reactos/drivers/usb/miniport/linux/pci_hal.c delete mode 100644 reactos/drivers/usb/miniport/linux/pci_ids.h delete mode 100644 reactos/drivers/usb/miniport/linux/usb.h delete mode 100644 reactos/drivers/usb/miniport/linux/usb_ch9.h delete mode 100644 reactos/drivers/usb/miniport/sys/BootUSB.c delete mode 100644 reactos/drivers/usb/miniport/sys/linuxwrapper.c delete mode 100644 reactos/drivers/usb/miniport/sys/risefall.c delete mode 100644 reactos/drivers/usb/miniport/sys/ros_wrapper.c delete mode 100644 reactos/drivers/usb/miniport/sys/sys.rbuild delete mode 100644 reactos/drivers/usb/miniport/sys/usbkey.c delete mode 100644 reactos/drivers/usb/miniport/sys/usbwrapper.c delete mode 100644 reactos/drivers/usb/miniport/sys/xpad.c delete mode 100644 reactos/drivers/usb/miniport/sys/xremote.c delete mode 100644 reactos/drivers/usb/miniport/usb_wrapper.h delete mode 100644 reactos/drivers/usb/miniport/usbohci/makefile.crom delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci-dbg.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci-hcd.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci-hub.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci-mem.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci-pci.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci-q.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci.c delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci.h delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci.rc delete mode 100644 reactos/drivers/usb/miniport/usbohci/ohci_config.h delete mode 100644 reactos/drivers/usb/miniport/usbohci/usbohci.rbuild delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci-debug.c delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci-hcd.c delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci-hcd.h delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci-hub.c delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci.c delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci.h delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci.rc delete mode 100644 reactos/drivers/usb/miniport/usbuhci/uhci_config.h delete mode 100644 reactos/drivers/usb/miniport/usbuhci/usbuhci.rbuild delete mode 100644 reactos/drivers/usb/usbport/buffer_simple.c delete mode 100644 reactos/drivers/usb/usbport/config.c delete mode 100644 reactos/drivers/usb/usbport/core_drivers/usbkey.c delete mode 100644 reactos/drivers/usb/usbport/core_drivers/usbmouse.c delete mode 100644 reactos/drivers/usb/usbport/hcd-pci.c delete mode 100644 reactos/drivers/usb/usbport/hcd.c delete mode 100644 reactos/drivers/usb/usbport/hcd.h delete mode 100644 reactos/drivers/usb/usbport/hub.c delete mode 100644 reactos/drivers/usb/usbport/hub.h delete mode 100644 reactos/drivers/usb/usbport/makefile.crom delete mode 100644 reactos/drivers/usb/usbport/message.c delete mode 100644 reactos/drivers/usb/usbport/urb.c delete mode 100644 reactos/drivers/usb/usbport/usb-debug.c delete mode 100644 reactos/drivers/usb/usbport/usb.c delete mode 100644 reactos/drivers/usb/usbport/usb.h delete mode 100644 reactos/drivers/usb/usbport/usbcore.c delete mode 100644 reactos/drivers/usb/usbport/usbcore.rc delete mode 100644 reactos/drivers/usb/usbport/usbport.def delete mode 100644 reactos/drivers/usb/usbport/usbport.rbuild diff --git a/reactos/drivers/usb/directory.rbuild b/reactos/drivers/usb/directory.rbuild index 084d6236cec..b8ac026db23 100644 --- a/reactos/drivers/usb/directory.rbuild +++ b/reactos/drivers/usb/directory.rbuild @@ -1,18 +1,12 @@ - - - + - - - - diff --git a/reactos/drivers/usb/miniport/common/common.rbuild b/reactos/drivers/usb/miniport/common/common.rbuild deleted file mode 100644 index 715d2dc70bb..00000000000 --- a/reactos/drivers/usb/miniport/common/common.rbuild +++ /dev/null @@ -1,9 +0,0 @@ - - - ../linux - . - fdo.c - main.c - misc.c - pdo.c - diff --git a/reactos/drivers/usb/miniport/common/fdo.c b/reactos/drivers/usb/miniport/common/fdo.c deleted file mode 100644 index ff0c4aaa7bd..00000000000 --- a/reactos/drivers/usb/miniport/common/fdo.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * PROJECT: ReactOS USB miniport driver (Cromwell type) - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/miniport/common/fdo.c - * PURPOSE: Operations on FDOs - * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) - * Copyright James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net) - */ - -#define NDEBUG -#include - -#include "usbcommon.h" - -#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) - -static VOID -UsbMpGetUserBuffers( - IN PIRP Irp, - IN ULONG IoControlCode, - OUT PVOID* BufferIn, - OUT PVOID* BufferOut) -{ - ASSERT(Irp); - ASSERT(BufferIn); - ASSERT(BufferOut); - - switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) - { - case METHOD_BUFFERED: - *BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer; - break; - case METHOD_IN_DIRECT: - case METHOD_OUT_DIRECT: - *BufferIn = Irp->AssociatedIrp.SystemBuffer; - *BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress); - break; - case METHOD_NEITHER: - *BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer; - *BufferOut = Irp->UserBuffer; - break; - default: - /* Should never happen */ - *BufferIn = NULL; - *BufferOut = NULL; - break; - } -} - -NTSTATUS -UsbMpFdoCreate( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - PUSBMP_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - - DPRINT("IRP_MJ_CREATE\n"); - Stack = IoGetCurrentIrpStackLocation(Irp); - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE) - { - CHECKPOINT; - Status = STATUS_NOT_A_DIRECTORY; - goto ByeBye; - } - - InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened); - Status = STATUS_SUCCESS; - -ByeBye: - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -NTSTATUS -UsbMpFdoClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PUSBMP_DEVICE_EXTENSION pDeviceExtension; - - DPRINT("IRP_MJ_CLOSE\n"); - pDeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - InterlockedDecrement((PLONG)&pDeviceExtension->DeviceOpened); - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; -} - -NTSTATUS -UsbMpFdoCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT("IRP_MJ_CLEANUP\n"); - - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; -} - -static NTSTATUS -UsbMpFdoStartDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); - PDRIVER_OBJECT DriverObject; - PUSBMP_DRIVER_EXTENSION DriverExtension; - PUSBMP_DEVICE_EXTENSION DeviceExtension; - PCM_RESOURCE_LIST AllocatedResources; - ULONG Size; - NTSTATUS Status; - - if (DeviceObject == KeyboardFdo || DeviceObject == MouseFdo) - return STATUS_SUCCESS; - - /* - * Get the initialization data we saved in VideoPortInitialize. - */ - DriverObject = DeviceObject->DriverObject; - DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - /* - * Store some resources in the DeviceExtension. - */ - AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources; - if (AllocatedResources != NULL) - { - CM_FULL_RESOURCE_DESCRIPTOR *FullList; - CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor; - ULONG ResourceCount; - ULONG ResourceListSize; - - /* Save the resource list */ - ResourceCount = AllocatedResources->List[0].PartialResourceList.Count; - - ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList. - PartialDescriptors[ResourceCount]); - - DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize); - if (DeviceExtension->AllocatedResources == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlCopyMemory(DeviceExtension->AllocatedResources, - AllocatedResources, - ResourceListSize); - - /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */ - for (FullList = AllocatedResources->List; - FullList < AllocatedResources->List + AllocatedResources->Count; - FullList++) - { - /* FIXME: Is this ASSERT ok for resources from the PNP manager? */ - /*ASSERT(FullList->InterfaceType == PCIBus && - FullList->BusNumber == DeviceExtension->SystemIoBusNumber && - 1 == FullList->PartialResourceList.Version && - 1 == FullList->PartialResourceList.Revision);*/ - for (Descriptor = FullList->PartialResourceList.PartialDescriptors; - Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count; - Descriptor++) - { - if (Descriptor->Type == CmResourceTypeInterrupt) - { - DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level; - DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector; - } - else if (Descriptor->Type == CmResourceTypePort) - { - DeviceExtension->BaseAddress = Descriptor->u.Port.Start; - DeviceExtension->BaseAddrLength = Descriptor->u.Port.Length; - DeviceExtension->Flags = Descriptor->Flags; - - ((struct hc_driver *)pci_ids->driver_data)->flags &= ~HCD_MEMORY; - } - else if (Descriptor->Type == CmResourceTypeMemory) - { - DeviceExtension->BaseAddress = Descriptor->u.Memory.Start; - DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length; - DeviceExtension->Flags = Descriptor->Flags; - - ((struct hc_driver *)pci_ids->driver_data)->flags |= HCD_MEMORY; - } - } - } - } - - /* Print assigned resources */ - DPRINT("Interrupt Vector 0x%lx, %S base 0x%lx, Length 0x%lx\n", - DeviceExtension->InterruptVector, - ((struct hc_driver *)pci_ids->driver_data)->flags & HCD_MEMORY ? L"Memory" : L"I/O", - DeviceExtension->BaseAddress, - DeviceExtension->BaseAddrLength); - - /* Get bus number from the upper level bus driver. */ - Size = sizeof(ULONG); - Status = IoGetDeviceProperty( - DeviceExtension->PhysicalDeviceObject, - DevicePropertyBusNumber, - Size, - &DeviceExtension->SystemIoBusNumber, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoGetDeviceProperty DevicePropertyBusNumber failed\n"); - DeviceExtension->SystemIoBusNumber = 0; - } - - DPRINT("Busnumber %d\n", DeviceExtension->SystemIoBusNumber); - - /* Init wrapper with this object */ - return InitLinuxWrapper(DeviceObject); -} - -static NTSTATUS -UsbMpFdoQueryBusRelations( - IN PDEVICE_OBJECT DeviceObject, - OUT PDEVICE_RELATIONS* pDeviceRelations) -{ - PUSBMP_DEVICE_EXTENSION DeviceExtension; - PDEVICE_RELATIONS DeviceRelations; - NTSTATUS Status = STATUS_SUCCESS; - - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - /* Handling this IRP is easy, as we only - * have one child: the root hub - */ - DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool( - PagedPool, - sizeof(DEVICE_RELATIONS)); - if (!DeviceRelations) - return STATUS_INSUFFICIENT_RESOURCES; - - /* Fill returned structure */ - DeviceRelations->Count = 1; - ObReferenceObject(DeviceExtension->RootHubPdo); - DeviceRelations->Objects[0] = DeviceExtension->RootHubPdo; - - *pDeviceRelations = DeviceRelations; - return Status; -} - -NTSTATUS -UsbMpFdoPnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IrpSp; - NTSTATUS Status; - ULONG MinorFunction; - ULONG_PTR Information = 0; - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = IrpSp->MinorFunction; - - switch (MinorFunction) - { - case IRP_MN_START_DEVICE: /* 0x00 */ - { - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject != NULL) - /* HACK due to the lack of lower device for legacy USB keyboard and mouse */ - Status = ForwardIrpAndWait(DeviceObject, Irp); - else - Status = STATUS_SUCCESS; - if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status)) - Status = UsbMpFdoStartDevice(DeviceObject, Irp); - break; - } - - case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */ - case IRP_MN_CANCEL_REMOVE_DEVICE: /* 0x03 */ - { - return ForwardIrpAndForget(DeviceObject, Irp); - } - - case IRP_MN_REMOVE_DEVICE: /* 0x02 */ - case IRP_MN_STOP_DEVICE: /* 0x04 */ - case IRP_MN_SURPRISE_REMOVAL: /* 0x17 */ - { - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject != NULL) - /* HACK due to the lack of lower device for legacy USB keyboard and mouse */ - Status = ForwardIrpAndWait(DeviceObject, Irp); - else - Status = STATUS_SUCCESS; - if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status)) - Status = STATUS_SUCCESS; - IoDeleteDevice(DeviceObject); // just delete device for now - break; - } - - case IRP_MN_QUERY_STOP_DEVICE: /* 0x05 */ - case IRP_MN_CANCEL_STOP_DEVICE: /* 0x06 */ - { - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ - { - switch (IrpSp->Parameters.QueryDeviceRelations.Type) - { - case BusRelations: - { - PDEVICE_RELATIONS DeviceRelations = NULL; - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); - Status = UsbMpFdoQueryBusRelations(DeviceObject, &DeviceRelations); - Information = (ULONG_PTR)DeviceRelations; - break; - } - case RemovalRelations: - { - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); - return ForwardIrpAndForget(DeviceObject, Irp); - } - default: - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", - IrpSp->Parameters.QueryDeviceRelations.Type); - return ForwardIrpAndForget(DeviceObject, Irp); - } - break; - } - - default: - { - DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); - return ForwardIrpAndForget(DeviceObject, Irp); - } - } - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -NTSTATUS -UsbMpFdoDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - ULONG IoControlCode; - PUSBMP_DEVICE_EXTENSION DeviceExtension; - ULONG LengthIn, LengthOut; - ULONG_PTR Information = 0; - PVOID BufferIn, BufferOut; - NTSTATUS Status; - - DPRINT("UsbDeviceControlFdo() called\n"); - - Stack = IoGetCurrentIrpStackLocation(Irp); - LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength; - LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength; - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode; - UsbMpGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut); - - switch (IoControlCode) - { - case IOCTL_GET_HCD_DRIVERKEY_NAME: - { - DPRINT("IOCTL_GET_HCD_DRIVERKEY_NAME\n"); - if (LengthOut < sizeof(USB_HCD_DRIVERKEY_NAME)) - Status = STATUS_BUFFER_TOO_SMALL; - else if (BufferOut == NULL) - Status = STATUS_INVALID_PARAMETER; - else - { - PUSB_HCD_DRIVERKEY_NAME StringDescriptor; - ULONG StringSize; - StringDescriptor = (PUSB_HCD_DRIVERKEY_NAME)BufferOut; - Status = IoGetDeviceProperty( - ((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PhysicalDeviceObject, - DevicePropertyDriverKeyName, - LengthOut - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), - StringDescriptor->DriverKeyName, - &StringSize); - if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) - { - StringDescriptor->ActualLength = StringSize + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName); - Information = LengthOut; - Status = STATUS_SUCCESS; - } - } - break; - } - case IOCTL_USB_GET_ROOT_HUB_NAME: - { - DPRINT("IOCTL_USB_GET_ROOT_HUB_NAME\n"); - if (LengthOut < sizeof(USB_ROOT_HUB_NAME)) - Status = STATUS_BUFFER_TOO_SMALL; - else if (BufferOut == NULL) - Status = STATUS_INVALID_PARAMETER; - else - { - PUSB_ROOT_HUB_NAME StringDescriptor; - PUNICODE_STRING RootHubInterfaceName; - StringDescriptor = (PUSB_ROOT_HUB_NAME)BufferOut; - DeviceObject = ((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->RootHubPdo; - RootHubInterfaceName = &((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->HcdInterfaceName; - - StringDescriptor->ActualLength = RootHubInterfaceName->Length + sizeof(WCHAR) + FIELD_OFFSET(USB_ROOT_HUB_NAME, RootHubName); - if (StringDescriptor->ActualLength <= LengthOut) - { - /* Copy root hub name */ - RtlCopyMemory( - StringDescriptor->RootHubName, - RootHubInterfaceName->Buffer, - RootHubInterfaceName->Length); - StringDescriptor->RootHubName[RootHubInterfaceName->Length / sizeof(WCHAR)] = UNICODE_NULL; - DPRINT("IOCTL_USB_GET_ROOT_HUB_NAME returns '%S'\n", StringDescriptor->RootHubName); - Information = StringDescriptor->ActualLength; - } - else - Information = sizeof(USB_ROOT_HUB_NAME); - Status = STATUS_SUCCESS; - } - break; - } - - default: - { - /* Pass Irp to lower driver */ - DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); - } - } - - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} diff --git a/reactos/drivers/usb/miniport/common/main.c b/reactos/drivers/usb/miniport/common/main.c deleted file mode 100644 index 5d2386c9295..00000000000 --- a/reactos/drivers/usb/miniport/common/main.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * PROJECT: ReactOS USB miniport driver (Cromwell type) - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/miniport/common/main.c - * PURPOSE: Driver entry - * PROGRAMMERS: Copyright Aleksey Bragin (aleksey@reactos.org) - * Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) - * Copyright James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net) - * - * Some parts of code are inspired (or even just copied) from - * ReactOS Videoport driver (drivers/video/videoprt) - */ - -#define NDEBUG -#include - -#define INITGUID -#include "usbcommon.h" - -/* Data for embedded drivers */ -CONNECT_DATA KbdClassInformation; -CONNECT_DATA MouseClassInformation; -PDEVICE_OBJECT KeyboardFdo = NULL; -PDEVICE_OBJECT MouseFdo = NULL; - -static NTSTATUS -CreateRootHubPdo( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Fdo, - OUT PDEVICE_OBJECT* pPdo) -{ - PDEVICE_OBJECT Pdo; - PUSBMP_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - - DPRINT("CreateRootHubPdo()\n"); - - Status = IoCreateDevice( - DriverObject, - sizeof(USBMP_DEVICE_EXTENSION), - NULL, /* DeviceName */ - FILE_DEVICE_BUS_EXTENDER, - FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME, - FALSE, - &Pdo); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoCreateDevice() call failed with status 0x%08x\n", Status); - return Status; - } - - Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; - Pdo->Flags |= DO_POWER_PAGABLE; - - /* Zerofill device extension */ - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)Pdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION)); - - DeviceExtension->IsFDO = FALSE; - DeviceExtension->FunctionalDeviceObject = Fdo; - - Pdo->Flags &= ~DO_DEVICE_INITIALIZING; - - *pPdo = Pdo; - return STATUS_SUCCESS; -} - -static NTSTATUS -AddRegistryEntry( - IN PCWSTR PortTypeName, - IN PUNICODE_STRING DeviceName, - IN PCWSTR RegistryPath) -{ - UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP"); - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hDeviceMapKey = (HANDLE)-1; - HANDLE hPortKey = (HANDLE)-1; - UNICODE_STRING PortTypeNameU; - NTSTATUS Status; - - InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - RtlInitUnicodeString(&PortTypeNameU, PortTypeName); - InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL); - Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL)); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - Status = STATUS_SUCCESS; - -cleanup: - if (hDeviceMapKey != (HANDLE)-1) - ZwClose(hDeviceMapKey); - if (hPortKey != (HANDLE)-1) - ZwClose(hPortKey); - return Status; -} - -static NTSTATUS -AddDevice_Keyboard( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo) -{ - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPortUSB"); - PUSBMP_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT Fdo; - NTSTATUS Status; - - Status = AddRegistryEntry(L"KeyboardPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbport"); - if (!NT_SUCCESS(Status)) - { - DPRINT1("AddRegistryEntry() for usb keyboard driver failed with status 0x%08lx\n", Status); - return Status; - } - - Status = IoCreateDevice(DriverObject, - sizeof(USBMP_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_KEYBOARD, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoCreateDevice() for usb keyboard driver failed with status 0x%08lx\n", Status); - return Status; - } - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)Fdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION)); - DeviceExtension->IsFDO = FALSE; - KeyboardFdo = Fdo; - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - DPRINT("Created keyboard Fdo: %p\n", Fdo); - - return STATUS_SUCCESS; -} - -static NTSTATUS -AddDevice_Mouse( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT Pdo) -{ - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerPortUSB"); - PUSBMP_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT Fdo; - NTSTATUS Status; - - Status = AddRegistryEntry(L"PointerPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbport"); - if (!NT_SUCCESS(Status)) - { - DPRINT1("AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status); - return Status; - } - - Status = IoCreateDevice(DriverObject, - sizeof(USBMP_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_MOUSE, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status); - return Status; - } - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)Fdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION)); - DeviceExtension->IsFDO = FALSE; - MouseFdo = Fdo; - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - DPRINT("Created mouse Fdo: %p\n", Fdo); - - return STATUS_SUCCESS; -} - -NTSTATUS NTAPI -AddDevice( - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT pdo) -{ - PDEVICE_OBJECT fdo = NULL; - NTSTATUS Status; - WCHAR DeviceBuffer[20]; - WCHAR LinkDeviceBuffer[20]; - UNICODE_STRING DeviceName; - UNICODE_STRING LinkDeviceName; - PUSBMP_DRIVER_EXTENSION DriverExtension; - PUSBMP_DEVICE_EXTENSION DeviceExtension = NULL; - static ULONG DeviceNumber = 0; - BOOLEAN AlreadyRestarted = FALSE; - - /* Allocate driver extension now */ - DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); - if (DriverExtension == NULL) - { - Status = IoAllocateDriverObjectExtension( - DriverObject, - DriverObject, - sizeof(USBMP_DRIVER_EXTENSION), - (PVOID *)&DriverExtension); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Allocating DriverObjectExtension failed.\n"); - goto cleanup; - } - } - - /* Create a unicode device name. Allocate a new device number every time */ - while (TRUE) - { - swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber); - RtlInitUnicodeString(&DeviceName, DeviceBuffer); - - Status = IoCreateDevice(DriverObject, - sizeof(USBMP_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_BUS_EXTENDER, - 0, - FALSE, - &fdo); - if (Status != STATUS_OBJECT_NAME_COLLISION) - break; - - if (DeviceNumber == 9999) - { - /* Hmm. We don't have a free number. */ - if (AlreadyRestarted) - { - Status = STATUS_TOO_MANY_NAMES; - break; - } - /* Start again at DeviceNumber = 0 to find a free number */ - DeviceNumber = 0; - AlreadyRestarted = TRUE; - } - else - DeviceNumber++; - } - - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoCreateDevice call failed with status 0x%08lx\n", Status); - goto cleanup; - } - - /* Zerofill device extension */ - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)fdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(USBMP_DEVICE_EXTENSION)); - - /* Create root hub Pdo */ - Status = CreateRootHubPdo(DriverObject, fdo, &DeviceExtension->RootHubPdo); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CreateRootHubPdo() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - /* Register device interface for controller */ - Status = IoRegisterDeviceInterface( - pdo, - &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, - NULL, - &DeviceExtension->HcdInterfaceName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status); - goto cleanup; - } - - DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo); - - /* Initialize device extension */ - DeviceExtension->IsFDO = TRUE; - DeviceExtension->DeviceNumber = DeviceNumber; - DeviceExtension->PhysicalDeviceObject = pdo; - DeviceExtension->FunctionalDeviceObject = fdo; - DeviceExtension->DriverExtension = DriverExtension; - - fdo->Flags &= ~DO_DEVICE_INITIALIZING; - - /* Use the same number as the FDO */ - swprintf(LinkDeviceBuffer, L"\\??\\HCD%lu", DeviceNumber); - - RtlInitUnicodeString(&LinkDeviceName, LinkDeviceBuffer); - Status = IoCreateSymbolicLink(&LinkDeviceName, &DeviceName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IoCreateSymbolicLink() call failed with status 0x%08x\n", Status); - goto cleanup; - } - - return STATUS_SUCCESS; - -cleanup: - if (DeviceExtension && DeviceExtension->RootHubPdo) - IoDeleteDevice(DeviceExtension->RootHubPdo); - if (fdo) - IoDeleteDevice(fdo); - return Status; -} - -NTSTATUS NTAPI -IrpStub( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - NTSTATUS Status = STATUS_NOT_SUPPORTED; - - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - { - DPRINT1("FDO stub for major function 0x%lx\n", - IoGetCurrentIrpStackLocation(Irp)->MajorFunction); - ASSERT(FALSE); - return ForwardIrpAndForget(DeviceObject, Irp); - } - else - { - /* We can't forward request to the lower driver, because - * we are a Pdo, so we don't have lower driver... - */ - DPRINT1("PDO stub for major function 0x%lx\n", - IoGetCurrentIrpStackLocation(Irp)->MajorFunction); - ASSERT(FALSE); - } - - Status = Irp->IoStatus.Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -static NTSTATUS NTAPI -DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbMpFdoCreate(DeviceObject, Irp); - else - return UsbMpPdoCreate(DeviceObject, Irp); -} - -static NTSTATUS NTAPI -DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbMpFdoClose(DeviceObject, Irp); - else - return UsbMpPdoClose(DeviceObject, Irp); -} - -static NTSTATUS NTAPI -DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbMpFdoCleanup(DeviceObject, Irp); - else - return UsbMpPdoCleanup(DeviceObject, Irp); -} - -static NTSTATUS NTAPI -DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbMpFdoDeviceControl(DeviceObject, Irp); - else - return IrpStub(DeviceObject, Irp); -} - -static NTSTATUS NTAPI -DispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return IrpStub(DeviceObject, Irp); - else - return UsbMpPdoInternalDeviceControl(DeviceObject, Irp); -} - -static NTSTATUS NTAPI -DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - if (((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO) - return UsbMpFdoPnp(DeviceObject, Irp); - else - return UsbMpPdoPnp(DeviceObject, Irp); -} - -static NTSTATUS NTAPI -DispatchPower(PDEVICE_OBJECT fido, PIRP Irp) -{ - DPRINT1("IRP_MJ_POWER unimplemented\n"); - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_SUPPORTED; -} - -/* - * Standard DriverEntry method. - */ -NTSTATUS NTAPI -DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath) -{ - USBPORT_INTERFACE UsbPortInterface; - ULONG i; - - DriverObject->DriverUnload = DriverUnload; - DriverObject->DriverExtension->AddDevice = AddDevice; - - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) - DriverObject->MajorFunction[i] = IrpStub; - - DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl; - DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; - DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; - - /* Register in usbcore.sys */ - UsbPortInterface.KbdConnectData = &KbdClassInformation; - UsbPortInterface.MouseConnectData = &MouseClassInformation; - - KbdClassInformation.ClassService = NULL; - KbdClassInformation.ClassDeviceObject = NULL; - MouseClassInformation.ClassService = NULL; - MouseClassInformation.ClassDeviceObject = NULL; - - RegisterPortDriver(DriverObject, &UsbPortInterface); - - AddDevice_Keyboard(DriverObject, NULL); - AddDevice_Mouse(DriverObject, NULL); - - return STATUS_SUCCESS; -} diff --git a/reactos/drivers/usb/miniport/common/misc.c b/reactos/drivers/usb/miniport/common/misc.c deleted file mode 100644 index 475beb06f6c..00000000000 --- a/reactos/drivers/usb/miniport/common/misc.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * PROJECT: ReactOS USB miniport driver (Cromwell type) - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/miniport/common/misc.c - * PURPOSE: Misceallenous operations - * PROGRAMMERS: Copyright 2005 Hervé Poussineau (hpoussin@reactos.org) - */ - -#define NDEBUG -#include - -#include "usbcommon.h" -#include - -NTSTATUS NTAPI -ForwardIrpAndWaitCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - if (Irp->PendingReturned) - KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -ForwardIrpAndWait( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PDEVICE_OBJECT LowerDevice = ((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject; - KEVENT Event; - NTSTATUS Status; - - ASSERT(LowerDevice); - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - IoCopyCurrentIrpStackLocationToNext(Irp); - - DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName); - IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); - - Status = IoCallDriver(LowerDevice, Irp); - if (Status == STATUS_PENDING) - { - Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); - if (NT_SUCCESS(Status)) - Status = Irp->IoStatus.Status; - } - - return Status; -} - -NTSTATUS -ForwardIrpAndForget( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PDEVICE_OBJECT LowerDevice = ((PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject; - - ASSERT(LowerDevice); - - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(LowerDevice, Irp); -} - -/* I really want PCSZ strings as last arguments because - * PnP ids are ANSI-encoded in PnP device string - * identification */ -NTSTATUS -UsbMpInitMultiSzString( - OUT PUNICODE_STRING Destination, - ... /* list of PCSZ */) -{ - va_list args; - PCSZ Source; - ANSI_STRING AnsiString; - UNICODE_STRING UnicodeString; - ULONG DestinationSize = 0; - NTSTATUS Status = STATUS_SUCCESS; - - ASSERT(Destination); - - /* Calculate length needed for destination unicode string */ - va_start(args, Destination); - Source = va_arg(args, PCSZ); - while (Source != NULL) - { - RtlInitAnsiString(&AnsiString, Source); - DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString) - + sizeof(WCHAR) /* final NULL */; - Source = va_arg(args, PCSZ); - } - va_end(args); - if (DestinationSize == 0) - { - RtlInitUnicodeString(Destination, NULL); - return STATUS_SUCCESS; - } - - /* Initialize destination string */ - DestinationSize += sizeof(WCHAR); // final NULL - Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, DestinationSize, USB_MINIPORT_TAG); - if (!Destination->Buffer) - return STATUS_INSUFFICIENT_RESOURCES; - Destination->Length = 0; - Destination->MaximumLength = (USHORT)DestinationSize; - - /* Copy arguments to destination string */ - /* Use a temporary unicode string, which buffer is shared with - * destination string, to copy arguments */ - UnicodeString.Length = Destination->Length; - UnicodeString.MaximumLength = Destination->MaximumLength; - UnicodeString.Buffer = Destination->Buffer; - va_start(args, Destination); - Source = va_arg(args, PCSZ); - while (Source != NULL) - { - RtlInitAnsiString(&AnsiString, Source); - Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); - if (!NT_SUCCESS(Status)) - { - ExFreePoolWithTag(Destination->Buffer, USB_MINIPORT_TAG); - break; - } - Destination->Length += UnicodeString.Length + sizeof(WCHAR); - UnicodeString.MaximumLength -= UnicodeString.Length + sizeof(WCHAR); - UnicodeString.Buffer += UnicodeString.Length / sizeof(WCHAR) + 1; - UnicodeString.Length = 0; - Source = va_arg(args, PCSZ); - } - va_end(args); - if (NT_SUCCESS(Status)) - { - /* Finish multi-sz string */ - Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0'; - Destination->Length += sizeof(WCHAR); - } - return Status; -} - -NTSTATUS -UsbMpDuplicateUnicodeString( - OUT PUNICODE_STRING Destination, - IN PUNICODE_STRING Source, - IN POOL_TYPE PoolType) -{ - ASSERT(Destination); - - if (Source == NULL) - { - RtlInitUnicodeString(Destination, NULL); - return STATUS_SUCCESS; - } - - Destination->Buffer = ExAllocatePool(PoolType, Source->MaximumLength); - if (Destination->Buffer == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - Destination->MaximumLength = Source->MaximumLength; - Destination->Length = Source->Length; - RtlCopyMemory(Destination->Buffer, Source->Buffer, Source->MaximumLength); - - return STATUS_SUCCESS; -} diff --git a/reactos/drivers/usb/miniport/common/pdo.c b/reactos/drivers/usb/miniport/common/pdo.c deleted file mode 100644 index bebe1c4629b..00000000000 --- a/reactos/drivers/usb/miniport/common/pdo.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * PROJECT: ReactOS USB miniport driver (Cromwell type) - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/miniport/common/pdo.c - * PURPOSE: Operations on PDOs - * PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau (hpoussin@reactos.org) - * Copyright James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net) - */ - -#define NDEBUG -#include - -#include "usbcommon.h" -#include - -extern struct usb_driver hub_driver; - -#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) - -NTSTATUS -UsbMpPdoCreate( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT("IRP_MJ_CREATE\n"); - - /* Nothing to do */ - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; -} - -NTSTATUS -UsbMpPdoClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT("IRP_MJ_CLOSE\n"); - - /* Nothing to do */ - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; -} - -NTSTATUS -UsbMpPdoCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT("IRP_MJ_CLEANUP\n"); - - /* Nothing to do */ - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; -} - -NTSTATUS -UsbMpPdoInternalDeviceControlCore( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - ULONG_PTR Information = 0; - NTSTATUS Status; - - DPRINT("UsbMpPdoInternalDeviceControl() called\n"); - - Stack = IoGetCurrentIrpStackLocation(Irp); - Status = Irp->IoStatus.Status; - - switch (Stack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: - { - PUSBMP_DEVICE_EXTENSION DeviceExtension; - - DPRINT("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n"); - if (Irp->AssociatedIrp.SystemBuffer == NULL - || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID)) - { - Status = STATUS_INVALID_PARAMETER; - } - else - { - PVOID* pRootHubPointer; - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceExtension->FunctionalDeviceObject->DeviceExtension; - - pRootHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer; - *pRootHubPointer = ((struct usb_hcd*)DeviceExtension->pdev->data)->self.root_hub; - Information = sizeof(PVOID); - Status = STATUS_SUCCESS; - } - break; - } - default: - { - DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - } - } - - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -static NTSTATUS -QueryId( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - OUT ULONG_PTR* Information) -{ - PUSBMP_DEVICE_EXTENSION DeviceExtension; - ULONG IdType; - UNICODE_STRING SourceString; - UNICODE_STRING String; - struct usb_device *roothub; - NTSTATUS Status = STATUS_SUCCESS; - - IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - RtlInitUnicodeString(&String, NULL); - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceExtension->FunctionalDeviceObject->DeviceExtension; - roothub = ((struct usb_hcd*)DeviceExtension->pdev->data)->self.root_hub; - - switch (IdType) - { - case BusQueryDeviceID: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); - if (roothub->speed == USB_SPEED_LOW || roothub->speed == USB_SPEED_FULL) - RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB"); /* USB 1.1 */ - else - RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB20"); /* USB 2.0 */ - break; - } - case BusQueryHardwareIDs: - { - CHAR Buffer[2][40]; - PCHAR RootHubName; - PCI_COMMON_CONFIG PciData; - ULONG BusNumber, SlotNumber; - ULONG ret; - PDEVICE_OBJECT Pdo; - - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); - - Pdo = DeviceExtension->PhysicalDeviceObject; - Status = IoGetDeviceProperty( - Pdo, - DevicePropertyBusNumber, - sizeof(ULONG), - &BusNumber, - &ret); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoGetDeviceProperty() failed with status 0x%08lx\n", Status); - break; - } - - Status = IoGetDeviceProperty( - Pdo, - DevicePropertyAddress, - sizeof(ULONG), - &SlotNumber, - &ret); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoGetDeviceProperty() failed with status 0x%08lx\n", Status); - break; - } - - ret = HalGetBusDataByOffset(PCIConfiguration, - BusNumber, - SlotNumber, - &PciData, - 0, - PCI_COMMON_HDR_LENGTH); - if (ret != PCI_COMMON_HDR_LENGTH) - { - DPRINT("HalGetBusDataByOffset() failed (ret = %ld)\n", ret); - Status = STATUS_IO_DEVICE_ERROR; - break; - } - - sprintf(Buffer[0], "USB\\VID%04X&PID%04X&REV%04X", - PciData.VendorID, PciData.DeviceID, PciData.RevisionID); - sprintf(Buffer[1], "USB\\VID%04X&PID%04X", - PciData.VendorID, PciData.DeviceID); - if (roothub->speed == USB_SPEED_LOW || roothub->speed == USB_SPEED_FULL) - RootHubName = "USB\\ROOT_HUB"; /* USB 1.1 */ - else - RootHubName = "USB\\ROOT_HUB20"; /* USB 2.0 */ - Status = UsbMpInitMultiSzString( - &SourceString, - Buffer[0], Buffer[1], RootHubName, NULL); - break; - } - case BusQueryCompatibleIDs: - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n"); - /* No compatible ID */ - *Information = 0; - return STATUS_NOT_SUPPORTED; - case BusQueryInstanceID: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); - *Information = 0; - return Status; - } - default: - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); - return STATUS_NOT_SUPPORTED; - } - - if (NT_SUCCESS(Status)) - { - Status = UsbMpDuplicateUnicodeString( - &String, - &SourceString, - PagedPool); - *Information = (ULONG_PTR)String.Buffer; - } - return Status; -} - -static NTSTATUS -QueryBusInformation( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - OUT ULONG_PTR* Information) -{ - PPNP_BUS_INFORMATION BusInformation; - - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n"); - - BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION)); - if (!BusInformation) - return STATUS_INSUFFICIENT_RESOURCES; - BusInformation->BusTypeGuid = GUID_BUS_TYPE_USB; - BusInformation->LegacyBusType = PNPBus; - BusInformation->BusNumber = 0; /* FIXME */ - return STATUS_SUCCESS; -} - -static NTSTATUS -StartDevice( - IN PDEVICE_OBJECT DeviceObject) -{ - PUSBMP_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - /* Register device interface for root hub */ - Status = IoRegisterDeviceInterface( - DeviceObject, - &GUID_DEVINTERFACE_USB_HUB, - NULL, - &DeviceExtension->HcdInterfaceName); - if (!NT_SUCCESS(Status)) - { - DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status); - return Status; - } - - return Status; -} - -NTSTATUS -UsbMpPdoPnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - ULONG MinorFunction; - PIO_STACK_LOCATION Stack; - ULONG_PTR Information = 0; - NTSTATUS Status; - - Stack = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = Stack->MinorFunction; - - switch (MinorFunction) - { - case IRP_MN_START_DEVICE: /* 0x00 */ - { - DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); - Status = StartDevice(DeviceObject); - break; - } - case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */ - { - PDEVICE_CAPABILITIES DeviceCapabilities; - ULONG i; - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); - - DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities; - /* FIXME: capabilities can change with connected device */ - DeviceCapabilities->LockSupported = FALSE; - DeviceCapabilities->EjectSupported = FALSE; - DeviceCapabilities->Removable = FALSE; - DeviceCapabilities->DockDevice = FALSE; - DeviceCapabilities->UniqueID = FALSE; - DeviceCapabilities->SilentInstall = TRUE; - DeviceCapabilities->RawDeviceOK = FALSE; - DeviceCapabilities->SurpriseRemovalOK = FALSE; - DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */ - //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */ - DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */ - for (i = 0; i < PowerSystemMaximum; i++) - DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */ - //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */ - DeviceCapabilities->D1Latency = 0; /* FIXME */ - DeviceCapabilities->D2Latency = 0; /* FIXME */ - DeviceCapabilities->D3Latency = 0; /* FIXME */ - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_QUERY_RESOURCES: /* 0x0a */ - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n"); - /* Root buses don't need resources, except the ones of - * the usb controller. This PDO is the root bus PDO, so - * report no resource by not changing Information and - * Status - */ - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - break; - } - case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */ - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); - /* Root buses don't need resources, except the ones of - * the usb controller. This PDO is the root bus PDO, so - * report no resource by not changing Information and - * Status - */ - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - break; - } - case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */ - { - switch (Stack->Parameters.QueryDeviceText.DeviceTextType) - { - case DeviceTextDescription: - { - UNICODE_STRING SourceString = RTL_CONSTANT_STRING(L"Root USB hub"); - UNICODE_STRING Description; - - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n"); - - Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &SourceString, &Description); - if (NT_SUCCESS(Status)) - Information = (ULONG_PTR)Description.Buffer; - break; - } - case DeviceTextLocationInformation: - { - /* We don't have any text location to report, - * and this query is optional, so ignore it. - */ - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - break; - } - default: - { - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n", - Stack->Parameters.QueryDeviceText.DeviceTextType); - ASSERT(FALSE); - Status = STATUS_NOT_SUPPORTED; - } - } - break; - } - case IRP_MN_QUERY_ID: /* 0x13 */ - { - Status = QueryId(DeviceObject, Irp, &Information); - break; - } - case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */ - { - Status = QueryBusInformation(DeviceObject, Irp, &Information); - break; - } - default: - { - /* We can't forward request to the lower driver, because - * we are a Pdo, so we don't have lower driver... - */ - DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - ASSERT(FALSE); - } - } - - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -NTSTATUS -UsbMpPdoInternalDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; - - DPRINT("UsbMpDeviceInternalControlPdo(DO %p, code 0x%lx) called\n", - DeviceObject, - IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode); - - if (DeviceObject == KeyboardFdo) - { - // it's keyboard's IOCTL - PIO_STACK_LOCATION Stk; - - Irp->IoStatus.Information = 0; - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_KEYBOARD_CONNECT: - DPRINT("IOCTL_INTERNAL_KEYBOARD_CONNECT\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) { - DPRINT1("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure; - } - - RtlCopyMemory(&KbdClassInformation, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - sizeof(CONNECT_DATA)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - - case IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER: - DPRINT("IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < 1) { - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure; - } -/* if (!DevExt->KeyboardInterruptObject) { - Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; - goto intcontfailure; - }*/ - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: - DPRINT("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_ATTRIBUTES)) { - DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES: " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardAttributes, - sizeof(KEYBOARD_ATTRIBUTES));*/ - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_INDICATORS: - DPRINT("IOCTL_KEYBOARD_QUERY_INDICATORS\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_INDICATORS: " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardIndicators, - sizeof(KEYBOARD_INDICATOR_PARAMETERS));*/ - - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - break; - case IOCTL_KEYBOARD_QUERY_TYPEMATIC: - DPRINT("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC: " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardTypematic, - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/ - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_SET_INDICATORS: - DPRINT("IOCTL_KEYBOARD_SET_INDICATORS\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS: " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - - /*RtlCopyMemory(&DevExt->KeyboardIndicators, - Irp->AssociatedIrp.SystemBuffer, - sizeof(KEYBOARD_INDICATOR_PARAMETERS));*/ - - //DPRINT("%x\n", DevExt->KeyboardIndicators.LedFlags); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_SET_TYPEMATIC: - DPRINT("IOCTL_KEYBOARD_SET_TYPEMATIC\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { - DPRINT("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - - /*RtlCopyMemory(&DevExt->KeyboardTypematic, - Irp->AssociatedIrp.SystemBuffer, - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/ - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: - /* We should check the UnitID, but it's kind of pointless as - * all keyboards are supposed to have the same one - */ -#if 0 - DPRINT("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION\n"); - if (Stk->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)) { - DPRINT("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: " - "invalid buffer size (expected)\n"); - /* It's to query the buffer size */ - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - goto intcontfailure; - } - Irp->IoStatus.Information = - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION); -#endif - /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, - &IndicatorTranslation, - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION));*/ - - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - break; - case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: - /* Nothing to do here */ - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - default: - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - break; - } - - intcontfailure: - Status = Irp->IoStatus.Status; - } - else if (DeviceObject == MouseFdo) - { - // it's mouse's IOCTL - PIO_STACK_LOCATION Stk; - - Irp->IoStatus.Information = 0; - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_MOUSE_CONNECT: - DPRINT("IOCTL_INTERNAL_MOUSE_CONNECT\n"); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) { - DPRINT1("IOCTL_INTERNAL_MOUSE_CONNECT: " - "invalid buffer size\n"); - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure2; - } - - RtlCopyMemory(&MouseClassInformation, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - sizeof(CONNECT_DATA)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - - default: - Irp->IoStatus.Status = STATUS_SUCCESS;//STATUS_INVALID_DEVICE_REQUEST; - break; - } - intcontfailure2: - Status = Irp->IoStatus.Status; - } - else - { - return UsbMpPdoInternalDeviceControlCore(DeviceObject, Irp); - } - - - if (Status == STATUS_INVALID_DEVICE_REQUEST) { - DPRINT1("Invalid internal device request!\n"); - } - - if (Status != STATUS_PENDING) - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} diff --git a/reactos/drivers/usb/miniport/common/usbcommon.h b/reactos/drivers/usb/miniport/common/usbcommon.h deleted file mode 100644 index f48c2244a42..00000000000 --- a/reactos/drivers/usb/miniport/common/usbcommon.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _USBMP_COMMON_H_ -#define _USBMP_COMMON_H_ - -// config and include core/hcd.h, for hc_device struct struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) - -#include "../usb_wrapper.h" -#include -#include -#include -#include - -#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) -#define USB_MINIPORT_TAG TAG('u','s','b','m') - -#include "../../usbport/hcd.h" -#include "usbcommon_types.h" - -extern CONNECT_DATA KbdClassInformation; -extern CONNECT_DATA MouseClassInformation; -extern PDEVICE_OBJECT KeyboardFdo; -extern PDEVICE_OBJECT MouseFdo; - -/* fdo.c */ -NTSTATUS -UsbMpFdoCreate( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpFdoClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpFdoCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpFdoPnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpFdoDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -/* misc.c */ -NTSTATUS -ForwardIrpAndWait( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -ForwardIrpAndForget( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpDuplicateUnicodeString( - OUT PUNICODE_STRING Destination, - IN PUNICODE_STRING Source, - IN POOL_TYPE PoolType); - -NTSTATUS -UsbMpInitMultiSzString( - OUT PUNICODE_STRING Destination, - ... /* list of PCSZ */); - -/* pdo.c */ -NTSTATUS -UsbMpPdoCreate( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpPdoClose( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpPdoCleanup( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpPdoPnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpInternalPdoDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -UsbMpPdoInternalDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -/* - * Needed by this object library, but not - * present in any file of this library - */ -VOID NTAPI -DriverUnload(PDRIVER_OBJECT DriverObject); - -NTSTATUS -InitLinuxWrapper(PDEVICE_OBJECT DeviceObject); - -extern struct pci_device_id* pci_ids; - -#endif diff --git a/reactos/drivers/usb/miniport/common/usbcommon_types.h b/reactos/drivers/usb/miniport/common/usbcommon_types.h deleted file mode 100644 index b3ab535edf5..00000000000 --- a/reactos/drivers/usb/miniport/common/usbcommon_types.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _USBMP_COMMON_TYPES_H_ -#define _USBMP_COMMON_TYPES_H_ - -typedef struct _USBMP_DRIVER_EXTENSION -{ - //OHCI_HW_INITIALIZATION_DATA InitializationData; - //PVOID HwContext; - //UNICODE_STRING RegistryPath; - -} USBMP_DRIVER_EXTENSION, *PUSBMP_DRIVER_EXTENSION; - -typedef struct _USBMP_DEVICE_EXTENSTION -{ - ULONG DeviceNumber; - PDEVICE_OBJECT PhysicalDeviceObject; - PDEVICE_OBJECT FunctionalDeviceObject; - PDEVICE_OBJECT NextDeviceObject; - //UNICODE_STRING RegistryPath; - UNICODE_STRING HcdInterfaceName; - //KSPIN_LOCK InterruptSpinLock; - PCM_RESOURCE_LIST AllocatedResources; - - /* Interrupt-related info */ - PKINTERRUPT InterruptObject; - ULONG InterruptVector; - ULONG InterruptLevel; - KINTERRUPT_MODE InterruptMode; - BOOLEAN InterruptShare; - KAFFINITY InterruptAffinity; - - PHYSICAL_ADDRESS BaseAddress; - ULONG BaseAddrLength; - ULONG Flags; - //ULONG AdapterInterfaceType; - ULONG SystemIoBusNumber; - ULONG SystemIoSlotNumber; - //LIST_ENTRY AddressMappingListHead; - - // DMA stuff, and buffers - PDMA_ADAPTER pDmaAdapter; - //PVOID MapRegisterBase; - ULONG mapRegisterCount; -#ifdef USB_DMA_SINGLE_SUPPORT - //PHYSICAL_ADDRESS Buffer; - //PVOID VirtualBuffer; - //ULONG BufferSize; - - // Mdl used for single DMA transfers - //PMDL Mdl; -#endif - - //KDPC DpcObject; - PUSBMP_DRIVER_EXTENSION DriverExtension; - ULONG DeviceOpened; - //KMUTEX DeviceLock; - //CHAR MiniPortDeviceExtension[1]; - BOOLEAN IsFDO; - struct pci_dev * pdev; - PDEVICE_OBJECT RootHubPdo; -} USBMP_DEVICE_EXTENSION, *PUSBMP_DEVICE_EXTENSION; - -#endif diff --git a/reactos/drivers/usb/miniport/directory.rbuild b/reactos/drivers/usb/miniport/directory.rbuild deleted file mode 100644 index 360613a367a..00000000000 --- a/reactos/drivers/usb/miniport/directory.rbuild +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/reactos/drivers/usb/miniport/linux/asm/bitops.h b/reactos/drivers/usb/miniport/linux/asm/bitops.h deleted file mode 100644 index bb194fa25f2..00000000000 --- a/reactos/drivers/usb/miniport/linux/asm/bitops.h +++ /dev/null @@ -1,384 +0,0 @@ -#ifndef _I386_BITOPS_H -#define _I386_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - */ - -//#include - -/* - * These have to be done with inline assembly: that way the bit-setting - * is guaranteed to be atomic. All bit operations return 0 if the bit - * was cleared before the operation and != 0 if it was not. - * - * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). - */ - -#ifdef CONFIG_SMP -#define LOCK_PREFIX "lock ; " -#else -#define LOCK_PREFIX "" -#endif - -#define ADDR (*(volatile long *) addr) - -/** - * set_bit - Atomically set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * This function is atomic and may not be reordered. See __set_bit() - * if you do not require the atomic guarantees. - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. - */ -static __inline__ void set_bit(int nr, volatile void * addr) -{ - __asm__ __volatile__( LOCK_PREFIX - "btsl %1,%0" - :"=m" (ADDR) - :"Ir" (nr)); -} - -/** - * __set_bit - Set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Unlike set_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ -static __inline__ void __set_bit(int nr, volatile void * addr) -{ - __asm__( - "btsl %1,%0" - :"=m" (ADDR) - :"Ir" (nr)); -} - -/** - * clear_bit - Clears a bit in memory - * @nr: Bit to clear - * @addr: Address to start counting from - * - * clear_bit() is atomic and may not be reordered. However, it does - * not contain a memory barrier, so if it is used for locking purposes, - * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() - * in order to ensure changes are visible on other processors. - */ -static __inline__ void clear_bit(int nr, volatile void * addr) -{ - __asm__ __volatile__( LOCK_PREFIX - "btrl %1,%0" - :"=m" (ADDR) - :"Ir" (nr)); -} -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() - -/** - * __change_bit - Toggle a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Unlike change_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ -static __inline__ void __change_bit(int nr, volatile void * addr) -{ - __asm__ __volatile__( - "btcl %1,%0" - :"=m" (ADDR) - :"Ir" (nr)); -} - -/** - * change_bit - Toggle a bit in memory - * @nr: Bit to clear - * @addr: Address to start counting from - * - * change_bit() is atomic and may not be reordered. - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. - */ -static __inline__ void change_bit(int nr, volatile void * addr) -{ - __asm__ __volatile__( LOCK_PREFIX - "btcl %1,%0" - :"=m" (ADDR) - :"Ir" (nr)); -} - -/** - * test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static __inline__ int test_and_set_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__ __volatile__( LOCK_PREFIX - "btsl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"Ir" (nr) : "memory"); - return oldbit; -} - -/** - * __test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is non-atomic and can be reordered. - * If two examples of this operation race, one can appear to succeed - * but actually fail. You must protect multiple accesses with a lock. - */ -static __inline__ int __test_and_set_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__( - "btsl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"Ir" (nr)); - return oldbit; -} - -/** - * test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static __inline__ int test_and_clear_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__ __volatile__( LOCK_PREFIX - "btrl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"Ir" (nr) : "memory"); - return oldbit; -} - -/** - * __test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is non-atomic and can be reordered. - * If two examples of this operation race, one can appear to succeed - * but actually fail. You must protect multiple accesses with a lock. - */ -static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__( - "btrl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"Ir" (nr)); - return oldbit; -} - -/* WARNING: non atomic and it can be reordered! */ -static __inline__ int __test_and_change_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__ __volatile__( - "btcl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"Ir" (nr) : "memory"); - return oldbit; -} - -/** - * test_and_change_bit - Change a bit and return its new value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static __inline__ int test_and_change_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__ __volatile__( LOCK_PREFIX - "btcl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (ADDR) - :"Ir" (nr) : "memory"); - return oldbit; -} - -#if 0 /* Fool kernel-doc since it doesn't do macros yet */ -/** - * test_bit - Determine whether a bit is set - * @nr: bit number to test - * @addr: Address to start counting from - */ -static int test_bit(int nr, const volatile void * addr); -#endif - -static __inline__ int constant_test_bit(int nr, const volatile void * addr) -{ - return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; -} - -static __inline__ int variable_test_bit(int nr, volatile void * addr) -{ - int oldbit; - - __asm__ __volatile__( - "btl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit) - :"m" (ADDR),"Ir" (nr)); - return oldbit; -} - -#define test_bit(nr,addr) \ -(__builtin_constant_p(nr) ? \ - constant_test_bit((nr),(addr)) : \ - variable_test_bit((nr),(addr))) - -/** - * find_first_zero_bit - find the first zero bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit-number of the first zero bit, not the number of the byte - * containing a bit. - */ -static __inline__ int find_first_zero_bit(void * addr, unsigned size) -{ - int d0, d1, d2; - int res; - - if (!size) - return 0; - /* This looks at memory. Mark it volatile to tell gcc not to move it around */ - __asm__ __volatile__( - "movl $-1,%%eax\n\t" - "xorl %%edx,%%edx\n\t" - "repe; scasl\n\t" - "je 1f\n\t" - "xorl -4(%%edi),%%eax\n\t" - "subl $4,%%edi\n\t" - "bsfl %%eax,%%edx\n" - "1:\tsubl %%ebx,%%edi\n\t" - "shll $3,%%edi\n\t" - "addl %%edi,%%edx" - :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) - :"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); - return res; -} - -/** - * find_next_zero_bit - find the first zero bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -static __inline__ int find_next_zero_bit (void * addr, int size, int offset) -{ - unsigned long * p = ((unsigned long *) addr) + (offset >> 5); - int set = 0, bit = offset & 31, res; - - if (bit) { - /* - * Look for zero in first byte - */ - __asm__("bsfl %1,%0\n\t" - "jne 1f\n\t" - "movl $32, %0\n" - "1:" - : "=r" (set) - : "r" (~(*p >> bit))); - if (set < (32 - bit)) - return set + offset; - set = 32 - bit; - p++; - } - /* - * No zero yet, search remaining full bytes for a zero - */ - res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); - return (offset + set + res); -} - -/** - * ffz - find first zero in word. - * @word: The word to search - * - * Undefined if no zero exists, so code should check against ~0UL first. - */ -static __inline__ unsigned long ffz(unsigned long word) -{ - __asm__("bsfl %1,%0" - :"=r" (word) - :"r" (~word)); - return word; -} - -#ifdef __KERNEL__ - -/** - * ffs - find first bit set - * @x: the word to search - * - * This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ -static __inline__ int ffs(int x) -{ - int r; - - __asm__("bsfl %1,%0\n\t" - "jnz 1f\n\t" - "movl $-1,%0\n" - "1:" : "=r" (r) : "rm" (x)); - return r+1; -} - -/** - * hweightN - returns the hamming weight of a N-bit word - * @x: the word to weigh - * - * The Hamming Weight of a number is the total number of bits set in it. - */ - -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -#endif /* __KERNEL__ */ - -#ifdef __KERNEL__ - -#define ext2_set_bit __test_and_set_bit -#define ext2_clear_bit __test_and_clear_bit -#define ext2_test_bit test_bit -#define ext2_find_first_zero_bit find_first_zero_bit -#define ext2_find_next_zero_bit find_next_zero_bit - -/* Bitmap functions for the minix filesystem. */ -#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr) -#define minix_set_bit(nr,addr) __set_bit(nr,addr) -#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr) -#define minix_test_bit(nr,addr) test_bit(nr,addr) -#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) - -#endif /* __KERNEL__ */ - -#endif /* _I386_BITOPS_H */ diff --git a/reactos/drivers/usb/miniport/linux/bitops.h b/reactos/drivers/usb/miniport/linux/bitops.h deleted file mode 100644 index ac05ed65c53..00000000000 --- a/reactos/drivers/usb/miniport/linux/bitops.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _LINUX_BITOPS_H -#define _LINUX_BITOPS_H - - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ - -static inline int generic_ffs(int x) -{ - int r = 1; - - if (!x) - return 0; - if (!(x & 0xffff)) { - x >>= 16; - r += 16; - } - if (!(x & 0xff)) { - x >>= 8; - r += 8; - } - if (!(x & 0xf)) { - x >>= 4; - r += 4; - } - if (!(x & 3)) { - x >>= 2; - r += 2; - } - if (!(x & 1)) { - x >>= 1; - r += 1; - } - return r; -} - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ - -static inline unsigned int generic_hweight32(unsigned int w) -{ - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); -} - -static inline unsigned int generic_hweight16(unsigned int w) -{ - unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555); - res = (res & 0x3333) + ((res >> 2) & 0x3333); - res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); - return (res & 0x00FF) + ((res >> 8) & 0x00FF); -} - -static inline unsigned int generic_hweight8(unsigned int w) -{ - unsigned int res = (w & 0x55) + ((w >> 1) & 0x55); - res = (res & 0x33) + ((res >> 2) & 0x33); - return (res & 0x0F) + ((res >> 4) & 0x0F); -} - -#include "asm/bitops.h" - - -#endif diff --git a/reactos/drivers/usb/miniport/linux/boot.h b/reactos/drivers/usb/miniport/linux/boot.h deleted file mode 100644 index db64976aa76..00000000000 --- a/reactos/drivers/usb/miniport/linux/boot.h +++ /dev/null @@ -1,337 +0,0 @@ -#ifndef _Boot_H_ -#define _Boot_H_ - -#include "config.h" - -/*************************************************************************** - Includes used by XBox boot code - ***************************************************************************/ -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -///////////////////////////////// -// configuration - -#include "consts.h" -#include "stdint.h" -#include "cromwell_types.h" - - -unsigned int cromwell_config; -unsigned int cromwell_retryload; -unsigned int cromwell_loadbank; -unsigned int cromwell_Biostype; - -unsigned int xbox_ram; - -#define XROMWELL 0 -#define CROMWELL 1 - -#define ICON_WIDTH 64 -#define ICON_HEIGHT 64 -/* -static double min (double a, double b) -{ - if (a < b) return a; else return b; -} - -static inline double max (double a, double b) -{ - if (a > b) return a; else return b; -} -*/ -//#include "iso_fs.h" -//#include "BootVideo.h" - -//#define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } } - -#if 0 -extern volatile CURRENT_VIDEO_MODE_DETAILS vmode; -unsigned int video_encoder; - -volatile u32 VIDEO_CURSOR_POSX; -volatile u32 VIDEO_CURSOR_POSY; -volatile u32 VIDEO_ATTR; -volatile u32 VIDEO_LUMASCALING; -volatile u32 VIDEO_RSCALING; -volatile u32 VIDEO_BSCALING; -volatile u32 BIOS_TICK_COUNT; -volatile u32 VIDEO_VSYNC_POSITION; -volatile u32 VIDEO_VSYNC_DIR; -volatile u32 DVD_TRAY_STATE; - -u8 VIDEO_AV_MODE ; - -#define DVD_CLOSED 0 -#define DVD_CLOSING 1 -#define DVD_OPEN 2 -#define DVD_OPENING 3 - -///////////////////////////////// -// Superfunky i386 internal structures - -typedef struct gdt_t { - unsigned short m_wSize __attribute__ ((packed)); - unsigned long m_dwBase32 __attribute__ ((packed)); - unsigned short m_wDummy __attribute__ ((packed)); -} ts_descriptor_pointer; - -typedef struct { // inside an 8-byte protected mode interrupt vector - u16 m_wHandlerHighAddressLow16; - u16 m_wSelector; - u16 m_wType; - u16 m_wHandlerLinearAddressHigh16; -} ts_pm_interrupt; - -typedef enum { - EDT_UNKNOWN= 0, - EDT_XBOXFS -} enumDriveType; - -typedef struct tsHarddiskInfo { // this is the retained knowledge about an IDE device after init - unsigned short m_fwPortBase; - unsigned short m_wCountHeads; - unsigned short m_wCountCylinders; - unsigned short m_wCountSectorsPerTrack; - unsigned long m_dwCountSectorsTotal; /* total */ - unsigned char m_bLbaMode; /* am i lba (0x40) or chs (0x00) */ - unsigned char m_szIdentityModelNumber[40]; - unsigned char term_space_1[2]; - unsigned char m_szSerial[20]; - unsigned char term_space_2[2]; - char m_szFirmware[8]; - unsigned char term_space_3[2]; - unsigned char m_fDriveExists; - unsigned char m_fAtapi; // true if a CDROM, etc - enumDriveType m_enumDriveType; - unsigned char m_bCableConductors; // valid for device 0 if present - unsigned short m_wAtaRevisionSupported; - unsigned char s_length; - unsigned char m_length; - unsigned char m_fHasMbr; - unsigned short m_securitySettings; //This contains the contents of the ATA security regs -} tsHarddiskInfo; - -///////////////////////////////// -// LED-flashing codes -// or these together as argument to I2cSetFrontpanelLed - -enum { - I2C_LED_RED0 = 0x80, - I2C_LED_RED1 = 0x40, - I2C_LED_RED2 = 0x20, - I2C_LED_RED3 = 0x10, - I2C_LED_GREEN0 = 0x08, - I2C_LED_GREEN1 = 0x04, - I2C_LED_GREEN2 = 0x02, - I2C_LED_GREEN3 = 0x01 -}; - -/////////////////////////////// -/* BIOS-wide error codes all have b31 set */ - -enum { - ERR_SUCCESS = 0, // completed without error - - ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time - ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error - - ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test -}; - -///////////////////////////////// -// some Boot API prototypes - -//////// BootPerformPicChallengeResponseAction.c - -/* ---------------------------- IO primitives ----------------------------------------------------------- -*/ - -static __inline void IoOutputByte(u16 wAds, u8 bValue) { -// __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) ); - __asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds)); -} - -static __inline void IoOutputWord(u16 wAds, u16 wValue) { -// __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) ); - __asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds)); - } - -static __inline void IoOutputDword(u16 wAds, u32 dwValue) { -// __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) ); - __asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds)); -} - - -static __inline u8 IoInputByte(u16 wAds) { - unsigned char _v; - - __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds)); - return _v; -} - -static __inline u16 IoInputWord(u16 wAds) { - u16 _v; - - __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds)); - return _v; -} - -static __inline u32 IoInputDword(u16 wAds) { - u32 _v; - - __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds)); - return _v; -} - -#define rdmsr(msr,val1,val2) \ - __asm__ __volatile__("rdmsr" \ - : "=a" (val1), "=d" (val2) \ - : "c" (msr)) - -#define wrmsr(msr,val1,val2) \ - __asm__ __volatile__("wrmsr" \ - : /* no outputs */ \ - : "c" (msr), "a" (val1), "d" (val2)) - - -void BootPciInterruptEnable(void); - - // boot process -int BootPerformPicChallengeResponseAction(void); - // LED control (see associated enum above) -int I2cSetFrontpanelLed(u8 b); - -#define bprintf(...) - -#if PRINT_TRACE -#define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__); -#else -#define TRACE -#endif - -typedef struct _LIST_ENTRY { - struct _LIST_ENTRY *m_plistentryNext; - struct _LIST_ENTRY *m_plistentryPrevious; -} LIST_ENTRY; - -void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew); -void ListEntryRemove(LIST_ENTRY *plistentryCurrent); - -////////// BootPerformXCodeActions.c - -int BootPerformXCodeActions(void); - -#include "BootEEPROM.h" -#include "BootParser.h" - -////////// BootStartBios.c - -void StartBios(CONFIGENTRY *config,int nActivePartition, int nFATXPresent,int bootfrom); -int BootMenu(CONFIGENTRY *config,int nDrive,int nActivePartition, int nFATXPresent); - -////////// BootResetActions.c -void ClearIDT (void); -void BootResetAction(void); -void BootCpuCache(bool fEnable) ; -int printk(const char *szFormat, ...); -void BiosCmosWrite(u8 bAds, u8 bData); -u8 BiosCmosRead(u8 bAds); - - -///////// BootPciPeripheralInitialization.c -void BootPciPeripheralInitialization(void); -void BootAGPBUSInitialization(void); -void BootDetectMemorySize(void); -extern void ReadPCIByte(unsigned int bus, unsigned int dev, unsigned intfunc, unsigned int reg_off, unsigned char *pbyteval); -extern void WritePCIByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval); -extern void ReadPCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int *pdwordval); -extern void WritePCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dwordval); -extern void ReadPCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes); -extern void WritePCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes); - -void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func, - unsigned int reg_off, unsigned char byteval); -u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off); -u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw); -u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off); - -///////// BootPerformPicChallengeResponseAction.c - -int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite); -int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite); -bool I2CGetTemperature(int *, int *); -void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask); - -///////// BootIde.c - -extern tsHarddiskInfo tsaHarddiskInfo[]; // static struct stores data about attached drives -int BootIdeInit(void); -int BootIdeReadSector(int nDriveIndex, void * pbBuffer, unsigned int block, int byte_offset, int n_bytes); -int BootIdeBootSectorHddOrElTorito(int nDriveIndex, u8 * pbaResult); -int BootIdeAtapiAdditionalSenseCode(int nDrive, u8 * pba, int nLengthMaxReturn); -int BootIdeSetTransferMode(int nIndexDrive, int nMode); -int BootIdeWaitNotBusy(unsigned uIoBase); -bool BootIdeAtapiReportFriendlyError(int nDriveIndex, char * szErrorReturn, int nMaxLengthError); -void BootIdeAtapiPrintkFriendlyError(int nDriveIndex); - -///////// BootUSB.c - -void BootStopUSB(void); -void BootStartUSB(void); -void USBGetEvents(void); - -#include "xpad.h" - -extern struct xpad_data XPAD_current[4]; -extern struct xpad_data XPAD_last[4]; - -extern void wait_ms(u32 ticks); -extern void wait_us(u32 ticks); -extern void wait_smalldelay(void); - - -void * memcpy(void *dest, const void *src, size_t size); -void * memset(void *dest, int data, size_t size); -int memcmp(const void *buffer1, const void *buffer2, size_t num); -int _strncmp(const char *sz1, const char *sz2, int nMax); -char * strcpy(char *sz, const char *szc); -char * _strncpy (char * dest, const char * src, size_t n); -void chrreplace(char *string, char search, char ch); - -#define printf printk -#define sleep wait_ms -int tolower(int ch); -int isspace (int c); - -void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength); -void * malloc(size_t size); -void free(void *); - -extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde; -extern volatile bool fSeenPowerdown; -typedef enum { - ETS_OPEN_OR_OPENING=0, - ETS_CLOSING, - ETS_CLOSED -} TRAY_STATE; -extern volatile TRAY_STATE traystate; - - -extern void BootInterruptsWriteIdt(void); -#endif -int copy_swap_trim(unsigned char *dst, unsigned char *src, int len); -void HMAC_SHA1( unsigned char *result, - unsigned char *key, int key_length, - unsigned char *text1, int text1_length, - unsigned char *text2, int text2_length ); - -char *strrchr0(char *string, char ch); - -#endif // _Boot_H_ diff --git a/reactos/drivers/usb/miniport/linux/consts.h b/reactos/drivers/usb/miniport/linux/consts.h deleted file mode 100644 index d3fb6cebae0..00000000000 --- a/reactos/drivers/usb/miniport/linux/consts.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _Consts_H_ -#define _Consts_H_ - -/* - * - * includes for startup code in a form usable by the .S files - * - */ - - /*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#define PCI_CFG_ADDR 0x0CF8 -#define PCI_CFG_DATA 0x0CFC - - -#define I2C_IO_BASE 0xc000 - -#define BUS_0 0 -#define BUS_1 1 - -#define DEV_0 0 -#define DEV_1 1 -#define DEV_2 2 -#define DEV_3 3 -#define DEV_4 4 -#define DEV_5 5 -#define DEV_6 6 -#define DEV_7 7 -#define DEV_8 8 -#define DEV_9 9 -#define DEV_a 0xa -#define DEV_b 0xb -#define DEV_c 0xc -#define DEV_d 0xd -#define DEV_e 0xe -#define DEV_f 0xf -#define DEV_10 0x10 -#define DEV_11 0x11 -#define DEV_12 0x12 -#define DEV_13 0x13 -#define DEV_14 0x14 -#define DEV_15 0x15 -#define DEV_16 0x16 -#define DEV_17 0x17 -#define DEV_18 0x18 -#define DEV_19 0x19 -#define DEV_1a 0x1a -#define DEV_1b 0x1b -#define DEV_1c 0x1c -#define DEV_1d 0x1d -#define DEV_1e 0x1e -#define DEV_1f 0x1f - -#define FUNC_0 0 -/* -#define boot_post_macro(value) \ - movb $(value), %al ;\ - outb %al, $0x80 -*/ - -#endif // _Consts_H_ - - diff --git a/reactos/drivers/usb/miniport/linux/cromwell_types.h b/reactos/drivers/usb/miniport/linux/cromwell_types.h deleted file mode 100644 index cccc05c681b..00000000000 --- a/reactos/drivers/usb/miniport/linux/cromwell_types.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef cromwell_types_h -#define cromwell_types_h - -///////////////////////////////// -// some typedefs to make for easy sizing - -//typedef unsigned long ULONG; -typedef unsigned int u32; -typedef unsigned short u16; -typedef unsigned char u8; -#ifndef bool_already_defined_ - typedef int bool; -#endif -typedef unsigned long RGBA; // LSB=R -> MSB = A -//typedef long long __int64; - -#define guint int -#define guint8 unsigned char - -#define true 1 -#define false 0 - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#endif /* #ifndef cromwell_types_h */ diff --git a/reactos/drivers/usb/miniport/linux/errno.h b/reactos/drivers/usb/miniport/linux/errno.h deleted file mode 100644 index 1b667890877..00000000000 --- a/reactos/drivers/usb/miniport/linux/errno.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef _I386_ERRNO_H -#define _I386_ERRNO_H - -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Argument list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define EDEADLK 35 /* Resource deadlock would occur */ -#define ENAMETOOLONG 36 /* File name too long */ -#define ENOLCK 37 /* No record locks available */ -#define ENOSYS 38 /* Function not implemented */ -#define ENOTEMPTY 39 /* Directory not empty */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define EILSEQ 84 /* Illegal byte sequence */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ - -#endif diff --git a/reactos/drivers/usb/miniport/linux/linux_wrapper.h b/reactos/drivers/usb/miniport/linux/linux_wrapper.h deleted file mode 100644 index aa5ff204fd5..00000000000 --- a/reactos/drivers/usb/miniport/linux/linux_wrapper.h +++ /dev/null @@ -1,856 +0,0 @@ -/* - * linux-wrapper.h - * - * Hard coded Linux kernel replacements for x86 - * - * (c) 2003 Georg Acher (georg@acher.org) - * - * Emulation of: - * typedefs - * structs - * macros - * - * All structs and prototypes are based on kernel source 2.5.72 - * - * Modified by Aleksey Bragin (aleksey@reactos.com) for ReactOS needs - * - * - * #include - */ - -/*------------------------------------------------------------------------*/ -/* Typedefs */ -/*------------------------------------------------------------------------*/ -#include "cromwell_types.h" - -typedef unsigned int __u32; -//typedef __u32 u32; -typedef unsigned short __u16; -//typedef __u16 u16; -typedef unsigned char __u8; -//typedef __u8 u8; - -typedef short s16; - -typedef u32 dma_addr_t; - -typedef struct -{ - KSPIN_LOCK SpinLock; - KIRQL OldIrql; -} spinlock_t; - -typedef int atomic_t; -#ifndef STANDALONE -#ifndef _MODE_T_ -#define _MODE_T_ -typedef int mode_t; -#endif -#ifndef _PID_T_ -#define _PID_T_ -typedef int pid_t; -#endif -#ifndef _SSIZE_T_ -#define _SSIZE_T_ -typedef int ssize_t; -#endif - -#endif -typedef int irqreturn_t; -typedef unsigned long kernel_ulong_t; - -typedef int wait_queue_head_t; -/*------------------------------------------------------------------------*/ -/* Stuff from xbox/linux environment */ -/*------------------------------------------------------------------------*/ - -#include "list.h" - -#ifndef STANDALONE -#ifdef MODULE -typedef int size_t; -#define NULL ((void*)0) -extern void * memset(void *,int,unsigned int); -extern void * memcpy(void *,const void *,unsigned int); -#if 0 -extern char * strcpy(char *,const char *); -#else -static inline char * strcpy(char * dest,const char *src) -{ -int d0, d1, d2; -__asm__ __volatile__( - "1:\tlodsb\n\t" - "stosb\n\t" - "testb %%al,%%al\n\t" - "jne 1b" - : "=&S" (d0), "=&D" (d1), "=&a" (d2) - :"0" (src),"1" (dest) : "memory"); -return dest; -} -#endif -extern size_t strlen(const char *); - -extern int memcmp(const void *,const void *,unsigned int); - -#else -#include "boot.h" -#include "config.h" -#endif -#else -#include -#include -#include -#include "consts.h" -#include -#endif - -/*------------------------------------------------------------------------*/ -/* General structs */ -/*------------------------------------------------------------------------*/ - -struct timer_list { - void (*function)(unsigned long); - unsigned long data; - int expires; - struct list_head timer_list; -}; - -struct work_struct { - void (*func)(void *); -}; -struct device { - char name[128]; - struct bus_type *bus; - int dma_mask; - char bus_id[16]; - struct device_driver* driver; - void *driver_data; - struct device *parent; - struct list_head driver_list; - void (*release)(struct device * dev); - - PDEVICE_OBJECT dev_ext; // ReactOS-specific: pointer to windows device object -}; -struct class_device{int a;}; -struct semaphore{int a;}; - -struct device_driver{ - char *name; - struct bus_type *bus; - int (*probe) (struct device * dev); - int (*remove) (struct device * dev); - struct list_head devices; -}; - -struct bus_type { - char * name; - int (*match)(struct device * dev, struct device_driver * drv); - struct device * (*add) (struct device * parent, char * bus_id); - int (*hotplug) (struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); -}; - -struct dummy_process -{ - int flags; -}; - -struct pt_regs -{ - int a; -}; -struct completion { - unsigned int done; - KEVENT wait; - //wait_queue_head_t wait; -}; - -// windows lookaside list head -typedef void* kmem_cache_t; - -struct dma_pool -{ - int dummy; -}; - -/* These definitions mirror those in pci.h, so they can be used - * interchangeably with their PCI_ counterparts */ -enum dma_data_direction { - DMA_BIDIRECTIONAL = 0, - DMA_TO_DEVICE = 1, - DMA_FROM_DEVICE = 2, - DMA_NONE = 3, -}; - -/* compatibility */ -#define PCI_DMA_TODEVICE DMA_TO_DEVICE -#define PCI_DMA_FROMDEVICE DMA_FROM_DEVICE - -/* from mod_devicetable.h */ -struct usb_device_id { - /* which fields to match against? */ - __u16 match_flags; - - /* Used for product specific matches; range is inclusive */ - __u16 idVendor; - __u16 idProduct; - __u16 bcdDevice_lo; - __u16 bcdDevice_hi; - - /* Used for device class matches */ - __u8 bDeviceClass; - __u8 bDeviceSubClass; - __u8 bDeviceProtocol; - - /* Used for interface class matches */ - __u8 bInterfaceClass; - __u8 bInterfaceSubClass; - __u8 bInterfaceProtocol; - - /* not matched against */ - kernel_ulong_t driver_info; -}; - -/* Some useful macros to use to create struct usb_device_id */ -#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 -#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 -#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 -#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 -#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 -#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 -#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 -#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 -#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 -#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 - -/*------------------------------------------------------------------------*/ -/* imported functions from top-level */ -/*------------------------------------------------------------------------*/ - -//void zxprintf(char* fmt, ...); -//void zxsprintf(char *buffer, char* fmt, ...); -//int zxsnprintf(char *buffer, size_t s, char* fmt, ...); - -/*------------------------------------------------------------------------*/ -/* PCI structs (taken from linux/pci.h et al., but slightly modified) */ -/*------------------------------------------------------------------------*/ - -struct pci_dev { - int vendor; - int device; - struct pci_bus *bus; - int irq; - char *slot_name; - struct device dev; - int base[4]; - int flags[4]; - void * data; - void * dev_ext; // link to Windows DeviceExtension -}; - -struct pci_bus { - unsigned char number; -}; - -struct pci_device_id { - __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ - __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ - __u32 class, class_mask; /* (class,subclass,prog-if) triplet */ - kernel_ulong_t driver_data; /* Data private to the driver */ -}; - -struct pci_driver { - struct list_head node; - char *name; - const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ - int STDCALL (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ - void STDCALL (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ - int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */ - int (*suspend) (struct pci_dev *dev, u32 state); /* Device suspended */ - int (*resume) (struct pci_dev *dev); /* Device woken up */ - int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */ -}; - -struct scatterlist -{ - int page; - int offset; - int length; -}; - -struct usbdevfs_hub_portinfo -{ - int nports; - int port[8]; -}; - -/*------------------------------------------------------------------------*/ -/* constant defines */ -/*------------------------------------------------------------------------*/ - -#define TASK_UNINTERRUPTIBLE 0 -#define HZ 100 /* Don't rely on that... */ -#define KERN_DEBUG "DBG: " -#define KERN_ERR "ERR: " -#define KERN_WARNING "WRN: " -#define KERN_INFO "INF: " -#define GFP_KERNEL 0 -#define GFP_ATOMIC 0x20 -#define GFP_NOIO 0 -#define SLAB_ATOMIC 0 -#define PCI_ANY_ID (~0) -#define SIGKILL 9 -#define THIS_MODULE 0 -//#define PAGE_SIZE 4096 - - -#define CLONE_FS 0 -#define CLONE_FILES 0 -#define CLONE_SIGHAND 0 -#define PF_FREEZE 0 -#define PF_IOTHREAD 0 - - -#define USBDEVFS_HUB_PORTINFO 1234 -#define SA_SHIRQ 0 - -#undef PCI_COMMAND -#define PCI_COMMAND 0 -#undef PCI_COMMAND_MASTER -#define PCI_COMMAND_MASTER 0 -/*------------------------------------------------------------------------*/ -/* Module/export macros */ -/*------------------------------------------------------------------------*/ - -#define MODULE_AUTHOR(a) -#define MODULE_DESCRIPTION(a) -#define MODULE_LICENSE(a) -#define MODULE_DEVICE_TABLE(type,name) void* module_table_##name=&name -#define MODULE_PARM(a,b) -#define MODULE_PARM_DESC(a,b) - -#define __devinit -#define __exit -#define __init -#define __devinitdata -#define module_init(x) static void module_init_##x(void){ x();} -#define module_exit(x) void module_exit_##x(void){ x();} -#define EXPORT_SYMBOL_GPL(x) -#define EXPORT_SYMBOL(x) - -#define __setup(x,y) int setup_##y=(int)y -#define subsys_initcall(x) void subsys_##x(void){x();} - -/*------------------------------------------------------------------------*/ -/* Access macros */ -/*------------------------------------------------------------------------*/ - -#define dev_get_drvdata(a) (a)->driver_data -#define dev_set_drvdata(a,b) (a)->driver_data=(b) - -#define __io_virt(x) ((void *)(x)) -#define readl(addr) (*(volatile unsigned int *) __io_virt(addr)) -#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b)) -#define likely(x) (x) -#define unlikely(x) (x) -#define prefetch(x) 1 - -#define inw(x) READ_PORT_USHORT((PUSHORT)(x)) -#define outw(x,p) WRITE_PORT_USHORT((PUSHORT)(p),(x)) -#define outl(x,p) WRITE_PORT_ULONG((PULONG)(p),(x)) - -/* The kernel macro for list_for_each_entry makes nonsense (have no clue - * why, this is just the same definition...) */ - -#undef list_for_each_entry -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/*------------------------------------------------------------------------*/ -/* function wrapper macros */ -/*------------------------------------------------------------------------*/ -#define kmalloc(x,y) ExAllocatePool(PagedPool,x) -#define kfree(x) ExFreePool(x) - -//#define sprintf(a,b,format, arg...) zxsprintf((a),(b),format, ## arg) -//#define snprintf(a,b,format, arg...) zxsnprintf((a),(b),format, ##arg) -//#define printk(format, arg...) zxprintf(format, ## arg) -#define snprintf(a,b,format, arg...) _snprintf((a),(b),format, ##arg) -#define printk(format, arg...) DPRINT1(format, ## arg) -#define BUG(...) do {} while(0) - -/* Locks & friends */ - -#define DECLARE_MUTEX(x) struct semaphore x -#define init_MUTEX(x) - -#define SPIN_LOCK_UNLOCKED 0 - -#define spin_lock_init(a) my_spin_lock_init(a) -void my_spin_lock_init(spinlock_t *sl); - -#define spin_lock(a) my_spin_lock(a) -void my_spin_lock(spinlock_t *sl); - -#define spin_unlock(a) my_spin_unlock(a) -void my_spin_unlock(spinlock_t *sl); - -#define spin_lock_irqsave(a,b) b=0, my_spin_lock_irqsave(a,b) -void my_spin_lock_irqsave(spinlock_t *sl, int flags); -#define spin_unlock_irqrestore(a,b) my_spin_unlock(a) - -#if 0 -#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory") -#define local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc") -#else -#define local_irq_save(x) do {} while(0) -#define local_irq_restore(x) do {} while(0) -#endif - -#define atomic_inc(x) *(x)+=1 -#define atomic_dec(x) *(x)-=1 -#define atomic_dec_and_test(x) (*(x)-=1,(*(x))==0) -#define atomic_set(x,a) *(x)=a -#define atomic_read(x) *(x) -#define ATOMIC_INIT(x) (x) - -#define down(x) do {} while(0) -#define up(x) do {} while(0) -#define down_trylock(a) 0 - -#define down_read(a) do {} while(0) -#define up_read(a) do {} while(0) - -#define DECLARE_WAIT_QUEUE_HEAD(x) KEVENT x - -#define DECLARE_COMPLETION(x) struct completion x - -/* driver */ - -#define driver_unregister(a) do {} while(0) -#define put_device(a) do {} while(0) - - -/* PCI */ -#define MAX_POOL_PAGES 2 -#define BITS_PER_LONG 32 - -struct pci_page -{ - PHYSICAL_ADDRESS dmaAddress; - PVOID virtualAddress; - - unsigned long bitmap[128]; // 128 == 32bits*4096 blocks -}; - -struct pci_pool -{ - char name[32]; - size_t size; - size_t allocation; - size_t blocks_per_page; - struct pci_dev *pdev; - - // internal stuff - int pages_allocated; - int blocks_allocated; - - struct pci_page pages[MAX_POOL_PAGES]; -}; - -#define to_pci_dev(n) container_of(n, struct pci_dev, dev) - -#define pci_pool_create(a,b,c,d,e) my_pci_pool_create(a,b,c,d,e) -struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, size_t size, size_t align, size_t allocation); - -#define pci_pool_alloc(a,b,c) my_pci_pool_alloc(a,b,c) -void *my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_handle); - -#define pci_pool_free(a,b,c) my_pci_pool_free(a,b,c) -void my_pci_pool_free(struct pci_pool * pool, void * vaddr, dma_addr_t dma); - -#define pci_alloc_consistent(a,b,c) my_pci_alloc_consistent(a,b,c) -void *my_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle); - -#define pci_free_consistent(a,b,c,d) kfree(c) -#define pci_pool_destroy(a) my_pci_pool_destroy(a) -void my_pci_pool_destroy (struct pci_pool * pool); - -#define pci_module_init(x) my_pci_module_init(x) -int my_pci_module_init(struct pci_driver *x); - -#define pci_unregister_driver(a) do {} while(0) - -#define pci_write_config_word(a,b,c) my_pci_write_config_word(a,b,c) - -#define bus_register(a) do {} while(0) -#define bus_unregister(a) do {} while(0) - -/* DMA */ -//#define dma_pool_alloc(a,b,c) my_dma_pool_alloc((a),(b),(c)) -#define dma_pool_alloc(a,b,c) pci_pool_alloc(a,b,c) -#define dma_pool_create(a,b,c,d,e) pci_pool_create(a,b,c,d,e) -#define dma_pool_free(a,b,c) pci_pool_free(a,b,c) -#define dma_pool_destroy(a) pci_pool_destroy(a) - -//#define dma_alloc_coherent(a,b,c,d) NULL -//#define dma_free_coherent(a,b,c,d) do {} while(0) -#define dma_map_single(a,b,c,d) my_dma_map_single(a,b,c,d) -dma_addr_t my_dma_map_single(struct device *hwdev, void *ptr, size_t size, enum dma_data_direction direction); - -#define dma_unmap_single(a,b,c,d) my_dma_unmap_single(a,b,c,d) -void my_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction); - -#define pci_unmap_single(a,b,c,d) my_pci_unmap_single(a,b,c,d) -void my_pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction); - -#define dma_sync_single(a,b,c,d) my_dma_sync_single(a,b,c,d) -void my_dma_sync_single(struct device *hwdev, dma_addr_t dma_handle, size_t size, int direction); - -#define dma_sync_sg(a,b,c,d) my_dma_sync_sg(a,b,c,d) -void my_dma_sync_sg(struct device *hwdev, struct scatterlist *sg, int nelems, int direction); - -#define dma_map_sg(a,b,c,d) my_dma_map_sg(a,b,c,d) -int my_dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction); - -#define dma_unmap_sg(a,b,c,d) my_dma_unmap_sg(a,b,c,d) -void my_dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction); - -#define usb_create_driverfs_dev_files(a) do {} while(0) -#define usb_create_driverfs_intf_files(a) do {} while(0) -#define sg_dma_address(x) ((u32)((x)->page*4096 + (x)->offset)) -#define sg_dma_len(x) ((x)->length) - -#define page_address(x) ((void*)(x/4096)) - -#define PCI_ROM_RESOURCE 1 -#define IORESOURCE_IO CM_RESOURCE_PORT_IO - -#define DECLARE_WAITQUEUE(a,b) KEVENT a=0 -#define init_waitqueue_head(a) my_init_waitqueue_head(a) -#define add_wait_queue(a,b) do {} while(0) -#define remove_wait_queue(a,b) do {} while(0) -void my_init_waitqueue_head(PKEVENT a); - -VOID KeMemoryBarrier(VOID); - -#define mb() KeMemoryBarrier() -#define wmb() do {} while (0) -#define rmb() do {} while (0) -/*#define wmb() __asm__ __volatile__ ("": : :"memory") -#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")*/ - -#define in_interrupt() 0 - -#define init_completion(x) my_init_completion(x) -void my_init_completion(struct completion *); -#define wait_for_completion(x) my_wait_for_completion(x) -void my_wait_for_completion(struct completion*); - -#define IRQ_NONE 0 -#define IRQ_HANDLED 1 - -#define INIT_WORK(a,b,c) (a)->func=b - -#define set_current_state(a) do {} while(0) - -#define might_sleep() do {} while(0) -#define daemonize(a) do {} while(0) -#define allow_signal(a) do {} while(0) -#define wait_event_interruptible(x,y) do {} while(0) - -#define interruptible_sleep_on(a) my_interruptible_sleep_on(a) -void my_interruptible_sleep_on(PKEVENT evnt); - -#define flush_scheduled_work() do {} while(0) -#define refrigerator(x) do {} while(0) -#define signal_pending(x) 0 // Don't fall through threads! ReactOS implements this correctly -#define complete_and_exit(a,b) return 0 - -//#define kill_proc(a,b,c) 0 -#define kill_proc(a,b,c) my_kill_proc(a, b, c); -int my_kill_proc(int pid, int signal, int unk); - -#define yield() do {} while(0) -#define cpu_relax() do {} while(0) - -#define WARN_ON(a) do {} while(0) - -/*------------------------------------------------------------------------*/ -/* Lookaside lists funcs */ -/*------------------------------------------------------------------------*/ -#define kmem_cache_create(a,b,c,d,e,f) my_kmem_cache_create((a),(b),(c),(d),(e),(f)) -#define kmem_cache_destroy(a) my_kmem_cache_destroy((a)) -#define kmem_cache_alloc(co, flags) my_kmem_cache_alloc((co), (flags)) -#define kmem_cache_free(co, ptr) my_kmem_cache_free((co), (ptr)) - -kmem_cache_t *my_kmem_cache_create(const char *tag, size_t alloc_size, - size_t offset, unsigned long flags, - void *ctor, - void *dtor); - -BOOLEAN my_kmem_cache_destroy(kmem_cache_t *co); -void *my_kmem_cache_alloc(kmem_cache_t *co, int flags); -void my_kmem_cache_free(kmem_cache_t *co, void *ptr); - -/*------------------------------------------------------------------------*/ -/* Kernel macros */ -/*------------------------------------------------------------------------*/ - -#define LINUX_VERSION_CODE 0x020572 -#define UTS_SYSNAME "XBOX" -#define UTS_RELEASE "----" - -/* from linux/kernel.h */ -#define max_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) - -#define min_t(type,x,y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* from linux/stddef.h */ - -#undef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - -/*------------------------------------------------------------------------*/ -/* Conversion macros */ -/*------------------------------------------------------------------------*/ - -#define __constant_cpu_to_le32(x) (x) -#define cpu_to_le16(x) (x) -#define le16_to_cpu(x) (x) -#define cpu_to_le32(x) (x) -#define cpu_to_le32p(x) (*(__u32*)(x)) -#define le32_to_cpup(x) (*(__u32*)(x)) -#define le32_to_cpu(x) ((u32)x) -#define le16_to_cpus(x) do {} while (0) -#define le16_to_cpup(x) (*(__u16*)(x)) -#define cpu_to_le16p(x) (*(__u16*)(x)) - -/*------------------------------------------------------------------------*/ -/* Debug output */ -/*------------------------------------------------------------------------*/ -#ifdef DEBUG_MODE -#define dev_printk(lvl,x,f,arg...) printk(f, ## arg) -#define dev_dbg(x,f,arg...) printk(f, ## arg) -#define dev_info(x,f,arg...) printk(f,## arg) -#define dev_warn(x,f,arg...) printk(f,## arg) -#define dev_err(x,f,arg...) printk(f,## arg) -#define pr_debug(x,f,arg...) printk(f,## arg) -#define usbprintk printk -#endif - -#ifndef DEBUG_MODE -#define dev_printk(lvl,x,f,arg...) do {} while (0) -#define dev_dbg(x,f,arg...) do {} while (0) //printk(f, ## arg) -#define dev_info(x,f,arg...) do {} while (0) -#define dev_warn(x,f,arg...) do {} while (0) -#define dev_err(x,f,arg...) do {} while (0) -#define pr_debug(x,f,arg...) do {} while (0) -#define usbprintk(arg...) dev_printk(0,0,0,## arg) -#endif - - - -#define PCI_DEVFN(a,b) 0 -#define PCI_SLOT(a) 0 - -/** - * PCI_DEVICE_CLASS - macro used to describe a specific pci device class - * @dev_class: the class, subclass, prog-if triple for this device - * @dev_class_mask: the class mask for this device - * - * This macro is used to create a struct pci_device_id that matches a - * specific PCI class. The vendor, device, subvendor, and subdevice - * fields will be set to PCI_ANY_ID. - */ -#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \ - .class = (dev_class), .class_mask = (dev_class_mask), \ - .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID - - -/*------------------------------------------------------------------------*/ -/* Stuff from kernel */ -/*------------------------------------------------------------------------*/ - -#include "errno.h" -#include "bitops.h" -//#include "linux/pci_ids.h" - -/*------------------------------------------------------------------------*/ -/* global variables */ -/*------------------------------------------------------------------------*/ - -#define jiffies my_jiffies -extern int my_jiffies; -#define current my_current -extern struct dummy_process *my_current; - -extern struct list_head interrupt_list; - -/*------------------------------------------------------------------------*/ -/* Function prototypes */ -/*------------------------------------------------------------------------*/ -void STDCALL usb_hcd_pci_remove (struct pci_dev *dev); - -#define my_wait_ms(x) wait_ms(x) // milliseconds - -#define udelay(x) my_udelay(x) // microseconds - -#define my_mdelay(x) wait_ms(1+x/1000); -#define mdelay(x) my_mdelay(x); // milliseconds = udelay(1000*x) - -#define pci_find_slot(a,b) my_pci_find_slot(a,b) -struct pci_dev *my_pci_find_slot(int a,int b); - -/*------------------------------------------------------------------------*/ -/* Timer management */ -/*------------------------------------------------------------------------*/ - -#define MAX_TIMERS 20 -extern struct timer_list *main_timer_list[MAX_TIMERS]; - -static void __inline__ init_timer(struct timer_list* t) -{ - INIT_LIST_HEAD(&t->timer_list); - t->function=NULL; - t->expires=0; -} - -static void __inline__ add_timer(struct timer_list* t) -{ - int n; - for(n=0;nexpires=ex; - add_timer(t); -} - -#define time_after_eq(a,b) \ - (((long)(a) - (long)(b) >= 0)) - -/*------------------------------------------------------------------------*/ -/* Device driver and process related stuff */ -/*------------------------------------------------------------------------*/ - -static int __inline__ usb_major_init(void){return 0;} -static void __inline__ usb_major_cleanup(void){} -static void __inline__ schedule_work(void* p){} - -#define device_initialize(x) my_device_initialize(x) -void my_device_initialize(struct device *dev); - -#define get_device(x) my_get_device(x) -struct device *my_get_device(struct device *dev); - -#define device_add(x) my_device_add(x) -int my_device_add(struct device *dev); - -#define driver_register(x) my_driver_register(x) -int my_driver_register(struct device_driver *driver); - -#define device_unregister(a) my_device_unregister(a) -int my_device_unregister(struct device *dev); - -#define DEVICE_ATTR(a,b,c,d) int xxx_##a -#define device_create_file(a,b) do {} while(0) -#define device_remove_file(a,b) do {} while(0) - -#define schedule_timeout(x) my_schedule_timeout(x) -int my_schedule_timeout(int x); - -#define wake_up(x) my_wake_up(x) -void my_wake_up(PKEVENT); - -// cannot be mapped via macro due to collision with urb->complete -static void __inline__ complete(struct completion *p) -{ - printk("completing event 0x%08x\n", (ULONG)p); - /* Wake up x->wait */ - p->done++; - wake_up((PKEVENT)&p->wait); -} - -#define kernel_thread(a,b,c) my_kernel_thread(a,b,c) -int my_kernel_thread(int STDCALL (*handler)(void*), void* parm, int flags); - -/*------------------------------------------------------------------------*/ -/* PCI, simple and inlined... */ -/*------------------------------------------------------------------------*/ -#include "pci_hal.c" - -/*------------------------------------------------------------------------*/ -/* IRQ handling */ -/*------------------------------------------------------------------------*/ - -#define request_irq(a,b,c,d,e) my_request_irq(a,b,c,d,e) -int my_request_irq(unsigned int irq, - int (*handler)(int, void *, struct pt_regs *), - unsigned long mode, const char *desc, void *data); - -#define free_irq(a,b) my_free_irq(a,b) -int free_irq(int irq, void* p); - - - -struct my_irqs { - int (*handler)(int, void *, struct pt_regs *); - int irq; - void* data; -}; - -#define MAX_IRQS 8 - -// Exported to top level - -void handle_irqs(int irq); -void inc_jiffies(int); -void init_wrapper(struct pci_dev *pci_dev); -void do_all_timers(void); - -int my_pci_write_config_word(struct pci_dev *, int, u16); - -void UsbKeyBoardInit(void); -void UsbKeyBoardRemove(void); -void UsbMouseInit(void); -void UsbMouseRemove(void); diff --git a/reactos/drivers/usb/miniport/linux/list.h b/reactos/drivers/usb/miniport/linux/list.h deleted file mode 100644 index ef8fdd29f55..00000000000 --- a/reactos/drivers/usb/miniport/linux/list.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef _BOOT_LIST_H -#define _BOOT_LIST_H - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = (void *) 0; - entry->prev = (void *) 0; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(struct list_head *head) -{ - return head->next == head; -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member) \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -#endif diff --git a/reactos/drivers/usb/miniport/linux/pci_hal.c b/reactos/drivers/usb/miniport/linux/pci_hal.c deleted file mode 100644 index 57e74081c0e..00000000000 --- a/reactos/drivers/usb/miniport/linux/pci_hal.c +++ /dev/null @@ -1,162 +0,0 @@ -// PCI -> HAL interface -// this file is part of linux_wrapper.h - -//FIXME: Move this file, make its definitions more general -#include "../common/usbcommon_types.h" - -/* - Initialize device before it's used by a driver. Ask low-level code to enable I/O and memory. - Wake up the device if it was suspended. Beware, this function can fail. - */ -static int __inline__ pci_enable_device(struct pci_dev *dev) -{ - DPRINT1("pci_enable_device() called...\n"); - return 0; -} - -// Get physical address where resource x resides -static PHYSICAL_ADDRESS __inline__ pci_resource_start (struct pci_dev *dev, int x) -{ - PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext; - DPRINT1("pci_resource_start() called, x=0x%x\n", x); - - //FIXME: Take x into account - return dev_ext->BaseAddress; - //return dev->base[x]; -} - -// ??? -static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x) -{ - PUSBMP_DEVICE_EXTENSION ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext; - - DPRINT1("pci_resource_len() called, x=0x%x\n", x); - - //FIXME: Take x into account - return ext->BaseAddrLength; -} - -// ??? -static int __inline__ pci_resource_flags(struct pci_dev *dev, int x) -{ - PUSBMP_DEVICE_EXTENSION ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext; - - DPRINT1("pci_resource_flags() called, x=0x%x\n", x); - - //FIXME: Take x into account - return ext->Flags; -} - -/* - Enables bus-mastering for device dev -*/ -static int __inline__ pci_set_master(struct pci_dev *dev) {return 0;} - -// Store pointer to data for this device -static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d) -{ - DPRINT1("pci_set_drvdata() called...\n"); - dev->data=(void*)d; - return 0; -} - -// Get pointer to previously saved data -static void __inline__ *pci_get_drvdata(struct pci_dev *dev) -{ - DPRINT1("pci_get_drvdata() called...\n"); - return dev->data; -} - - -/* - =========================================================================== - I/O mem related stuff below -*/ - -/* -Allocate I/O memory region. - -Parameters: -start begin of region -n length of region -name name of requester -*/ -static int __inline__ request_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d) -{ - DPRINT1("request_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len); - return ~0; -} - -/* -Unmap I/O memory from kernel address space. - -Parameters: -addr virtual start address - -*/ -static int __inline__ iounmap(void* p) -{ - DPRINT1("iounmap(): p=0x%x. FIXME - how to obtain len of mapped region?\n", p); - - //MmUnnapIoSpace(p); - - return 0; -} - -/* -Release I/O port region. - -Parameters: -start begin of region -n length of region -*/ -static int __inline__ release_region(PHYSICAL_ADDRESS addr, unsigned long len) -{ - DPRINT1("release_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len); - return 0; -} - -/* -Allocate I/O memory region. - -Parameters: -start begin of region -n length of region -name name of requester -*/ -static int __inline__ request_mem_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d) -{ - DPRINT1("request_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len); - return 1; -} - -/* -Remap I/O memory into kernel address space (no cache). - -Parameters: -phys_addr begin of physical address range -size size of physical address range - -Returns: -virtual start address of mapped range -*/ -static void __inline__ *ioremap_nocache(PHYSICAL_ADDRESS addr, unsigned long len) -{ - // MmMapIoSpace with NoCache param - DPRINT1("ioremap_nocache(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len); - - return MmMapIoSpace(addr, len, MmNonCached); -} - -/* -Release I/O memory region. - -Parameters: -start begin of region -n length of region -*/ -static int __inline__ release_mem_region(PHYSICAL_ADDRESS addr, unsigned long len) -{ - DPRINT1("release_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len); - return 0; -} diff --git a/reactos/drivers/usb/miniport/linux/pci_ids.h b/reactos/drivers/usb/miniport/linux/pci_ids.h deleted file mode 100644 index 64b293d8ebf..00000000000 --- a/reactos/drivers/usb/miniport/linux/pci_ids.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef PCI_IDS__H -#define PCI_IDS__H - -#define PCI_VENDOR_ID_NS 0x100b -#define PCI_VENDOR_ID_AMD 0x1022 -#define PCI_VENDOR_ID_OPTI 0x1045 -#define PCI_VENDOR_ID_VIA 0x1106 -#define PCI_VENDOR_ID_INTEL 0x8086 - -#define PCI_DEVICE_ID_NS_87560_LIO 0x000e -#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112 - -#define PCI_CLASS_SERIAL_USB ((PCI_CLASS_SERIAL_BUS_CTLR << 8) + PCI_SUBCLASS_SB_USB) - -#endif - diff --git a/reactos/drivers/usb/miniport/linux/usb.h b/reactos/drivers/usb/miniport/linux/usb.h deleted file mode 100644 index 3e787afe26d..00000000000 --- a/reactos/drivers/usb/miniport/linux/usb.h +++ /dev/null @@ -1,1037 +0,0 @@ -#ifndef __LINUX_USB_H -#define __LINUX_USB_H - - -#include "usb_ch9.h" - -#define USB_MAJOR 180 - - -#ifdef __KERNEL__ -#if 0 -#include -#include /* for -ENODEV */ -#include /* for mdelay() */ -#include /* for in_interrupt() */ -#include /* for struct list_head */ -#include /* for struct device */ -#include /* for struct file_operations */ -#include /* for struct completion */ -#include /* for current && schedule_timeout */ - - -static __inline__ void wait_ms(unsigned int ms) -{ - if(!in_interrupt()) { - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(1 + ms * HZ / 1000); - } - else - mdelay(ms); -} -#endif -struct usb_device; - -/*-------------------------------------------------------------------------*/ - -/* - * Host-side wrappers for standard USB descriptors ... these are parsed - * from the data provided by devices. Parsing turns them from a flat - * sequence of descriptors into a hierarchy: - * - * - devices have one (usually) or more configs; - * - configs have one (often) or more interfaces; - * - interfaces have one (usually) or more settings; - * - each interface setting has zero or (usually) more endpoints. - * - * And there might be other descriptors mixed in with those. - * - * Devices may also have class-specific or vendor-specific descriptors. - */ - -/* host-side wrapper for parsed endpoint descriptors */ -struct usb_host_endpoint { - struct usb_endpoint_descriptor desc; - - unsigned char *extra; /* Extra descriptors */ - int extralen; -}; - -/* host-side wrapper for one interface setting's parsed descriptors */ -struct usb_host_interface { - struct usb_interface_descriptor desc; - - /* array of desc.bNumEndpoint endpoints associated with this - * interface setting. these will be in no particular order. - */ - struct usb_host_endpoint *endpoint; - - unsigned char *extra; /* Extra descriptors */ - int extralen; -}; - -/** - * struct usb_interface - what usb device drivers talk to - * @altsetting: array of interface descriptors, one for each alternate - * setting that may be selected. Each one includes a set of - * endpoint configurations and will be in numberic order, - * 0..num_altsetting. - * @num_altsetting: number of altsettings defined. - * @act_altsetting: index of current altsetting. this number is always - * less than num_altsetting. after the device is configured, each - * interface uses its default setting of zero. - * @max_altsetting: - * @minor: the minor number assigned to this interface, if this - * interface is bound to a driver that uses the USB major number. - * If this interface does not use the USB major, this field should - * be unused. The driver should set this value in the probe() - * function of the driver, after it has been assigned a minor - * number from the USB core by calling usb_register_dev(). - * @dev: driver model's view of this device - * @class_dev: driver model's class view of this device. - * - * USB device drivers attach to interfaces on a physical device. Each - * interface encapsulates a single high level function, such as feeding - * an audio stream to a speaker or reporting a change in a volume control. - * Many USB devices only have one interface. The protocol used to talk to - * an interface's endpoints can be defined in a usb "class" specification, - * or by a product's vendor. The (default) control endpoint is part of - * every interface, but is never listed among the interface's descriptors. - * - * The driver that is bound to the interface can use standard driver model - * calls such as dev_get_drvdata() on the dev member of this structure. - * - * Each interface may have alternate settings. The initial configuration - * of a device sets the first of these, but the device driver can change - * that setting using usb_set_interface(). Alternate settings are often - * used to control the the use of periodic endpoints, such as by having - * different endpoints use different amounts of reserved USB bandwidth. - * All standards-conformant USB devices that use isochronous endpoints - * will use them in non-default settings. - */ - -struct usb_interface { - /* array of alternate settings for this interface. - * these will be in numeric order, 0..num_altsettting - */ - - struct usb_host_interface *altsetting; - - unsigned act_altsetting; /* active alternate setting */ - unsigned num_altsetting; /* number of alternate settings */ - unsigned max_altsetting; /* total memory allocated */ - - struct usb_driver *driver; /* driver */ - int minor; /* minor number this interface is bound to */ - struct device dev; /* interface specific device info */ - struct class_device class_dev; -}USB_INTERFACE, *PUSB_INTERFACE; -#define to_usb_interface(d) container_of(d, struct usb_interface, dev) -#define class_dev_to_usb_interface(d) container_of(d, struct usb_interface, class_dev) -#define interface_to_usbdev(intf) \ - container_of(intf->dev.parent, struct usb_device, dev) - -static inline void *usb_get_intfdata (struct usb_interface *intf) -{ - return dev_get_drvdata (&intf->dev); -} - -static inline void usb_set_intfdata (struct usb_interface *intf, void *data) -{ - dev_set_drvdata(&intf->dev, data); -} - -/* USB_DT_CONFIG: Configuration descriptor information. - * - * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the - * descriptor type is different. Highspeed-capable devices can look - * different depending on what speed they're currently running. Only - * devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG. - */ -struct usb_host_config { - struct usb_config_descriptor desc; - - /* the interfaces associated with this configuration - * these will be in numeric order, 0..desc.bNumInterfaces - */ - - struct usb_interface *interface; - - unsigned char *extra; /* Extra descriptors */ - int extralen; -}; - -// FIXME remove; exported only for drivers/usb/misc/auserwald.c -// prefer usb_device->epnum[0..31] -extern struct usb_endpoint_descriptor * - usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum); - -int __usb_get_extra_descriptor(char *buffer, unsigned size, - unsigned char type, void **ptr); -#define usb_get_extra_descriptor(ifpoint,type,ptr)\ - __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\ - type,(void**)ptr) - -void usb_choose_address(struct usb_device *dev); - -/* -------------------------------------------------------------------------- */ - -struct usb_operations; - -/* USB device number allocation bitmap */ -struct usb_devmap { - unsigned long devicemap[128 / (8*sizeof(unsigned long))]; -}; - -/* - * Allocated per bus (tree of devices) we have: - */ -struct usb_bus { - struct device *controller; /* host/master side hardware */ - int busnum; /* Bus number (in order of reg) */ - char *bus_name; /* stable id (PCI slot_name etc) */ - - int devnum_next; /* Next open device number in round-robin allocation */ - - struct usb_devmap devmap; /* device address allocation map */ - struct usb_operations *op; /* Operations (specific to the HC) */ - struct usb_device *root_hub; /* Root hub */ - struct list_head bus_list; /* list of busses */ - void *hcpriv; /* Host Controller private data */ - - int bandwidth_allocated; /* on this bus: how much of the time - * reserved for periodic (intr/iso) - * requests is used, on average? - * Units: microseconds/frame. - * Limits: Full/low speed reserve 90%, - * while high speed reserves 80%. - */ - int bandwidth_int_reqs; /* number of Interrupt requests */ - int bandwidth_isoc_reqs; /* number of Isoc. requests */ - - struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */ - struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the bus */ - - atomic_t refcnt; -}; - - -/* -------------------------------------------------------------------------- */ - -/* This is arbitrary. - * From USB 2.0 spec Table 11-13, offset 7, a hub can - * have up to 255 ports. The most yet reported is 10. - */ -#define USB_MAXCHILDREN (16) - -struct usb_tt; - -struct usb_device { - int devnum; /* Address on USB bus */ - char devpath [16]; /* Use in messages: /port/port/... */ - enum usb_device_state state; /* configured, not attached, etc */ - enum usb_device_speed speed; /* high/full/low (or error) */ - - struct usb_tt *tt; /* low/full speed dev, highspeed hub */ - int ttport; /* device port on that tt hub */ - - struct semaphore serialize; - - unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */ - unsigned int halted[2]; /* endpoint halts; one bit per endpoint # & direction; */ - /* [0] = IN, [1] = OUT */ - int epmaxpacketin[16]; /* INput endpoint specific maximums */ - int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ - - struct usb_device *parent; /* our hub, unless we're the root */ - struct usb_bus *bus; /* Bus we're part of */ - - struct device dev; /* Generic device interface */ - - struct usb_device_descriptor descriptor;/* Descriptor */ - struct usb_host_config *config; /* All of the configs */ - struct usb_host_config *actconfig;/* the active configuration */ - - char **rawdescriptors; /* Raw descriptors for each config */ - - int have_langid; /* whether string_langid is valid yet */ - int string_langid; /* language ID for strings */ - - void *hcpriv; /* Host Controller private data */ - - struct list_head filelist; - struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ - struct dentry *usbdevfs_dentry; /* usbdevfs dentry entry for the device */ - - /* - * Child devices - these can be either new devices - * (if this is a hub device), or different instances - * of this same device. - * - * Each instance needs its own set of data structures. - */ - - int maxchild; /* Number of ports if hub */ - struct usb_device *children[USB_MAXCHILDREN]; -}; -#define to_usb_device(d) container_of(d, struct usb_device, dev) - -extern struct usb_device STDCALL *usb_alloc_dev(struct usb_device *parent, struct usb_bus *); -extern struct usb_device STDCALL *usb_get_dev(struct usb_device *dev); -extern void STDCALL usb_put_dev(struct usb_device *dev); - -/* mostly for devices emulating SCSI over USB */ -extern int usb_reset_device(struct usb_device *dev); - -extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); - -/* for drivers using iso endpoints */ -extern int usb_get_current_frame_number (struct usb_device *usb_dev); - -/* used these for multi-interface device registration */ -extern void usb_driver_claim_interface(struct usb_driver *driver, - struct usb_interface *iface, void* priv); -extern int usb_interface_claimed(struct usb_interface *iface); -extern void usb_driver_release_interface(struct usb_driver *driver, - struct usb_interface *iface); -const struct usb_device_id *usb_match_id(struct usb_interface *interface, - const struct usb_device_id *id); - -extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor); -extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); - - -/** - * usb_make_path - returns stable device path in the usb tree - * @dev: the device whose path is being constructed - * @buf: where to put the string - * @size: how big is "buf"? - * - * Returns length of the string (> 0) or negative if size was too small. - * - * This identifier is intended to be "stable", reflecting physical paths in - * hardware such as physical bus addresses for host controllers or ports on - * USB hubs. That makes it stay the same until systems are physically - * reconfigured, by re-cabling a tree of USB devices or by moving USB host - * controllers. Adding and removing devices, including virtual root hubs - * in host controller driver modules, does not change these path identifers; - * neither does rebooting or re-enumerating. These are more useful identifiers - * than changeable ("unstable") ones like bus numbers or device addresses. - * - * With a partial exception for devices connected to USB 2.0 root hubs, these - * identifiers are also predictable. So long as the device tree isn't changed, - * plugging any USB device into a given hub port always gives it the same path. - * Because of the use of "companion" controllers, devices connected to ports on - * USB 2.0 root hubs (EHCI host controllers) will get one path ID if they are - * high speed, and a different one if they are full or low speed. - */ -static inline int usb_make_path (struct usb_device *dev, char *buf, size_t size) -{ - int actual; - actual = snprintf (buf, size, "usb-%s-%s", dev->bus->bus_name, dev->devpath); - return (actual >= size) ? -1 : actual; -} - -/*-------------------------------------------------------------------------*/ - -#define USB_DEVICE_ID_MATCH_DEVICE (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) -#define USB_DEVICE_ID_MATCH_DEV_RANGE (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI) -#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE) -#define USB_DEVICE_ID_MATCH_DEV_INFO \ - (USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL) -#define USB_DEVICE_ID_MATCH_INT_INFO \ - (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL) - -/** - * USB_DEVICE - macro used to describe a specific usb device - * @vend: the 16 bit USB Vendor ID - * @prod: the 16 bit USB Product ID - * - * This macro is used to create a struct usb_device_id that matches a - * specific device. - */ -#define USB_DEVICE(vend,prod) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), .idProduct = (prod) -/** - * USB_DEVICE_VER - macro used to describe a specific usb device with a version range - * @vend: the 16 bit USB Vendor ID - * @prod: the 16 bit USB Product ID - * @lo: the bcdDevice_lo value - * @hi: the bcdDevice_hi value - * - * This macro is used to create a struct usb_device_id that matches a - * specific device, with a version range. - */ -#define USB_DEVICE_VER(vend,prod,lo,hi) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), .bcdDevice_hi = (hi) - -/** - * USB_DEVICE_INFO - macro used to describe a class of usb devices - * @cl: bDeviceClass value - * @sc: bDeviceSubClass value - * @pr: bDeviceProtocol value - * - * This macro is used to create a struct usb_device_id that matches a - * specific class of devices. - */ -#define USB_DEVICE_INFO(cl,sc,pr) \ - .match_flags = USB_DEVICE_ID_MATCH_DEV_INFO, .bDeviceClass = (cl), .bDeviceSubClass = (sc), .bDeviceProtocol = (pr) - -/** - * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces - * @cl: bInterfaceClass value - * @sc: bInterfaceSubClass value - * @pr: bInterfaceProtocol value - * - * This macro is used to create a struct usb_device_id that matches a - * specific class of interfaces. - */ -#define USB_INTERFACE_INFO(cl,sc,pr) \ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr) - -/* -------------------------------------------------------------------------- */ - -/** - * struct usb_driver - identifies USB driver to usbcore - * @owner: Pointer to the module owner of this driver; initialize - * it using THIS_MODULE. - * @name: The driver name should be unique among USB drivers, - * and should normally be the same as the module name. - * @probe: Called to see if the driver is willing to manage a particular - * interface on a device. If it is, probe returns zero and uses - * dev_set_drvdata() to associate driver-specific data with the - * interface. It may also use usb_set_interface() to specify the - * appropriate altsetting. If unwilling to manage the interface, - * return a negative errno value. - * @disconnect: Called when the interface is no longer accessible, usually - * because its device has been (or is being) disconnected or the - * driver module is being unloaded. - * @ioctl: Used for drivers that want to talk to userspace through - * the "usbfs" filesystem. This lets devices provide ways to - * expose information to user space regardless of where they - * do (or don't) show up otherwise in the filesystem. - * @id_table: USB drivers use ID table to support hotplugging. - * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set - * or your driver's probe function will never get called. - * - * USB drivers must provide a name, probe() and disconnect() methods, - * and an id_table. Other driver fields are optional. - * - * The id_table is used in hotplugging. It holds a set of descriptors, - * and specialized data may be associated with each entry. That table - * is used by both user and kernel mode hotplugging support. - * - * The probe() and disconnect() methods are called in a context where - * they can sleep, but they should avoid abusing the privilege. Most - * work to connect to a device should be done when the device is opened, - * and undone at the last close. The disconnect code needs to address - * concurrency issues with respect to open() and close() methods, as - * well as forcing all pending I/O requests to complete (by unlinking - * them as necessary, and blocking until the unlinks complete). - */ -struct usb_driver { - struct module *owner; - - const char *name; - - int (*probe) (struct usb_interface *intf, - const struct usb_device_id *id); - - void (*disconnect) (struct usb_interface *intf); - - int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf); - - const struct usb_device_id *id_table; - - struct device_driver driver; - - struct semaphore serialize; -}; -#define to_usb_driver(d) container_of(d, struct usb_driver, driver) - -extern struct bus_type usb_bus_type; - -/** - * struct usb_class_driver - identifies a USB driver that wants to use the USB major number - * @name: devfs name for this driver. Will also be used by the driver - * class code to create a usb class device. - * @fops: pointer to the struct file_operations of this driver. - * @mode: the mode for the devfs file to be created for this driver. - * @minor_base: the start of the minor range for this driver. - * - * This structure is used for the usb_register_dev() and - * usb_unregister_dev() functions, to consolodate a number of the - * paramaters used for them. - */ -struct usb_class_driver { - char *name; - struct file_operations *fops; - mode_t mode; - int minor_base; -}; - -/* - * use these in module_init()/module_exit() - * and don't forget MODULE_DEVICE_TABLE(usb, ...) - */ -extern int usb_register(struct usb_driver *); -extern void usb_deregister(struct usb_driver *); - -extern int usb_register_dev(struct usb_interface *intf, - struct usb_class_driver *class_driver); -extern void usb_deregister_dev(struct usb_interface *intf, - struct usb_class_driver *class_driver); - -extern int usb_device_probe(struct device *dev); -extern int usb_device_remove(struct device *dev); -extern int STDCALL usb_disabled(void); - -/* -------------------------------------------------------------------------- */ - -/* - * URB support, for asynchronous request completions - */ - -/* - * urb->transfer_flags: - */ -#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */ -#define URB_ISO_ASAP 0x0002 /* iso-only, urb->start_frame ignored */ -#define URB_NO_DMA_MAP 0x0004 /* urb->*_dma are valid on submit */ -#define URB_ASYNC_UNLINK 0x0008 /* usb_unlink_urb() returns asap */ -#define URB_NO_FSBR 0x0020 /* UHCI-specific */ -#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */ -#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */ - -struct usb_iso_packet_descriptor { - unsigned int offset; - unsigned int length; /* expected length */ - unsigned int actual_length; - unsigned int status; -}; - -struct urb; -struct pt_regs; - -typedef void (*usb_complete_t)(struct urb *, struct pt_regs *); - -/** - * struct urb - USB Request Block - * @urb_list: For use by current owner of the URB. - * @pipe: Holds endpoint number, direction, type, and more. - * Create these values with the eight macros available; - * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl" - * (control), "bulk", "int" (interrupt), or "iso" (isochronous). - * For example usb_sndbulkpipe() or usb_rcvintpipe(). Endpoint - * numbers range from zero to fifteen. Note that "in" endpoint two - * is a different endpoint (and pipe) from "out" endpoint two. - * The current configuration controls the existence, type, and - * maximum packet size of any given endpoint. - * @dev: Identifies the USB device to perform the request. - * @status: This is read in non-iso completion functions to get the - * status of the particular request. ISO requests only use it - * to tell whether the URB was unlinked; detailed status for - * each frame is in the fields of the iso_frame-desc. - * @transfer_flags: A variety of flags may be used to affect how URB - * submission, unlinking, or operation are handled. Different - * kinds of URB can use different flags. - * @transfer_buffer: This identifies the buffer to (or from) which - * the I/O request will be performed (unless URB_NO_DMA_MAP is set). - * This buffer must be suitable for DMA; allocate it with kmalloc() - * or equivalent. For transfers to "in" endpoints, contents of - * this buffer will be modified. This buffer is used for data - * phases of control transfers. - * @transfer_dma: When transfer_flags includes URB_NO_DMA_MAP, the device - * driver is saying that it provided this DMA address, which the host - * controller driver should use instead of the transfer_buffer. - * @transfer_buffer_length: How big is transfer_buffer. The transfer may - * be broken up into chunks according to the current maximum packet - * size for the endpoint, which is a function of the configuration - * and is encoded in the pipe. When the length is zero, neither - * transfer_buffer nor transfer_dma is used. - * @actual_length: This is read in non-iso completion functions, and - * it tells how many bytes (out of transfer_buffer_length) were - * transferred. It will normally be the same as requested, unless - * either an error was reported or a short read was performed. - * The URB_SHORT_NOT_OK transfer flag may be used to make such - * short reads be reported as errors. - * @setup_packet: Only used for control transfers, this points to eight bytes - * of setup data. Control transfers always start by sending this data - * to the device. Then transfer_buffer is read or written, if needed. - * (Not used when URB_NO_DMA_MAP is set.) - * @setup_dma: For control transfers with URB_NO_DMA_MAP set, the device - * driver has provided this DMA address for the setup packet. The - * host controller driver should use this instead of setup_buffer. - * If there is a data phase, its buffer is identified by transfer_dma. - * @start_frame: Returns the initial frame for interrupt or isochronous - * transfers. - * @number_of_packets: Lists the number of ISO transfer buffers. - * @interval: Specifies the polling interval for interrupt or isochronous - * transfers. The units are frames (milliseconds) for for full and low - * speed devices, and microframes (1/8 millisecond) for highspeed ones. - * @error_count: Returns the number of ISO transfers that reported errors. - * @context: For use in completion functions. This normally points to - * request-specific driver context. - * @complete: Completion handler. This URB is passed as the parameter to the - * completion function. The completion function may then do what - * it likes with the URB, including resubmitting or freeing it. - * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to - * collect the transfer status for each buffer. - * - * This structure identifies USB transfer requests. URBs must be allocated by - * calling usb_alloc_urb() and freed with a call to usb_free_urb(). - * Initialization may be done using various usb_fill_*_urb() functions. URBs - * are submitted using usb_submit_urb(), and pending requests may be canceled - * using usb_unlink_urb(). - * - * Data Transfer Buffers: - * - * Normally drivers provide I/O buffers allocated with kmalloc() or otherwise - * taken from the general page pool. That is provided by transfer_buffer - * (control requests also use setup_packet), and host controller drivers - * perform a dma mapping (and unmapping) for each buffer transferred. Those - * mapping operations can be expensive on some platforms (perhaps using a dma - * bounce buffer or talking to an IOMMU), - * although they're cheap on commodity x86 and ppc hardware. - * - * Alternatively, drivers may pass the URB_NO_DMA_MAP transfer flag, which - * tells the host controller driver that no such mapping is needed since - * the device driver is DMA-aware. For example, they might allocate a DMA - * buffer with usb_buffer_alloc(), or call usb_buffer_map(). - * When this transfer flag is provided, host controller drivers will use the - * dma addresses found in the transfer_dma and/or setup_dma fields rather than - * determing a dma address themselves. - * - * Initialization: - * - * All URBs submitted must initialize dev, pipe, - * transfer_flags (may be zero), complete, timeout (may be zero). - * The URB_ASYNC_UNLINK transfer flag affects later invocations of - * the usb_unlink_urb() routine. - * - * All URBs must also initialize - * transfer_buffer and transfer_buffer_length. They may provide the - * URB_SHORT_NOT_OK transfer flag, indicating that short reads are - * to be treated as errors; that flag is invalid for write requests. - * - * Bulk URBs may - * use the URB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers - * should always terminate with a short packet, even if it means adding an - * extra zero length packet. - * - * Control URBs must provide a setup_packet. - * - * Interrupt UBS must provide an interval, saying how often (in milliseconds - * or, for highspeed devices, 125 microsecond units) - * to poll for transfers. After the URB has been submitted, the interval - * and start_frame fields reflect how the transfer was actually scheduled. - * The polling interval may be more frequent than requested. - * For example, some controllers have a maximum interval of 32 microseconds, - * while others support intervals of up to 1024 microseconds. - * Isochronous URBs also have transfer intervals. (Note that for isochronous - * endpoints, as well as high speed interrupt endpoints, the encoding of - * the transfer interval in the endpoint descriptor is logarithmic.) - * - * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling - * the host controller to schedule the transfer as soon as bandwidth - * utilization allows, and then set start_frame to reflect the actual frame - * selected during submission. Otherwise drivers must specify the start_frame - * and handle the case where the transfer can't begin then. However, drivers - * won't know how bandwidth is currently allocated, and while they can - * find the current frame using usb_get_current_frame_number () they can't - * know the range for that frame number. (Ranges for frame counter values - * are HC-specific, and can go from 256 to 65536 frames from "now".) - * - * Isochronous URBs have a different data transfer model, in part because - * the quality of service is only "best effort". Callers provide specially - * allocated URBs, with number_of_packets worth of iso_frame_desc structures - * at the end. Each such packet is an individual ISO transfer. Isochronous - * URBs are normally queued, submitted by drivers to arrange that - * transfers are at least double buffered, and then explicitly resubmitted - * in completion handlers, so - * that data (such as audio or video) streams at as constant a rate as the - * host controller scheduler can support. - * - * Completion Callbacks: - * - * The completion callback is made in_interrupt(), and one of the first - * things that a completion handler should do is check the status field. - * The status field is provided for all URBs. It is used to report - * unlinked URBs, and status for all non-ISO transfers. It should not - * be examined before the URB is returned to the completion handler. - * - * The context field is normally used to link URBs back to the relevant - * driver or request state. - * - * When completion callback is invoked for non-isochronous URBs, the - * actual_length field tells how many bytes were transferred. - * - * ISO transfer status is reported in the status and actual_length fields - * of the iso_frame_desc array, and the number of errors is reported in - * error_count. Completion callbacks for ISO transfers will normally - * (re)submit URBs to ensure a constant transfer rate. - */ -struct urb -{ - spinlock_t lock; /* lock for the URB */ - atomic_t count; /* reference count of the URB */ - void *hcpriv; /* private data for host controller */ - struct list_head urb_list; /* list pointer to all active urbs */ - struct usb_device *dev; /* (in) pointer to associated device */ - unsigned int pipe; /* (in) pipe information */ - int status; /* (return) non-ISO status */ - unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ - void *transfer_buffer; /* (in) associated data buffer */ - dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */ - int transfer_buffer_length; /* (in) data buffer length */ - int actual_length; /* (return) actual transfer length */ - int bandwidth; /* bandwidth for INT/ISO request */ - unsigned char *setup_packet; /* (in) setup packet (control only) */ - dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ - int start_frame; /* (modify) start frame (INT/ISO) */ - int number_of_packets; /* (in) number of ISO packets */ - int interval; /* (in) transfer interval (INT/ISO) */ - int error_count; /* (return) number of ISO errors */ - int timeout; /* (in) timeout, in jiffies */ - void *context; /* (in) context for completion */ - usb_complete_t complete; /* (in) completion routine */ - struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */ -}; - -/* -------------------------------------------------------------------------- */ - -/** - * usb_fill_control_urb - initializes a control urb - * @urb: pointer to the urb to initialize. - * @dev: pointer to the struct usb_device for this urb. - * @pipe: the endpoint pipe - * @setup_packet: pointer to the setup_packet buffer - * @transfer_buffer: pointer to the transfer buffer - * @buffer_length: length of the transfer buffer - * @complete: pointer to the usb_complete_t function - * @context: what to set the urb context to. - * - * Initializes a control urb with the proper information needed to submit - * it to a device. - */ -static inline void usb_fill_control_urb (struct urb *urb, - struct usb_device *dev, - unsigned int pipe, - unsigned char *setup_packet, - void *transfer_buffer, - int buffer_length, - usb_complete_t complete, - void *context) -{ - spin_lock_init(&urb->lock); - urb->dev = dev; - urb->pipe = pipe; - urb->setup_packet = setup_packet; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = buffer_length; - urb->complete = complete; - urb->context = context; -} - -/** - * usb_fill_bulk_urb - macro to help initialize a bulk urb - * @urb: pointer to the urb to initialize. - * @dev: pointer to the struct usb_device for this urb. - * @pipe: the endpoint pipe - * @transfer_buffer: pointer to the transfer buffer - * @buffer_length: length of the transfer buffer - * @complete: pointer to the usb_complete_t function - * @context: what to set the urb context to. - * - * Initializes a bulk urb with the proper information needed to submit it - * to a device. - */ -static inline void usb_fill_bulk_urb (struct urb *urb, - struct usb_device *dev, - unsigned int pipe, - void *transfer_buffer, - int buffer_length, - usb_complete_t complete, - void *context) -{ - spin_lock_init(&urb->lock); - urb->dev = dev; - urb->pipe = pipe; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = buffer_length; - urb->complete = complete; - urb->context = context; -} - -/** - * usb_fill_int_urb - macro to help initialize a interrupt urb - * @urb: pointer to the urb to initialize. - * @dev: pointer to the struct usb_device for this urb. - * @pipe: the endpoint pipe - * @transfer_buffer: pointer to the transfer buffer - * @buffer_length: length of the transfer buffer - * @complete: pointer to the usb_complete_t function - * @context: what to set the urb context to. - * @interval: what to set the urb interval to, encoded like - * the endpoint descriptor's bInterval value. - * - * Initializes a interrupt urb with the proper information needed to submit - * it to a device. - * Note that high speed interrupt endpoints use a logarithmic encoding of - * the endpoint interval, and express polling intervals in microframes - * (eight per millisecond) rather than in frames (one per millisecond). - */ -static inline void usb_fill_int_urb (struct urb *urb, - struct usb_device *dev, - unsigned int pipe, - void *transfer_buffer, - int buffer_length, - usb_complete_t complete, - void *context, - int interval) -{ - spin_lock_init(&urb->lock); - urb->dev = dev; - urb->pipe = pipe; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = buffer_length; - urb->complete = complete; - urb->context = context; - if (dev->speed == USB_SPEED_HIGH) - urb->interval = 1 << (interval - 1); - else - urb->interval = interval; - urb->start_frame = -1; -} - -extern void STDCALL usb_init_urb(struct urb *urb); -extern struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags); -extern void STDCALL usb_free_urb(struct urb *urb); -#define usb_put_urb usb_free_urb -extern struct urb STDCALL *usb_get_urb(struct urb *urb); -extern int STDCALL usb_submit_urb(struct urb *urb, int mem_flags); -extern int STDCALL usb_unlink_urb(struct urb *urb); - -#define HAVE_USB_BUFFERS -void *usb_buffer_alloc (struct usb_device *dev, size_t size, - int mem_flags, dma_addr_t *dma); -void usb_buffer_free (struct usb_device *dev, size_t size, - void *addr, dma_addr_t dma); - -struct urb *usb_buffer_map (struct urb *urb); -void usb_buffer_dmasync (struct urb *urb); -void usb_buffer_unmap (struct urb *urb); - -struct scatterlist; -int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int nents); -void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int n_hw_ents); -void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int n_hw_ents); - -/*-------------------------------------------------------------------* - * SYNCHRONOUS CALL SUPPORT * - *-------------------------------------------------------------------*/ - -extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, - __u8 request, __u8 requesttype, __u16 value, __u16 index, - void *data, __u16 size, int timeout); -extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, - void *data, int len, int *actual_length, - int timeout); - -/* wrappers around usb_control_msg() for the most common standard requests */ -extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, - unsigned char descindex, void *buf, int size); -extern int usb_get_device_descriptor(struct usb_device *dev); -extern int usb_get_status(struct usb_device *dev, - int type, int target, void *data); -extern int usb_get_string(struct usb_device *dev, - unsigned short langid, unsigned char index, void *buf, int size); -extern int usb_string(struct usb_device *dev, int index, - char *buf, size_t size); - -/* wrappers that also update important state inside usbcore */ -extern int usb_clear_halt(struct usb_device *dev, int pipe); -extern int usb_set_configuration(struct usb_device *dev, int configuration); -extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); - -/* - * timeouts, in seconds, used for sending/receiving control messages - * they typically complete within a few frames (msec) after they're issued - * USB identifies 5 second timeouts, maybe more in a few cases, and a few - * slow devices (like some MGE Ellipse UPSes) actually push that limit. - */ -#define USB_CTRL_GET_TIMEOUT 5 -#define USB_CTRL_SET_TIMEOUT 5 - - -/** - * struct usb_sg_request - support for scatter/gather I/O - * @status: zero indicates success, else negative errno - * @bytes: counts bytes transferred. - * - * These requests are initialized using usb_sg_init(), and then are used - * as request handles passed to usb_sg_wait() or usb_sg_cancel(). Most - * members of the request object aren't for driver access. - * - * The status and bytecount values are valid only after usb_sg_wait() - * returns. If the status is zero, then the bytecount matches the total - * from the request. - * - * After an error completion, drivers may need to clear a halt condition - * on the endpoint. - */ -struct usb_sg_request { - int status; - size_t bytes; - - // members not documented above are private to usbcore, - // and are not provided for driver access! - spinlock_t lock; - - struct usb_device *dev; - int pipe; - struct scatterlist *sg; - int nents; - - int entries; - struct urb **urbs; - - int count; - struct completion complete; -}; - -int usb_sg_init ( - struct usb_sg_request *io, - struct usb_device *dev, - unsigned pipe, - unsigned period, - struct scatterlist *sg, - int nents, - size_t length, - int mem_flags -); -void usb_sg_cancel (struct usb_sg_request *io); -void usb_sg_wait (struct usb_sg_request *io); - - -/* -------------------------------------------------------------------------- */ - -/* - * Calling this entity a "pipe" is glorifying it. A USB pipe - * is something embarrassingly simple: it basically consists - * of the following information: - * - device number (7 bits) - * - endpoint number (4 bits) - * - current Data0/1 state (1 bit) [Historical; now gone] - * - direction (1 bit) - * - speed (1 bit) [Historical and specific to USB 1.1; now gone.] - * - max packet size (2 bits: 8, 16, 32 or 64) [Historical; now gone.] - * - pipe type (2 bits: control, interrupt, bulk, isochronous) - * - * That's 18 bits. Really. Nothing more. And the USB people have - * documented these eighteen bits as some kind of glorious - * virtual data structure. - * - * Let's not fall in that trap. We'll just encode it as a simple - * unsigned int. The encoding is: - * - * - max size: bits 0-1 [Historical; now gone.] - * - direction: bit 7 (0 = Host-to-Device [Out], - * 1 = Device-to-Host [In] ... - * like endpoint bEndpointAddress) - * - device: bits 8-14 ... bit positions known to uhci-hcd - * - endpoint: bits 15-18 ... bit positions known to uhci-hcd - * - Data0/1: bit 19 [Historical; now gone. ] - * - lowspeed: bit 26 [Historical; now gone. ] - * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, - * 10 = control, 11 = bulk) - * - * Why? Because it's arbitrary, and whatever encoding we select is really - * up to us. This one happens to share a lot of bit positions with the UHCI - * specification, so that much of the uhci driver can just mask the bits - * appropriately. - */ - -/* NOTE: these are not the standard USB_ENDPOINT_XFER_* values!! */ -#define PIPE_ISOCHRONOUS 0 -#define PIPE_INTERRUPT 1 -#define PIPE_CONTROL 2 -#define PIPE_BULK 3 - -#define usb_maxpacket(dev, pipe, out) (out \ - ? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \ - : (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] ) - -#define usb_pipein(pipe) ((pipe) & USB_DIR_IN) -#define usb_pipeout(pipe) (!usb_pipein(pipe)) -#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) -#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) -#define usb_pipetype(pipe) (((pipe) >> 30) & 3) -#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) -#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) -#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) -#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) - -/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ -#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) -#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep))) -#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep))) - -/* Endpoint halt control/status ... likewise USE WITH CAUTION */ -#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) -#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) - - -static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint) -{ - return (dev->devnum << 8) | (endpoint << 15); -} - -/* Create various pipes... */ -#define usb_sndctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvctrlpipe(dev,endpoint) ((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#define usb_sndisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvisocpipe(dev,endpoint) ((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#define usb_sndbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvbulkpipe(dev,endpoint) ((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) -#define usb_sndintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint)) -#define usb_rcvintpipe(dev,endpoint) ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN) - -/* -------------------------------------------------------------------------- */ - -/* - * Debugging and troubleshooting/diagnostic helpers. - */ -void usb_show_device_descriptor(struct usb_device_descriptor *); -void usb_show_config_descriptor(struct usb_config_descriptor *); -void usb_show_interface_descriptor(struct usb_interface_descriptor *); -void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *); -void usb_show_device(struct usb_device *); -void usb_show_string(struct usb_device *dev, char *id, int index); - -#ifdef DEBUG -#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg) -#else -#define dbg(format, arg...) do {} while (0) -#endif - - - -#ifdef DEBUG_MODE -#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg) -#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg) -#endif - -#ifndef DEBUG_MODE -#define info(format, arg...) do {} while (0) -#define err(format, arg...) do {} while (0) -#define warn(format, arg...) do {} while (0) -#endif - -#endif /* __KERNEL__ */ - -#endif diff --git a/reactos/drivers/usb/miniport/linux/usb_ch9.h b/reactos/drivers/usb/miniport/linux/usb_ch9.h deleted file mode 100644 index 109ec384d59..00000000000 --- a/reactos/drivers/usb/miniport/linux/usb_ch9.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * This file holds USB constants and structures that are needed for USB - * device APIs. These are used by the USB device model, which is defined - * in chapter 9 of the USB 2.0 specification. Linux has several APIs in C - * that need these: - * - * - the master/host side Linux-USB kernel driver API; - * - the "usbfs" user space API; and - * - (eventually) a Linux "gadget" slave/device side driver API. - * - * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems - * act either as a USB master/host or as a USB slave/device. That means - * the master and slave side APIs will benefit from working well together. - */ - -#ifndef __LINUX_USB_CH9_H -#define __LINUX_USB_CH9_H -#if 0 -#include /* __u8 etc */ -#endif -/*-------------------------------------------------------------------------*/ - -/* CONTROL REQUEST SUPPORT */ - -/* - * USB directions - * - * This bit flag is used in endpoint descriptors' bEndpointAddress field. - * It's also one of three fields in control requests bRequestType. - */ -#define USB_DIR_OUT 0 /* to device */ -#define USB_DIR_IN 0x80 /* to host */ - -/* - * USB types, the second of three bRequestType fields - */ -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -/* - * USB recipients, the third of three bRequestType fields - */ -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 - -/* - * Standard requests, for the bRequest field of a SETUP packet. - * - * These are qualified by the bRequestType field, so that for example - * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved - * by a GET_STATUS request. - */ -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - - -/** - * struct usb_ctrlrequest - SETUP data for a USB device control request - * @bRequestType: matches the USB bmRequestType field - * @bRequest: matches the USB bRequest field - * @wValue: matches the USB wValue field (le16 byte order) - * @wIndex: matches the USB wIndex field (le16 byte order) - * @wLength: matches the USB wLength field (le16 byte order) - * - * This structure is used to send control requests to a USB device. It matches - * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the - * USB spec for a fuller description of the different fields, and what they are - * used for. - * - * Note that the driver for any interface can issue control requests. - * For most devices, interfaces don't coordinate with each other, so - * such requests may be made at any time. - */ -struct usb_ctrlrequest { - __u8 bRequestType; - __u8 bRequest; - __u16 wValue; - __u16 wIndex; - __u16 wLength; -} __attribute__ ((packed)); - -/*-------------------------------------------------------------------------*/ - -/* - * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or - * (rarely) accepted by SET_DESCRIPTOR. - * - * Note that all multi-byte values here are encoded in little endian - * byte order "on the wire". But when exposed through Linux-USB APIs, - * they've been converted to cpu byte order. - */ - -/* - * Descriptor types ... USB 2.0 spec table 9.5 - */ -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 -#define USB_DT_DEVICE_QUALIFIER 0x06 -#define USB_DT_OTHER_SPEED_CONFIG 0x07 -#define USB_DT_INTERFACE_POWER 0x08 - -/* All standard descriptors have these 2 fields at the beginning */ -struct usb_descriptor_header { - __u8 bLength; - __u8 bDescriptorType; -} __attribute__ ((packed)); - - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_DEVICE: Device descriptor */ -struct usb_device_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u16 bcdUSB; - __u8 bDeviceClass; - __u8 bDeviceSubClass; - __u8 bDeviceProtocol; - __u8 bMaxPacketSize0; - __u16 idVendor; - __u16 idProduct; - __u16 bcdDevice; - __u8 iManufacturer; - __u8 iProduct; - __u8 iSerialNumber; - __u8 bNumConfigurations; -} __attribute__ ((packed)); - -#define USB_DT_DEVICE_SIZE 18 - - -/* - * Device and/or Interface Class codes - * as found in bDeviceClass or bInterfaceClass - * and defined by www.usb.org documents - */ -#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ -#define USB_CLASS_AUDIO 1 -#define USB_CLASS_COMM 2 -#define USB_CLASS_HID 3 -#define USB_CLASS_PHYSICAL 5 -#define USB_CLASS_STILL_IMAGE 6 -#define USB_CLASS_PRINTER 7 -#define USB_CLASS_MASS_STORAGE 8 -#define USB_CLASS_HUB 9 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ -#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_CONFIG: Configuration descriptor information. - * - * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the - * descriptor type is different. Highspeed-capable devices can look - * different depending on what speed they're currently running. Only - * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG - * descriptors. - */ -struct usb_config_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u16 wTotalLength; - __u8 bNumInterfaces; - __u8 bConfigurationValue; - __u8 iConfiguration; - __u8 bmAttributes; - __u8 bMaxPower; -} __attribute__ ((packed)); - -#define USB_DT_CONFIG_SIZE 9 - -/* from config descriptor bmAttributes */ -#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ -#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ -#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_STRING: String descriptor */ -struct usb_string_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u16 wData[1]; /* UTF-16LE encoded */ -} __attribute__ ((packed)); - -/* note that "string" zero is special, it holds language codes that - * the device supports, not Unicode characters. - */ - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_INTERFACE: Interface descriptor */ -struct usb_interface_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bInterfaceNumber; - __u8 bAlternateSetting; - __u8 bNumEndpoints; - __u8 bInterfaceClass; - __u8 bInterfaceSubClass; - __u8 bInterfaceProtocol; - __u8 iInterface; -} __attribute__ ((packed)); - -#define USB_DT_INTERFACE_SIZE 9 - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_ENDPOINT: Endpoint descriptor */ -struct usb_endpoint_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bEndpointAddress; - __u8 bmAttributes; - __u16 wMaxPacketSize; - __u8 bInterval; - - // NOTE: these two are _only_ in audio endpoints. - // use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. - __u8 bRefresh; - __u8 bSynchAddress; -} __attribute__ ((packed)); - -#define USB_DT_ENDPOINT_SIZE 7 -#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ - - -/* - * Endpoints - */ -#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ -#define USB_ENDPOINT_DIR_MASK 0x80 - -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 - - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ -struct usb_qualifier_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u16 bcdUSB; - __u8 bDeviceClass; - __u8 bDeviceSubClass; - __u8 bDeviceProtocol; - __u8 bMaxPacketSize0; - __u8 bNumConfigurations; - __u8 bRESERVED; -} __attribute__ ((packed)); - - -/*-------------------------------------------------------------------------*/ - -/* USB 2.0 defines three speeds, here's how Linux identifies them */ - -enum usb_device_speed { - USB_SPEED_UNKNOWN = 0, /* enumerating */ - USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ - USB_SPEED_HIGH /* usb 2.0 */ -}; - -enum usb_device_state { - /* NOTATTACHED isn't in the USB spec, and this state acts - * the same as ATTACHED ... but it's clearer this way. - */ - USB_STATE_NOTATTACHED = 0, - - /* the chapter 9 device states */ - USB_STATE_ATTACHED, - USB_STATE_POWERED, - USB_STATE_DEFAULT, /* limited function */ - USB_STATE_ADDRESS, - USB_STATE_CONFIGURED, /* most functions */ - - USB_STATE_SUSPENDED - - /* NOTE: there are actually four different SUSPENDED - * states, returning to POWERED, DEFAULT, ADDRESS, or - * CONFIGURED respectively when SOF tokens flow again. - */ -}; - -#endif /* __LINUX_USB_CH9_H */ diff --git a/reactos/drivers/usb/miniport/sys/BootUSB.c b/reactos/drivers/usb/miniport/sys/BootUSB.c deleted file mode 100644 index 243d101f9e7..00000000000 --- a/reactos/drivers/usb/miniport/sys/BootUSB.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * USB support for XBOX, based on Linux kernel source - * - * 2003-06-21 Georg Acher (georg@acher.org) - * -*/ - -#include "../usb_wrapper.h" - -void subsys_usb_init(void); -void module_exit_usb_exit(void); - -extern struct pci_device_id *module_table_pci_ids; - -// straigth call... -int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id); -void usb_hcd_pci_remove (struct pci_dev *dev); - -void XPADInit(void); -void XPADRemove(void); -void XRemoteInit(void); -void XRemoteRemove(void); - -extern int (*thread_handler)(void*); -int (*hub_thread_handler)(void*); - -extern int nousb; -extern int xpad_num; - -struct pci_dev xx_ohci_dev={ - .vendor = 0, - .device = 0, - .bus = NULL, - .irq = 1, // currently not used... - .slot_name = "OHCI", - .dev = {.name = "PCI",.dma_mask=1}, - .base = {0xfed00000}, - .flags = {} -}; - -/*------------------------------------------------------------------------*/ -void BootStartUSB(void) -{ - int n; - - nousb=0; - - init_wrapper(); - subsys_usb_init(); - hub_thread_handler=thread_handler; - usb_hcd_pci_probe(&xx_ohci_dev, module_table_pci_ids); - XPADInit(); - - XRemoteInit(); - - UsbKeyBoardInit(); - - for(n=0;n<30;n++) { - USBGetEvents(); - wait_ms(1); - } -} -/*------------------------------------------------------------------------*/ -void USBGetEvents(void) -{ - inc_jiffies(1); - do_all_timers(); - hub_thread_handler(NULL); - handle_irqs(-1); -} -/*------------------------------------------------------------------------*/ -void BootStopUSB(void) -{ - int n; - - XPADRemove(); - XRemoteRemove(); - UsbKeyBoardRemove(); - - for(n=0;n<100;n++) - { - USBGetEvents(); - wait_ms(1); - } - - module_exit_usb_exit(); - usb_hcd_pci_remove(&xx_ohci_dev); - -} -/*------------------------------------------------------------------------*/ diff --git a/reactos/drivers/usb/miniport/sys/linuxwrapper.c b/reactos/drivers/usb/miniport/sys/linuxwrapper.c deleted file mode 100644 index 376b37fd1d2..00000000000 --- a/reactos/drivers/usb/miniport/sys/linuxwrapper.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * USB support based on Linux kernel source - * - * 2003-06-21 Georg Acher (georg@acher.org) - * - * Concept: - * - * 1) Forget all device interrupts, scheduling, semaphores, threads etc. - * 1a) Forget all DMA and PCI helper functions - * 2) Forget usbdevfs, procfs and ioctls - * 3) Emulate xHCI interrupts and root hub timer by polling - * 4) Emulate hub kernel thread by polling - * 5) Emulate synchronous USB-messages (usb_*_msg) with busy waiting - * - * To be done: - * 6) Remove code bloat - * - */ - -#include "../usb_wrapper.h" - -/* internal state */ - -static struct pci_dev *pci_probe_dev; -extern int (*thread_handler)(void*); -extern void* thread_parm; - -struct my_irqs reg_irqs[MAX_IRQS]; -int num_irqs; -int need_wakeup; - -int my_jiffies; - -struct timer_list *main_timer_list[MAX_TIMERS]; -struct dummy_process act_cur={0}; -struct dummy_process *my_current; - -int (*thread_handler)(void*); -void* thread_parm; - -#define MAX_DRVS 8 -static struct device_driver *m_drivers[MAX_DRVS]; -static int drvs_num=0; -unsigned int LAST_USB_EVENT_TICK; - -NTSTATUS init_dma(PUSBMP_DEVICE_EXTENSION pDevExt); - -/*------------------------------------------------------------------------*/ -/* - * Helper functions for top-level system - */ -/*------------------------------------------------------------------------*/ -void init_wrapper(struct pci_dev *probe_dev) -{ - int n; - for(n=0;ndev_ext); -} -/*------------------------------------------------------------------------*/ -void handle_irqs(int irq) -{ - int n; - //printk("handle irqs\n"); - for(n=0;nfunction) - { - void (*function)(unsigned long)=main_timer_list[n]->function; - unsigned long data=main_timer_list[n]->data; - - if (main_timer_list[n]->expires>1) { - main_timer_list[n]->expires--; - } else { - - main_timer_list[n]->expires=0; - main_timer_list[n]=0; // remove timer - // Call Timer Function Data - function(data); - } - } - } -} -/*------------------------------------------------------------------------*/ -// Purpose: Remember thread procedure and data in global var -// ReactOS Purpose: Create real kernel thread -int my_kernel_thread(int STDCALL (*handler)(void*), void* parm, int flags) -{ - HANDLE hThread = NULL; - //thread_handler=handler; - //thread_parm=parm; - //return 42; // PID :-) - - ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); - - PsCreateSystemThread(&hThread, - THREAD_ALL_ACCESS, - NULL, - NULL, - NULL, - (PKSTART_ROUTINE)handler, - parm); - - DPRINT1("usbcore: Created system thread %d\n", (int)hThread); - - return (int)hThread; // FIXME: Correct? -} - -// Kill the process -int my_kill_proc(int pid, int signal, int unk) -{ - HANDLE hThread; - - // TODO: Implement actual process killing - - hThread = (HANDLE)pid; - ZwClose(hThread); - - return 0; -} - -/*------------------------------------------------------------------------*/ -/* Device management - * As simple as possible, but as complete as necessary ... - */ -/*------------------------------------------------------------------------*/ - - -/* calls probe function for hotplug (which does device matching), this is the -only link between usbcore and the registered device drivers! */ -int my_device_add(struct device *dev) -{ - int n,found=0; - printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe); - - if (dev->driver) - { - if (dev->driver->probe) - return dev->driver->probe(dev); - } - else - { - for(n=0;nprobe) - { - dev->driver=m_drivers[n]; - printk("probe%i %p\n",n,m_drivers[n]->probe); - - if (m_drivers[n]->probe(dev) == 0) - { -// return 0; - found=1; - } - } - } - if (found) return 0; - } - dev->driver=NULL; - return -ENODEV; -} -/*------------------------------------------------------------------------*/ -int my_driver_register(struct device_driver *driver) -{ - - if (drvs_numprobe); - - m_drivers[drvs_num++]=driver; - return 0; - } - return -1; -} -/*------------------------------------------------------------------------*/ -int my_device_unregister(struct device *dev) -{ - if (dev->driver && dev->driver->remove) - dev->driver->remove(dev); - return 0; - -} -/*------------------------------------------------------------------------*/ -struct device *my_get_device(struct device *dev) -{ - return NULL; -} -/*------------------------------------------------------------------------*/ -void my_device_initialize(struct device *dev) -{ -} -/*------------------------------------------------------------------------*/ -void my_wake_up(PKEVENT evnt) -{ - need_wakeup=1; - - KeSetEvent(evnt, 0, FALSE); // Signal event -} -/*------------------------------------------------------------------------*/ -void my_init_waitqueue_head(PKEVENT evnt) -{ - // this is used only in core/message.c, and it isn't needed there - //KeInitializeEvent(evnt, NotificationEvent, TRUE); // signalled state -} -/*------------------------------------------------------------------------*/ -/* wait until woken up (only one wait allowed!) */ -extern unsigned int LAST_USB_IRQ; - -int my_schedule_timeout(int x) -{ - LONGLONG HH; - //LONGLONG temp; - LARGE_INTEGER delay; - //PULONG tmp_debug=NULL; - //extern unsigned int LAST_USB_EVENT_TICK; - - //*tmp_debug = 0xFFAAFFAA; - - printk("schedule_timeout: %d ms\n", x); - - //delay.QuadPart = -x*10000; // convert to 100ns units - //KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1); - - /* - x+=5; // safety - x = x*1000; // to us format - */ - x = 50; // it's enough for most purposes - - while(x>0) - { - KeQueryTickCount((LARGE_INTEGER *)&HH);//IoInputDword(0x8008); - //temp = HH - LAST_USB_EVENT_TICK; - - //if (temp>(3579)) { //3579 = 1ms! - //if (temp>1000) { - do_all_timers(); - // LAST_USB_EVENT_TICK = HH; - //} - - handle_irqs(-1); - - if (need_wakeup) - break; - - delay.QuadPart = -10; - KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1); - x-=1; - //DPRINT("schedule_timeout(): time left: %d\n", x); - } - need_wakeup=0; - - printk("schedule DONE!!!!!!\n"); - - return 0;//x; -} -/*------------------------------------------------------------------------*/ -void my_wait_for_completion(struct completion *x) -{ -// LONGLONG HH; -// LONGLONG temp; - LARGE_INTEGER delay; - - //extern unsigned int LAST_USB_EVENT_TICK; - - printk("wait for completion, x=0x%08x\n", (DWORD)x); - - int n=10; - n = n*1000; // to us format - - while(!x->done && (n>0)) - { - //KeQueryTickCount((LARGE_INTEGER *)&HH);//IoInputDword(0x8008); - //temp = HH - LAST_USB_EVENT_TICK; - - //if (temp>(3579)) { - //if (temp>(1000)) { - do_all_timers(); - // LAST_USB_EVENT_TICK = HH; - //} - - handle_irqs(-1); - - delay.QuadPart = -10; - KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1); - n--; - } - printk("wait for completion done %i\n",x->done); - -} -/*------------------------------------------------------------------------*/ -void my_init_completion(struct completion *x) -{ - x->done=0; - KeInitializeEvent(&x->wait, NotificationEvent, FALSE); -} -/*------------------------------------------------------------------------*/ -void my_interruptible_sleep_on(PKEVENT evnt) -{ - KeWaitForSingleObject(evnt, Executive, KernelMode, FALSE, NULL); - KeClearEvent(evnt); // reset to not-signalled -} -/*------------------------------------------------------------------------*/ -// Helper for pci_module_init -/*------------------------------------------------------------------------*/ -int my_pci_module_init(struct pci_driver *x) -{ - struct pci_dev *dev=pci_probe_dev; - const struct pci_device_id *id=NULL; - if (!pci_probe_dev) - { - DPRINT1("PCI device not set!\n"); - return 0; - } - x->probe(dev, id); - return 0; -} -/*------------------------------------------------------------------------*/ -struct pci_dev *my_pci_find_slot(int a,int b) -{ - return NULL; -} -/*------------------------------------------------------------------------*/ -int my_pci_write_config_word(struct pci_dev *dev, int where, u16 val) -{ - //dev->bus, dev->devfn, where, val - PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext; - - //FIXME: Is returning this value correct? - //FIXME: Mixing pci_dev and win structs isn't a good thing at all - return HalSetBusDataByOffset(PCIConfiguration, dev->bus->number, dev_ext->SystemIoSlotNumber, &val, where, sizeof(val)); -} -/*------------------------------------------------------------------------*/ -int my_request_irq(unsigned int irq, - int (*handler)(int,void *, struct pt_regs *), - unsigned long mode, const char *desc, void *data) -{ - if (num_irqsdmaChannel; - dd.MaximumLength = 128;//MAX_DMA_LENGTH; - dd.DmaWidth = Width32Bits; - dd.DmaSpeed = MaximumDmaSpeed; - - // The following taken from Win2k DDB: - // "Compute the maximum number of mapping regs - // this device could possibly need. Since the - // transfer may not be paged aligned, add one - // to allow the max xfer size to span a page." - //pDevExt->mapRegisterCount = (MAX_DMA_LENGTH / PAGE_SIZE) + 1; - - // TODO: Free it somewhere (PutDmaAdapter) - pDevExt->pDmaAdapter = - IoGetDmaAdapter( pDevExt->PhysicalDeviceObject, - &dd, - &pDevExt->mapRegisterCount); - - DPRINT1("IoGetDmaAdapter done 0x%X, mapRegisterCount=%d\n", pDevExt->pDmaAdapter, pDevExt->mapRegisterCount); - - // Fail if failed - if (pDevExt->pDmaAdapter == NULL) - return STATUS_INSUFFICIENT_RESOURCES; - -#ifdef USB_DMA_SINGLE_SUPPORT - /* Allocate buffer now */ - pDevExt->BufferSize = pDevExt->mapRegisterCount * PAGE_SIZE; - DPRINT1("Bufsize = %u\n", pDevExt->BufferSize); - pDevExt->VirtualBuffer = pDevExt->pDmaAdapter->DmaOperations->AllocateCommonBuffer( - pDevExt->pDmaAdapter, pDevExt->BufferSize, &pDevExt->Buffer, FALSE); - DPRINT1("Bufsize = %u, Buffer = 0x%x", pDevExt->BufferSize, pDevExt->Buffer.LowPart); - - if (!pDevExt->VirtualBuffer) - { - DPRINT1("Could not allocate buffer\n"); - // should try again with smaller buffer... - return STATUS_INSUFFICIENT_RESOURCES; - } - - DPRINT1("Calling IoAllocateMdl()\n"); - pDevExt->Mdl = IoAllocateMdl(pDevExt->VirtualBuffer, pDevExt->BufferSize, FALSE, FALSE, NULL); - DPRINT1("Bufsize == %u\n", pDevExt->BufferSize); - - if (!pDevExt->Mdl) - { - DPRINT1("IoAllocateMdl() FAILED\n"); - //TODO: Free the HAL buffer - return STATUS_INSUFFICIENT_RESOURCES; - } - - DPRINT1("VBuffer == 0x%x Mdl == %u Bufsize == %u\n", pDevExt->VirtualBuffer, pDevExt->Mdl, pDevExt->BufferSize); - - DPRINT1("Calling MmBuildMdlForNonPagedPool\n"); - MmBuildMdlForNonPagedPool(pDevExt->Mdl); - - - /* Get map registers for DMA */ - KeInitializeEvent(&DMAEvent, SynchronizationEvent, FALSE); - - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - // TODO: Free adapter channel somewhere - Status = pDevExt->pDmaAdapter->DmaOperations->AllocateAdapterChannel(pDevExt->pDmaAdapter, - pDevExt->PhysicalDeviceObject, pDevExt->mapRegisterCount, MapRegisterCallback, &DMAEvent); - KeLowerIrql(OldIrql); - - DPRINT1("VBuffer == 0x%x Bufsize == %u\n", pDevExt->VirtualBuffer, pDevExt->BufferSize); - KeWaitForSingleObject(&DMAEvent, Executive, KernelMode, FALSE, NULL); - - if(Status != STATUS_SUCCESS) - { - DPRINT("init_dma(): unable to allocate adapter channels\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } -#endif - return STATUS_SUCCESS; -} - -/* - * FUNCTION: Acquire map registers in prep for DMA - * ARGUMENTS: - * DeviceObject: unused - * Irp: unused - * MapRegisterBase: returned to blocked thread via a member var - * Context: contains a pointer to the right ControllerInfo - * struct - * RETURNS: - * KeepObject, because that's what the DDK says to do - */ -#ifdef USB_DMA_SINGLE_SUPPORT -static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback(PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID MapRegisterBase, - PVOID Context) -{ - PUSBMP_DEVICE_EXTENSION pDevExt = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - UNREFERENCED_PARAMETER(Irp); - - DPRINT("usb_linuxwrapper: MapRegisterCallback Called, base=0x%08x\n", MapRegisterBase); - - pDevExt->MapRegisterBase = MapRegisterBase; - - // signal that we are finished - KeSetEvent(Context, 0, FALSE); - - return KeepObject;//DeallocateObjectKeepRegisters; -} -#endif - -void *my_dma_pool_alloc(struct dma_pool *pool, int gfp_flags, dma_addr_t *dma_handle) -{ - // HalAllocCommonBuffer - // But ideally IoGetDmaAdapter - - DPRINT1("dma_pool_alloc() called\n"); - return NULL; -} - -/* -pci_pool_create -- Creates a pool of pci consistent memory blocks, for dma. - -struct pci_pool * pci_pool_create (const char * name, struct pci_dev * pdev, size_t size, size_t align, size_t allocation, int flags); - -Arguments: -name - name of pool, for diagnostics -pdev - pci device that will be doing the DMA -size - size of the blocks in this pool. -align - alignment requirement for blocks; must be a power of two -allocation - returned blocks won't cross this boundary (or zero) -flags - SLAB_* flags (not all are supported). - -Description: -Returns a pci allocation pool with the requested characteristics, or null if one can't be created. -Given one of these pools, pci_pool_alloc may be used to allocate memory. Such memory will all have -"consistent" DMA mappings, accessible by the device and its driver without using cache flushing -primitives. The actual size of blocks allocated may be larger than requested because of alignment. -If allocation is nonzero, objects returned from pci_pool_alloc won't cross that size boundary. -This is useful for devices which have addressing restrictions on individual DMA transfers, such -as not crossing boundaries of 4KBytes. -*/ -struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, size_t size, size_t align, size_t allocation) -{ - struct pci_pool *retval; - - if (align == 0) - align = 1; - if (size == 0) - return 0; - else if (size < align) - size = align; - else if ((size % align) != 0) { - size += align + 1; - size &= ~(align - 1); - } - - if (allocation == 0) { - if (PAGE_SIZE < size) - allocation = size; - else - allocation = PAGE_SIZE; - // FIXME: round up for less fragmentation - } else if (allocation < size) - return 0; - - retval = ExAllocatePool(NonPagedPool, sizeof(struct pci_pool)); // Non-paged because could be - // accesses at IRQL < PASSIVE - - // fill retval structure - strncpy (retval->name, name, sizeof retval->name); - retval->name[sizeof retval->name - 1] = 0; - - retval->allocation = allocation; - retval->size = size; - retval->blocks_per_page = allocation / size; - retval->pdev = pdev; - - retval->pages_allocated = 0; - retval->blocks_allocated = 0; - - DPRINT("pci_pool_create(): %s/%s size %d, %d/page (%d alloc)\n", - pdev ? pdev->slot_name : NULL, retval->name, size, - retval->blocks_per_page, allocation); - - return retval; -} - -/* -Name: -pci_pool_alloc -- get a block of consistent memory - -Synopsis: -void * pci_pool_alloc (struct pci_pool * pool, int mem_flags, dma_addr_t * handle); - -Arguments: -pool - pci pool that will produce the block - -mem_flags - SLAB_KERNEL or SLAB_ATOMIC - -handle - pointer to dma address of block - -Description: -This returns the kernel virtual address of a currently unused block, and reports its dma -address through the handle. If such a memory block can't be allocated, null is returned. -*/ -void * my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_handle) -{ - PVOID result; - PUSBMP_DEVICE_EXTENSION devExt = (PUSBMP_DEVICE_EXTENSION)pool->pdev->dev_ext; - int page=0, offset; - int map, i, block; - - //DPRINT1("pci_pool_alloc() called, blocks already allocated=%d, dma_handle=%p\n", pool->blocks_allocated, dma_handle); - //ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); - - if (pool->pages_allocated == 0) - { - // we need to allocate at least one page - pool->pages[pool->pages_allocated].virtualAddress = - devExt->pDmaAdapter->DmaOperations->AllocateCommonBuffer(devExt->pDmaAdapter, - PAGE_SIZE, &pool->pages[pool->pages_allocated].dmaAddress, FALSE); //FIXME: Cache-enabled? - - // mark all blocks as free (bit=set) - memset(pool->pages[pool->pages_allocated].bitmap, 0xFF, 128*sizeof(unsigned long)); - - /* FIXME: the next line replaces physical address by virtual address: - * this change is needed to boot VMWare, but I'm really not sure this - * change is correct! - */ - //pool->pages[pool->pages_allocated].dmaAddress.QuadPart = (ULONG_PTR)pool->pages[pool->pages_allocated].virtualAddress; - pool->pages_allocated++; - } - - // search for a free block in all pages - for (page=0; pagepages_allocated; page++) - { - for (map=0,i=0; i < pool->blocks_per_page; i+= BITS_PER_LONG, map++) - { - if (pool->pages[page].bitmap[map] == 0) - continue; - - block = ffz(~ pool->pages[page].bitmap[map]); - - if ((i + block) < pool->blocks_per_page) - { - //DPRINT("pci_pool_alloc(): Allocating block %p:%d:%d:%d\n", pool, page, map, block); - clear_bit(block, &pool->pages[page].bitmap[map]); - offset = (BITS_PER_LONG * map) + block; - offset *= pool->size; - goto ready; - } - } - } - - //TODO: alloc page here then - DPRINT1("Panic!! We need one more page to be allocated, and Fireball doesn't want to alloc it!\n"); - offset = 0; - return 0; - -ready: - *dma_handle = pool->pages[page].dmaAddress.QuadPart + offset; - result = (char *)pool->pages[page].virtualAddress + offset; - pool->blocks_allocated++; - - return result; -} - -/* -Name -pci_pool_free -- put block back into pci pool -Synopsis - -void pci_pool_free (struct pci_pool * pool, void * vaddr, dma_addr_t dma); - -Arguments - -pool - the pci pool holding the block - -vaddr - virtual address of block - -dma - dma address of block - -Description: -Caller promises neither device nor driver will again touch this block unless it is first re-allocated. -*/ -void my_pci_pool_free (struct pci_pool * pool, void * vaddr, dma_addr_t dma) -{ - int page, block, map; - - // Find page - for (page=0; pagepages_allocated; page++) - { - if (dma < pool->pages[page].dmaAddress.QuadPart) - continue; - if (dma < (pool->pages[page].dmaAddress.QuadPart + pool->allocation)) - break; - } - - block = dma - pool->pages[page].dmaAddress.QuadPart; - block /= pool->size; - map = block / BITS_PER_LONG; - block %= BITS_PER_LONG; - - // mark as free - set_bit (block, &pool->pages[page].bitmap[map]); - - pool->blocks_allocated--; - //DPRINT("pci_pool_free(): alloc'd: %d\n", pool->blocks_allocated); -} - -/* -pci_pool_destroy -- destroys a pool of pci memory blocks. -Synopsis - -void pci_pool_destroy (struct pci_pool * pool); - - -Arguments: -pool - pci pool that will be destroyed - -Description -Caller guarantees that no more memory from the pool is in use, and that nothing will try to -use the pool after this call. -*/ -void __inline__ my_pci_pool_destroy (struct pci_pool * pool) -{ - DPRINT1("pci_pool_destroy(): alloc'd: %d, UNIMPLEMENTED\n", pool->blocks_allocated); - - ExFreePool(pool); -} - -void *my_pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) -{ - PUSBMP_DEVICE_EXTENSION devExt = (PUSBMP_DEVICE_EXTENSION)hwdev->dev_ext; - DPRINT1("pci_alloc_consistent() size=%d\n", size); - - return devExt->pDmaAdapter->DmaOperations->AllocateCommonBuffer(devExt->pDmaAdapter, size, (PPHYSICAL_ADDRESS)dma_handle, FALSE); //FIXME: Cache-enabled? -} - -dma_addr_t my_dma_map_single(struct device *hwdev, void *ptr, size_t size, enum dma_data_direction direction) -{ - //PHYSICAL_ADDRESS BaseAddress; - //PUSBMP_DEVICE_EXTENSION pDevExt = (PUSBMP_DEVICE_EXTENSION)hwdev->dev_ext; - //PUCHAR VirtualAddress = (PUCHAR) MmGetMdlVirtualAddress(pDevExt->Mdl); - //ULONG transferSize = size; - //BOOLEAN WriteToDevice; - - //DPRINT1("dma_map_single() ptr=0x%lx, size=0x%x, dir=%d\n", ptr, size, direction); - /*ASSERT(pDevExt->BufferSize > size); - - // FIXME: It must be an error if DMA_BIDIRECTIONAL trasnfer happens, since MSDN says - // the buffer is locked - if (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE) - WriteToDevice = TRUE; - else - WriteToDevice = FALSE; - - DPRINT1("IoMapTransfer\n"); - BaseAddress = pDevExt->pDmaAdapter->DmaOperations->MapTransfer(pDevExt->pDmaAdapter, - pDevExt->Mdl, - pDevExt->MapRegisterBase, - (PUCHAR) MmGetMdlVirtualAddress(pDevExt->Mdl), - &transferSize, - WriteToDevice); - - if (WriteToDevice) - { - DPRINT1("Writing to the device...\n"); - memcpy(VirtualAddress, ptr, size); - } - else - { - DPRINT1("Reading from the device...\n"); - memcpy(ptr, VirtualAddress, size); - }*/ - - //DPRINT1("VBuffer == 0x%x (really 0x%x?) transf_size == %u\n", pDevExt->VirtualBuffer, MmGetPhysicalAddress(pDevExt->VirtualBuffer).LowPart, transferSize); - //DPRINT1("VBuffer == 0x%x (really 0x%x?) transf_size == %u\n", ptr, MmGetPhysicalAddress(ptr).LowPart, transferSize); - - return MmGetPhysicalAddress(ptr).QuadPart;//BaseAddress.QuadPart; /* BIG HACK */ -} - -// 2.6 version of pci_unmap_single -//void my_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction) -void my_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction) -{ - //DPRINT1("dma_unmap_single() called, nothing to do\n"); - /* nothing yet */ -} - -void my_dma_sync_single(struct device *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - DPRINT1("dma_sync_single() called, UNIMPLEMENTED\n"); - /* nothing yet */ -} - -void my_dma_sync_sg(struct device *hwdev, - struct scatterlist *sg, - int nelems, int direction) -{ - DPRINT1("dma_sync_sg() called, UNIMPLEMENTED\n"); - /* nothing yet */ -} - - -int my_dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction) -{ - DPRINT1("dma_map_sg() called, UNIMPLEMENTED\n"); - return 0; -} - -void my_dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction) -{ - DPRINT1("dma_unmap_sg() called, UNIMPLEMENTED\n"); - /* nothing yet */ -} - -/* forwarder ro dma_ equivalent */ -void my_pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction) -{ - my_dma_unmap_single(&hwdev->dev, dma_addr, size, direction); -} - - -/*------------------------------------------------------------------------*/ -/* SPINLOCK routines */ -/*------------------------------------------------------------------------*/ -void my_spin_lock_init(spinlock_t *sl) -{ - KeInitializeSpinLock(&sl->SpinLock); -} - -void my_spin_lock(spinlock_t *sl) -{ - //KeAcquireSpinLock(&sl->SpinLock, &sl->OldIrql); -} - -void my_spin_unlock(spinlock_t *sl) -{ - //KeReleaseSpinLock(&sl->SpinLock, sl->OldIrql); -} - -void my_spin_lock_irqsave(spinlock_t *sl, int flags) -{ - my_spin_lock(sl); -} diff --git a/reactos/drivers/usb/miniport/sys/risefall.c b/reactos/drivers/usb/miniport/sys/risefall.c deleted file mode 100644 index c1df183567d..00000000000 --- a/reactos/drivers/usb/miniport/sys/risefall.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "../usb_wrapper.h" -#include "config.h" -#include "xremote.h" - -// This is for the Xpad -extern unsigned char xpad_button_history[7]; - -// This is for the Keyboard -extern unsigned int current_keyboard_key; - -int risefall_xpad_BUTTON(unsigned char selected_Button) { - - int xpad_id; - int match; - extern int xpad_num; - - // USB keyboard section - - match=0; - if (current_keyboard_key!=0) { - switch (selected_Button) { - case TRIGGER_XPAD_KEY_A : - if (current_keyboard_key == 0x28) match=1; - break; - case TRIGGER_XPAD_KEY_B : - if (current_keyboard_key == 0x29) match=1; - break; - case TRIGGER_XPAD_PAD_UP : - if (current_keyboard_key == 0x52) match=1; - break; - case TRIGGER_XPAD_PAD_DOWN : - if (current_keyboard_key == 0x51) match=1; - break; - case TRIGGER_XPAD_PAD_LEFT : - if (current_keyboard_key == 0x50) match=1; - break; - case TRIGGER_XPAD_PAD_RIGHT : - if (current_keyboard_key == 0x4f) match=1; - break; - } - - if (match) { - //A match occurred, so the event has now been processed - //Clear it, and return success - current_keyboard_key=0; - return 1; - } - } - - // Xbox IR remote section - - match=0; - if (!remotekeyIsRepeat) { - /* We only grab the key event when the button is first pressed. - * If it's being held down, we ignore the multiple events this - * generates */ - - switch (selected_Button) { - case TRIGGER_XPAD_KEY_A: - if (current_remote_key == RC_KEY_SELECT) match=1; - break; - case TRIGGER_XPAD_PAD_UP: - if (current_remote_key == RC_KEY_UP) match=1; - break; - case TRIGGER_XPAD_PAD_DOWN: - if (current_remote_key == RC_KEY_DOWN) match=1; - break; - case TRIGGER_XPAD_PAD_LEFT: - if (current_remote_key == RC_KEY_LEFT) match=1; - break; - case TRIGGER_XPAD_PAD_RIGHT: - if (current_remote_key == RC_KEY_RIGHT) match=1; - break; - case TRIGGER_XPAD_KEY_BACK: - if (current_remote_key == RC_KEY_BACK) match=1; - break; - } - if (match) { - //A match occurred, so the event has now been processed - //Clear it, and return success - current_remote_key=0; - remotekeyIsRepeat=0; - return 1; - } - } - - // Xbox controller section - if (selected_Button < 6) { - - unsigned char Button; - - Button = XPAD_current[0].keys[selected_Button]; - - if ((Button>0x30)&&(xpad_button_history[selected_Button]==0)) { - // Button Rising Edge - xpad_button_history[selected_Button] = 1; - return 1; - } - - if ((Button==0x00)&&(xpad_button_history[selected_Button]==1)) { - // Button Falling Edge - xpad_button_history[selected_Button] = 0; - return -1; - } - } - - if ((selected_Button > 5) & (selected_Button < 10) ) { - - unsigned char Buttonmask; - - switch (selected_Button) { - case TRIGGER_XPAD_PAD_UP : - Buttonmask = XPAD_PAD_UP; - break; - case TRIGGER_XPAD_PAD_DOWN : - Buttonmask = XPAD_PAD_DOWN; - break; - case TRIGGER_XPAD_PAD_LEFT : - Buttonmask = XPAD_PAD_LEFT; - break; - case TRIGGER_XPAD_PAD_RIGHT : - Buttonmask = XPAD_PAD_RIGHT; - break; - } - - // Rising Edge - if (((XPAD_current[0].pad&Buttonmask) != 0) & ((xpad_button_history[6]&Buttonmask) == 0)) { - xpad_button_history[6] ^= Buttonmask; // Flip the Bit - return 1; - } - // Falling Edge - if (((XPAD_current[0].pad&Buttonmask) == 0) & ((xpad_button_history[6]&Buttonmask) != 0)) { - xpad_button_history[6] ^= Buttonmask; // Flip the Bit - return -1; - } - } - return 0; -} diff --git a/reactos/drivers/usb/miniport/sys/ros_wrapper.c b/reactos/drivers/usb/miniport/sys/ros_wrapper.c deleted file mode 100644 index 17f5cf1f851..00000000000 --- a/reactos/drivers/usb/miniport/sys/ros_wrapper.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "../usb_wrapper.h" - - -void wait_ms(int mils) -{ - LARGE_INTEGER Interval; - - DPRINT1("wait_ms(%d)\n", mils); - - Interval.QuadPart = -(mils+1)*10000; - KeDelayExecutionThread(KernelMode, FALSE, &Interval); - -// schedule_timeout(1 + mils * HZ / 1000); -} - -void my_udelay(int us) -{ - LARGE_INTEGER Interval; - - DPRINT1("udelay(%d)\n", us); - - Interval.QuadPart = -us*10; - KeDelayExecutionThread(KernelMode, FALSE, &Interval); -} diff --git a/reactos/drivers/usb/miniport/sys/sys.rbuild b/reactos/drivers/usb/miniport/sys/sys.rbuild deleted file mode 100644 index 4cd92675fa4..00000000000 --- a/reactos/drivers/usb/miniport/sys/sys.rbuild +++ /dev/null @@ -1,7 +0,0 @@ - - - - include - ros_wrapper.c - linuxwrapper.c - \ No newline at end of file diff --git a/reactos/drivers/usb/miniport/sys/usbkey.c b/reactos/drivers/usb/miniport/sys/usbkey.c deleted file mode 100644 index 5411055493d..00000000000 --- a/reactos/drivers/usb/miniport/sys/usbkey.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "../usb_wrapper.h" - -#define keyboarddebug 1 - -#if keyboarddebug -//extern int printk(const char *szFormat, ...); -int ycoffset = 0; -#endif - -unsigned int current_keyboard_key; - -struct usb_kbd_info { - struct urb *urb; - unsigned char kbd_pkt[8]; - unsigned char old[8]; - - /* - struct input_dev dev; - struct usb_device *usbdev; - struct urb irq, led; - struct usb_ctrlrequest dr; - unsigned char leds, newleds; - char name[128]; - int open; - */ -}; - -static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_kbd_info *kbd = urb->context; - //int i; - - if (urb->status) return; - - memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8); - - current_keyboard_key = kbd->kbd_pkt[2]; - - - #if keyboarddebug - //ycoffset += 15; - //ycoffset = ycoffset % 600; - //VIDEO_CURSOR_POSX=20; - //VIDEO_CURSOR_POSY=ycoffset; - printk(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]); - #endif - - usb_submit_urb(urb,GFP_ATOMIC); - -} - -static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct urb *urb; - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_endpoint_descriptor *ep_irq_in; - //struct usb_endpoint_descriptor *ep_irq_out; - struct usb_kbd_info *usbk; - - //int i, pipe, maxp; - //char *buf; - - usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0); - if (!usbk) return -1; - - urb=usb_alloc_urb(0,0); - if (!urb) return -1; - - usbk->urb=urb; - - ep_irq_in = &intf->altsetting[0].endpoint[0].desc; - usb_fill_int_urb(urb, udev, - usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), - usbk->kbd_pkt, 8, usb_kbd_irq, - usbk, 8); - - usb_submit_urb(urb,GFP_ATOMIC); - usb_set_intfdata(intf,usbk); - #if keyboarddebug - printk("USB Keyboard Connected\n"); - #endif - - return 0; -} - - -static void usb_kbd_disconnect(struct usb_interface *intf) -{ - struct usb_kbd_info *usbk = usb_get_intfdata (intf); - usbprintk("Keyboard disconnected\n "); - usb_unlink_urb(usbk->urb); - usb_free_urb(usbk->urb); - kfree(usbk); -} - -static struct usb_device_id usb_kbd_id_table [] = { - { USB_INTERFACE_INFO(3, 1, 1) }, - { } /* Terminating entry */ -}; - - -static struct usb_driver usb_kbd_driver = { - .owner = THIS_MODULE, - .name = "keyboard", - .probe = usb_kbd_probe, - .disconnect = usb_kbd_disconnect, - .id_table = usb_kbd_id_table, -}; - -void UsbKeyBoardInit(void) -{ - //current_remote_key=0; - //sbprintk("Keyboard probe %p ",xremote_probe); - if (usb_register(&usb_kbd_driver) < 0) { - #if keyboarddebug - printk("Unable to register Keyboard driver"); - #endif - return; - } -} - -void UsbKeyBoardRemove(void) { - usb_deregister(&usb_kbd_driver); -} diff --git a/reactos/drivers/usb/miniport/sys/usbwrapper.c b/reactos/drivers/usb/miniport/sys/usbwrapper.c deleted file mode 100644 index ce952e4ab4a..00000000000 --- a/reactos/drivers/usb/miniport/sys/usbwrapper.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Interface calls to BIOS - * - * 2003-06-21 Georg Acher (georg@acher.org) - * - */ - -#include "boot.h" -#include -#include "video.h" - -/*------------------------------------------------------------------------*/ -// Output window for USB messages -int usb_curs_x=0; -int usb_curs_y=0; - -void zxprintf(char* fmt, ...) -{ - va_list ap; - char buffer[1024]; - int tmp_x, tmp_y; - tmp_x=VIDEO_CURSOR_POSX; - tmp_y=VIDEO_CURSOR_POSY; - - VIDEO_CURSOR_POSX=usb_curs_x; - VIDEO_CURSOR_POSY=usb_curs_y; - - if ((VIDEO_CURSOR_POSY==0) || (VIDEO_CURSOR_POSY > (vmode.height -16))) - { - BootVideoClearScreen(&jpegBackdrop, 3*vmode.height/4, - vmode.height); - VIDEO_CURSOR_POSY=3*vmode.height/4; - } - - va_start(ap, fmt); - vsprintf(buffer,fmt,ap); - //printk(buffer); - va_end(ap); - - usb_curs_x=VIDEO_CURSOR_POSX; - usb_curs_y=VIDEO_CURSOR_POSY; - VIDEO_CURSOR_POSX=tmp_x; - VIDEO_CURSOR_POSY=tmp_y; -} -/*------------------------------------------------------------------------*/ -int zxsnprintf(char *buffer, size_t s, char* fmt, ...) -{ - va_list ap; - int x; - va_start(ap, fmt); - x=vsprintf(buffer,fmt,ap); - va_end(ap); - return x; -} -/*------------------------------------------------------------------------*/ -int zxsprintf(char *buffer, char* fmt, ...) -{ - va_list ap; - int x; - va_start(ap, fmt); - x=vsprintf(buffer,fmt,ap); - va_end(ap); - return x; -} -/*------------------------------------------------------------------------*/ diff --git a/reactos/drivers/usb/miniport/sys/xpad.c b/reactos/drivers/usb/miniport/sys/xpad.c deleted file mode 100644 index 55360369955..00000000000 --- a/reactos/drivers/usb/miniport/sys/xpad.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Simple XPAD driver for XBOX - * - * (c) 2003-07-04, Georg Acher (georg@acher.org) - * - * Inspired by linux/drivers/usb/input/xpad.c - * by Marko Friedemann - * - */ - - - -#include "../usb_wrapper.h" -#include "config.h" - -// history for the Rising - falling events -unsigned char xpad_button_history[7]; - -/* Stores time and XPAD state */ -struct xpad_data XPAD_current[4]; -struct xpad_data XPAD_last[4]; - -struct xpad_info -{ - struct urb *urb; - int num; - unsigned char data[32]; -}; - -int xpad_num=0; -/*------------------------------------------------------------------------*/ -static void xpad_irq(struct urb *urb, struct pt_regs *regs) -{ - struct xpad_info *xpi = urb->context; - unsigned char* data= urb->transfer_buffer; - -// struct xpad_data *xp=&XPAD_current[xpi->num]; -// struct xpad_data *xpo=&XPAD_last[xpi->num]; - - /* This hack means the xpad event always gets posted to the - * first xpad - avoids problems iterating over multiple xpads - * as the xpi->num entries are not reused when xpads are - * connected, then removed */ - - struct xpad_data *xp=&XPAD_current[0]; - struct xpad_data *xpo=&XPAD_last[0]; - - if (xpi->num<0 || xpi->num>3) - return; - - memcpy(xpo,xp,sizeof(struct xpad_data)); - - xp->stick_left_x=(short) (((short)data[13] << 8) | data[12]); - xp->stick_left_y=(short) (((short)data[15] << 8) | data[14]); - xp->stick_right_x=(short) (((short)data[17] << 8) | data[16]); - xp->stick_right_y=(short) (((short)data[19] << 8) | data[18]); - xp->trig_left= data[10]; - xp->trig_right= data[11]; - xp->pad = data[2]&0xf; - xp->state = (data[2]>>4)&0xf; - xp->keys[0] = data[4]; // a - xp->keys[1] = data[5]; // b - xp->keys[2] = data[6]; // x - xp->keys[3] = data[7]; // y - xp->keys[4] = data[8]; // black - xp->keys[5] = data[9]; // white - xp->timestamp=jiffies; // FIXME: A more uniform flowing time would be better... - usb_submit_urb(urb,GFP_ATOMIC); - -} -/*------------------------------------------------------------------------*/ -static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct urb *urb; - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_endpoint_descriptor *ep_irq_in; - struct usb_endpoint_descriptor *ep_irq_out; - struct xpad_info *xpi; - - xpi=kmalloc(sizeof(struct xpad_info),GFP_KERNEL); - if (!xpi) return -1; - - urb=usb_alloc_urb(0,0); - if (!urb) return -1; - - xpi->urb=urb; - xpi->num=xpad_num; - ep_irq_in = &intf->altsetting[0].endpoint[0].desc; - usb_fill_int_urb(urb, udev, - usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), - xpi->data, 32, xpad_irq, - xpi, 32); - - usb_submit_urb(urb,GFP_ATOMIC); - - usb_set_intfdata(intf,xpi); - usbprintk("XPAD #%i connected\n",xpad_num); - #ifdef XPAD_VIBRA_STARTUP - { - // Brum Brum - char data1[6]={0,6,0,120,0,120}; - char data2[6]={0,6,0,0,0,0}; - int dummy; - - usb_bulk_msg(udev, usb_sndbulkpipe(udev,2), - data1, 6, &dummy, 500); - wait_ms(500); - usb_bulk_msg(udev, usb_sndbulkpipe(udev,2), - data2, 6, &dummy, 500); - } - #endif - xpad_num++; - return 0; -} -/*------------------------------------------------------------------------*/ -static void xpad_disconnect(struct usb_interface *intf) -{ - struct xpad_info *xpi=usb_get_intfdata (intf); - usb_unlink_urb(xpi->urb); - usb_free_urb(xpi->urb); - kfree(xpi); - xpad_num--; -} -/*------------------------------------------------------------------------*/ -static struct usb_device_id xpad_ids [] = { - { USB_DEVICE(0x044f, 0x0f07) },//Thrustmaster, Inc. Controller - { USB_DEVICE(0x045e, 0x0202) },//Microsoft Xbox Controller - { USB_DEVICE(0x045e, 0x0285) },//Microsoft Xbox Controller S - { USB_DEVICE(0x045e, 0x0289) },//Microsoft Xbox Controller S - { USB_DEVICE(0x046d, 0xca88) },//Logitech Compact Controller for Xbox - { USB_DEVICE(0x05fd, 0x1007) },//???Mad Catz Controller??? - { USB_DEVICE(0x05fd, 0x107a) },//InterAct PowerPad Pro - { USB_DEVICE(0x0738, 0x4516) },//Mad Catz Control Pad - { USB_DEVICE(0x0738, 0x4522) },//Mad Catz LumiCON - { USB_DEVICE(0x0738, 0x4526) },//Mad Catz Control Pad Pro - { USB_DEVICE(0x0738, 0x4536) },//Mad Catz MicroCON - { USB_DEVICE(0x0738, 0x4556) },//Mad Catz Lynx Wireless Controller - { USB_DEVICE(0x0c12, 0x9902) },//HAMA VibraX - *FAULTY HARDWARE* - { USB_DEVICE(0x0e4c, 0x1097) },//Radica Gamester Controller - { USB_DEVICE(0x0e4c, 0x2390) },//Radica Games Jtech Controller - { USB_DEVICE(0x0e6f, 0x0003) },//Logic3 Freebird wireless Controller - { USB_DEVICE(0x0e6f, 0x0005) },//Eclipse wireless Controlle - { USB_DEVICE(0x0f30, 0x0202) },//Joytech Advanced Controller - { USB_DEVICE(0xffff, 0xffff) },//Chinese-made Xbox Controller - { USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL - { } /* Terminating entry */ -}; - - -static struct usb_driver xpad_driver = { - .owner = THIS_MODULE, - .name = "XPAD", - .probe = xpad_probe, - .disconnect = xpad_disconnect, - .id_table = xpad_ids, -}; - -/*------------------------------------------------------------------------*/ -void XPADInit(void) -{ - int n; - for(n=0;n<4;n++) - { - memset(&XPAD_current[n], 0, sizeof(struct xpad_data)); - memset(&XPAD_last[n], 0, sizeof(struct xpad_data)); - } - memset(&xpad_button_history, 0, sizeof(xpad_button_history)); - - usbprintk("XPAD probe %p ",xpad_probe); - if (usb_register(&xpad_driver) < 0) { - err("Unable to register XPAD driver"); - return; - } -} -/*------------------------------------------------------------------------*/ -void XPADRemove(void) { - usb_deregister(&xpad_driver); -} - -/*------------------------------------------------------------------------*/ - - - diff --git a/reactos/drivers/usb/miniport/sys/xremote.c b/reactos/drivers/usb/miniport/sys/xremote.c deleted file mode 100644 index 3b98dec8572..00000000000 --- a/reactos/drivers/usb/miniport/sys/xremote.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * $Id$ - * - * Copyright (c) 2002 Steven Toth - * - * XBOX DVD dongle infrared device driver for the input driver suite. - * - * This work was derived from the usbkbd.c kernel module. - * - * History: - * - * 2002_08_31 - 0.1 - Initial release - * 2002_09_02 - 0.2 - Added IOCTL support enabling user space administration - * of the translation matrix. - * - */ - -#include "../usb_wrapper.h" - - -u16 current_remote_key; -u8 remotekeyIsRepeat; - -struct xremote_info -{ - struct urb *urb; - unsigned char irpkt[8]; -}; - -/* USB callback completion handler - * Code in transfer_buffer is received as six unsigned chars - * Example PLAY=00 06 ea 0a 40 00 - * The command is located in byte[2], the rest are ignored. - * Key position is byte[4] bit0 (7-0 format) 0=down, 1=up - * All other bits are unknown / now required. - */ - -static void xremote_irq(struct urb *urb, struct pt_regs *regs) -{ - struct xremote_info *xri = urb->context; - - if (urb->status) return; - if (urb->actual_length < 6) return; - - /* Messy/unnecessary, fix this */ - memcpy(xri->irpkt, urb->transfer_buffer, 6); - - /* Set the key action based in the sent action */ - current_remote_key = ((xri->irpkt[2] & 0xff)<<8) | (xri->irpkt[3] & 0xff); - - if (((xri->irpkt[4] & 0xff) + ((xri->irpkt[5] & 0xff ) << 8))>0x41) { - remotekeyIsRepeat=0; - } - else remotekeyIsRepeat=1; - - usb_submit_urb(urb,GFP_ATOMIC); -} - -static int xremote_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct urb *urb; - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_endpoint_descriptor *ep_irq_in; - struct usb_endpoint_descriptor *ep_irq_out; - struct xremote_info *xri; - - xri=(struct xremote_info *)kmalloc(sizeof(struct xremote_info),0); - if (!xri) return -1; - - urb=usb_alloc_urb(0,0); - if (!urb) return -1; - - xri->urb=urb; - - ep_irq_in = &intf->altsetting[0].endpoint[0].desc; - usb_fill_int_urb(urb, udev, - usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), - xri->irpkt, 8, xremote_irq, - xri, 8); - - usb_submit_urb(urb,GFP_ATOMIC); - usb_set_intfdata(intf,xri); - - usbprintk("DVD Remote connected\n"); - return 0; -} - -static void xremote_disconnect(struct usb_interface *intf) -{ - struct xremote_info *xri = usb_get_intfdata (intf); - usbprintk("DVD Remote disconnected\n "); - usb_unlink_urb(xri->urb); - usb_free_urb(xri->urb); - kfree(xri); -} - -static struct usb_device_id xremote_id_table [] = { - { USB_DEVICE(0x040b, 0x6521) }, /* Gamester Xbox DVD Movie Playback Kit IR */ - { USB_DEVICE(0x045e, 0x0284) }, /* Microsoft Xbox DVD Movie Playback Kit IR */ - { USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL - { } /* Terminating entry */ -}; - -static struct usb_driver xremote_driver = { - .owner = THIS_MODULE, - .name = "XRemote", - .probe = xremote_probe, - .disconnect = xremote_disconnect, - .id_table = xremote_id_table, -}; - -void XRemoteInit(void) -{ - - current_remote_key=0; - usbprintk("XRemote probe %p ",xremote_probe); - if (usb_register(&xremote_driver) < 0) { - err("Unable to register XRemote driver"); - return; - } -} - -void XRemoteRemove(void) { - usb_deregister(&xremote_driver); -} diff --git a/reactos/drivers/usb/miniport/usb_wrapper.h b/reactos/drivers/usb/miniport/usb_wrapper.h deleted file mode 100644 index f8af80646ed..00000000000 --- a/reactos/drivers/usb/miniport/usb_wrapper.h +++ /dev/null @@ -1,48 +0,0 @@ -//#include -//#include -//#include - -/* - TODO: Do a major cleanup of this file! - Lots of definitions should go to corresponding files -*/ - -#include -#include -#include - -#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24)) - -void wait_ms(int mils); -void my_udelay(int us); - -// For now this is needed only for correct operation of embedded keyboard and mouse drvs -typedef struct _USBPORT_INTERFACE -{ - PCONNECT_DATA KbdConnectData; - PCONNECT_DATA MouseConnectData; -} USBPORT_INTERFACE, *PUSBPORT_INTERFACE; - -// Register in usbcore.sys -void STDCALL RegisterPortDriver(PDRIVER_OBJECT, PUSBPORT_INTERFACE); - -#ifndef _snprintf -int _snprintf(char * buf, size_t cnt, const char *fmt, ...); -#endif -#ifndef sprintf -int sprintf(char * buf, const char *fmt, ...); -#endif -#ifndef swprintf -int swprintf(wchar_t *buf, const wchar_t *fmt, ...); -#endif - -#undef interface - -#include "linux/linux_wrapper.h" -#define __KERNEL__ -#undef CONFIG_PCI -#define CONFIG_PCI - -#include "linux/usb.h" -#include "linux/pci_ids.h" - diff --git a/reactos/drivers/usb/miniport/usbohci/makefile.crom b/reactos/drivers/usb/miniport/usbohci/makefile.crom deleted file mode 100644 index d8bfc9a4c4f..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/makefile.crom +++ /dev/null @@ -1,3 +0,0 @@ -O_TARGET := ohci-hcd.o - -include $(TOPDIR)/Rules.make diff --git a/reactos/drivers/usb/miniport/usbohci/ohci-dbg.c b/reactos/drivers/usb/miniport/usbohci/ohci-dbg.c deleted file mode 100644 index 0997ddfa28e..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci-dbg.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * This file is licenced under the GPL. - */ - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG - -#define edstring(ed_type) ({ char *temp; \ - switch (ed_type) { \ - case PIPE_CONTROL: temp = "ctrl"; break; \ - case PIPE_BULK: temp = "bulk"; break; \ - case PIPE_INTERRUPT: temp = "intr"; break; \ - default: temp = "isoc"; break; \ - }; temp;}) -#define pipestring(pipe) edstring(usb_pipetype(pipe)) - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header - */ -static void __attribute__((unused)) -urb_print (struct urb * urb, char * str, int small) -{ - unsigned int pipe= urb->pipe; - - if (!urb->dev || !urb->dev->bus) { - dbg("%s URB: no dev", str); - return; - } - -#ifndef OHCI_VERBOSE_DEBUG - if (urb->status != 0) -#endif - dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d", - str, - urb, - usb_pipedevice (pipe), - usb_pipeendpoint (pipe), - usb_pipeout (pipe)? "out" : "in", - pipestring (pipe), - urb->transfer_flags, - urb->actual_length, - urb->transfer_buffer_length, - urb->status); - -#ifdef OHCI_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol (pipe)) { - printk (KERN_DEBUG __FILE__ ": setup(8):"); - for (i = 0; i < 8 ; i++) - printk (" %02x", ((__u8 *) urb->setup_packet) [i]); - printk ("\n"); - } - if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { - printk (KERN_DEBUG __FILE__ ": data(%d/%d):", - urb->actual_length, - urb->transfer_buffer_length); - len = usb_pipeout (pipe)? - urb->transfer_buffer_length: urb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); - printk ("%s stat:%d\n", i < len? "...": "", urb->status); - } - } -#endif -} - -#define ohci_dbg_sw(ohci, next, size, format, arg...) \ - do { \ - if (next) { \ - unsigned s_len; \ - s_len = snprintf (*next, *size, format, ## arg ); \ - *size -= s_len; *next += s_len; \ - } else \ - ohci_dbg(ohci,format, ## arg ); \ - } while (0); - - -static void ohci_dump_intr_mask ( - struct ohci_hcd *ohci, - char *label, - u32 mask, - char **next, - unsigned *size) -{ - ohci_dbg_sw (ohci, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s\n", - label, - mask, - (mask & OHCI_INTR_MIE) ? " MIE" : "", - (mask & OHCI_INTR_OC) ? " OC" : "", - (mask & OHCI_INTR_RHSC) ? " RHSC" : "", - (mask & OHCI_INTR_FNO) ? " FNO" : "", - (mask & OHCI_INTR_UE) ? " UE" : "", - (mask & OHCI_INTR_RD) ? " RD" : "", - (mask & OHCI_INTR_SF) ? " SF" : "", - (mask & OHCI_INTR_WDH) ? " WDH" : "", - (mask & OHCI_INTR_SO) ? " SO" : "" - ); -} - -static void maybe_print_eds ( - struct ohci_hcd *ohci, - char *label, - u32 value, - char **next, - unsigned *size) -{ - if (value) - ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value); -} - -static char *hcfs2string (int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} - -// dump control and status registers -static void -ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) -{ - struct ohci_regs *regs = controller->regs; - u32 temp; - - temp = readl (®s->revision) & 0xff; - ohci_dbg_sw (controller, next, size, - "OHCI %d.%d, %s legacy support registers\n", - 0x03 & (temp >> 4), (temp & 0x0f), - (temp & 0x10) ? "with" : "NO"); - - temp = readl (®s->control); - ohci_dbg_sw (controller, next, size, - "control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", - temp, - (temp & OHCI_CTRL_RWE) ? " RWE" : "", - (temp & OHCI_CTRL_RWC) ? " RWC" : "", - (temp & OHCI_CTRL_IR) ? " IR" : "", - hcfs2string (temp & OHCI_CTRL_HCFS), - (temp & OHCI_CTRL_BLE) ? " BLE" : "", - (temp & OHCI_CTRL_CLE) ? " CLE" : "", - (temp & OHCI_CTRL_IE) ? " IE" : "", - (temp & OHCI_CTRL_PLE) ? " PLE" : "", - temp & OHCI_CTRL_CBSR - ); - - temp = readl (®s->cmdstatus); - ohci_dbg_sw (controller, next, size, - "cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp, - (temp & OHCI_SOC) >> 16, - (temp & OHCI_OCR) ? " OCR" : "", - (temp & OHCI_BLF) ? " BLF" : "", - (temp & OHCI_CLF) ? " CLF" : "", - (temp & OHCI_HCR) ? " HCR" : "" - ); - - ohci_dump_intr_mask (controller, "intrstatus", - readl (®s->intrstatus), next, size); - ohci_dump_intr_mask (controller, "intrenable", - readl (®s->intrenable), next, size); - // intrdisable always same as intrenable - - maybe_print_eds (controller, "ed_periodcurrent", - readl (®s->ed_periodcurrent), next, size); - - maybe_print_eds (controller, "ed_controlhead", - readl (®s->ed_controlhead), next, size); - maybe_print_eds (controller, "ed_controlcurrent", - readl (®s->ed_controlcurrent), next, size); - - maybe_print_eds (controller, "ed_bulkhead", - readl (®s->ed_bulkhead), next, size); - maybe_print_eds (controller, "ed_bulkcurrent", - readl (®s->ed_bulkcurrent), next, size); - - maybe_print_eds (controller, "donehead", - readl (®s->donehead), next, size); -} - -#define dbg_port_sw(hc,num,value,next,size) \ - ohci_dbg_sw (hc, next, size, \ - "roothub.portstatus [%d] " \ - "0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ - num, temp, \ - (temp & RH_PS_PRSC) ? " PRSC" : "", \ - (temp & RH_PS_OCIC) ? " OCIC" : "", \ - (temp & RH_PS_PSSC) ? " PSSC" : "", \ - (temp & RH_PS_PESC) ? " PESC" : "", \ - (temp & RH_PS_CSC) ? " CSC" : "", \ - \ - (temp & RH_PS_LSDA) ? " LSDA" : "", \ - (temp & RH_PS_PPS) ? " PPS" : "", \ - (temp & RH_PS_PRS) ? " PRS" : "", \ - (temp & RH_PS_POCI) ? " POCI" : "", \ - (temp & RH_PS_PSS) ? " PSS" : "", \ - \ - (temp & RH_PS_PES) ? " PES" : "", \ - (temp & RH_PS_CCS) ? " CCS" : "" \ - ); - - -static void -ohci_dump_roothub ( - struct ohci_hcd *controller, - int verbose, - char **next, - unsigned *size) -{ - u32 temp, ndp, i; - - temp = roothub_a (controller); - if (temp == ~(u32)0) - return; - ndp = (temp & RH_A_NDP); - - if (verbose) { - ohci_dbg_sw (controller, next, size, - "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, - ((temp & RH_A_POTPGT) >> 24) & 0xff, - (temp & RH_A_NOCP) ? " NOCP" : "", - (temp & RH_A_OCPM) ? " OCPM" : "", - (temp & RH_A_DT) ? " DT" : "", - (temp & RH_A_NPS) ? " NPS" : "", - (temp & RH_A_PSM) ? " PSM" : "", - ndp - ); - temp = roothub_b (controller); - ohci_dbg_sw (controller, next, size, - "roothub.b %08x PPCM=%04x DR=%04x\n", - temp, - (temp & RH_B_PPCM) >> 16, - (temp & RH_B_DR) - ); - temp = roothub_status (controller); - ohci_dbg_sw (controller, next, size, - "roothub.status %08x%s%s%s%s%s%s\n", - temp, - (temp & RH_HS_CRWE) ? " CRWE" : "", - (temp & RH_HS_OCIC) ? " OCIC" : "", - (temp & RH_HS_LPSC) ? " LPSC" : "", - (temp & RH_HS_DRWE) ? " DRWE" : "", - (temp & RH_HS_OCI) ? " OCI" : "", - (temp & RH_HS_LPS) ? " LPS" : "" - ); - } - - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus (controller, i); - dbg_port_sw (controller, i, temp, next, size); - } -} - -static void ohci_dump (struct ohci_hcd *controller, int verbose) -{ - ohci_dbg (controller, "OHCI controller state\n"); - - // dumps some of the state we know about - ohci_dump_status (controller, NULL, 0); - if (controller->hcca) - ohci_dbg (controller, - "hcca frame #%04x\n", controller->hcca->frame_no); - ohci_dump_roothub (controller, 1, NULL, 0); -} - -static const char data0 [] = "DATA0"; -static const char data1 [] = "DATA1"; - -static void ohci_dump_td (struct ohci_hcd *ohci, char *label, struct td *td) -{ - u32 tmp = le32_to_cpup (&td->hwINFO); - - ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x", - label, td, - (tmp & TD_DONE) ? " (DONE)" : "", - td->urb, td->index, - le32_to_cpup (&td->hwNextTD)); - if ((tmp & TD_ISO) == 0) { - const char *toggle, *pid; - u32 cbp, be; - - switch (tmp & TD_T) { - case TD_T_DATA0: toggle = data0; break; - case TD_T_DATA1: toggle = data1; break; - case TD_T_TOGGLE: toggle = "(CARRY)"; break; - default: toggle = "(?)"; break; - } - switch (tmp & TD_DP) { - case TD_DP_SETUP: pid = "SETUP"; break; - case TD_DP_IN: pid = "IN"; break; - case TD_DP_OUT: pid = "OUT"; break; - default: pid = "(bad pid)"; break; - } - ohci_dbg (ohci, " info %08x CC=%x %s DI=%d %s %s", tmp, - TD_CC_GET(tmp), /* EC, */ toggle, - (tmp & TD_DI) >> 21, pid, - (tmp & TD_R) ? "R" : ""); - cbp = le32_to_cpup (&td->hwCBP); - be = le32_to_cpup (&td->hwBE); - ohci_dbg (ohci, " cbp %08x be %08x (len %d)", cbp, be, - cbp ? (be + 1 - cbp) : 0); - } else { - unsigned i; - ohci_dbg (ohci, " info %08x CC=%x FC=%d DI=%d SF=%04x", tmp, - TD_CC_GET(tmp), - (tmp >> 24) & 0x07, - (tmp & TD_DI) >> 21, - tmp & 0x0000ffff); - ohci_dbg (ohci, " bp0 %08x be %08x", - le32_to_cpup (&td->hwCBP) & ~0x0fff, - le32_to_cpup (&td->hwBE)); - for (i = 0; i < MAXPSW; i++) { - u16 psw = le16_to_cpup (&td->hwPSW [i]); - int cc = (psw >> 12) & 0x0f; - ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d", i, - psw, cc, - (cc >= 0x0e) ? "OFFSET" : "SIZE", - psw & 0x0fff); - } - } -} - -/* caller MUST own hcd spinlock if verbose is set! */ -static void __attribute__((unused)) -ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose) -{ - u32 tmp = ed->hwINFO; - char *type = ""; - - ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x", - label, - ed, ed->state, edstring (ed->type), - le32_to_cpup (&ed->hwNextED)); - switch (tmp & (ED_IN|ED_OUT)) { - case ED_OUT: type = "-OUT"; break; - case ED_IN: type = "-IN"; break; - /* else from TDs ... control */ - } - ohci_dbg (ohci, - " info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp), - 0x03ff & (le32_to_cpu (tmp) >> 16), - (tmp & ED_DEQUEUE) ? " DQ" : "", - (tmp & ED_ISO) ? " ISO" : "", - (tmp & ED_SKIP) ? " SKIP" : "", - (tmp & ED_LOWSPEED) ? " LOW" : "", - 0x000f & (le32_to_cpu (tmp) >> 7), - type, - 0x007f & le32_to_cpu (tmp)); - ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s", - tmp = le32_to_cpup (&ed->hwHeadP), - (ed->hwHeadP & ED_C) ? data1 : data0, - (ed->hwHeadP & ED_H) ? " HALT" : "", - le32_to_cpup (&ed->hwTailP), - verbose ? "" : " (not listing)"); - if (verbose) { - struct list_head *tmp; - - /* use ed->td_list because HC concurrently modifies - * hwNextTD as it accumulates ed_donelist. - */ - list_for_each (tmp, &ed->td_list) { - struct td *td; - td = list_entry (tmp, struct td, td_list); - ohci_dump_td (ohci, " ->", td); - } - } -} - -#else -static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {} - -#undef OHCI_VERBOSE_DEBUG - -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files (struct ohci_hcd *bus) { } -static inline void remove_debug_files (struct ohci_hcd *bus) { } - -#else - -static inline struct ohci_hcd *dev_to_ohci (struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata (dev); - - return hcd_to_ohci (hcd); -} - -static ssize_t -show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) -{ - unsigned temp, size = count; - - if (!ed) - return 0; - - /* print first --> last */ - while (ed->ed_prev) - ed = ed->ed_prev; - - /* dump a snapshot of the bulk or control schedule */ - while (ed) { - u32 info = ed->hwINFO; - u32 scratch = cpu_to_le32p (&ed->hwINFO); - struct list_head *entry; - struct td *td; - - temp = snprintf (buf, size, - "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s", - ed, - (info & ED_LOWSPEED) ? 'l' : 'f', - scratch & 0x7f, - (scratch >> 7) & 0xf, - (info & ED_IN) ? "in" : "out", - 0x03ff & (scratch >> 16), - scratch, - (info & ED_SKIP) ? " s" : "", - (ed->hwHeadP & ED_H) ? " H" : "", - (ed->hwHeadP & ED_C) ? data1 : data0); - size -= temp; - buf += temp; - - list_for_each (entry, &ed->td_list) { - u32 cbp, be; - - td = list_entry (entry, struct td, td_list); - scratch = cpu_to_le32p (&td->hwINFO); - cbp = le32_to_cpup (&td->hwCBP); - be = le32_to_cpup (&td->hwBE); - temp = snprintf (buf, size, - "\n\ttd %p %s %d cc=%x urb %p (%08x)", - td, - ({ char *pid; - switch (scratch & TD_DP) { - case TD_DP_SETUP: pid = "setup"; break; - case TD_DP_IN: pid = "in"; break; - case TD_DP_OUT: pid = "out"; break; - default: pid = "(?)"; break; - } pid;}), - cbp ? (be + 1 - cbp) : 0, - TD_CC_GET (scratch), td->urb, scratch); - size -= temp; - buf += temp; - } - - temp = snprintf (buf, size, "\n"); - size -= temp; - buf += temp; - - ed = ed->ed_next; - } - return count - size; -} - -static ssize_t -show_async (struct device *dev, char *buf) -{ - struct ohci_hcd *ohci; - size_t temp; - unsigned long flags; - - ohci = dev_to_ohci(dev); - - /* display control and bulk lists together, for simplicity */ - spin_lock_irqsave (&ohci->lock, flags); - temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail); - temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail); - spin_unlock_irqrestore (&ohci->lock, flags); - - return temp; -} -static DEVICE_ATTR (async, S_IRUGO, show_async, NULL); - - -#define DBG_SCHED_LIMIT 64 - -static ssize_t -show_periodic (struct device *dev, char *buf) -{ - struct ohci_hcd *ohci; - struct ed **seen, *ed; - unsigned long flags; - unsigned temp, size, seen_count; - char *next; - unsigned i; - - if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) - return 0; - seen_count = 0; - - ohci = dev_to_ohci(dev); - next = buf; - size = PAGE_SIZE; - - temp = snprintf (next, size, "size = %d\n", NUM_INTS); - size -= temp; - next += temp; - - /* dump a snapshot of the periodic schedule (and load) */ - spin_lock_irqsave (&ohci->lock, flags); - for (i = 0; i < NUM_INTS; i++) { - if (!(ed = ohci->periodic [i])) - continue; - - temp = snprintf (next, size, "%2d [%3d]:", i, ohci->load [i]); - size -= temp; - next += temp; - - do { - temp = snprintf (next, size, " ed%d/%p", - ed->interval, ed); - size -= temp; - next += temp; - for (temp = 0; temp < seen_count; temp++) { - if (seen [temp] == ed) - break; - } - - /* show more info the first time around */ - if (temp == seen_count) { - u32 info = ed->hwINFO; - u32 scratch = cpu_to_le32p (&ed->hwINFO); - - temp = snprintf (next, size, - " (%cs dev%d%s ep%d%s" - " max %d %08x%s%s)", - (info & ED_LOWSPEED) ? 'l' : 'f', - scratch & 0x7f, - (info & ED_ISO) ? " iso" : "", - (scratch >> 7) & 0xf, - (info & ED_IN) ? "in" : "out", - 0x03ff & (scratch >> 16), - scratch, - (info & ED_SKIP) ? " s" : "", - (ed->hwHeadP & ED_H) ? " H" : ""); - size -= temp; - next += temp; - - // FIXME some TD info too - - if (seen_count < DBG_SCHED_LIMIT) - seen [seen_count++] = ed; - - ed = ed->ed_next; - - } else { - /* we've seen it and what's after */ - temp = 0; - ed = 0; - } - - } while (ed); - - temp = snprintf (next, size, "\n"); - size -= temp; - next += temp; - } - spin_unlock_irqrestore (&ohci->lock, flags); - kfree (seen); - - return PAGE_SIZE - size; -} -static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); - - -#undef DBG_SCHED_LIMIT - -static ssize_t -show_registers (struct device *dev, char *buf) -{ - struct ohci_hcd *ohci; - struct ohci_regs *regs; - unsigned long flags; - unsigned temp, size; - char *next; - u32 rdata; - - ohci = dev_to_ohci(dev); - regs = ohci->regs; - next = buf; - size = PAGE_SIZE; - - spin_lock_irqsave (&ohci->lock, flags); - - /* dump driver info, then registers in spec order */ - - ohci_dbg_sw (ohci, &next, &size, - "%s version " DRIVER_VERSION "\n", hcd_name); - - ohci_dump_status(ohci, &next, &size); - - /* hcca */ - if (ohci->hcca) - ohci_dbg_sw (ohci, &next, &size, - "hcca frame 0x%04x\n", ohci->hcca->frame_no); - - /* other registers mostly affect frame timings */ - rdata = readl (®s->fminterval); - temp = snprintf (next, size, - "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", - rdata, (rdata >> 31) ? " FIT" : "", - (rdata >> 16) & 0xefff, rdata & 0xffff); - size -= temp; - next += temp; - - rdata = readl (®s->fmremaining); - temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", - rdata, (rdata >> 31) ? " FRT" : "", - rdata & 0x3fff); - size -= temp; - next += temp; - - rdata = readl (®s->periodicstart); - temp = snprintf (next, size, "periodicstart 0x%04x\n", - rdata & 0x3fff); - size -= temp; - next += temp; - - rdata = readl (®s->lsthresh); - temp = snprintf (next, size, "lsthresh 0x%04x\n", - rdata & 0x3fff); - size -= temp; - next += temp; - - /* roothub */ - ohci_dump_roothub (ohci, 1, &next, &size); - - spin_unlock_irqrestore (&ohci->lock, flags); - - return PAGE_SIZE - size; -} -static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); - - -static inline void create_debug_files (struct ohci_hcd *bus) -{ - device_create_file (bus->hcd.controller, &dev_attr_async); - device_create_file (bus->hcd.controller, &dev_attr_periodic); - device_create_file (bus->hcd.controller, &dev_attr_registers); - ohci_dbg (bus, "created debug files\n"); -} - -static inline void remove_debug_files (struct ohci_hcd *bus) -{ - device_remove_file (bus->hcd.controller, &dev_attr_async); - device_remove_file (bus->hcd.controller, &dev_attr_periodic); - device_remove_file (bus->hcd.controller, &dev_attr_registers); -} - -#endif - -/*-------------------------------------------------------------------------*/ - diff --git a/reactos/drivers/usb/miniport/usbohci/ohci-hcd.c b/reactos/drivers/usb/miniport/usbohci/ohci-hcd.c deleted file mode 100644 index 285d163b31f..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci-hcd.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * [ Initialisation is based on Linus' ] - * [ uhci code and gregs ohci fragments ] - * [ (C) Copyright 1999 Linus Torvalds ] - * [ (C) Copyright 1999 Gregory P. Smith] - * - * - * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller - * interfaces (though some non-x86 Intel chips use it). It supports - * smarter hardware than UHCI. A download link for the spec available - * through the http://www.usb.org website. - * - * History: - * - * 2003/02/24 show registers in sysfs (Kevin Brosius) - * - * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and - * bandwidth accounting; if debugging, show schedules in driverfs - * 2002/07/19 fixes to management of ED and schedule state. - * 2002/06/09 SA-1111 support (Christopher Hoover) - * 2002/06/01 remember frame when HC won't see EDs any more; use that info - * to fix urb unlink races caused by interrupt latency assumptions; - * minor ED field and function naming updates - * 2002/01/18 package as a patch for 2.5.3; this should match the - * 2.4.17 kernel modulo some bugs being fixed. - * - * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes - * from post-2.4.5 patches. - * 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning - * 2001/09/07 match PCI PM changes, errnos from Linus' tree - * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify; - * pbook pci quirks gone (please fix pbook pci sw!) (db) - * - * 2001/04/08 Identify version on module load (gb) - * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); - pci_map_single (db) - * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) - * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) - * - * 2000/09/26 fixed races in removing the private portion of the urb - * 2000/09/07 disable bulk and control lists when unlinking the last - * endpoint descriptor in order to avoid unrecoverable errors on - * the Lucent chips. (rwc@sgi) - * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some - * urb unlink probs, indentation fixes - * 2000/08/11 various oops fixes mostly affecting iso and cleanup from - * device unplugs. - * 2000/06/28 use PCI hotplug framework, for better power management - * and for Cardbus support (David Brownell) - * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling - * when the controller loses power; handle UE; cleanup; ... - * - * v5.2 1999/12/07 URB 3rd preview, - * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) - * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume - * i386: HUB, Keyboard, Mouse, Printer - * - * v4.3 1999/10/27 multiple HCs, bulk_request - * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes - * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. - * v4.0 1999/08/18 - * v3.0 1999/06/25 - * v2.1 1999/05/09 code clean up - * v2.0 1999/05/04 - * v1.0 1999/04/27 initial release - * - * This file is licenced under the GPL. - */ - -#if 0 -#include - -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#else -# undef DEBUG -#endif - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for in_interrupt () */ -#include -#include "hcd.h" - -#include -#include -#include -#include -#include -#else -#include "ohci_config.h" - -#include "../../usbport/hcd.h" - -//#define OHCI_VERBOSE_DEBUG -#endif - -/* - * TO DO: - * - * - "disabled" and "sleeping" should be in hcd->state - * - lots more testing!! - */ - -#define DRIVER_VERSION "2003 Feb 24" -#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" -#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" - -/*-------------------------------------------------------------------------*/ - -// #define OHCI_VERBOSE_DEBUG /* not always helpful */ - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT \ - (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE - -#define OHCI_UNLINK_TIMEOUT (HZ / 10) - -/*-------------------------------------------------------------------------*/ - -static const char hcd_name [] = "ohci-hcd"; - -#include "ohci.h" - -static inline void disable (struct ohci_hcd *ohci) -{ - ohci->disabled = 1; - ohci->hcd.state = USB_STATE_HALT; -} - -#include "ohci-hub.c" -#include "ohci-dbg.c" -#include "ohci-mem.c" -#include "ohci-q.c" - -/*-------------------------------------------------------------------------*/ - -/* - * queue up an urb for anything except the root hub - */ -static int ohci_urb_enqueue ( - struct usb_hcd *hcd, - struct urb *urb, - int mem_flags -) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct ed *ed; - urb_priv_t *urb_priv; - unsigned int pipe = urb->pipe; - int i, size = 0; - unsigned long flags; - int retval = 0; - -#ifdef OHCI_VERBOSE_DEBUG - urb_print (urb, "SUB", usb_pipein (pipe)); -#endif - - /* every endpoint has a ed, locate and maybe (re)initialize it */ - if (! (ed = ed_get (ohci, urb->dev, pipe, urb->interval))) - return -ENOMEM; - - /* for the private part of the URB we need the number of TDs (size) */ - switch (ed->type) { - case PIPE_CONTROL: - /* td_submit_urb() doesn't yet handle these */ - if (urb->transfer_buffer_length > 4096) - return -EMSGSIZE; - - /* 1 TD for setup, 1 for ACK, plus ... */ - size = 2; - /* FALLTHROUGH */ - // case PIPE_INTERRUPT: - // case PIPE_BULK: - default: - /* one TD for every 4096 Bytes (can be upto 8K) */ - size += urb->transfer_buffer_length / 4096; - /* ... and for any remaining bytes ... */ - if ((urb->transfer_buffer_length % 4096) != 0) - size++; - /* ... and maybe a zero length packet to wrap it up */ - if (size == 0) - size++; - else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 - && (urb->transfer_buffer_length - % usb_maxpacket (urb->dev, pipe, - usb_pipeout (pipe))) == 0) - size++; - break; - case PIPE_ISOCHRONOUS: /* number of packets from URB */ - size = urb->number_of_packets; - break; - } - - /* allocate the private part of the URB */ - urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *), - mem_flags); - if (!urb_priv) - return -ENOMEM; - memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); - - /* fill the private part of the URB */ - urb_priv->length = size; - urb_priv->ed = ed; - - /* allocate the TDs (deferring hash chain updates) */ - for (i = 0; i < size; i++) { - urb_priv->td [i] = td_alloc (ohci, mem_flags); - if (!urb_priv->td [i]) { - urb_priv->length = i; - urb_free_priv (ohci, urb_priv); - return -ENOMEM; - } - } - - spin_lock_irqsave (&ohci->lock, flags); - - /* don't submit to a dead HC */ - if (ohci->disabled || ohci->sleeping) { - retval = -ENODEV; - goto fail; - } - - /* schedule the ed if needed */ - if (ed->state == ED_IDLE) { - retval = ed_schedule (ohci, ed); - if (retval < 0) - goto fail; - if (ed->type == PIPE_ISOCHRONOUS) { - u16 frame = le16_to_cpu (ohci->hcca->frame_no); - - /* delay a few frames before the first TD */ - frame += max_t (u16, 8, ed->interval); - frame &= ~(ed->interval - 1); - frame |= ed->branch; - urb->start_frame = frame; - - /* yes, only URB_ISO_ASAP is supported, and - * urb->start_frame is never used as input. - */ - } - } else if (ed->type == PIPE_ISOCHRONOUS) - urb->start_frame = ed->last_iso + ed->interval; - - /* fill the TDs and link them to the ed; and - * enable that part of the schedule, if needed - * and update count of queued periodic urbs - */ - urb->hcpriv = urb_priv; - td_submit_urb (ohci, urb); - -fail: - if (retval) - urb_free_priv (ohci, urb_priv); - spin_unlock_irqrestore (&ohci->lock, flags); - return retval; -} - -/* - * decouple the URB from the HC queues (TDs, urb_priv); it's - * already marked using urb->status. reporting is always done - * asynchronously, and we might be dealing with an urb that's - * partially transferred, or an ED with other urbs being unlinked. - */ -static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - unsigned long flags; - -#ifdef OHCI_VERBOSE_DEBUG - urb_print (urb, "UNLINK", 1); -#endif - - spin_lock_irqsave (&ohci->lock, flags); - if (!ohci->disabled) { - urb_priv_t *urb_priv; - - /* Unless an IRQ completed the unlink while it was being - * handed to us, flag it for unlink and giveback, and force - * some upcoming INTR_SF to call finish_unlinks() - */ - urb_priv = urb->hcpriv; - if (urb_priv) { - urb_priv->state = URB_DEL; - if (urb_priv->ed->state == ED_OPER) - start_urb_unlink (ohci, urb_priv->ed); - } - } else { - /* - * with HC dead, we won't respect hc queue pointers - * any more ... just clean up every urb's memory. - */ - if (urb->hcpriv) { - spin_unlock (&ohci->lock); - finish_urb (ohci, urb, NULL); - spin_lock (&ohci->lock); - } - } - spin_unlock_irqrestore (&ohci->lock, flags); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* frees config/altsetting state for endpoints, - * including ED memory, dummy TD, and bulk/intr data toggle - */ - -static void -ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int epnum = ep & USB_ENDPOINT_NUMBER_MASK; - unsigned long flags; - struct ed *ed; - - /* ASSERT: any requests/urbs are being unlinked */ - /* ASSERT: nobody can be submitting urbs for this any more */ - - epnum <<= 1; - if (epnum != 0 && !(ep & USB_DIR_IN)) - epnum |= 1; - -rescan: - spin_lock_irqsave (&ohci->lock, flags); - ed = dev->ep [epnum]; - if (!ed) - goto done; - - if (!HCD_IS_RUNNING (ohci->hcd.state) || ohci->disabled) - ed->state = ED_IDLE; - switch (ed->state) { - case ED_UNLINK: /* wait for hw to finish? */ - spin_unlock_irqrestore (&ohci->lock, flags); - set_current_state (TASK_UNINTERRUPTIBLE); - schedule_timeout (1); - goto rescan; - case ED_IDLE: /* fully unlinked */ - if (list_empty (&ed->td_list)) { - td_free (ohci, ed->dummy); - ed_free (ohci, ed); - break; - } - /* else FALL THROUGH */ - default: - /* caller was supposed to have unlinked any requests; - * that's not our job. can't recover; must leak ed. - */ - ohci_err (ohci, "ed %p (#%d) state %d%s\n", - ed, epnum, ed->state, - list_empty (&ed->td_list) ? "" : "(has tds)"); - td_free (ohci, ed->dummy); - break; - } - dev->ep [epnum] = 0; -done: - spin_unlock_irqrestore (&ohci->lock, flags); - return; -} - -static int ohci_get_frame (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - return le16_to_cpu (ohci->hcca->frame_no); -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -/* reset the HC and BUS */ - -static int hc_reset (struct ohci_hcd *ohci) -{ - u32 temp; - - /* SMM owns the HC? not for long! - * On PA-RISC, PDC can leave IR set incorrectly; ignore it there. - */ -#ifndef __hppa__ - if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { - ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n"); - - /* this timeout is arbitrary. we make it long, so systems - * depending on usb keyboards may be usable even if the - * BIOS/SMM code seems pretty broken. - */ - temp = 500; /* arbitrary: five seconds */ - - writel (OHCI_INTR_OC, &ohci->regs->intrenable); - writel (OHCI_OCR, &ohci->regs->cmdstatus); - while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { - wait_ms (10); - if (--temp == 0) { - ohci_err (ohci, "USB HC TakeOver failed!\n"); - return -1; - } - } - } -#endif - - /* Disable HC interrupts */ - writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); - - ohci_dbg (ohci, "USB HC reset_hc %s: ctrl = 0x%x ;\n", - hcd_to_bus (&ohci->hcd)->bus_name, - readl (&ohci->regs->control)); - - /* Reset USB (needed by some controllers); RemoteWakeupConnected - * saved if boot firmware (BIOS/SMM/...) told us it's connected - */ - ohci->hc_control = readl (&ohci->regs->control); - ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */ - writel (ohci->hc_control, &ohci->regs->control); - // flush those pci writes - (void) readl (&ohci->regs->control); - wait_ms (50); - - /* HC Reset requires max 10 us delay */ - writel (OHCI_HCR, &ohci->regs->cmdstatus); - temp = 30; /* ... allow extra time */ - while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--temp == 0) { - ohci_err (ohci, "USB HC reset timed out!\n"); - return -1; - } - udelay (1); - } - - /* now we're in the SUSPEND state ... must go OPERATIONAL - * within 2msec else HC enters RESUME - * - * ... but some hardware won't init fmInterval "by the book" - * (SiS, OPTi ...), so reset again instead. SiS doesn't need - * this if we write fmInterval after we're OPERATIONAL. - */ - writel (ohci->hc_control, &ohci->regs->control); - // flush those pci writes - (void) readl (&ohci->regs->control); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#define FI 0x2edf /* 12000 bits per frame (-1) */ -#define LSTHRESH 0x628 /* lowspeed bit threshold */ - -/* Start an OHCI controller, set the BUS operational - * enable interrupts - * connect the virtual root hub - */ -static int hc_start (struct ohci_hcd *ohci) -{ - u32 mask, tmp; - struct usb_device *udev; - struct usb_bus *bus; - - spin_lock_init (&ohci->lock); - ohci->disabled = 1; - ohci->sleeping = 0; - - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - writel (0, &ohci->regs->ed_controlhead); - writel (0, &ohci->regs->ed_bulkhead); - - /* a reset clears this */ - writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); - usbprintk("HCCA: %p \n",ohci->regs->hcca); - - /* force default fmInterval (we won't adjust it); init thresholds - * for last FS and LS packets, reserve 90% for periodic. - */ - writel ((((6 * (FI - 210)) / 7) << 16) | FI, &ohci->regs->fminterval); - writel (((9 * FI) / 10) & 0x3fff, &ohci->regs->periodicstart); - writel (LSTHRESH, &ohci->regs->lsthresh); - - /* some OHCI implementations are finicky about how they init. - * bogus values here mean not even enumeration could work. - */ - if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0 - || !readl (&ohci->regs->periodicstart)) { - ohci_err (ohci, "init err\n"); - return -EOVERFLOW; - } - - /* start controller operations */ - ohci->hc_control &= OHCI_CTRL_RWC; - ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - ohci->disabled = 0; - writel (ohci->hc_control, &ohci->regs->control); - - /* Choose the interrupts we care about now, others later on demand */ - mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH; - writel (mask, &ohci->regs->intrstatus); - writel (mask, &ohci->regs->intrenable); - - /* handle root hub init quirks ... */ - tmp = roothub_a (ohci); - tmp &= ~(RH_A_PSM | RH_A_OCPM); - if (ohci->flags & OHCI_QUIRK_SUPERIO) { - /* NSC 87560 and maybe others */ - tmp |= RH_A_NOCP; - tmp &= ~(RH_A_POTPGT | RH_A_NPS); - } else { - /* hub power always on; required for AMD-756 and some - * Mac platforms, use this mode everywhere by default - */ - tmp |= RH_A_NPS; - } - writel (tmp, &ohci->regs->roothub.a); - writel (RH_HS_LPSC, &ohci->regs->roothub.status); - writel (0, &ohci->regs->roothub.b); - // flush those pci writes - (void) readl (&ohci->regs->control); - - // POTPGT delay is bits 24-31, in 2 ms units. - mdelay (((int)(roothub_a (ohci) >> 23) & 0x1fe)); - - /* connect the virtual root hub */ - bus = hcd_to_bus (&ohci->hcd); - bus->root_hub = udev = usb_alloc_dev (NULL, bus); - ohci->hcd.state = USB_STATE_READY; - if (!udev) { - disable (ohci); - ohci->hc_control &= ~OHCI_CTRL_HCFS; - writel (ohci->hc_control, &ohci->regs->control); - ohci_err(ohci,"out of mem"); - return -ENOMEM; - } - - usb_connect (udev); - udev->speed = USB_SPEED_FULL; - if (hcd_register_root (&ohci->hcd) != 0) { - usb_put_dev (udev); - bus->root_hub = NULL; - disable (ohci); - ohci->hc_control &= ~OHCI_CTRL_HCFS; - writel (ohci->hc_control, &ohci->regs->control); - return -ENODEV; - } - create_debug_files (ohci); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static -int ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct ohci_regs *regs = ohci->regs; - int ints; - - /* we can eliminate a (slow) readl() if _only_ WDH caused this irq */ - if ((ohci->hcca->done_head != 0) - && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { - ints = OHCI_INTR_WDH; - - /* cardbus/... hardware gone before remove() */ - } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) { - disable (ohci); - ohci_dbg (ohci, "device removed!\n"); - return 0; - - /* interrupt for some other device? */ - } else if ((ints &= readl (®s->intrenable)) == 0) { - return 0; - } - - if (ints & OHCI_INTR_UE) { - disable (ohci); - ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); - // e.g. due to PCI Master/Target Abort - - ohci_dump (ohci, 1); - hc_reset (ohci); - } - - if (ints & OHCI_INTR_WDH) { - writel (OHCI_INTR_WDH, ®s->intrdisable); - dl_done_list (ohci, dl_reverse_done_list (ohci), ptregs); - writel (OHCI_INTR_WDH, ®s->intrenable); - } - - /* could track INTR_SO to reduce available PCI/... bandwidth */ - - /* handle any pending URB/ED unlinks, leaving INTR_SF enabled - * when there's still unlinking to be done (next frame). - */ - spin_lock (&ohci->lock); - if (ohci->ed_rm_list) - finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no), - ptregs); - if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list) - writel (OHCI_INTR_SF, ®s->intrdisable); - spin_unlock (&ohci->lock); - - writel (ints, ®s->intrstatus); - writel (OHCI_INTR_MIE, ®s->intrenable); - // flush those pci writes - (void) readl (&ohci->regs->control); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG_MODE -// HCFS itself -static char *hcfs2string (int state) -{ - switch (state) { - case OHCI_USB_RESET: return "reset"; - case OHCI_USB_RESUME: return "resume"; - case OHCI_USB_OPER: return "operational"; - case OHCI_USB_SUSPEND: return "suspend"; - } - return "?"; -} -#endif - -static void ohci_stop (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - ohci_dbg (ohci, "stop %s controller%s\n", - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), - ohci->disabled ? " (disabled)" : "" - ); - //ohci_dump (ohci, 1); - - if (!ohci->disabled) - hc_reset (ohci); - - //remove_debug_files (ohci); - ohci_mem_cleanup (ohci); - if (ohci->hcca) { - pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, - ohci->hcca, ohci->hcca_dma); - ohci->hcca = NULL; - ohci->hcca_dma = 0; - } -} - -/*-------------------------------------------------------------------------*/ - -// FIXME: this restart logic should be generic, -// and handle full hcd state cleanup - -/* controller died; cleanup debris, then restart */ -/* must not be called from interrupt context */ - -#ifdef CONFIG_PM -static int hc_restart (struct ohci_hcd *ohci) -{ - int temp; - int i; - - ohci->disabled = 1; - ohci->sleeping = 0; - if (hcd_to_bus (&ohci->hcd)->root_hub) - usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub); - - /* empty the interrupt branches */ - for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; - for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; - - /* no EDs to remove */ - ohci->ed_rm_list = NULL; - - /* empty control and bulk lists */ - ohci->ed_controltail = NULL; - ohci->ed_bulktail = NULL; - - if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { - ohci_err (ohci, "can't restart, %d\n", temp); - return temp; - } else - ohci_dbg (ohci, "restart complete\n"); - return 0; -} -#endif - -/*-------------------------------------------------------------------------*/ - -#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC - -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_INFO); -MODULE_LICENSE ("GPL"); - -#ifdef CONFIG_PCI -#include "ohci-pci.c" -#endif - -#ifdef CONFIG_SA1111 -#include "ohci-sa1111.c" -#endif - -#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111)) -#error "missing bus glue for ohci-hcd" -#endif diff --git a/reactos/drivers/usb/miniport/usbohci/ohci-hub.c b/reactos/drivers/usb/miniport/usbohci/ohci-hub.c deleted file mode 100644 index a3a1c3bca6c..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci-hub.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * This file is licenced under GPL - */ - -/*-------------------------------------------------------------------------*/ - -/* - * OHCI Root Hub ... the nonsharable stuff - * - * Registers don't need cpu_to_le32, that happens transparently - */ - -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -#define read_roothub(hc, register, mask) ({ \ - u32 temp = readl (&hc->regs->roothub.register); \ - if (temp == -1) \ - disable (hc); \ - else if (hc->flags & OHCI_QUIRK_AMD756) \ - while (temp & mask) \ - temp = readl (&hc->regs->roothub.register); \ - temp; }) - -static u32 roothub_a (struct ohci_hcd *hc) - { return read_roothub (hc, a, 0xfc0fe000); } -static inline u32 roothub_b (struct ohci_hcd *hc) - { return readl (&hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci_hcd *hc) - { return readl (&hc->regs->roothub.status); } -static u32 roothub_portstatus (struct ohci_hcd *hc, int i) - { return read_roothub (hc, portstatus [i], 0xffe0fce0); } - -/*-------------------------------------------------------------------------*/ - -#define dbg_port(hc,label,num,value) \ - ohci_dbg (hc, \ - "%s roothub.portstatus [%d] " \ - "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ - label, num, temp, \ - (temp & RH_PS_PRSC) ? " PRSC" : "", \ - (temp & RH_PS_OCIC) ? " OCIC" : "", \ - (temp & RH_PS_PSSC) ? " PSSC" : "", \ - (temp & RH_PS_PESC) ? " PESC" : "", \ - (temp & RH_PS_CSC) ? " CSC" : "", \ - \ - (temp & RH_PS_LSDA) ? " LSDA" : "", \ - (temp & RH_PS_PPS) ? " PPS" : "", \ - (temp & RH_PS_PRS) ? " PRS" : "", \ - (temp & RH_PS_POCI) ? " POCI" : "", \ - (temp & RH_PS_PSS) ? " PSS" : "", \ - \ - (temp & RH_PS_PES) ? " PES" : "", \ - (temp & RH_PS_CCS) ? " CCS" : "" \ - ); - - -/*-------------------------------------------------------------------------*/ - -/* build "status change" packet (one or two bytes) from HC registers */ - -static int -ohci_hub_status_data (struct usb_hcd *hcd, char *buf) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ports, i, changed = 0, length = 1; - - ports = roothub_a (ohci) & RH_A_NDP; - if (ports > MAX_ROOT_PORTS) { - if (ohci->disabled) - return -ESHUTDOWN; - ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", - ports, readl (&ohci->regs->roothub.a) & RH_A_NDP); - /* retry later; "should not happen" */ - return 0; - } - - /* init status */ - if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) - buf [0] = changed = 1; - else - buf [0] = 0; - if (ports > 7) { - buf [1] = 0; - length++; - } - - /* look at each port */ - for (i = 0; i < ports; i++) { - u32 status = roothub_portstatus (ohci, i); - - status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC - | RH_PS_OCIC | RH_PS_PRSC; - if (status) { - changed = 1; - if (i < 7) - buf [0] |= 1 << (i + 1); - else - buf [1] |= 1 << (i - 7); - } - } - return changed ? length : 0; -} - -/*-------------------------------------------------------------------------*/ - -static void -ohci_hub_descriptor ( - struct ohci_hcd *ohci, - struct usb_hub_descriptor *desc -) { - u32 rh = roothub_a (ohci); - int ports = rh & RH_A_NDP; - u16 temp; - - desc->bDescriptorType = 0x29; - desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = ports; - temp = 1 + (ports / 8); - desc->bDescLength = 7 + 2 * temp; - - temp = 0; - if (rh & RH_A_PSM) /* per-port power switching? */ - temp |= 0x0001; - if (rh & RH_A_NOCP) /* no overcurrent reporting? */ - temp |= 0x0010; - else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */ - temp |= 0x0008; - desc->wHubCharacteristics = cpu_to_le16 (temp); - - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - rh = roothub_b (ohci); - desc->bitmap [0] = rh & RH_B_DR; - if (ports > 7) { - desc->bitmap [1] = (rh & RH_B_DR) >> 8; - desc->bitmap [2] = desc->bitmap [3] = 0xff; - } else - desc->bitmap [1] = 0xff; -} - -/*-------------------------------------------------------------------------*/ - -static int ohci_hub_control ( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - u8 *buf, - u16 wLength -) { - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ports = hcd_to_bus (hcd)->root_hub->maxchild; - u32 temp; - int retval = 0; - - switch (typeReq) { - case ClearHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - writel (RH_HS_OCIC, &ohci->regs->roothub.status); - case C_HUB_LOCAL_POWER: - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - temp = RH_PS_CCS; - break; - case USB_PORT_FEAT_C_ENABLE: - temp = RH_PS_PESC; - break; - case USB_PORT_FEAT_SUSPEND: - temp = RH_PS_POCI; - break; - case USB_PORT_FEAT_C_SUSPEND: - temp = RH_PS_PSSC; - break; - case USB_PORT_FEAT_POWER: - temp = RH_PS_LSDA; - break; - case USB_PORT_FEAT_C_CONNECTION: - temp = RH_PS_CSC; - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - temp = RH_PS_OCIC; - break; - case USB_PORT_FEAT_C_RESET: - temp = RH_PS_PRSC; - break; - default: - goto error; - } - writel (temp, &ohci->regs->roothub.portstatus [wIndex]); - // readl (&ohci->regs->roothub.portstatus [wIndex]); - break; - case GetHubDescriptor: - ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); - break; - case GetHubStatus: - temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE); - *(u32 *) buf = cpu_to_le32 (temp); - break; - case GetPortStatus: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = roothub_portstatus (ohci, wIndex); - *(u32 *) buf = cpu_to_le32 (temp); - -#ifndef OHCI_VERBOSE_DEBUG - if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ -#endif - dbg_port (ohci, "GetStatus", wIndex + 1, temp); - break; - case SetHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - // FIXME: this can be cleared, yes? - case C_HUB_LOCAL_POWER: - break; - default: - goto error; - } - break; - case SetPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - writel (RH_PS_PSS, - &ohci->regs->roothub.portstatus [wIndex]); - break; - case USB_PORT_FEAT_POWER: - writel (RH_PS_PPS, - &ohci->regs->roothub.portstatus [wIndex]); - break; - case USB_PORT_FEAT_RESET: - temp = readl (&ohci->regs->roothub.portstatus [wIndex]); - if (temp & RH_PS_CCS) - writel (RH_PS_PRS, - &ohci->regs->roothub.portstatus [wIndex]); - break; - default: - goto error; - } - break; - - default: -error: - /* "protocol stall" on error */ - retval = -EPIPE; - } - return retval; -} - diff --git a/reactos/drivers/usb/miniport/usbohci/ohci-mem.c b/reactos/drivers/usb/miniport/usbohci/ohci-mem.c deleted file mode 100644 index 4fc839304ce..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci-mem.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * This file is licenced under the GPL. - */ - -/*-------------------------------------------------------------------------*/ - -/* - * There's basically three types of memory: - * - data used only by the HCD ... kmalloc is fine - * - async and periodic schedules, shared by HC and HCD ... these - * need to use pci_pool or pci_alloc_consistent - * - driver buffers, read/written by HC ... the hcd glue or the - * device driver provides us with dma addresses - * - * There's also PCI "register" data, which is memory mapped. - * No memory seen by this driver is pagable. - */ - -/*-------------------------------------------------------------------------*/ - -static struct usb_hcd *ohci_hcd_alloc (void) -{ - struct ohci_hcd *ohci; - - ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL); - if (ohci != 0) { - memset (ohci, 0, sizeof (struct ohci_hcd)); - return &ohci->hcd; - } - return 0; -} - -static void ohci_hcd_free (struct usb_hcd *hcd) -{ - kfree (hcd_to_ohci (hcd)); -} - -/*-------------------------------------------------------------------------*/ - -static int ohci_mem_init (struct ohci_hcd *ohci) -{ - ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev, - sizeof (struct td), - 32 /* byte alignment */, - 0 /* no page-crossing issues */); - if (!ohci->td_cache) - return -ENOMEM; - ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev, - sizeof (struct ed), - 16 /* byte alignment */, - 0 /* no page-crossing issues */); - if (!ohci->ed_cache) { - pci_pool_destroy (ohci->td_cache); - return -ENOMEM; - } - return 0; -} - -static void ohci_mem_cleanup (struct ohci_hcd *ohci) -{ - if (ohci->td_cache) { - pci_pool_destroy (ohci->td_cache); - ohci->td_cache = 0; - } - if (ohci->ed_cache) { - pci_pool_destroy (ohci->ed_cache); - ohci->ed_cache = 0; - } -} - -/*-------------------------------------------------------------------------*/ - -/* ohci "done list" processing needs this mapping */ -static inline struct td * -dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) -{ - struct td *td; - - td_dma &= TD_MASK; - td = hc->td_hash [TD_HASH_FUNC(td_dma)]; - while (td && td->td_dma != td_dma) - td = td->td_hash; - return td; -} - -/* TDs ... */ -static struct td * -td_alloc (struct ohci_hcd *hc, int mem_flags) -{ - dma_addr_t dma; - struct td *td; - - td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); - if (td) { - /* in case hc fetches it, make it look dead */ - memset (td, 0, sizeof *td); - td->hwNextTD = cpu_to_le32 (dma); - td->td_dma = dma; - /* hashed in td_fill */ - } - return td; -} - -static void -td_free (struct ohci_hcd *hc, struct td *td) -{ - struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)]; - - while (*prev && *prev != td) - prev = &(*prev)->td_hash; - if (*prev) - *prev = td->td_hash; - else if ((td->hwINFO & TD_DONE) != 0) - ohci_dbg (hc, "no hash for td %p\n", td); - pci_pool_free (hc->td_cache, td, td->td_dma); -} - -/*-------------------------------------------------------------------------*/ - -/* EDs ... */ -static struct ed * -ed_alloc (struct ohci_hcd *hc, int mem_flags) -{ - dma_addr_t dma; - struct ed *ed; - - ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma); - if (ed) { - memset (ed, 0, sizeof (*ed)); - INIT_LIST_HEAD (&ed->td_list); - ed->dma = dma; - } - return ed; -} - -static void -ed_free (struct ohci_hcd *hc, struct ed *ed) -{ - pci_pool_free (hc->ed_cache, ed, ed->dma); -} - diff --git a/reactos/drivers/usb/miniport/usbohci/ohci-pci.c b/reactos/drivers/usb/miniport/usbohci/ohci-pci.c deleted file mode 100644 index 2ba3d7df51f..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci-pci.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * [ Initialisation is based on Linus' ] - * [ uhci code and gregs ohci fragments ] - * [ (C) Copyright 1999 Linus Torvalds ] - * [ (C) Copyright 1999 Gregory P. Smith] - * - * PCI Bus Glue - * - * This file is licenced under the GPL. - */ - -#ifdef CONFIG_PMAC_PBOOK -#include -#include -#include -#include -#ifndef CONFIG_PM -# define CONFIG_PM -#endif -#endif - -#ifndef CONFIG_PCI -#error "This file is PCI bus glue. CONFIG_PCI must be defined." -#endif - -#include "../linux/pci_ids.h" - -/*-------------------------------------------------------------------------*/ - -static int __devinit -ohci_pci_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - DPRINT("ohci_pci_start()\n"); - - if (hcd->pdev) { - ohci->hcca = pci_alloc_consistent (hcd->pdev, - sizeof *ohci->hcca, &ohci->hcca_dma); - if (!ohci->hcca) - return -ENOMEM; - - /* AMD 756, for most chips (early revs), corrupts register - * values on read ... so enable the vendor workaround. - */ - if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD - && hcd->pdev->device == 0x740c) { - ohci->flags = OHCI_QUIRK_AMD756; - ohci_info (ohci, "AMD756 erratum 4 workaround\n"); - } - - /* FIXME for some of the early AMD 760 southbridges, OHCI - * won't work at all. blacklist them. - */ - - /* Apple's OHCI driver has a lot of bizarre workarounds - * for this chip. Evidently control and bulk lists - * can get confused. (B&W G3 models, and ...) - */ - else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI - && hcd->pdev->device == 0xc861) { - ohci_info (ohci, - "WARNING: OPTi workarounds unavailable\n"); - } - - /* Check for NSC87560. We have to look at the bridge (fn1) to - * identify the USB (fn2). This quirk might apply to more or - * even all NSC stuff. - */ - else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) { - struct pci_dev *b, *hc; - - hc = hcd->pdev; - b = pci_find_slot (hc->bus->number, - PCI_DEVFN (PCI_SLOT (hc->devfn), 1)); - if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO - && b->vendor == PCI_VENDOR_ID_NS) { - ohci->flags |= OHCI_QUIRK_SUPERIO; - ohci_info (ohci, "Using NSC SuperIO setup\n"); - } - } - - } - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); - if ((ret = ohci_mem_init (ohci)) < 0) { - ohci_stop (hcd); - return ret; - } - ohci->regs = hcd->regs; - - DPRINT("Controller memory init done\n"); - - if (hc_reset (ohci) < 0) { - ohci_stop (hcd); - return -ENODEV; - } - DPRINT("Controller reset done\n"); - - if (hc_start (ohci) < 0) { - ohci_err (ohci, "can't start\n"); - ohci_stop (hcd); - return -EBUSY; - } - DPRINT("Controller start done\n"); - -#ifdef DEBUG - ohci_dump (ohci, 1); -#endif - return 0; -} - -#ifdef CONFIG_PM - -static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - unsigned long flags; - u16 cmd; - - if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { - ohci_dbg (ohci, "can't suspend (state is %s)\n", - hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); - return -EIO; - } - - /* act as if usb suspend can always be used */ - ohci_dbg (ohci, "suspend to %d\n", state); - ohci->sleeping = 1; - - /* First stop processing */ - spin_lock_irqsave (&ohci->lock, flags); - ohci->hc_control &= - ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); - writel (ohci->hc_control, &ohci->regs->control); - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - (void) readl (&ohci->regs->intrstatus); - spin_unlock_irqrestore (&ohci->lock, flags); - - /* Wait a frame or two */ - mdelay (1); - if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) - mdelay (1); - -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq (hcd->pdev->irq); - /* else, 2.4 assumes shared irqs -- don't disable */ -#endif - - /* Enable remote wakeup */ - writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, - &ohci->regs->intrenable); - - /* Suspend chip and let things settle down a bit */ - ohci->hc_control = OHCI_USB_SUSPEND; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (500); /* No schedule here ! */ - - switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { - case OHCI_USB_RESET: - ohci_dbg (ohci, "suspend->reset ?\n"); - break; - case OHCI_USB_RESUME: - ohci_dbg (ohci, "suspend->resume ?\n"); - break; - case OHCI_USB_OPER: - ohci_dbg (ohci, "suspend->operational ?\n"); - break; - case OHCI_USB_SUSPEND: - ohci_dbg (ohci, "suspended\n"); - break; - } - - /* In some rare situations, Apple's OHCI have happily trashed - * memory during sleep. We disable its bus master bit during - * suspend - */ - pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); - cmd &= ~PCI_COMMAND_MASTER; - pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Disable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (hcd->pdev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); - } -#endif - return 0; -} - - -static int ohci_pci_resume (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int temp; - int retval = 0; - unsigned long flags; - -#ifdef CONFIG_PMAC_PBOOK - { - struct device_node *of_node; - - /* Re-enable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (hcd->pdev); - if (of_node) - pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); - } -#endif - /* did we suspend, or were we powered off? */ - ohci->hc_control = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - -#ifdef DEBUG - /* the registers may look crazy here */ - ohci_dump_status (ohci, 0, 0); -#endif - - /* Re-enable bus mastering */ - pci_set_master (ohci->hcd.pdev); - - switch (temp) { - - case OHCI_USB_RESET: // lost power - ohci_info (ohci, "USB restart\n"); - retval = hc_restart (ohci); - break; - - case OHCI_USB_SUSPEND: // host wakeup - case OHCI_USB_RESUME: // remote wakeup - ohci_info (ohci, "USB continue from %s wakeup\n", - (temp == OHCI_USB_SUSPEND) - ? "host" : "remote"); - ohci->hc_control = OHCI_USB_RESUME; - writel (ohci->hc_control, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (20); /* no schedule here ! */ - /* Some controllers (lucent) need a longer delay here */ - mdelay (15); - - temp = readl (&ohci->regs->control); - temp = ohci->hc_control & OHCI_CTRL_HCFS; - if (temp != OHCI_USB_RESUME) { - ohci_err (ohci, "controller won't resume\n"); - ohci->disabled = 1; - retval = -EIO; - break; - } - - /* Some chips likes being resumed first */ - writel (OHCI_USB_OPER, &ohci->regs->control); - (void) readl (&ohci->regs->control); - mdelay (3); - - /* Then re-enable operations */ - spin_lock_irqsave (&ohci->lock, flags); - ohci->disabled = 0; - ohci->sleeping = 0; - ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; - if (!ohci->ed_rm_list) { - if (ohci->ed_controltail) - ohci->hc_control |= OHCI_CTRL_CLE; - if (ohci->ed_bulktail) - ohci->hc_control |= OHCI_CTRL_BLE; - } - hcd->state = USB_STATE_READY; - writel (ohci->hc_control, &ohci->regs->control); - - /* trigger a start-frame interrupt (why?) */ - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - - /* Check for a pending done list */ - writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); - (void) readl (&ohci->regs->intrdisable); - spin_unlock_irqrestore (&ohci->lock, flags); - -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - enable_irq (hcd->pdev->irq); -#endif - if (ohci->hcca->done_head) - dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); - writel (OHCI_INTR_WDH, &ohci->regs->intrenable); - - /* assume there are TDs on the bulk and control lists */ - writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); - -// ohci_dump_status (ohci); -ohci_dbg (ohci, "sleeping = %d, disabled = %d\n", - ohci->sleeping, ohci->disabled); - break; - - default: - ohci_warn (ohci, "odd PCI resume\n"); - } - return retval; -} - -#endif /* CONFIG_PM */ - - -/*-------------------------------------------------------------------------*/ - -static struct hc_driver ohci_pci_hc_driver = { - .description = hcd_name, - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_MEMORY | HCD_USB11, - - /* - * basic lifecycle operations - */ - .start = ohci_pci_start, -#ifdef CONFIG_PM - .suspend = ohci_pci_suspend, - .resume = ohci_pci_resume, -#endif - .stop = ohci_stop, - - /* - * memory lifecycle (except per-request) - */ - .hcd_alloc = ohci_hcd_alloc, - .hcd_free = ohci_hcd_free, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ohci_urb_enqueue, - .urb_dequeue = ohci_urb_dequeue, - .endpoint_disable = ohci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ohci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, -}; - -/*-------------------------------------------------------------------------*/ - -const struct pci_device_id __devinitdata ohci_pci_ids [] = { { - - /* handle any USB OHCI controller */ - .class = (PCI_CLASS_SERIAL_USB << 8) | 0x10, - .class_mask = ~0, - .driver_data = (unsigned long) &ohci_pci_hc_driver, - - /* no matter who makes it */ - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE (pci, ohci_pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -struct pci_driver ohci_pci_driver = { - .name = (char *) hcd_name, - .id_table = ohci_pci_ids, - - .probe = usb_hcd_pci_probe, - .remove = usb_hcd_pci_remove, - -#ifdef CONFIG_PM - .suspend = usb_hcd_pci_suspend, - .resume = usb_hcd_pci_resume, -#endif -}; - - -int ohci_hcd_pci_init (void) -{ - printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); - if (usb_disabled()) - return -ENODEV; - - // causes page fault in reactos - //printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, - // sizeof (struct ed), sizeof (struct td)); - return pci_module_init (&ohci_pci_driver); -} -/*module_init (ohci_hcd_pci_init);*/ - -/*-------------------------------------------------------------------------*/ - -void ohci_hcd_pci_cleanup (void) -{ - pci_unregister_driver (&ohci_pci_driver); -} -/*module_exit (ohci_hcd_pci_cleanup);*/ diff --git a/reactos/drivers/usb/miniport/usbohci/ohci-q.c b/reactos/drivers/usb/miniport/usbohci/ohci-q.c deleted file mode 100644 index eae584ae317..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci-q.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * This file is licenced under the GPL. - */ - -static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) -{ - int last = urb_priv->length - 1; - - if (last >= 0) { - int i; - struct td *td; - - for (i = 0; i <= last; i++) { - td = urb_priv->td [i]; - if (td) - td_free (hc, td); - } - } - - kfree (urb_priv); -} - -/*-------------------------------------------------------------------------*/ - -/* - * URB goes back to driver, and isn't reissued. - * It's completely gone from HC data structures. - * PRECONDITION: no locks held, irqs blocked (Giveback can call into HCD.) - */ -static void -finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) -{ - // ASSERT (urb->hcpriv != 0); - - urb_free_priv (ohci, urb->hcpriv); - urb->hcpriv = NULL; - - spin_lock (&urb->lock); - if (likely (urb->status == -EINPROGRESS)) - urb->status = 0; - spin_unlock (&urb->lock); - - // what lock protects these? - switch (usb_pipetype (urb->pipe)) { - case PIPE_ISOCHRONOUS: - hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--; - break; - case PIPE_INTERRUPT: - hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs--; - break; - } - -#ifdef OHCI_VERBOSE_DEBUG - urb_print (urb, "RET", usb_pipeout (urb->pipe)); -#endif - usb_hcd_giveback_urb (&ohci->hcd, urb, regs); -} - - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -/* search for the right schedule branch to use for a periodic ed. - * does some load balancing; returns the branch, or negative errno. - */ -static int balance (struct ohci_hcd *ohci, int interval, int load) -{ - int i, branch = -ENOSPC; - - /* iso periods can be huge; iso tds specify frame numbers */ - if (interval > NUM_INTS) - interval = NUM_INTS; - - /* search for the least loaded schedule branch of that period - * that has enough bandwidth left unreserved. - */ - for (i = 0; i < interval ; i++) { - if (branch < 0 || ohci->load [branch] > ohci->load [i]) { -#if 1 /* CONFIG_USB_BANDWIDTH */ - int j; - - /* usb 1.1 says 90% of one frame */ - for (j = i; j < NUM_INTS; j += interval) { - if ((ohci->load [j] + load) > 900) - break; - } - if (j < NUM_INTS) - continue; -#endif - branch = i; - } - } - return branch; -} - -/*-------------------------------------------------------------------------*/ - -/* both iso and interrupt requests have periods; this routine puts them - * into the schedule tree in the apppropriate place. most iso devices use - * 1msec periods, but that's not required. - */ -static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) -{ - unsigned i; - - ohci_vdbg (ohci, "link %sed %p branch %d [%dus.], interval %d\n", - (ed->hwINFO & ED_ISO) ? "iso " : "", - ed, ed->branch, ed->load, ed->interval); - - for (i = ed->branch; i < NUM_INTS; i += ed->interval) { - struct ed **prev = &ohci->periodic [i]; - u32 *prev_p = &ohci->hcca->int_table [i]; - struct ed *here = *prev; - - /* sorting each branch by period (slow before fast) - * lets us share the faster parts of the tree. - * (plus maybe: put interrupt eds before iso) - */ - while (here && ed != here) { - if (ed->interval > here->interval) - break; - prev = &here->ed_next; - prev_p = &here->hwNextED; - here = *prev; - } - if (ed != here) { - ed->ed_next = here; - if (here) - ed->hwNextED = *prev_p; - wmb (); - *prev = ed; - *prev_p = cpu_to_le32p (&ed->dma); - } - ohci->load [i] += ed->load; - } - hcd_to_bus (&ohci->hcd)->bandwidth_allocated += ed->load / ed->interval; -} - -/* link an ed into one of the HC chains */ - -static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) -{ - int branch; - - ed->state = ED_OPER; - ed->ed_prev = 0; - ed->ed_next = 0; - ed->hwNextED = 0; - wmb (); - - /* we care about rm_list when setting CLE/BLE in case the HC was at - * work on some TD when CLE/BLE was turned off, and isn't quiesced - * yet. finish_unlinks() restarts as needed, some upcoming INTR_SF. - * - * control and bulk EDs are doubly linked (ed_next, ed_prev), but - * periodic ones are singly linked (ed_next). that's because the - * periodic schedule encodes a tree like figure 3-5 in the ohci - * spec: each qh can have several "previous" nodes, and the tree - * doesn't have unused/idle descriptors. - */ - switch (ed->type) { - case PIPE_CONTROL: - if (ohci->ed_controltail == NULL) { - writel (ed->dma, &ohci->regs->ed_controlhead); - } else { - ohci->ed_controltail->ed_next = ed; - ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); - } - ed->ed_prev = ohci->ed_controltail; - if (!ohci->ed_controltail && !ohci->ed_rm_list) { - ohci->hc_control |= OHCI_CTRL_CLE; - writel (0, &ohci->regs->ed_controlcurrent); - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_controltail = ed; - break; - - case PIPE_BULK: - if (ohci->ed_bulktail == NULL) { - writel (ed->dma, &ohci->regs->ed_bulkhead); - } else { - ohci->ed_bulktail->ed_next = ed; - ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); - } - ed->ed_prev = ohci->ed_bulktail; - if (!ohci->ed_bulktail && !ohci->ed_rm_list) { - ohci->hc_control |= OHCI_CTRL_BLE; - writel (0, &ohci->regs->ed_bulkcurrent); - writel (ohci->hc_control, &ohci->regs->control); - } - ohci->ed_bulktail = ed; - break; - - // case PIPE_INTERRUPT: - // case PIPE_ISOCHRONOUS: - default: - branch = balance (ohci, ed->interval, ed->load); - if (branch < 0) { - ohci_dbg (ohci, - "ERR %d, interval %d msecs, load %d\n", - branch, ed->interval, ed->load); - // FIXME if there are TDs queued, fail them! - return branch; - } - ed->branch = branch; - periodic_link (ohci, ed); - } - - /* the HC may not see the schedule updates yet, but if it does - * then they'll be properly ordered. - */ - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* scan the periodic table to find and unlink this ED */ -static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) -{ - int i; - - for (i = ed->branch; i < NUM_INTS; i += ed->interval) { - struct ed *temp; - struct ed **prev = &ohci->periodic [i]; - u32 *prev_p = &ohci->hcca->int_table [i]; - - while (*prev && (temp = *prev) != ed) { - prev_p = &temp->hwNextED; - prev = &temp->ed_next; - } - if (*prev) { - *prev_p = ed->hwNextED; - *prev = ed->ed_next; - } - ohci->load [i] -= ed->load; - } - hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval; - - ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", - (ed->hwINFO & ED_ISO) ? "iso " : "", - ed, ed->branch, ed->load, ed->interval); -} - -/* unlink an ed from one of the HC chains. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed - */ -static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) -{ - ed->hwINFO |= ED_SKIP; - - switch (ed->type) { - case PIPE_CONTROL: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); - writel (0, &ohci->regs->ed_controlcurrent); - // post those pci writes - (void) readl (&ohci->regs->control); - } - writel (le32_to_cpup (&ed->hwNextED), - &ohci->regs->ed_controlhead); - } else { - ed->ed_prev->ed_next = ed->ed_next; - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_controltail == ed) { - ohci->ed_controltail = ed->ed_prev; - if (ohci->ed_controltail) - ohci->ed_controltail->ed_next = 0; - } else if (ed->ed_next) { - ed->ed_next->ed_prev = ed->ed_prev; - } - break; - - case PIPE_BULK: - if (ed->ed_prev == NULL) { - if (!ed->hwNextED) { - ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); - writel (0, &ohci->regs->ed_bulkcurrent); - // post those pci writes - (void) readl (&ohci->regs->control); - } - writel (le32_to_cpup (&ed->hwNextED), - &ohci->regs->ed_bulkhead); - } else { - ed->ed_prev->ed_next = ed->ed_next; - ed->ed_prev->hwNextED = ed->hwNextED; - } - if (ohci->ed_bulktail == ed) { - ohci->ed_bulktail = ed->ed_prev; - if (ohci->ed_bulktail) - ohci->ed_bulktail->ed_next = 0; - } else if (ed->ed_next) { - ed->ed_next->ed_prev = ed->ed_prev; - } - break; - - // case PIPE_INTERRUPT: - // case PIPE_ISOCHRONOUS: - default: - periodic_unlink (ohci, ed); - break; - } - - /* NOTE: Except for a couple of exceptionally clean unlink cases - * (like unlinking the only c/b ED, with no TDs) HCs may still be - * caching this operational ED (or its address). Safe unlinking - * involves not marking it ED_IDLE till INTR_SF; we always do that - * if td_list isn't empty. Otherwise the race is small; but ... - */ - if (ed->state == ED_OPER) { - ed->state = ED_IDLE; - ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); - ed->hwHeadP &= ~ED_H; - wmb (); - } -} - - -/*-------------------------------------------------------------------------*/ - -/* get and maybe (re)init an endpoint. init _should_ be done only as part - * of usb_set_configuration() or usb_set_interface() ... but the USB stack - * isn't very stateful, so we re-init whenever the HC isn't looking. - */ -static struct ed *ed_get ( - struct ohci_hcd *ohci, - struct usb_device *udev, - unsigned int pipe, - int interval -) { - int is_out = !usb_pipein (pipe); - int type = usb_pipetype (pipe); - struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv; - struct ed *ed; - unsigned ep; - unsigned long flags; - - ep = usb_pipeendpoint (pipe) << 1; - if (type != PIPE_CONTROL && is_out) - ep |= 1; - - spin_lock_irqsave (&ohci->lock, flags); - - if (!(ed = dev->ep [ep])) { - struct td *td; - - ed = ed_alloc (ohci, SLAB_ATOMIC); - if (!ed) { - /* out of memory */ - goto done; - } - dev->ep [ep] = ed; - - /* dummy td; end of td list for ed */ - td = td_alloc (ohci, SLAB_ATOMIC); - if (!td) { - /* out of memory */ - ed_free (ohci, ed); - ed = 0; - goto done; - } - ed->dummy = td; - ed->hwTailP = cpu_to_le32 (td->td_dma); - ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ - ed->state = ED_IDLE; - ed->type = type; - } - - /* NOTE: only ep0 currently needs this "re"init logic, during - * enumeration (after set_address, or if ep0 maxpacket >8). - */ - if (ed->state == ED_IDLE) { - u32 info; - - info = usb_pipedevice (pipe); - info |= (ep >> 1) << 7; - info |= usb_maxpacket (udev, pipe, is_out) << 16; - info = cpu_to_le32 (info); - if (udev->speed == USB_SPEED_LOW) - info |= ED_LOWSPEED; - /* only control transfers store pids in tds */ - if (type != PIPE_CONTROL) { - info |= is_out ? ED_OUT : ED_IN; - if (type != PIPE_BULK) { - /* periodic transfers... */ - if (type == PIPE_ISOCHRONOUS) - info |= ED_ISO; - else if (interval > 32) /* iso can be bigger */ - interval = 32; - ed->interval = interval; - ed->load = usb_calc_bus_time ( - udev->speed, !is_out, - type == PIPE_ISOCHRONOUS, - usb_maxpacket (udev, pipe, is_out)) - / 1000; - } - } - ed->hwINFO = info; - } - -done: - spin_unlock_irqrestore (&ohci->lock, flags); - return ed; -} - -/*-------------------------------------------------------------------------*/ - -/* request unlinking of an endpoint from an operational HC. - * put the ep on the rm_list - * real work is done at the next start frame (SF) hardware interrupt - */ -static void start_urb_unlink (struct ohci_hcd *ohci, struct ed *ed) -{ - ed->hwINFO |= ED_DEQUEUE; - ed->state = ED_UNLINK; - ed_deschedule (ohci, ed); - - /* SF interrupt might get delayed; record the frame counter value that - * indicates when the HC isn't looking at it, so concurrent unlinks - * behave. frame_no wraps every 2^16 msec, and changes right before - * SF is triggered. - */ - ed->tick = le16_to_cpu (ohci->hcca->frame_no) + 1; - - /* rm_list is just singly linked, for simplicity */ - ed->ed_next = ohci->ed_rm_list; - ed->ed_prev = 0; - ohci->ed_rm_list = ed; - - /* enable SOF interrupt */ - if (!ohci->sleeping) { - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - // flush those pci writes - (void) readl (&ohci->regs->control); - } -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void -td_fill (struct ohci_hcd *ohci, u32 info, - dma_addr_t data, int len, - struct urb *urb, int index) -{ - struct td *td, *td_pt; - struct urb_priv *urb_priv = urb->hcpriv; - int is_iso = info & TD_ISO; - int hash; - - // ASSERT (index < urb_priv->length); - - /* aim for only one interrupt per urb. mostly applies to control - * and iso; other urbs rarely need more than one TD per urb. - * this way, only final tds (or ones with an error) cause IRQs. - * at least immediately; use DI=6 in case any control request is - * tempted to die part way through. - * - * NOTE: could delay interrupts even for the last TD, and get fewer - * interrupts ... increasing per-urb latency by sharing interrupts. - * Drivers that queue bulk urbs may request that behavior. - */ - if (index != (urb_priv->length - 1) - || (urb->transfer_flags & URB_NO_INTERRUPT)) - info |= TD_DI_SET (6); - - /* use this td as the next dummy */ - td_pt = urb_priv->td [index]; - - /* fill the old dummy TD */ - td = urb_priv->td [index] = urb_priv->ed->dummy; - urb_priv->ed->dummy = td_pt; - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->urb = urb; - td->data_dma = data; - if (!len) - data = 0; - - td->hwINFO = cpu_to_le32 (info); - if (is_iso) { - td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); - td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); - td->ed->last_iso = info & 0xffff; - } else { - td->hwCBP = cpu_to_le32 (data); - } - if (data) - td->hwBE = cpu_to_le32 (data + len - 1); - else - td->hwBE = 0; - td->hwNextTD = cpu_to_le32 (td_pt->td_dma); - - /* append to queue */ - list_add_tail (&td->td_list, &td->ed->td_list); - - /* hash it for later reverse mapping */ - hash = TD_HASH_FUNC (td->td_dma); - td->td_hash = ohci->td_hash [hash]; - ohci->td_hash [hash] = td; - - /* HC might read the TD (or cachelines) right away ... */ - wmb (); - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* Prepare all TDs of a transfer, and queue them onto the ED. - * Caller guarantees HC is active. - * Usually the ED is already on the schedule, so TDs might be - * processed as soon as they're queued. - */ -static void td_submit_urb ( - struct ohci_hcd *ohci, - struct urb *urb -) { - struct urb_priv *urb_priv = urb->hcpriv; - dma_addr_t data; - int data_len = urb->transfer_buffer_length; - int cnt = 0; - u32 info = 0; - int is_out = usb_pipeout (urb->pipe); - - /* OHCI handles the bulk/interrupt data toggles itself. We just - * use the device toggle bits for resetting, and rely on the fact - * that resetting toggle is meaningless if the endpoint is active. - */ - if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), - is_out, 1); - urb_priv->ed->hwHeadP &= ~ED_C; - } - - urb_priv->td_cnt = 0; - - if (data_len) - data = urb->transfer_dma; - else - data = 0; - - /* NOTE: TD_CC is set so we can tell which TDs the HC processed by - * using TD_CC_GET, as well as by seeing them on the done list. - * (CC = NotAccessed ... 0x0F, or 0x0E in PSWs for ISO.) - */ - switch (urb_priv->ed->type) { - - /* Bulk and interrupt are identical except for where in the schedule - * their EDs live. - */ - case PIPE_INTERRUPT: - /* ... and periodic urbs have extra accounting */ - hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++; - /* FALLTHROUGH */ - case PIPE_BULK: - info = is_out - ? TD_T_TOGGLE | TD_CC | TD_DP_OUT - : TD_T_TOGGLE | TD_CC | TD_DP_IN; - /* TDs _could_ transfer up to 8K each */ - while (data_len > 4096) { - td_fill (ohci, info, data, 4096, urb, cnt); - data += 4096; - data_len -= 4096; - cnt++; - } - /* maybe avoid ED halt on final TD short read */ - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) - info |= TD_R; - td_fill (ohci, info, data, data_len, urb, cnt); - cnt++; - if ((urb->transfer_flags & URB_ZERO_PACKET) - && cnt < urb_priv->length) { - td_fill (ohci, info, 0, 0, urb, cnt); - cnt++; - } - /* maybe kickstart bulk list */ - if (urb_priv->ed->type == PIPE_BULK) { - wmb (); - writel (OHCI_BLF, &ohci->regs->cmdstatus); - } - break; - - /* control manages DATA0/DATA1 toggle per-request; SETUP resets it, - * any DATA phase works normally, and the STATUS ack is special. - */ - case PIPE_CONTROL: - info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (ohci, info, urb->setup_dma, 8, urb, cnt++); - if (data_len > 0) { - info = TD_CC | TD_R | TD_T_DATA1; - info |= is_out ? TD_DP_OUT : TD_DP_IN; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill (ohci, info, data, data_len, urb, cnt++); - } - info = is_out - ? TD_CC | TD_DP_IN | TD_T_DATA1 - : TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (ohci, info, data, 0, urb, cnt++); - /* maybe kickstart control list */ - wmb (); - writel (OHCI_CLF, &ohci->regs->cmdstatus); - break; - - /* ISO has no retransmit, so no toggle; and it uses special TDs. - * Each TD could handle multiple consecutive frames (interval 1); - * we could often reduce the number of TDs here. - */ - case PIPE_ISOCHRONOUS: - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { - int frame = urb->start_frame; - - // FIXME scheduling should handle frame counter - // roll-around ... exotic case (and OHCI has - // a 2^16 iso range, vs other HCs max of 2^10) - frame += cnt * urb->interval; - frame &= 0xffff; - td_fill (ohci, TD_CC | TD_ISO | frame, - data + urb->iso_frame_desc [cnt].offset, - urb->iso_frame_desc [cnt].length, urb, cnt); - } - hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++; - break; - } - // ASSERT (urb_priv->length == cnt); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - -/* calculate transfer length/status and update the urb - * PRECONDITION: irqsafe (only for urb->status locking) - */ -static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) -{ - u32 tdINFO = le32_to_cpup (&td->hwINFO); - int cc = 0; - - list_del (&td->td_list); - - /* ISO ... drivers see per-TD length/status */ - if (tdINFO & TD_ISO) { - u16 tdPSW = le16_to_cpu (td->hwPSW [0]); - int dlen = 0; - - /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */ - - cc = (tdPSW >> 12) & 0xF; - if (tdINFO & TD_CC) /* hc didn't touch? */ - return; - - if (usb_pipeout (urb->pipe)) - dlen = urb->iso_frame_desc [td->index].length; - else { - /* short reads are always OK for ISO */ - if (cc == TD_DATAUNDERRUN) - cc = TD_CC_NOERROR; - dlen = tdPSW & 0x3ff; - } - urb->actual_length += dlen; - urb->iso_frame_desc [td->index].actual_length = dlen; - urb->iso_frame_desc [td->index].status = cc_to_error [cc]; - - if (cc != TD_CC_NOERROR) - ohci_vdbg (ohci, - "urb %p iso td %p (%d) len %d cc %d\n", - urb, td, 1 + td->index, dlen, cc); - - /* BULK, INT, CONTROL ... drivers see aggregate length/status, - * except that "setup" bytes aren't counted and "short" transfers - * might not be reported as errors. - */ - } else { - int type = usb_pipetype (urb->pipe); - u32 tdBE = le32_to_cpup (&td->hwBE); - - cc = TD_CC_GET (tdINFO); - - /* control endpoints only have soft stalls */ - if (type != PIPE_CONTROL && cc == TD_CC_STALL) - usb_endpoint_halt (urb->dev, - usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)); - - /* update packet status if needed (short is normally ok) */ - if (cc == TD_DATAUNDERRUN - && !(urb->transfer_flags & URB_SHORT_NOT_OK)) - cc = TD_CC_NOERROR; - if (cc != TD_CC_NOERROR && cc < 0x0E) { - spin_lock (&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = cc_to_error [cc]; - spin_unlock (&urb->lock); - } - - /* count all non-empty packets except control SETUP packet */ - if ((type != PIPE_CONTROL || td->index != 0) && tdBE != 0) { - if (td->hwCBP == 0) - urb->actual_length += tdBE - td->data_dma + 1; - else - urb->actual_length += - le32_to_cpup (&td->hwCBP) - - td->data_dma; - } - - if (cc != TD_CC_NOERROR && cc < 0x0E) - ohci_vdbg (ohci, - "urb %p td %p (%d) cc %d, len=%d/%d\n", - urb, td, 1 + td->index, cc, - urb->actual_length, - urb->transfer_buffer_length); - } -} - -/*-------------------------------------------------------------------------*/ - -static inline struct td * -ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) -{ - struct urb *urb = td->urb; - struct ed *ed = td->ed; - struct list_head *tmp = td->td_list.next; - u32 toggle = ed->hwHeadP & ED_C; - - /* clear ed halt; this is the td that caused it, but keep it inactive - * until its urb->complete() has a chance to clean up. - */ - ed->hwINFO |= ED_SKIP; - wmb (); - ed->hwHeadP &= ~ED_H; - - /* put any later tds from this urb onto the donelist, after 'td', - * order won't matter here: no errors, and nothing was transferred. - * also patch the ed so it looks as if those tds completed normally. - */ - while (tmp != &ed->td_list) { - struct td *next; - u32 info; - - next = list_entry (tmp, struct td, td_list); - tmp = next->td_list.next; - - if (next->urb != urb) - break; - - /* NOTE: if multi-td control DATA segments get supported, - * this urb had one of them, this td wasn't the last td - * in that segment (TD_R clear), this ed halted because - * of a short read, _and_ URB_SHORT_NOT_OK is clear ... - * then we need to leave the control STATUS packet queued - * and clear ED_SKIP. - */ - info = next->hwINFO; - info |= cpu_to_le32 (TD_DONE); - info &= ~cpu_to_le32 (TD_CC); - next->hwINFO = info; - - next->next_dl_td = rev; - rev = next; - - if (ed->hwTailP == cpu_to_le32 (next->td_dma)) - ed->hwTailP = next->hwNextTD; - ed->hwHeadP = next->hwNextTD | toggle; - } - - /* help for troubleshooting: report anything that - * looks odd ... that doesn't include protocol stalls - * (or maybe some other things) - */ - if (cc != TD_CC_STALL || !usb_pipecontrol (urb->pipe)) - ohci_dbg (ohci, - "urb %p path %s ep%d%s %08x cc %d --> status %d\n", - urb, urb->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - le32_to_cpu (td->hwINFO), - cc, cc_to_error [cc]); - - return rev; -} - -/* replies to the request have to be on a FIFO basis so - * we unreverse the hc-reversed done-list - */ -static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) -{ - u32 td_dma; - struct td *td_rev = NULL; - struct td *td = NULL; - unsigned long flags; - - spin_lock_irqsave (&ohci->lock, flags); - td_dma = le32_to_cpup (&ohci->hcca->done_head); - ohci->hcca->done_head = 0; - - /* get TD from hc's singly linked list, and - * prepend to ours. ed->td_list changes later. - */ - while (td_dma) { - int cc; - - td = dma_to_td (ohci, td_dma); - if (!td) { - ohci_err (ohci, "bad entry %8x\n", td_dma); - break; - } - - td->hwINFO |= cpu_to_le32 (TD_DONE); - cc = TD_CC_GET (le32_to_cpup (&td->hwINFO)); - - /* Non-iso endpoints can halt on error; un-halt, - * and dequeue any other TDs from this urb. - * No other TD could have caused the halt. - */ - if (cc != TD_CC_NOERROR && (td->ed->hwHeadP & ED_H)) - td_rev = ed_halted (ohci, td, cc, td_rev); - - td->next_dl_td = td_rev; - td_rev = td; - td_dma = le32_to_cpup (&td->hwNextTD); - } - spin_unlock_irqrestore (&ohci->lock, flags); - return td_rev; -} - -/*-------------------------------------------------------------------------*/ - -/* wrap-aware logic stolen from */ -#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0) - -/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ -static void -finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs) -{ - struct ed *ed, **last; - -rescan_all: - for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) { - struct list_head *entry, *tmp; - int completed, modified; - u32 *prev; - - /* only take off EDs that the HC isn't using, accounting for - * frame counter wraps. - */ - if (tick_before (tick, ed->tick) && !ohci->disabled) { - last = &ed->ed_next; - continue; - } - - /* reentrancy: if we drop the schedule lock, someone might - * have modified this list. normally it's just prepending - * entries (which we'd ignore), but paranoia won't hurt. - */ - *last = ed->ed_next; - ed->ed_next = 0; - modified = 0; - - /* unlink urbs as requested, but rescan the list after - * we call a completion since it might have unlinked - * another (earlier) urb - */ -rescan_this: - completed = 0; - prev = &ed->hwHeadP; - list_for_each_safe (entry, tmp, &ed->td_list) { - struct td *td; - struct urb *urb; - urb_priv_t *urb_priv; - u32 savebits; - - td = list_entry (entry, struct td, td_list); - urb = td->urb; - urb_priv = td->urb->hcpriv; - - if (urb_priv->state != URB_DEL) { - prev = &td->hwNextTD; - continue; - } - - /* patch pointers hc uses ... tail, if we're removing - * an otherwise active td, and whatever td pointer - * points to this td - */ - if (ed->hwTailP == cpu_to_le32 (td->td_dma)) - ed->hwTailP = td->hwNextTD; - savebits = *prev & ~cpu_to_le32 (TD_MASK); - *prev = td->hwNextTD | savebits; - - /* HC may have partly processed this TD */ - td_done (ohci, urb, td); - urb_priv->td_cnt++; - - /* if URB is done, clean up */ - if (urb_priv->td_cnt == urb_priv->length) { - modified = completed = 1; - spin_unlock (&ohci->lock); - finish_urb (ohci, urb, regs); - spin_lock (&ohci->lock); - } - } - if (completed && !list_empty (&ed->td_list)) - goto rescan_this; - - /* ED's now officially unlinked, hc doesn't see */ - ed->state = ED_IDLE; - ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); - ed->hwHeadP &= ~ED_H; - ed->hwNextED = 0; - - /* but if there's work queued, reschedule */ - if (!list_empty (&ed->td_list)) { - if (!ohci->disabled && !ohci->sleeping) - ed_schedule (ohci, ed); - } - - if (modified) - goto rescan_all; - } - - /* maybe reenable control and bulk lists */ - if (!ohci->disabled && !ohci->ed_rm_list) { - u32 command = 0, control = 0; - - if (ohci->ed_controltail) { - command |= OHCI_CLF; - if (!(ohci->hc_control & OHCI_CTRL_CLE)) { - control |= OHCI_CTRL_CLE; - writel (0, &ohci->regs->ed_controlcurrent); - } - } - if (ohci->ed_bulktail) { - command |= OHCI_BLF; - if (!(ohci->hc_control & OHCI_CTRL_BLE)) { - control |= OHCI_CTRL_BLE; - writel (0, &ohci->regs->ed_bulkcurrent); - } - } - - /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ - if (control) { - ohci->hc_control |= control; - writel (ohci->hc_control, &ohci->regs->control); - } - if (command) - writel (command, &ohci->regs->cmdstatus); - } -} - - - -/*-------------------------------------------------------------------------*/ - -/* - * Process normal completions (error or success) and clean the schedules. - * - * This is the main path for handing urbs back to drivers. The only other - * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of - * scanning the (re-reversed) donelist as this does. - */ -static void -dl_done_list (struct ohci_hcd *ohci, struct td *td, struct pt_regs *regs) -{ - unsigned long flags; - - spin_lock_irqsave (&ohci->lock, flags); - while (td) { - struct td *td_next = td->next_dl_td; - struct urb *urb = td->urb; - urb_priv_t *urb_priv = urb->hcpriv; - struct ed *ed = td->ed; - - /* update URB's length and status from TD */ - td_done (ohci, urb, td); - urb_priv->td_cnt++; - - /* If all this urb's TDs are done, call complete() */ - if (urb_priv->td_cnt == urb_priv->length) { - spin_unlock (&ohci->lock); - finish_urb (ohci, urb, regs); - spin_lock (&ohci->lock); - } - - /* clean schedule: unlink EDs that are no longer busy */ - if (list_empty (&ed->td_list)) - ed_deschedule (ohci, ed); - /* ... reenabling halted EDs only after fault cleanup */ - else if (!(ed->hwINFO & ED_DEQUEUE)) { - td = list_entry (ed->td_list.next, struct td, td_list); - if (!(td->hwINFO & TD_DONE)) - ed->hwINFO &= ~ED_SKIP; - } - - td = td_next; - } - spin_unlock_irqrestore (&ohci->lock, flags); -} diff --git a/reactos/drivers/usb/miniport/usbohci/ohci.c b/reactos/drivers/usb/miniport/usbohci/ohci.c deleted file mode 100644 index 92396dc6060..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci.c +++ /dev/null @@ -1,76 +0,0 @@ -#define NDEBUG -#include - -#include "ohci.h" - -extern struct pci_driver ohci_pci_driver; -extern struct pci_device_id ohci_pci_ids[]; -struct pci_device_id* pci_ids = &ohci_pci_ids[0]; - -NTSTATUS -InitLinuxWrapper(PDEVICE_OBJECT DeviceObject) -{ - NTSTATUS Status; - PUSBMP_DEVICE_EXTENSION DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - /* Create generic linux structure */ - struct pci_dev *dev; - dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_OHCI_TAG); - DeviceExtension->pdev = dev; - - /* Initialize generic linux structure */ - dev->irq = DeviceExtension->InterruptVector; - dev->dev_ext = (PVOID)DeviceExtension; - dev->dev.dev_ext = DeviceObject; - dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_OHCI_TAG); // 128 max len for slot name - - /* Init wrapper */ - init_wrapper(dev); - - strcpy(dev->dev.name, "OpenHCI PCI-USB Controller"); - strcpy(dev->slot_name, "OHCD PCI Slot"); - - /* Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL */ - Status = ohci_hcd_pci_init(); - if (!NT_SUCCESS(Status)) - { - DPRINT("OHCI: ohci_hcd_pci_init() failed with status 0x%08lx\n", Status); - /* FIXME: deinitialize linux wrapper */ - ExFreePoolWithTag(dev, USB_OHCI_TAG); - return Status; - } - - /* Init core usb */ - usb_init(); - - /* Probe device with real id now */ - ohci_pci_driver.probe(dev, ohci_pci_ids); - - return STATUS_SUCCESS; -} - -VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject) -{ - PUSBMP_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT DeviceObject; - struct pci_dev *dev; - - DeviceObject = DriverObject->DeviceObject; - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - dev = DeviceExtension->pdev; - - DPRINT1("DriverUnload()\n"); - - // Exit usb device - usb_exit(); - - // Remove device (ohci_pci_driver.remove) - ohci_pci_driver.remove(dev); - - ExFreePool(dev->slot_name); - ExFreePool(dev); - - // Perform some cleanup - ohci_hcd_pci_cleanup(); -} diff --git a/reactos/drivers/usb/miniport/usbohci/ohci.h b/reactos/drivers/usb/miniport/usbohci/ohci.h deleted file mode 100644 index 673be66daed..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - * OHCI HCD (Host Controller Driver) for USB. - * - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * This file is licenced under the GPL. - */ - -#include "usbcommon.h" -#define USB_OHCI_TAG TAG('u','s','b','o') - -/* declare basic init functions and structures */ -int ohci_hcd_pci_init(void); -void ohci_hcd_pci_cleanup(void); -int STDCALL usb_init(void); -void STDCALL usb_exit(void); - -/* - * OHCI Endpoint Descriptor (ED) ... holds TD queue - * See OHCI spec, section 4.2 - * - * This is a "Queue Head" for those transfers, which is why - * both EHCI and UHCI call similar structures a "QH". - */ -struct ed { - /* first fields are hardware-specified, le32 */ - __u32 hwINFO; /* endpoint config bitmap */ - /* info bits defined by hcd */ -#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27) - /* info bits defined by the hardware */ -#define ED_ISO __constant_cpu_to_le32(1 << 15) -#define ED_SKIP __constant_cpu_to_le32(1 << 14) -#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13) -#define ED_OUT __constant_cpu_to_le32(0x01 << 11) -#define ED_IN __constant_cpu_to_le32(0x02 << 11) - __u32 hwTailP; /* tail of TD list */ - __u32 hwHeadP; /* head of TD list (hc r/w) */ -#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */ -#define ED_H __constant_cpu_to_le32(0x01) /* halted */ - __u32 hwNextED; /* next ED in list */ - - /* rest are purely for the driver's use */ - dma_addr_t dma; /* addr of ED */ - struct td *dummy; /* next TD to activate */ - - /* host's view of schedule */ - struct ed *ed_next; /* on schedule or rm_list */ - struct ed *ed_prev; /* for non-interrupt EDs */ - struct list_head td_list; /* "shadow list" of our TDs */ - - /* create --> IDLE --> OPER --> ... --> IDLE --> destroy - * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... - * some special cases : OPER --> IDLE ... - */ - u8 state; /* ED_{IDLE,UNLINK,OPER} */ -#define ED_IDLE 0x00 /* NOT linked to HC */ -#define ED_UNLINK 0x01 /* being unlinked from hc */ -#define ED_OPER 0x02 /* IS linked to hc */ - - u8 type; /* PIPE_{BULK,...} */ - - /* periodic scheduling params (for intr and iso) */ - u8 branch; - u16 interval; - u16 load; - u16 last_iso; /* iso only */ - - /* HC may see EDs on rm_list until next frame (frame_no == tick) */ - u16 tick; -} __attribute__ ((aligned(16))); - -#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ - - -/* - * OHCI Transfer Descriptor (TD) ... one per transfer segment - * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) - * and 4.3.2 (iso) - */ -struct td { - /* first fields are hardware-specified, le32 */ - __u32 hwINFO; /* transfer info bitmask */ - - /* hwINFO bits for both general and iso tds: */ -#define TD_CC 0xf0000000 /* condition code */ -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_DI 0x00E00000 /* frames before interrupt */ -#define TD_DI_SET(X) (((X) & 0x07)<< 21) - /* these two bits are available for definition/use by HCDs in both - * general and iso tds ... others are available for only one type - */ -#define TD_DONE 0x00020000 /* retired to donelist */ -#define TD_ISO 0x00010000 /* copy of ED_ISO */ - - /* hwINFO bits for general tds: */ -#define TD_EC 0x0C000000 /* error count */ -#define TD_T 0x03000000 /* data toggle state */ -#define TD_T_DATA0 0x02000000 /* DATA0 */ -#define TD_T_DATA1 0x03000000 /* DATA1 */ -#define TD_T_TOGGLE 0x00000000 /* uses ED_C */ -#define TD_DP 0x00180000 /* direction/pid */ -#define TD_DP_SETUP 0x00000000 /* SETUP pid */ -#define TD_DP_IN 0x00100000 /* IN pid */ -#define TD_DP_OUT 0x00080000 /* OUT pid */ - /* 0x00180000 rsvd */ -#define TD_R 0x00040000 /* round: short packets OK? */ - - /* (no hwINFO #defines yet for iso tds) */ - - __u32 hwCBP; /* Current Buffer Pointer (or 0) */ - __u32 hwNextTD; /* Next TD Pointer */ - __u32 hwBE; /* Memory Buffer End Pointer */ - - /* PSW is only for ISO */ -#define MAXPSW 1 /* hardware allows 8 */ - __u16 hwPSW [MAXPSW]; - - /* rest are purely for the driver's use */ - __u8 index; - struct ed *ed; - struct td *td_hash; /* dma-->td hashtable */ - struct td *next_dl_td; - struct urb *urb; - - dma_addr_t td_dma; /* addr of this TD */ - dma_addr_t data_dma; /* addr of data it points to */ - - struct list_head td_list; /* "shadow list", TDs on same ED */ -} __attribute__ ((aligned(32))); /* c/b/i need 16; only iso needs 32 */ - -#define TD_MASK ((u32)~0x1f) /* strip hw status in low addr bits */ - -/* - * Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW - */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 - /* 0x0A, 0x0B reserved for hardware */ -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D - /* 0x0E, 0x0F reserved for HCD */ -#define TD_NOTACCESSED 0x0F - - -/* map OHCI TD status codes (CC) to errno values */ -static const int cc_to_error [16] = { - /* No Error */ 0, - /* CRC Error */ -EILSEQ, - /* Bit Stuff */ -EPROTO, - /* Data Togg */ -EILSEQ, - /* Stall */ -EPIPE, - /* DevNotResp */ -ETIMEDOUT, - /* PIDCheck */ -EPROTO, - /* UnExpPID */ -EPROTO, - /* DataOver */ -EOVERFLOW, - /* DataUnder */ -EREMOTEIO, - /* (for hw) */ -EIO, - /* (for hw) */ -EIO, - /* BufferOver */ -ECOMM, - /* BuffUnder */ -ENOSR, - /* (for HCD) */ -EALREADY, - /* (for HCD) */ -EALREADY -}; - - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined section 4.4.1 of the OHCI spec. The HC is - * told the base address of it. It must be 256-byte aligned. - */ -struct ohci_hcca { -#define NUM_INTS 32 - __u32 int_table [NUM_INTS]; /* periodic schedule */ - __u16 frame_no; /* current frame number */ - __u16 pad1; /* set to 0 on each frame_no change */ - __u32 done_head; /* info returned for an interrupt */ - u8 reserved_for_hc [116]; - u8 what [4]; /* spec only identifies 252 bytes :) */ -} __attribute__ ((aligned(256))); - - -/* - * This is the structure of the OHCI controller's memory mapped I/O region. - * You must use readl() and writel() (in ) to access these fields!! - * Layout is in section 7 (and appendix B) of the spec. - */ -struct ohci_regs { - /* control and status registers (section 7.1) */ - __u32 revision; - __u32 control; - __u32 cmdstatus; - __u32 intrstatus; - __u32 intrenable; - __u32 intrdisable; - - /* memory pointers (section 7.2) */ - __u32 hcca; - __u32 ed_periodcurrent; - __u32 ed_controlhead; - __u32 ed_controlcurrent; - __u32 ed_bulkhead; - __u32 ed_bulkcurrent; - __u32 donehead; - - /* frame counters (section 7.3) */ - __u32 fminterval; - __u32 fmremaining; - __u32 fmnumber; - __u32 periodicstart; - __u32 lsthresh; - - /* Root hub ports (section 7.4) */ - struct ohci_roothub_regs { - __u32 a; - __u32 b; - __u32 status; -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */ - __u32 portstatus [MAX_ROOT_PORTS]; - } roothub; - - /* and optional "legacy support" registers (appendix B) at 0x0100 */ - -} __attribute__ ((aligned(32))); - - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -#define OHCI_USB_RESET (0 << 6) -#define OHCI_USB_RESUME (1 << 6) -#define OHCI_USB_OPER (2 << 6) -#define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - - -/* hcd-private per-urb state */ -typedef struct urb_priv { - struct ed *ed; - __u16 length; // # tds in this request - __u16 td_cnt; // tds already serviced - int state; - struct td *td [0]; // all TDs in this request - -} urb_priv_t; - -#define URB_DEL 1 - -#define TD_HASH_SIZE 64 /* power'o'two */ -// sizeof (struct td) ~= 64 == 2^6 ... -#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) - - -/* - * This is the full ohci controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - -struct ohci_hcd { - spinlock_t lock; - - /* - * I/O memory used to communicate with the HC (dma-consistent) - */ - struct ohci_regs *regs; - - /* - * main memory used to communicate with the HC (dma-consistent). - * hcd adds to schedule for a live hc any time, but removals finish - * only at the start of the next frame. - */ - struct ohci_hcca *hcca; - dma_addr_t hcca_dma; - - struct ed *ed_rm_list; /* to be removed */ - - struct ed *ed_bulktail; /* last in bulk list */ - struct ed *ed_controltail; /* last in ctrl list */ - struct ed *periodic [NUM_INTS]; /* shadow int_table */ - - /* - * memory management for queue data structures - */ - struct pci_pool *td_cache; - struct pci_pool *ed_cache; - struct td *td_hash [TD_HASH_SIZE]; - - /* - * driver state - */ - int disabled; /* e.g. got a UE, we're hung */ - int sleeping; - int load [NUM_INTS]; - u32 hc_control; /* copy of hc control reg */ - - unsigned long flags; /* for HC bugs */ -#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ -#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ - // there are also chip quirks/bugs in init logic - - /* - * framework state - */ - struct usb_hcd hcd; -}; - -#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd) - -/*-------------------------------------------------------------------------*/ - -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -#define ohci_dbg(ohci, fmt, args...) \ - dev_dbg ((ohci)->hcd.controller , fmt , ## args ) -#define ohci_err(ohci, fmt, args...) \ - dev_err ((ohci)->hcd.controller , fmt , ## args ) -#define ohci_info(ohci, fmt, args...) \ - dev_info ((ohci)->hcd.controller , fmt , ## args ) -#define ohci_warn(ohci, fmt, args...) \ - dev_warn ((ohci)->hcd.controller , fmt , ## args ) - -#ifdef OHCI_VERBOSE_DEBUG -# define ohci_vdbg ohci_dbg -#else -# define ohci_vdbg(ohci, fmt, args...) do { } while (0) -#endif - diff --git a/reactos/drivers/usb/miniport/usbohci/ohci.rc b/reactos/drivers/usb/miniport/usbohci/ohci.rc deleted file mode 100644 index a31d60c3796..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USB OHCI Device Driver\0" -#define REACTOS_STR_INTERNAL_NAME "ohci\0" -#define REACTOS_STR_ORIGINAL_FILENAME "ohci.sys\0" -#include diff --git a/reactos/drivers/usb/miniport/usbohci/ohci_config.h b/reactos/drivers/usb/miniport/usbohci/ohci_config.h deleted file mode 100644 index 01fd7cdcb08..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/ohci_config.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Configs for OHCI - */ - -#define CONFIG_PCI diff --git a/reactos/drivers/usb/miniport/usbohci/usbohci.rbuild b/reactos/drivers/usb/miniport/usbohci/usbohci.rbuild deleted file mode 100644 index 68242814c60..00000000000 --- a/reactos/drivers/usb/miniport/usbohci/usbohci.rbuild +++ /dev/null @@ -1,13 +0,0 @@ - - - ../linux - - sys_base - usbminiportcommon - usbport - ntoskrnl - hal - ohci.c - ohci-hcd.c - ohci.rc - diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci-debug.c b/reactos/drivers/usb/miniport/usbuhci/uhci-debug.c deleted file mode 100644 index c2577597608..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci-debug.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * UHCI-specific debugging code. Invaluable when something - * goes wrong, but don't get in my face. - * - * Kernel visible pointers are surrounded in []'s and bus - * visible pointers are surrounded in ()'s - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2001 Johannes Erdfelt - */ - -#if 0 -#include -#include -#include -#include -#include -#endif - -#include "uhci-hcd.h" - -/* Handle REALLY large printk's so we don't overflow buffers */ -static inline void lprintk(char *buf) -{ - char *p; - - /* Just write one line at a time */ - while (buf) { - p = strchr(buf, '\n'); - if (p) - *p = 0; - printk(KERN_DEBUG "%s\n", buf); - buf = p; - if (buf) - buf++; - } -} - -static inline int uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - int i; - - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (qh == uhci->skelqh[i]) - return 1; - - return 0; -} - -static int uhci_show_td(struct uhci_td *td, char *buf, int len, int space) -{ - char *out = buf; - char *spid; - u32 status, token; - - /* Try to make sure there's enough memory */ - if (len < 160) - return 0; - - status = td_status(td); - out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, le32_to_cpu(td->link)); - out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ", - ((status >> 27) & 3), - (status & TD_CTRL_SPD) ? "SPD " : "", - (status & TD_CTRL_LS) ? "LS " : "", - (status & TD_CTRL_IOC) ? "IOC " : "", - (status & TD_CTRL_ACTIVE) ? "Active " : "", - (status & TD_CTRL_STALLED) ? "Stalled " : "", - (status & TD_CTRL_DBUFERR) ? "DataBufErr " : "", - (status & TD_CTRL_BABBLE) ? "Babble " : "", - (status & TD_CTRL_NAK) ? "NAK " : "", - (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", - (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", - status & 0x7ff); - - token = td_token(td); - switch (uhci_packetid(token)) { - case USB_PID_SETUP: - spid = "SETUP"; - break; - case USB_PID_OUT: - spid = "OUT"; - break; - case USB_PID_IN: - spid = "IN"; - break; - default: - spid = "?"; - break; - } - - out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ", - token >> 21, - ((token >> 19) & 1), - (token >> 15) & 15, - (token >> 8) & 127, - (token & 0xff), - spid); - out += sprintf(out, "(buf=%08x)\n", le32_to_cpu(td->buffer)); - - return out - buf; -} - -static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) -{ - char *out = buf; - struct urb_priv *urbp; - struct list_head *head, *tmp; - struct uhci_td *td; - int i = 0, checked = 0, prevactive = 0; - - /* Try to make sure there's enough memory */ - if (len < 80 * 6) - return 0; - - out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "", - qh, le32_to_cpu(qh->link), le32_to_cpu(qh->element)); - - if (qh->element & UHCI_PTR_QH) - out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); - - if (qh->element & UHCI_PTR_DEPTH) - out += sprintf(out, "%*s Depth traverse\n", space, ""); - - if (qh->element & cpu_to_le32(8)) - out += sprintf(out, "%*s Bit 3 set (bug?)\n", space, ""); - - if (!(qh->element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH))) - out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); - - if (!qh->urbp) { - out += sprintf(out, "%*s urbp == NULL\n", space, ""); - goto out; - } - - urbp = qh->urbp; - - head = &urbp->td_list; - tmp = head->next; - - td = list_entry(tmp, struct uhci_td, list); - - if (cpu_to_le32(td->dma_handle) != (qh->element & ~UHCI_PTR_BITS)) - out += sprintf(out, "%*s Element != First TD\n", space, ""); - - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - out += sprintf(out, "%*s%d: ", space + 2, "", i++); - out += uhci_show_td(td, out, len - (out - buf), 0); - - if (i > 10 && !checked && prevactive && tmp != head && - debug <= 2) { - struct list_head *ntmp = tmp; - struct uhci_td *ntd = td; - int active = 1, ni = i; - - checked = 1; - - while (ntmp != head && ntmp->next != head && active) { - ntd = list_entry(ntmp, struct uhci_td, list); - - ntmp = ntmp->next; - - active = td_status(ntd) & TD_CTRL_ACTIVE; - - ni++; - } - - if (active && ni > i) { - out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i); - tmp = ntmp; - td = ntd; - i = ni; - } - } - - prevactive = td_status(td) & TD_CTRL_ACTIVE; - } - - if (list_empty(&urbp->queue_list) || urbp->queued) - goto out; - - out += sprintf(out, "%*sQueued QH's:\n", -space, "--"); - - head = &urbp->queue_list; - tmp = head->next; - - while (tmp != head) { - struct urb_priv *nurbp = list_entry(tmp, struct urb_priv, - queue_list); - tmp = tmp->next; - - out += uhci_show_qh(nurbp->qh, out, len - (out - buf), space); - } - -out: - return out - buf; -} - -#define show_frame_num() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- Frame %d\n", i); \ - } - -#ifdef CONFIG_PROC_FS -static const char *qh_names[] = { - "skel_int128_qh", "skel_int64_qh", - "skel_int32_qh", "skel_int16_qh", - "skel_int8_qh", "skel_int4_qh", - "skel_int2_qh", "skel_int1_qh", - "skel_ls_control_qh", "skel_fs_control_qh", - "skel_bulk_qh", "skel_term_qh" -}; - -#define show_qh_name() \ - if (!shown) { \ - shown = 1; \ - out += sprintf(out, "- %s\n", qh_names[i]); \ - } - -static int uhci_show_sc(int port, unsigned short status, char *buf, int len) -{ - char *out = buf; - - /* Try to make sure there's enough memory */ - if (len < 160) - return 0; - - out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", - port, - status, - (status & USBPORTSC_SUSP) ? " Suspend" : "", - (status & USBPORTSC_OCC) ? " OverCurrentChange" : "", - (status & USBPORTSC_OC) ? " OverCurrent" : "", - (status & USBPORTSC_PR) ? " Reset" : "", - (status & USBPORTSC_LSDA) ? " LowSpeed" : "", - (status & USBPORTSC_RD) ? " ResumeDetect" : "", - (status & USBPORTSC_PEC) ? " EnableChange" : "", - (status & USBPORTSC_PE) ? " Enabled" : "", - (status & USBPORTSC_CSC) ? " ConnectChange" : "", - (status & USBPORTSC_CCS) ? " Connected" : ""); - - return out - buf; -} - -static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) -{ - char *out = buf; - unsigned int io_addr = uhci->io_addr; - unsigned short usbcmd, usbstat, usbint, usbfrnum; - unsigned int flbaseadd; - unsigned char sof; - unsigned short portsc1, portsc2; - - /* Try to make sure there's enough memory */ - if (len < 80 * 6) - return 0; - - usbcmd = inw(io_addr + 0); - usbstat = inw(io_addr + 2); - usbint = inw(io_addr + 4); - usbfrnum = inw(io_addr + 6); - flbaseadd = inl(io_addr + 8); - sof = inb(io_addr + 12); - portsc1 = inw(io_addr + 16); - portsc2 = inw(io_addr + 18); - - out += sprintf(out, " usbcmd = %04x %s%s%s%s%s%s%s%s\n", - usbcmd, - (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ", - (usbcmd & USBCMD_CF) ? "CF " : "", - (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "", - (usbcmd & USBCMD_FGR) ? "FGR " : "", - (usbcmd & USBCMD_EGSM) ? "EGSM " : "", - (usbcmd & USBCMD_GRESET) ? "GRESET " : "", - (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", - (usbcmd & USBCMD_RS) ? "RS " : ""); - - out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", - usbstat, - (usbstat & USBSTS_HCH) ? "HCHalted " : "", - (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "", - (usbstat & USBSTS_HSE) ? "HostSystemError " : "", - (usbstat & USBSTS_RD) ? "ResumeDetect " : "", - (usbstat & USBSTS_ERROR) ? "USBError " : "", - (usbstat & USBSTS_USBINT) ? "USBINT " : ""); - - out += sprintf(out, " usbint = %04x\n", usbint); - out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, - 0xfff & (4*(unsigned int)usbfrnum)); - out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); - out += sprintf(out, " sof = %02x\n", sof); - out += uhci_show_sc(1, portsc1, out, len - (out - buf)); - out += uhci_show_sc(2, portsc2, out, len - (out - buf)); - - return out - buf; -} - -static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *buf, int len) -{ - struct list_head *tmp; - char *out = buf; - int count = 0; - - if (len < 200) - return 0; - - out += sprintf(out, "urb_priv [%p] ", urbp); - out += sprintf(out, "urb [%p] ", urbp->urb); - out += sprintf(out, "qh [%p] ", urbp->qh); - out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); - out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); - - switch (usb_pipetype(urbp->urb->pipe)) { - case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break; - case PIPE_INTERRUPT: out += sprintf(out, "INT "); break; - case PIPE_BULK: out += sprintf(out, "BLK "); break; - case PIPE_CONTROL: out += sprintf(out, "CTL "); break; - } - - out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : "")); - out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : "")); - - if (urbp->urb->status != -EINPROGRESS) - out += sprintf(out, "Status=%d ", urbp->urb->status); - //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime); - //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); - - count = 0; - list_for_each(tmp, &urbp->td_list) - count++; - out += sprintf(out, "TDs=%d ",count); - - if (urbp->queued) - out += sprintf(out, "queued\n"); - else { - count = 0; - list_for_each(tmp, &urbp->queue_list) - count++; - out += sprintf(out, "queued URBs=%d\n", count); - } - - return out - buf; -} - -static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len) -{ - char *out = buf; - struct list_head *head, *tmp; - int count; - - out += sprintf(out, "Main list URBs:"); - if (list_empty(&uhci->urb_list)) - out += sprintf(out, " Empty\n"); - else { - out += sprintf(out, "\n"); - count = 0; - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - - out += sprintf(out, " %d: ", ++count); - out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); - tmp = tmp->next; - } - } - - out += sprintf(out, "Remove list URBs:"); - if (list_empty(&uhci->urb_remove_list)) - out += sprintf(out, " Empty\n"); - else { - out += sprintf(out, "\n"); - count = 0; - head = &uhci->urb_remove_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - - out += sprintf(out, " %d: ", ++count); - out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); - tmp = tmp->next; - } - } - - out += sprintf(out, "Complete list URBs:"); - if (list_empty(&uhci->complete_list)) - out += sprintf(out, " Empty\n"); - else { - out += sprintf(out, "\n"); - count = 0; - head = &uhci->complete_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - - out += sprintf(out, " %d: ", ++count); - out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); - tmp = tmp->next; - } - } - - return out - buf; -} - -static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) -{ - unsigned long flags; - char *out = buf; - int i, j; - struct uhci_qh *qh; - struct uhci_td *td; - struct list_head *tmp, *head; - - spin_lock_irqsave(&uhci->schedule_lock, flags); - - out += sprintf(out, "HC status\n"); - out += uhci_show_status(uhci, out, len - (out - buf)); - - out += sprintf(out, "Frame List\n"); - for (i = 0; i < UHCI_NUMFRAMES; ++i) { - int shown = 0; - td = uhci->fl->frame_cpu[i]; - if (!td) - continue; - - if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) { - show_frame_num(); - out += sprintf(out, " frame list does not match td->dma_handle!\n"); - } - show_frame_num(); - - head = &td->fl_list; - tmp = head; - do { - td = list_entry(tmp, struct uhci_td, fl_list); - tmp = tmp->next; - out += uhci_show_td(td, out, len - (out - buf), 4); - } while (tmp != head); - } - - out += sprintf(out, "Skeleton QH's\n"); - - for (i = 0; i < UHCI_NUM_SKELQH; ++i) { - int shown = 0; - - qh = uhci->skelqh[i]; - - if (debug > 1) { - show_qh_name(); - out += uhci_show_qh(qh, out, len - (out - buf), 4); - } - - /* Last QH is the Terminating QH, it's different */ - if (i == UHCI_NUM_SKELQH - 1) { - if (qh->link != UHCI_PTR_TERM) - out += sprintf(out, " bandwidth reclamation on!\n"); - - if (qh->element != cpu_to_le32(uhci->term_td->dma_handle)) - out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); - - continue; - } - - j = (i < 7) ? 7 : i+1; /* Next skeleton */ - if (list_empty(&qh->list)) { - if (i < UHCI_NUM_SKELQH - 1) { - if (qh->link != - (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) { - show_qh_name(); - out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n"); - } - } - - continue; - } - - show_qh_name(); - - head = &qh->list; - tmp = head->next; - - while (tmp != head) { - qh = list_entry(tmp, struct uhci_qh, list); - - tmp = tmp->next; - - out += uhci_show_qh(qh, out, len - (out - buf), 4); - } - - if (i < UHCI_NUM_SKELQH - 1) { - if (qh->link != - (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) - out += sprintf(out, " last QH not linked to next skeleton!\n"); - } - } - - if (debug > 2) - out += uhci_show_lists(uhci, out, len - (out - buf)); - - spin_unlock_irqrestore(&uhci->schedule_lock, flags); - - return out - buf; -} - -#define MAX_OUTPUT (64 * 1024) - -static struct proc_dir_entry *uhci_proc_root = NULL; - -struct uhci_proc { - int size; - char *data; - struct uhci_hcd *uhci; -}; - -static int uhci_proc_open(struct inode *inode, struct file *file) -{ - const struct proc_dir_entry *dp = PDE(inode); - struct uhci_hcd *uhci = dp->data; - struct uhci_proc *up; - int ret = -ENOMEM; - - lock_kernel(); - up = kmalloc(sizeof(*up), GFP_KERNEL); - if (!up) - goto out; - - up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); - if (!up->data) { - kfree(up); - goto out; - } - - up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); - - file->private_data = up; - - ret = 0; -out: - unlock_kernel(); - return ret; -} - -static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence) -{ - struct uhci_proc *up; - loff_t new = -1; - - lock_kernel(); - up = file->private_data; - - switch (whence) { - case 0: - new = off; - break; - case 1: - new = file->f_pos + off; - break; - } - if (new < 0 || new > up->size) { - unlock_kernel(); - return -EINVAL; - } - unlock_kernel(); - return (file->f_pos = new); -} - -static ssize_t uhci_proc_read(struct file *file, char *buf, size_t nbytes, - loff_t *ppos) -{ - struct uhci_proc *up = file->private_data; - unsigned int pos; - unsigned int size; - - pos = *ppos; - size = up->size; - if (pos >= size) - return 0; - if (nbytes >= size) - nbytes = size; - if (pos + nbytes > size) - nbytes = size - pos; - - if (!access_ok(VERIFY_WRITE, buf, nbytes)) - return -EINVAL; - - if (copy_to_user(buf, up->data + pos, nbytes)) - return -EFAULT; - - *ppos += nbytes; - - return nbytes; -} - -static int uhci_proc_release(struct inode *inode, struct file *file) -{ - struct uhci_proc *up = file->private_data; - - kfree(up->data); - kfree(up); - - return 0; -} - -static struct file_operations uhci_proc_operations = { - .open = uhci_proc_open, - .llseek = uhci_proc_lseek, - .read = uhci_proc_read, -// write: uhci_proc_write, - .release = uhci_proc_release, -}; -#endif diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci-hcd.c b/reactos/drivers/usb/miniport/usbuhci/uhci-hcd.c deleted file mode 100644 index 5adfa5ac2a7..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci-hcd.c +++ /dev/null @@ -1,2624 +0,0 @@ -/* - * Universal Host Controller Interface driver for USB. - * - * Maintainer: Johannes Erdfelt - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com - * (C) Copyright 1999 Randy Dunlap - * (C) Copyright 1999 Georg Acher, acher@in.tum.de - * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de - * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch - * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at - * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface - * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). - * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) - * - * Intel documents this fairly well, and as far as I know there - * are no royalties or anything like that, but even so there are - * people who decided that they want to do the same thing in a - * completely different way. - * - * WARNING! The USB documentation is downright evil. Most of it - * is just crap, written by a committee. You're better off ignoring - * most of it, the important stuff is: - * - the low-level protocol (fairly simple but lots of small details) - * - working around the horridness of the rest - */ - -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -//#ifdef CONFIG_USB_DEBUG -#define DEBUG -//#else -//#undef DEBUG -//#endif - -#if 0 -#include - -#include -#include -#include -#include -#endif - -#include "uhci_config.h" -#include "../usb_wrapper.h" -#include "../../usbport/hcd.h" -#include "uhci-hcd.h" - -#if 0 -#include -#endif - -/* - * Version Information - */ -#define DRIVER_VERSION "v2.1" -#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" -#define DRIVER_DESC "USB Universal Host Controller Interface driver" - -/* - * debug = 0, no debugging messages - * debug = 1, dump failed URB's except for stalls - * debug = 2, dump all failed URB's (including stalls) - * show all queues in /proc/driver/uhci/[pci_addr] - * debug = 3, show all TD's in URB's when dumping - */ -#ifdef DEBUG -static int debug = 3; -#else -static int debug = 2; -#endif -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug level"); -static char *errbuf; -#define ERRBUF_LEN (PAGE_SIZE * 8) - -#include "uhci-hub.c" -#include "uhci-debug.c" - -static kmem_cache_t *uhci_up_cachep; /* urb_priv */ - -static int uhci_get_current_frame_number(struct uhci_hcd *uhci); -static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); -static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); - -static void hc_state_transitions(struct uhci_hcd *uhci); - -/* If a transfer is still active after this much time, turn off FSBR */ -#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */ -#define FSBR_DELAY (HZ / 20) /* 50 ms */ - -/* When we timeout an idle transfer for FSBR, we'll switch it over to */ -/* depth first traversal. We'll do it in groups of this number of TD's */ -/* to make sure it doesn't hog all of the bandwidth */ -#define DEPTH_INTERVAL 5 - -/* - * Technically, updating td->status here is a race, but it's not really a - * problem. The worst that can happen is that we set the IOC bit again - * generating a spurious interrupt. We could fix this by creating another - * QH and leaving the IOC bit always set, but then we would have to play - * games with the FSBR code to make sure we get the correct order in all - * the cases. I don't think it's worth the effort - */ -static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) -{ - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) -{ - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static inline void uhci_add_complete(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - list_add_tail(&urbp->complete_list, &uhci->complete_list); - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); -} - -static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev) -{ - dma_addr_t dma_handle; - struct uhci_td *td; - - td = pci_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); - if (!td) - return NULL; - - td->dma_handle = dma_handle; - - td->link = UHCI_PTR_TERM; - td->buffer = 0; - - td->frame = -1; - td->dev = dev; - - INIT_LIST_HEAD(&td->list); - INIT_LIST_HEAD(&td->fl_list); - - usb_get_dev(dev); - - return td; -} - -static inline void uhci_fill_td(struct uhci_td *td, __u32 status, - __u32 token, __u32 buffer) -{ - td->status = cpu_to_le32(status); - td->token = cpu_to_le32(token); - td->buffer = cpu_to_le32(buffer); -} - -/* - * We insert Isochronous URB's directly into the frame list at the beginning - */ -static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum) -{ - unsigned long flags; - - framenum %= UHCI_NUMFRAMES; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - td->frame = framenum; - - /* Is there a TD already mapped there? */ - if (uhci->fl->frame_cpu[framenum]) { - struct uhci_td *ftd, *ltd; - - ftd = uhci->fl->frame_cpu[framenum]; - ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); - - list_add_tail(&td->fl_list, &ftd->fl_list); - - td->link = ltd->link; - mb(); - ltd->link = cpu_to_le32(td->dma_handle); - } else { - td->link = uhci->fl->frame[framenum]; - mb(); - uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); - uhci->fl->frame_cpu[framenum] = td; - } - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) -{ - unsigned long flags; - - /* If it's not inserted, don't remove it */ - spin_lock_irqsave(&uhci->frame_list_lock, flags); - if (td->frame == -1 && list_empty(&td->fl_list)) - goto out; - - if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { - if (list_empty(&td->fl_list)) { - uhci->fl->frame[td->frame] = td->link; - uhci->fl->frame_cpu[td->frame] = NULL; - } else { - struct uhci_td *ntd; - - ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); - uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle); - uhci->fl->frame_cpu[td->frame] = ntd; - } - } else { - struct uhci_td *ptd; - - ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list); - ptd->link = td->link; - } - - mb(); - td->link = UHCI_PTR_TERM; - - list_del_init(&td->fl_list); - td->frame = -1; - -out: - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -/* - * Inserts a td into qh list at the top. - */ -static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, u32 breadth) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td, *ptd; - - if (list_empty(&urbp->td_list)) - return; - - head = &urbp->td_list; - tmp = head->next; - - /* Ordering isn't important here yet since the QH hasn't been */ - /* inserted into the schedule yet */ - td = list_entry(tmp, struct uhci_td, list); - - /* Add the first TD to the QH element pointer */ - qh->element = cpu_to_le32(td->dma_handle) | breadth; - - ptd = td; - - /* Then link the rest of the TD's */ - tmp = tmp->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - ptd->link = cpu_to_le32(td->dma_handle) | breadth; - - ptd = td; - } - - ptd->link = UHCI_PTR_TERM; -} - -static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) -{ - if (!list_empty(&td->list)) - dbg("td %p is still in list!", td); - if (!list_empty(&td->fl_list)) - dbg("td %p is still in fl_list!", td); - - if (td->dev) - usb_put_dev(td->dev); - - pci_pool_free(uhci->td_pool, td, td->dma_handle); -} - -static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev) -{ - dma_addr_t dma_handle; - struct uhci_qh *qh; - - qh = pci_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); - if (!qh) - return NULL; - - qh->dma_handle = dma_handle; - - qh->element = UHCI_PTR_TERM; - qh->link = UHCI_PTR_TERM; - - qh->dev = dev; - qh->urbp = NULL; - - INIT_LIST_HEAD(&qh->list); - INIT_LIST_HEAD(&qh->remove_list); - - usb_get_dev(dev); - - return qh; -} - -static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - if (!list_empty(&qh->list)) - dbg("qh %p list not empty!", qh); - if (!list_empty(&qh->remove_list)) - dbg("qh %p still in remove_list!", qh); - - if (qh->dev) - usb_put_dev(qh->dev); - - pci_pool_free(uhci->qh_pool, qh, qh->dma_handle); -} - -/* - * Append this urb's qh after the last qh in skelqh->list - * MUST be called with uhci->frame_list_lock acquired - * - * Note that urb_priv.queue_list doesn't have a separate queue head; - * it's a ring with every element "live". - */ -static void _uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *tmp; - struct uhci_qh *lqh; - - /* Grab the last QH */ - lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); - - /* - * Patch this endpoint's URB's QHs to point to the next skelqh: - * skelqh --> ... lqh --> newqh --> next skelqh - * Do this first, so the HC always sees the right QH after this one. - */ - list_for_each (tmp, &urbp->queue_list) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - turbp->qh->link = lqh->link; - } - urbp->qh->link = lqh->link; - wmb(); /* Ordering is important */ - - /* - * Patch QHs for previous endpoint's queued URBs? HC goes - * here next, not to the next skelqh it now points to. - * - * lqh --> td ... --> qh ... --> td --> qh ... --> td - * | | | - * v v v - * +<----------------+-----------------+ - * v - * newqh --> td ... --> td - * | - * v - * ... - * - * The HC could see (and use!) any of these as we write them. - */ - if (lqh->urbp) { - list_for_each (tmp, &lqh->urbp->queue_list) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - turbp->qh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; - } - } - lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; - - list_add_tail(&urbp->qh->list, &skelqh->list); -} - -static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) -{ - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - _uhci_insert_qh(uhci, skelqh, urb); - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -/* - * Start removal of QH from schedule; it finishes next frame. - * TDs should be unlinked before this is called. - */ -static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) -{ - unsigned long flags; - struct uhci_qh *pqh; - - if (!qh) - return; - - qh->urbp = NULL; - - /* - * Only go through the hoops if it's actually linked in - * Queued QHs are removed in uhci_delete_queued_urb, - * since (for queued URBs) the pqh is pointed to the next - * QH in the queue, not the next endpoint's QH. - */ - spin_lock_irqsave(&uhci->frame_list_lock, flags); - if (!list_empty(&qh->list)) { - pqh = list_entry(qh->list.prev, struct uhci_qh, list); - - if (pqh->urbp) { - struct list_head *head, *tmp; - - head = &pqh->urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - turbp->qh->link = qh->link; - } - } - - pqh->link = qh->link; - mb(); - /* Leave qh->link in case the HC is on the QH now, it will */ - /* continue the rest of the schedule */ - qh->element = UHCI_PTR_TERM; - - list_del_init(&qh->list); - } - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); - - spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); - - /* Check to see if the remove list is empty. Set the IOC bit */ - /* to force an interrupt so we can remove the QH */ - if (list_empty(&uhci->qh_remove_list)) - uhci_set_next_interrupt(uhci); - - list_add(&qh->remove_list, &uhci->qh_remove_list); - - spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); -} - -static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; - - head = &urbp->td_list; - tmp = head->next; - while (head != tmp) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - if (toggle) - td->token |= cpu_to_le32(TD_TOKEN_TOGGLE); - else - td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE); - - - toggle ^= 1; - } - - return toggle; -} - -/* This function will append one URB's QH to another URB's QH. This is for */ -/* queuing interrupt, control or bulk transfers */ -static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb) -{ - struct urb_priv *eurbp, *urbp, *furbp, *lurbp; - struct list_head *tmp; - struct uhci_td *lltd; - unsigned long flags; - - eurbp = eurb->hcpriv; - urbp = urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - /* Find the first URB in the queue */ - if (eurbp->queued) { - struct list_head *head = &eurbp->queue_list; - - tmp = head->next; - while (tmp != head) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - if (!turbp->queued) - break; - - tmp = tmp->next; - } - } else - tmp = &eurbp->queue_list; - - furbp = list_entry(tmp, struct urb_priv, queue_list); - lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); - - lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); - - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), - uhci_fixup_toggle(urb, uhci_toggle(td_token(lltd)) ^ 1)); - - /* All qh's in the queue need to link to the next queue */ - urbp->qh->link = eurbp->qh->link; - - mb(); /* Make sure we flush everything */ - - lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; - - list_add_tail(&urbp->queue_list, &furbp->queue_list); - - urbp->queued = 1; - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp, *nurbp; - struct list_head *head, *tmp; - struct urb_priv *purbp; - struct uhci_td *pltd; - unsigned int toggle; - unsigned long flags; - - urbp = urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - if (list_empty(&urbp->queue_list)) - goto out; - - nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list); - - /* Fix up the toggle for the next URB's */ - if (!urbp->queued) - /* We just set the toggle in uhci_unlink_generic */ - toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - else { - /* If we're in the middle of the queue, grab the toggle */ - /* from the TD previous to us */ - purbp = list_entry(urbp->queue_list.prev, struct urb_priv, - queue_list); - - pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); - - toggle = uhci_toggle(td_token(pltd)) ^ 1; - } - - head = &urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp; - - turbp = list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - if (!turbp->queued) - break; - - toggle = uhci_fixup_toggle(turbp->urb, toggle); - } - - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), toggle); - - if (!urbp->queued) { - struct uhci_qh *pqh; - - nurbp->queued = 0; - - /* - * Fixup the previous QH's queue to link to the new head - * of this queue. - */ - pqh = list_entry(urbp->qh->list.prev, struct uhci_qh, list); - - if (pqh->urbp) { - struct list_head *head, *tmp; - - head = &pqh->urbp->queue_list; - tmp = head->next; - while (head != tmp) { - struct urb_priv *turbp = - list_entry(tmp, struct urb_priv, queue_list); - - tmp = tmp->next; - - turbp->qh->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; - } - } - - pqh->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; - - list_add_tail(&nurbp->qh->list, &urbp->qh->list); - list_del_init(&urbp->qh->list); - } else { - /* We're somewhere in the middle (or end). A bit trickier */ - /* than the head scenario */ - purbp = list_entry(urbp->queue_list.prev, struct urb_priv, - queue_list); - - pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); - if (nurbp->queued) - pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; - else - /* The next URB happens to be the beginning, so */ - /* we're the last, end the chain */ - pltd->link = UHCI_PTR_TERM; - } - - list_del_init(&urbp->queue_list); - -out: - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp; - - urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC); - if (!urbp) { - err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n"); - return NULL; - } - - memset((void *)urbp, 0, sizeof(*urbp)); - - urbp->inserttime = jiffies; - urbp->fsbrtime = jiffies; - urbp->urb = urb; - urbp->dev = urb->dev; - - INIT_LIST_HEAD(&urbp->td_list); - INIT_LIST_HEAD(&urbp->queue_list); - INIT_LIST_HEAD(&urbp->complete_list); - INIT_LIST_HEAD(&urbp->urb_list); - - list_add_tail(&urbp->urb_list, &uhci->urb_list); - - urb->hcpriv = urbp; - - return urbp; -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - td->urb = urb; - - list_add_tail(&td->list, &urbp->td_list); -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_remove_td_from_urb(struct uhci_td *td) -{ - if (list_empty(&td->list)) - return; - - list_del_init(&td->list); - - td->urb = NULL; -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *head, *tmp; - struct urb_priv *urbp; - - urbp = (struct urb_priv *)urb->hcpriv; - if (!urbp) - return; - - if (!list_empty(&urbp->urb_list)) - warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb); - - if (!list_empty(&urbp->complete_list)) - warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb); - - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - uhci_remove_td_from_urb(td); - uhci_remove_td(uhci, td); - uhci_free_td(uhci, td); - } - - urb->hcpriv = NULL; - kmem_cache_free(uhci_up_cachep, urbp); -} - -static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb) -{ - unsigned long flags; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) { - urbp->fsbr = 1; - if (!uhci->fsbr++ && !uhci->fsbrtimeout) - uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_hs_control_qh->dma_handle) | UHCI_PTR_QH; - } - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) -{ - unsigned long flags; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); - - if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) { - urbp->fsbr = 0; - if (!--uhci->fsbr) - uhci->fsbrtimeout = jiffies + FSBR_DELAY; - } - - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); -} - -/* - * Map status to standard result codes - * - * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)] - * is True for output TDs and False for input TDs. - */ -static int uhci_map_status(int status, int dir_out) -{ - if (!status) - return 0; - if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ - return -EPROTO; - if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ - if (dir_out) - return -ETIMEDOUT; - else - return -EILSEQ; - } - if (status & TD_CTRL_NAK) /* NAK */ - return -ETIMEDOUT; - if (status & TD_CTRL_BABBLE) /* Babble */ - return -EOVERFLOW; - if (status & TD_CTRL_DBUFERR) /* Buffer error */ - return -ENOSR; - if (status & TD_CTRL_STALLED) /* Stalled */ - return -EPIPE; - if (status & TD_CTRL_ACTIVE) /* Active */ - return 0; - - return -EINVAL; -} - -/* - * Control transfers - */ -static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_td *td; - struct uhci_qh *qh, *skelqh; - unsigned long destination, status; - int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - int len = urb->transfer_buffer_length; - dma_addr_t data = urb->transfer_dma; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; - - /* 3 errors */ - status = TD_CTRL_ACTIVE | uhci_maxerr(3); - if (urb->dev->speed == USB_SPEED_LOW) - status |= TD_CTRL_LS; - - /* - * Build the TD for the control request - */ - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(7), - urb->setup_dma); - - /* - * If direction is "send", change the frame from SETUP (0x2D) - * to OUT (0xE1). Else change it from SETUP to IN (0x69). - */ - destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe)); - - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) - status |= TD_CTRL_SPD; - - /* - * Build the DATA TD's - */ - while (len > 0) { - int pktsze = len; - - if (pktsze > maxsze) - pktsze = maxsze; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - /* Alternate Data0/1 (start with Data1) */ - destination ^= TD_TOKEN_TOGGLE; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1), - data); - - data += pktsze; - len -= pktsze; - } - - /* - * Build the final TD for control status - */ - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - /* - * It's IN if the pipe is an output pipe or we're not expecting - * data back. - */ - destination &= ~TD_TOKEN_PID_MASK; - if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) - destination |= USB_PID_IN; - else - destination |= USB_PID_OUT; - - destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ - - status &= ~TD_CTRL_SPD; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status | TD_CTRL_IOC, - destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); - - qh = uhci_alloc_qh(uhci, urb->dev); - if (!qh) - return -ENOMEM; - - urbp->qh = qh; - qh->urbp = urbp; - - uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); - - /* Low speed transfers get a different queue, and won't hog the bus */ - if (urb->dev->speed == USB_SPEED_LOW) - skelqh = uhci->skel_ls_control_qh; - else { - skelqh = uhci->skel_hs_control_qh; - uhci_inc_fsbr(uhci, urb); - } - - if (eurb) - uhci_append_queued_urb(uhci, eurb, urb); - else - uhci_insert_qh(uhci, skelqh, urb); - - return -EINPROGRESS; -} - -/* - * If control was short, then end status packet wasn't sent, so this - * reorganize s so it's sent to finish the transfer. The original QH is - * removed from the skel and discarded; all TDs except the last (status) - * are deleted; the last (status) TD is put on a new QH which is reinserted - * into the skel. Since the last TD and urb_priv are reused, the TD->link - * and urb_priv maintain any queued QHs. - */ -static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - - urbp->short_control_packet = 1; - - /* Create a new QH to avoid pointer overwriting problems */ - uhci_remove_qh(uhci, urbp->qh); - - /* Delete all of the TD's except for the status TD at the end */ - head = &urbp->td_list; - tmp = head->next; - while (tmp != head && tmp->next != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - uhci_remove_td_from_urb(td); - uhci_remove_td(uhci, td); - uhci_free_td(uhci, td); - } - - urbp->qh = uhci_alloc_qh(uhci, urb->dev); - if (!urbp->qh) { - err("unable to allocate new QH for control retrigger"); - return -ENOMEM; - } - - urbp->qh->urbp = urbp; - - /* One TD, who cares about Breadth first? */ - uhci_insert_tds_in_qh(urbp->qh, urb, UHCI_PTR_DEPTH); - - /* Low speed transfers get a different queue */ - if (urb->dev->speed == USB_SPEED_LOW) - uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); - else - uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb); - - return -EINPROGRESS; -} - - -static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status; - int ret = 0; - - if (list_empty(&urbp->td_list)) - return -EINVAL; - - head = &urbp->td_list; - - if (urbp->short_control_packet) { - tmp = head->prev; - goto status_phase; - } - - tmp = head->next; - td = list_entry(tmp, struct uhci_td, list); - - /* The first TD is the SETUP phase, check the status, but skip */ - /* the count */ - status = uhci_status_bits(td_status(td)); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (status) - goto td_error; - - urb->actual_length = 0; - - /* The rest of the TD's (but the last) are data */ - tmp = tmp->next; - while (tmp != head && tmp->next != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - status = uhci_status_bits(td_status(td)); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(td_status(td)); - - if (status) - goto td_error; - - /* Check to see if we received a short packet */ - if (uhci_actual_length(td_status(td)) < uhci_expected_length(td_token(td))) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; - } - - if (uhci_packetid(td_token(td)) == USB_PID_IN) - return usb_control_retrigger_status(uhci, urb); - else - return 0; - } - } - -status_phase: - td = list_entry(tmp, struct uhci_td, list); - - /* Control status phase */ - status = td_status(td); - -#ifdef I_HAVE_BUGGY_APC_BACKUPS - /* APC BackUPS Pro kludge */ - /* It tries to send all of the descriptor instead of the amount */ - /* we requested */ - if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ - status & TD_CTRL_ACTIVE && - status & TD_CTRL_NAK) - return 0; -#endif - - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - if (uhci_status_bits(status)) - goto td_error; - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - -err: - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dbg("uhci_result_control() failed with status %x", status); - - if (errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - - lprintk(errbuf); - } - } - - return ret; -} - -/* - * Common submit for bulk and interrupt - */ -static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh) -{ - struct uhci_td *td; - struct uhci_qh *qh; - unsigned long destination, status; - int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - int len = urb->transfer_buffer_length; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - dma_addr_t data = urb->transfer_dma; - - if (len < 0) - return -EINVAL; - - /* The "pipe" thing contains the destination in bits 8--18 */ - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - status = uhci_maxerr(3) | TD_CTRL_ACTIVE; - if (urb->dev->speed == USB_SPEED_LOW) - status |= TD_CTRL_LS; - if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) - status |= TD_CTRL_SPD; - - /* - * Build the DATA TD's - */ - do { /* Allow zero length packets */ - int pktsze = len; - - if (pktsze > maxsze) - pktsze = maxsze; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); - - data += pktsze; - len -= maxsze; - - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - } while (len > 0); - - /* - * URB_ZERO_PACKET means adding a 0-length packet, if direction - * is OUT and the transfer_length was an exact multiple of maxsze, - * hence (len = transfer_length - N * maxsze) == 0 - * however, if transfer_length == 0, the zero packet was already - * prepared above. - */ - if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && - !len && urb->transfer_buffer_length) { - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) | - (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), - data); - - usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe)); - } - - /* Set the flag on the last packet */ - td->status |= cpu_to_le32(TD_CTRL_IOC); - - qh = uhci_alloc_qh(uhci, urb->dev); - if (!qh) - return -ENOMEM; - - urbp->qh = qh; - qh->urbp = urbp; - - /* Always breadth first */ - uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); - - if (eurb) - uhci_append_queued_urb(uhci, eurb, urb); - else - uhci_insert_qh(uhci, skelqh, urb); - - return -EINPROGRESS; -} - -/* - * Common result for bulk and interrupt - */ -static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = urb->hcpriv; - struct uhci_td *td; - unsigned int status = 0; - int ret = 0; - - urb->actual_length = 0; - - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - status = uhci_status_bits(td_status(td)); - if (status & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - urb->actual_length += uhci_actual_length(td_status(td)); - - if (status) - goto td_error; - - if (uhci_actual_length(td_status(td)) < uhci_expected_length(td_token(td))) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - ret = -EREMOTEIO; - goto err; - } else - return 0; - } - } - - return 0; - -td_error: - ret = uhci_map_status(status, uhci_packetout(td_token(td))); - if (ret == -EPIPE) - /* endpoint has stalled - mark it halted */ - usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td))); - -err: - /* - * Enable this chunk of code if you want to see some more debugging. - * But be careful, it has the tendancy to starve out khubd and prevent - * disconnects from happening successfully if you have a slow debug - * log interface (like a serial console. - */ -#if 0 - if ((debug == 1 && ret != -EPIPE) || debug > 1) { - /* Some debugging code */ - dbg("uhci_result_common() failed with status %x", status); - - if (errbuf) { - /* Print the chain for debugging purposes */ - uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); - - lprintk(errbuf); - } - } -#endif - return ret; -} - -static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) -{ - int ret; - - /* Can't have low speed bulk transfers */ - if (urb->dev->speed == USB_SPEED_LOW) - return -EINVAL; - - ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh); - if (ret == -EINPROGRESS) - uhci_inc_fsbr(uhci, urb); - - return ret; -} - -static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) -{ - /* USB 1.1 interrupt transfers only involve one packet per interval; - * that's the uhci_submit_common() "breadth first" policy. Drivers - * can submit urbs of any length, but longer ones might need many - * intervals to complete. - */ - return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]); -} - -/* - * Bulk and interrupt use common result - */ -#define uhci_result_bulk uhci_result_common -#define uhci_result_interrupt uhci_result_common - -/* - * Isochronous transfers - */ -static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end) -{ - struct urb *last_urb = NULL; - struct list_head *tmp, *head; - int ret = 0; - - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); - struct urb *u = up->urb; - - tmp = tmp->next; - - /* look for pending URB's with identical pipe handle */ - if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && - (u->status == -EINPROGRESS) && (u != urb)) { - if (!last_urb) - *start = u->start_frame; - last_urb = u; - } - } - - if (last_urb) { - *end = (last_urb->start_frame + last_urb->number_of_packets * - last_urb->interval) & (UHCI_NUMFRAMES-1); - ret = 0; - } else - ret = -1; /* no previous urb found */ - - return ret; -} - -static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb) -{ - int limits; - unsigned int start = 0, end = 0; - - if (urb->number_of_packets > 900) /* 900? Why? */ - return -EFBIG; - - limits = isochronous_find_limits(uhci, urb, &start, &end); - - if (urb->transfer_flags & URB_ISO_ASAP) { - if (limits) { - int curframe; - - curframe = uhci_get_current_frame_number(uhci) % UHCI_NUMFRAMES; - urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES; - } else - urb->start_frame = end; - } else { - urb->start_frame %= UHCI_NUMFRAMES; - /* FIXME: Sanity check */ - } - - return 0; -} - -/* - * Isochronous transfers - */ -static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) -{ - struct uhci_td *td; - int i, ret, frame; - int status, destination; - - status = TD_CTRL_ACTIVE | TD_CTRL_IOS; - destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); - - ret = isochronous_find_start(uhci, urb); - if (ret) - return ret; - - frame = urb->start_frame; - for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) { - if (!urb->iso_frame_desc[i].length) - continue; - - td = uhci_alloc_td(uhci, urb->dev); - if (!td) - return -ENOMEM; - - uhci_add_td_to_urb(urb, td); - uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1), - urb->transfer_dma + urb->iso_frame_desc[i].offset); - - if (i + 1 >= urb->number_of_packets) - td->status |= cpu_to_le32(TD_CTRL_IOC); - - uhci_insert_td_frame_list(uhci, td, frame); - } - - return -EINPROGRESS; -} - -static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int status; - int i, ret = 0; - - urb->actual_length = 0; - - i = 0; - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - int actlength; - - tmp = tmp->next; - - if (td_status(td) & TD_CTRL_ACTIVE) - return -EINPROGRESS; - - actlength = uhci_actual_length(td_status(td)); - urb->iso_frame_desc[i].actual_length = actlength; - urb->actual_length += actlength; - - status = uhci_map_status(uhci_status_bits(td_status(td)), usb_pipeout(urb->pipe)); - urb->iso_frame_desc[i].status = status; - if (status) { - urb->error_count++; - ret = status; - } - - i++; - } - - return ret; -} - -/* - * MUST be called with uhci->urb_list_lock acquired - */ -static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *tmp, *head; - - /* We don't match Isoc transfers since they are special */ - if (usb_pipeisoc(urb->pipe)) - return NULL; - - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); - struct urb *u = up->urb; - - tmp = tmp->next; - - if (u->dev == urb->dev && u->status == -EINPROGRESS) { - /* For control, ignore the direction */ - if (usb_pipecontrol(urb->pipe) && - (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN)) - return u; - else if (u->pipe == urb->pipe) - return u; - } - } - - return NULL; -} - -static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags) -{ - int ret = -EINVAL; - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long flags; - struct urb *eurb; - int bustime; - - spin_lock_irqsave(&uhci->urb_list_lock, flags); - - eurb = uhci_find_urb_ep(uhci, urb); - - if (!uhci_alloc_urb_priv(uhci, urb)) { - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - return -ENOMEM; - } - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - ret = uhci_submit_control(uhci, urb, eurb); - break; - case PIPE_INTERRUPT: - if (!eurb) { - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) - ret = bustime; - else { - ret = uhci_submit_interrupt(uhci, urb, eurb); - if (ret == -EINPROGRESS) - usb_claim_bandwidth(urb->dev, urb, bustime, 0); - } - } else { /* inherit from parent */ - urb->bandwidth = eurb->bandwidth; - ret = uhci_submit_interrupt(uhci, urb, eurb); - } - break; - case PIPE_BULK: - ret = uhci_submit_bulk(uhci, urb, eurb); - break; - case PIPE_ISOCHRONOUS: - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) { - ret = bustime; - break; - } - - ret = uhci_submit_isochronous(uhci, urb); - if (ret == -EINPROGRESS) - usb_claim_bandwidth(urb->dev, urb, bustime, 1); - break; - } - - if (ret != -EINPROGRESS) { - /* Submit failed, so delete it from the urb_list */ - struct urb_priv *urbp = urb->hcpriv; - - list_del_init(&urbp->urb_list); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - uhci_destroy_urb_priv (uhci, urb); - - return ret; - } - - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - return 0; -} - -/* - * Return the result of a transfer - * - * MUST be called with urb_list_lock acquired - */ -static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) -{ - int ret = -EINVAL; - unsigned long flags; - struct urb_priv *urbp; - - spin_lock_irqsave(&urb->lock, flags); - - urbp = (struct urb_priv *)urb->hcpriv; - - if (urb->status != -EINPROGRESS) { - info("uhci_transfer_result: called for URB %p not in flight?", urb); - goto out; - } - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - ret = uhci_result_control(uhci, urb); - break; - case PIPE_INTERRUPT: - ret = uhci_result_interrupt(uhci, urb); - break; - case PIPE_BULK: - ret = uhci_result_bulk(uhci, urb); - break; - case PIPE_ISOCHRONOUS: - ret = uhci_result_isochronous(uhci, urb); - break; - } - - urbp->status = ret; - - if (ret == -EINPROGRESS) - goto out; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - case PIPE_BULK: - case PIPE_ISOCHRONOUS: - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Spinlock needed ? */ - if (urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 1); - uhci_unlink_generic(uhci, urb); - break; - case PIPE_INTERRUPT: - /* Release bandwidth for Interrupt or Isoc. transfers */ - /* Make sure we don't release if we have a queued URB */ - spin_lock(&uhci->frame_list_lock); - /* Spinlock needed ? */ - if (list_empty(&urbp->queue_list) && urb->bandwidth) - usb_release_bandwidth(urb->dev, urb, 0); - else - /* bandwidth was passed on to queued URB, */ - /* so don't let usb_unlink_urb() release it */ - urb->bandwidth = 0; - spin_unlock(&uhci->frame_list_lock); - uhci_unlink_generic(uhci, urb); - break; - default: - info("uhci_transfer_result: unknown pipe type %d for urb %p\n", - usb_pipetype(urb->pipe), urb); - } - - /* Remove it from uhci->urb_list */ - list_del_init(&urbp->urb_list); - - uhci_add_complete(uhci, urb); - -out: - spin_unlock_irqrestore(&urb->lock, flags); -} - -/* - * MUST be called with urb->lock acquired - */ -static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) -{ - struct list_head *head, *tmp; - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - int prevactive = 1; - - /* We can get called when urbp allocation fails, so check */ - if (!urbp) - return; - - uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ - - /* - * Now we need to find out what the last successful toggle was - * so we can update the local data toggle for the next transfer - * - * There's 3 way's the last successful completed TD is found: - * - * 1) The TD is NOT active and the actual length < expected length - * 2) The TD is NOT active and it's the last TD in the chain - * 3) The TD is active and the previous TD is NOT active - * - * Control and Isochronous ignore the toggle, so this is safe - * for all types - */ - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - if (!(td_status(td) & TD_CTRL_ACTIVE) && - (uhci_actual_length(td_status(td)) < uhci_expected_length(td_token(td)) || - tmp == head)) - usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td)), - uhci_toggle(td_token(td)) ^ 1); - else if ((td_status(td) & TD_CTRL_ACTIVE) && !prevactive) - usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), - uhci_packetout(td_token(td)), - uhci_toggle(td_token(td))); - - prevactive = td_status(td) & TD_CTRL_ACTIVE; - } - - uhci_delete_queued_urb(uhci, urb); - - /* The interrupt loop will reclaim the QH's */ - uhci_remove_qh(uhci, urbp->qh); - urbp->qh = NULL; -} - -static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned long flags; - struct urb_priv *urbp = urb->hcpriv; - - /* If this is an interrupt URB that is being killed in urb->complete, */ - /* then just set its status and return */ - if (!urbp) { - urb->status = -ECONNRESET; - return 0; - } - - spin_lock_irqsave(&uhci->urb_list_lock, flags); - - list_del_init(&urbp->urb_list); - - uhci_unlink_generic(uhci, urb); - - spin_lock(&uhci->urb_remove_list_lock); - - /* If we're the first, set the next interrupt bit */ - if (list_empty(&uhci->urb_remove_list)) - uhci_set_next_interrupt(uhci); - list_add(&urbp->urb_list, &uhci->urb_remove_list); - - spin_unlock(&uhci->urb_remove_list_lock); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - return 0; -} - -static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct list_head *head, *tmp; - int count = 0; - - uhci_dec_fsbr(uhci, urb); - - urbp->fsbr_timeout = 1; - - /* - * Ideally we would want to fix qh->element as well, but it's - * read/write by the HC, so that can introduce a race. It's not - * really worth the hassle - */ - - head = &urbp->td_list; - tmp = head->next; - while (tmp != head) { - struct uhci_td *td = list_entry(tmp, struct uhci_td, list); - - tmp = tmp->next; - - /* - * Make sure we don't do the last one (since it'll have the - * TERM bit set) as well as we skip every so many TD's to - * make sure it doesn't hog the bandwidth - */ - if (tmp != head && (count % DEPTH_INTERVAL) == (DEPTH_INTERVAL - 1)) - td->link |= UHCI_PTR_DEPTH; - - count++; - } - - return 0; -} - -/* - * uhci_get_current_frame_number() - * - * returns the current frame number for a USB bus/controller. - */ -static int uhci_get_current_frame_number(struct uhci_hcd *uhci) -{ - return inw(uhci->io_addr + USBFRNUM); -} - -static int init_stall_timer(struct usb_hcd *hcd); - -static void stall_callback(unsigned long ptr) -{ - struct usb_hcd *hcd = (struct usb_hcd *)ptr; - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - struct list_head list, *tmp, *head; - unsigned long flags; - - INIT_LIST_HEAD(&list); - - spin_lock_irqsave(&uhci->urb_list_lock, flags); - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); - struct urb *u = up->urb; - - tmp = tmp->next; - - spin_lock(&u->lock); - - /* Check if the FSBR timed out */ - if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) - uhci_fsbr_timeout(uhci, u); - - /* Check if the URB timed out */ - if (u->timeout && time_after_eq(jiffies, up->inserttime + u->timeout)) - list_move_tail(&up->urb_list, &list); - - spin_unlock(&u->lock); - } - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - head = &list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *up = list_entry(tmp, struct urb_priv, urb_list); - struct urb *u = up->urb; - - tmp = tmp->next; - - uhci_urb_dequeue(hcd, u); - } - - /* Really disable FSBR */ - if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { - uhci->fsbrtimeout = 0; - uhci->skel_term_qh->link = UHCI_PTR_TERM; - } - - /* Poll for and perform state transitions */ - hc_state_transitions(uhci); - - init_stall_timer(hcd); -} - -static int init_stall_timer(struct usb_hcd *hcd) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - - init_timer(&uhci->stall_timer); - uhci->stall_timer.function = stall_callback; - uhci->stall_timer.data = (unsigned long)hcd; - uhci->stall_timer.expires = jiffies + (HZ / 10); - add_timer(&uhci->stall_timer); - - return 0; -} - -static void uhci_free_pending_qhs(struct uhci_hcd *uhci) -{ - struct list_head *tmp, *head; - unsigned long flags; - - spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); - head = &uhci->qh_remove_list; - tmp = head->next; - while (tmp != head) { - struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list); - - tmp = tmp->next; - - list_del_init(&qh->remove_list); - - uhci_free_qh(uhci, qh); - } - spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); -} - -static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) -{ - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int status; - unsigned long flags; - - spin_lock_irqsave(&urb->lock, flags); - status = urbp->status; - uhci_destroy_urb_priv(uhci, urb); - - if (urb->status != -ENOENT && urb->status != -ECONNRESET) - urb->status = status; - spin_unlock_irqrestore(&urb->lock, flags); - - usb_hcd_giveback_urb(hcd, urb, regs); -} - -static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - struct list_head *tmp, *head; - unsigned long flags; - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - head = &uhci->complete_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list); - struct urb *urb = urbp->urb; - - list_del_init(&urbp->complete_list); - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); - - uhci_finish_urb(hcd, urb, regs); - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - head = &uhci->complete_list; - tmp = head->next; - } - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); -} - -static void uhci_remove_pending_qhs(struct uhci_hcd *uhci) -{ - struct list_head *tmp, *head; - unsigned long flags; - - spin_lock_irqsave(&uhci->urb_remove_list_lock, flags); - head = &uhci->urb_remove_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - struct urb *urb = urbp->urb; - - tmp = tmp->next; - - list_del_init(&urbp->urb_list); - - urbp->status = urb->status = -ECONNRESET; - - uhci_add_complete(uhci, urb); - } - spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags); -} - -static int uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned int io_addr = uhci->io_addr; - unsigned short status; - struct list_head *tmp, *head; - - /* - * Read the interrupt status, and write it back to clear the - * interrupt cause - */ - status = inw(io_addr + USBSTS); - if (!status) /* shared interrupt, not mine */ - return 0; - outw(status, io_addr + USBSTS); /* Clear it */ - - if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { - if (status & USBSTS_HSE) - err("%x: host system error, PCI problems?", io_addr); - if (status & USBSTS_HCPE) - err("%x: host controller process error. something bad happened", io_addr); - if ((status & USBSTS_HCH) && uhci->state > 0) { - err("%x: host controller halted. very bad", io_addr); - /* FIXME: Reset the controller, fix the offending TD */ - } - } - - if (status & USBSTS_RD) - uhci->resume_detect = 1; - - uhci_free_pending_qhs(uhci); - - uhci_remove_pending_qhs(uhci); - - uhci_clear_next_interrupt(uhci); - - /* Walk the list of pending URB's to see which ones completed */ - spin_lock(&uhci->urb_list_lock); - head = &uhci->urb_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - struct urb *urb = urbp->urb; - - tmp = tmp->next; - - /* Checks the status and does all of the magic necessary */ - uhci_transfer_result(uhci, urb); - } - spin_unlock(&uhci->urb_list_lock); - - uhci_finish_completion(hcd, regs); - - return 0; -} - -static void reset_hc(struct uhci_hcd *uhci) -{ - unsigned int io_addr = uhci->io_addr; - - /* Global reset for 50ms */ - uhci->state = UHCI_RESET; - outw(USBCMD_GRESET, io_addr + USBCMD); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((HZ*50+999) / 1000); - set_current_state(TASK_RUNNING); - outw(0, io_addr + USBCMD); - - /* Another 10ms delay */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((HZ*10+999) / 1000); - set_current_state(TASK_RUNNING); - uhci->resume_detect = 0; -} - -static void suspend_hc(struct uhci_hcd *uhci) -{ - unsigned int io_addr = uhci->io_addr; - - dbg("%x: suspend_hc", io_addr); - uhci->state = UHCI_SUSPENDED; - uhci->resume_detect = 0; - outw(USBCMD_EGSM, io_addr + USBCMD); -} - -static void wakeup_hc(struct uhci_hcd *uhci) -{ - unsigned int io_addr = uhci->io_addr; - - switch (uhci->state) { - case UHCI_SUSPENDED: /* Start the resume */ - dbg("%x: wakeup_hc", io_addr); - - /* Global resume for >= 20ms */ - outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); - uhci->state = UHCI_RESUMING_1; - uhci->state_end = jiffies + (20*HZ+999) / 1000; - break; - - case UHCI_RESUMING_1: /* End global resume */ - uhci->state = UHCI_RESUMING_2; - outw(0, io_addr + USBCMD); - /* Falls through */ - - case UHCI_RESUMING_2: /* Wait for EOP to be sent */ - if (inw(io_addr + USBCMD) & USBCMD_FGR) - break; - - /* Run for at least 1 second, and - * mark it configured with a 64-byte max packet */ - uhci->state = UHCI_RUNNING_GRACE; - uhci->state_end = jiffies + HZ; - outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, - io_addr + USBCMD); - break; - - case UHCI_RUNNING_GRACE: /* Now allowed to suspend */ - uhci->state = UHCI_RUNNING; - break; - - default: - break; - } -} - -static int ports_active(struct uhci_hcd *uhci) -{ - unsigned int io_addr = uhci->io_addr; - int connection = 0; - int i; - - for (i = 0; i < uhci->rh_numports; i++) - connection |= (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_CCS); - - return connection; -} - -static int suspend_allowed(struct uhci_hcd *uhci) -{ - unsigned int io_addr = uhci->io_addr; - int i; - - if (!uhci->hcd.pdev || - uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL || - uhci->hcd.pdev->device != PCI_DEVICE_ID_INTEL_82371AB_2) - return 1; - - /* This is a 82371AB/EB/MB USB controller which has a bug that - * causes false resume indications if any port has an - * over current condition. To prevent problems, we will not - * allow a global suspend if any ports are OC. - * - * Some motherboards using the 82371AB/EB/MB (but not the USB portion) - * appear to hardwire the over current inputs active to disable - * the USB ports. - */ - - /* check for over current condition on any port */ - for (i = 0; i < uhci->rh_numports; i++) { - if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC) - return 0; - } - - return 1; -} - -static void hc_state_transitions(struct uhci_hcd *uhci) -{ - switch (uhci->state) { - case UHCI_RUNNING: - - /* global suspend if nothing connected for 1 second */ - if (!ports_active(uhci) && suspend_allowed(uhci)) { - uhci->state = UHCI_SUSPENDING_GRACE; - uhci->state_end = jiffies + HZ; - } - break; - - case UHCI_SUSPENDING_GRACE: - if (ports_active(uhci)) - uhci->state = UHCI_RUNNING; - else if (time_after_eq(jiffies, uhci->state_end)) - suspend_hc(uhci); - break; - - case UHCI_SUSPENDED: - - /* wakeup if requested by a device */ - if (uhci->resume_detect) - wakeup_hc(uhci); - break; - - case UHCI_RESUMING_1: - case UHCI_RESUMING_2: - case UHCI_RUNNING_GRACE: - if (time_after_eq(jiffies, uhci->state_end)) - wakeup_hc(uhci); - break; - - default: - break; - } -} - -static void start_hc(struct uhci_hcd *uhci) -{ - unsigned int io_addr = uhci->io_addr; - int timeout = 1000; - - /* - * Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw(USBCMD_HCRESET, io_addr + USBCMD); - while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { - if (!--timeout) { - printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n"); - break; - } - } - - /* Turn on all interrupts */ - outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, - io_addr + USBINTR); - - /* Start at frame 0 */ - outw(0, io_addr + USBFRNUM); - outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); - - /* Run and mark it configured with a 64-byte max packet */ - uhci->state = UHCI_RUNNING_GRACE; - uhci->state_end = jiffies + HZ; - outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); - - uhci->hcd.state = USB_STATE_READY; -} - -/* - * De-allocate all resources.. - */ -static void release_uhci(struct uhci_hcd *uhci) -{ - int i; - - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (uhci->skelqh[i]) { - uhci_free_qh(uhci, uhci->skelqh[i]); - uhci->skelqh[i] = NULL; - } - - if (uhci->term_td) { - uhci_free_td(uhci, uhci->term_td); - uhci->term_td = NULL; - } - - if (uhci->qh_pool) { - pci_pool_destroy(uhci->qh_pool); - uhci->qh_pool = NULL; - } - - if (uhci->td_pool) { - pci_pool_destroy(uhci->td_pool); - uhci->td_pool = NULL; - } - - if (uhci->fl) { - pci_free_consistent(uhci->hcd.pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); - uhci->fl = NULL; - } - -#ifdef CONFIG_PROC_FS - if (uhci->proc_entry) { - remove_proc_entry(uhci->hcd.self.bus_name, uhci_proc_root); - uhci->proc_entry = NULL; - } -#endif -} - -/* - * Allocate a frame list, and then setup the skeleton - * - * The hardware doesn't really know any difference - * in the queues, but the order does matter for the - * protocols higher up. The order is: - * - * - any isochronous events handled before any - * of the queues. We don't do that here, because - * we'll create the actual TD entries on demand. - * - The first queue is the interrupt queue. - * - The second queue is the control queue, split into low and high speed - * - The third queue is bulk queue. - * - The fourth queue is the bandwidth reclamation queue, which loops back - * to the high speed control queue. - */ -static int __devinit uhci_start(struct usb_hcd *hcd) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int retval = -EBUSY; - int i, port; - unsigned io_size; - dma_addr_t dma_handle; - struct usb_device *udev; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *ent; -#endif - - uhci->io_addr = (unsigned long) hcd->regs; - io_size = pci_resource_len(hcd->pdev, hcd->region); - -#ifdef CONFIG_PROC_FS - ent = create_proc_entry(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root); - if (!ent) { - err("couldn't create uhci proc entry"); - retval = -ENOMEM; - goto err_create_proc_entry; - } - - ent->data = uhci; - ent->proc_fops = &uhci_proc_operations; - ent->size = 0; - uhci->proc_entry = ent; -#endif - - /* Reset here so we don't get any interrupts from an old setup */ - /* or broken setup */ - reset_hc(uhci); - - uhci->fsbr = 0; - uhci->fsbrtimeout = 0; - - spin_lock_init(&uhci->qh_remove_list_lock); - INIT_LIST_HEAD(&uhci->qh_remove_list); - - spin_lock_init(&uhci->urb_remove_list_lock); - INIT_LIST_HEAD(&uhci->urb_remove_list); - - spin_lock_init(&uhci->urb_list_lock); - INIT_LIST_HEAD(&uhci->urb_list); - - spin_lock_init(&uhci->complete_list_lock); - INIT_LIST_HEAD(&uhci->complete_list); - - spin_lock_init(&uhci->frame_list_lock); - - uhci->fl = pci_alloc_consistent(hcd->pdev, sizeof(*uhci->fl), &dma_handle); - if (!uhci->fl) { - err("unable to allocate consistent memory for frame list"); - goto err_alloc_fl; - } - - memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); - - uhci->fl->dma_handle = dma_handle; - - uhci->td_pool = pci_pool_create("uhci_td", hcd->pdev, - sizeof(struct uhci_td), 16, 0); - if (!uhci->td_pool) { - err("unable to create td pci_pool"); - goto err_create_td_pool; - } - - uhci->qh_pool = pci_pool_create("uhci_qh", hcd->pdev, - sizeof(struct uhci_qh), 16, 0); - if (!uhci->qh_pool) { - err("unable to create qh pci_pool"); - goto err_create_qh_pool; - } - - /* Initialize the root hub */ - - /* UHCI specs says devices must have 2 ports, but goes on to say */ - /* they may have more but give no way to determine how many they */ - /* have. However, according to the UHCI spec, Bit 7 is always set */ - /* to 1. So we try to use this to our advantage */ - for (port = 0; port < (io_size - 0x10) / 2; port++) { - unsigned int portstatus; - - portstatus = inw(uhci->io_addr + 0x10 + (port * 2)); - if (!(portstatus & 0x0080)) - break; - } - if (debug) - info("detected %d ports", port); - - /* This is experimental so anything less than 2 or greater than 8 is */ - /* something weird and we'll ignore it */ - if (port < 2 || port > 8) { - info("port count misdetected? forcing to 2 ports"); - port = 2; - } - - uhci->rh_numports = port; - - hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self); - if (!udev) { - err("unable to allocate root hub"); - goto err_alloc_root_hub; - } - hcd->pdev->bus = (struct pci_bus *)udev; /* Fix bus pointer for initial device */ - - uhci->term_td = uhci_alloc_td(uhci, udev); - if (!uhci->term_td) { - err("unable to allocate terminating TD"); - goto err_alloc_term_td; - } - - for (i = 0; i < UHCI_NUM_SKELQH; i++) { - uhci->skelqh[i] = uhci_alloc_qh(uhci, udev); - if (!uhci->skelqh[i]) { - err("unable to allocate QH %d", i); - goto err_alloc_skelqh; - } - } - - /* - * 8 Interrupt queues; link int2 to int1, int4 to int2, etc - * then link int1 to control and control to bulk - */ - uhci->skel_int128_qh->link = cpu_to_le32(uhci->skel_int64_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int64_qh->link = cpu_to_le32(uhci->skel_int32_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int32_qh->link = cpu_to_le32(uhci->skel_int16_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int16_qh->link = cpu_to_le32(uhci->skel_int8_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int8_qh->link = cpu_to_le32(uhci->skel_int4_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int4_qh->link = cpu_to_le32(uhci->skel_int2_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int2_qh->link = cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH; - - uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_hs_control_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_hs_control_qh->link = cpu_to_le32(uhci->skel_bulk_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH; - - /* This dummy TD is to work around a bug in Intel PIIX controllers */ - uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | - (0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0); - uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle); - - uhci->skel_term_qh->link = UHCI_PTR_TERM; - uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle); - - /* - * Fill the frame list: make all entries point to - * the proper interrupt queue. - * - * This is probably silly, but it's a simple way to - * scatter the interrupt queues in a way that gives - * us a reasonable dynamic range for irq latencies. - */ - for (i = 0; i < UHCI_NUMFRAMES; i++) { - int irq = 0; - - if (i & 1) { - irq++; - if (i & 2) { - irq++; - if (i & 4) { - irq++; - if (i & 8) { - irq++; - if (i & 16) { - irq++; - if (i & 32) { - irq++; - if (i & 64) - irq++; - } - } - } - } - } - } - - /* Only place we don't use the frame list routines */ - uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[7 - irq]->dma_handle); - } - - start_hc(uhci); - - init_stall_timer(hcd); - - /* disable legacy emulation */ - pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT); - - usb_connect(udev); - udev->speed = USB_SPEED_FULL; - - if (usb_register_root_hub(udev, &hcd->pdev->dev) != 0) { - err("unable to start root hub"); - retval = -ENOMEM; - goto err_start_root_hub; - } - - return 0; - -/* - * error exits: - */ -err_start_root_hub: - reset_hc(uhci); - - del_timer_sync(&uhci->stall_timer); - -err_alloc_skelqh: - for (i = 0; i < UHCI_NUM_SKELQH; i++) - if (uhci->skelqh[i]) { - uhci_free_qh(uhci, uhci->skelqh[i]); - uhci->skelqh[i] = NULL; - } - - uhci_free_td(uhci, uhci->term_td); - uhci->term_td = NULL; - -err_alloc_term_td: - usb_put_dev(udev); - hcd->self.root_hub = NULL; - -err_alloc_root_hub: - pci_pool_destroy(uhci->qh_pool); - uhci->qh_pool = NULL; - -err_create_qh_pool: - pci_pool_destroy(uhci->td_pool); - uhci->td_pool = NULL; - -err_create_td_pool: - pci_free_consistent(hcd->pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); - uhci->fl = NULL; - -err_alloc_fl: -#ifdef CONFIG_PROC_FS - remove_proc_entry(hcd->self.bus_name, uhci_proc_root); - uhci->proc_entry = NULL; - -err_create_proc_entry: -#endif - - return retval; -} - -static void uhci_stop(struct usb_hcd *hcd) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - - del_timer_sync(&uhci->stall_timer); - - /* - * At this point, we're guaranteed that no new connects can be made - * to this bus since there are no more parents - */ - uhci_free_pending_qhs(uhci); - uhci_remove_pending_qhs(uhci); - - reset_hc(uhci); - - uhci_free_pending_qhs(uhci); - - release_uhci(uhci); -} - -#ifdef CONFIG_PM -static int uhci_suspend(struct usb_hcd *hcd, u32 state) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - - /* Don't try to suspend broken motherboards, reset instead */ - if (suspend_allowed(uhci)) - suspend_hc(uhci); - else - reset_hc(uhci); - return 0; -} - -static int uhci_resume(struct usb_hcd *hcd) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - - pci_set_master(uhci->hcd.pdev); - - if (uhci->state == UHCI_SUSPENDED) - uhci->resume_detect = 1; - else { - reset_hc(uhci); - start_hc(uhci); - } - uhci->hcd.state = USB_STATE_READY; - return 0; -} -#endif - -static struct usb_hcd *uhci_hcd_alloc(void) -{ - struct uhci_hcd *uhci; - - uhci = (struct uhci_hcd *)kmalloc(sizeof(*uhci), GFP_KERNEL); - if (!uhci) - return NULL; - - memset(uhci, 0, sizeof(*uhci)); - return &uhci->hcd; -} - -static void uhci_hcd_free(struct usb_hcd *hcd) -{ - kfree(hcd_to_uhci(hcd)); -} - -static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) -{ - return uhci_get_current_frame_number(hcd_to_uhci(hcd)); -} - -static const char hcd_name[] = "uhci-hcd"; - -static struct hc_driver uhci_driver = { - .description = hcd_name, - - /* Generic hardware linkage */ - .irq = uhci_irq, - .flags = HCD_USB11, - - /* Basic lifecycle operations */ - .start = uhci_start, -#ifdef CONFIG_PM - .suspend = uhci_suspend, - .resume = uhci_resume, -#endif - .stop = uhci_stop, - - .hcd_alloc = uhci_hcd_alloc, - .hcd_free = uhci_hcd_free, - - .urb_enqueue = uhci_urb_enqueue, - .urb_dequeue = uhci_urb_dequeue, - - .get_frame_number = uhci_hcd_get_frame_number, - - .hub_status_data = uhci_hub_status_data, - .hub_control = uhci_hub_control, -}; - -const struct pci_device_id __devinitdata uhci_pci_ids[] = { { - - /* handle any USB UHCI controller */ - .class = ((PCI_CLASS_SERIAL_USB << 8) | 0x00), - .class_mask = ~0, - .driver_data = (unsigned long) &uhci_driver, - - /* no matter who makes it */ - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - - }, { /* end: all zeroes */ } -}; - -MODULE_DEVICE_TABLE(pci, uhci_pci_ids); - -struct pci_driver uhci_pci_driver = { - .name = (char *)hcd_name, - .id_table = uhci_pci_ids, - - .probe = usb_hcd_pci_probe, - .remove = usb_hcd_pci_remove, - -#ifdef CONFIG_PM - .suspend = usb_hcd_pci_suspend, - .resume = usb_hcd_pci_resume, -#endif /* PM */ -}; - -int __init uhci_hcd_init(void) -{ - int retval = -ENOMEM; - - info(DRIVER_DESC " " DRIVER_VERSION); - - if (usb_disabled()) - return -ENODEV; - - if (debug) { - errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL); - if (!errbuf) - goto errbuf_failed; - } - -#ifdef CONFIG_PROC_FS - uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, 0); - if (!uhci_proc_root) - goto proc_failed; -#endif - - uhci_up_cachep = kmem_cache_create("uhci_urb_priv", - sizeof(struct urb_priv), 0, 0, NULL, NULL); - if (!uhci_up_cachep) - goto up_failed; - - retval = pci_module_init(&uhci_pci_driver); - if (retval) - goto init_failed; - - return 0; - -init_failed: - if (kmem_cache_destroy(uhci_up_cachep)) - printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); - -up_failed: - -#ifdef CONFIG_PROC_FS - remove_proc_entry("driver/uhci", 0); - -proc_failed: -#endif - if (errbuf) - kfree(errbuf); - -errbuf_failed: - - return retval; -} - -void __exit uhci_hcd_cleanup(void) -{ - pci_unregister_driver(&uhci_pci_driver); - - if (kmem_cache_destroy(uhci_up_cachep)) - printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); - -#ifdef CONFIG_PROC_FS - remove_proc_entry("driver/uhci", 0); -#endif - - if (errbuf) - kfree(errbuf); -} - -/*module_init(uhci_hcd_init);*/ -module_exit(uhci_hcd_cleanup); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci-hcd.h b/reactos/drivers/usb/miniport/usbuhci/uhci-hcd.h deleted file mode 100644 index abe14480fc5..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci-hcd.h +++ /dev/null @@ -1,419 +0,0 @@ -#ifndef __LINUX_UHCI_HCD_H -#define __LINUX_UHCI_HCD_H - -#if 0 -#include -#include -#endif - -#define usb_packetid(pipe) (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT) -#define PIPE_DEVEP_MASK 0x0007ff00 - -/* - * Universal Host Controller Interface data structures and defines - */ - -/* Command register */ -#define USBCMD 0 -#define USBCMD_RS 0x0001 /* Run/Stop */ -#define USBCMD_HCRESET 0x0002 /* Host reset */ -#define USBCMD_GRESET 0x0004 /* Global reset */ -#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define USBCMD_FGR 0x0010 /* Force Global Resume */ -#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ -#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ -#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ - -/* Status register */ -#define USBSTS 2 -#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ -#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ -#define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ -#define USBSTS_HCH 0x0020 /* HC Halted */ - -/* Interrupt enable register */ -#define USBINTR 4 -#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ -#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ -#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ -#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ - -#define USBFRNUM 6 -#define USBFLBASEADD 8 -#define USBSOF 12 - -/* USB port status and control registers */ -#define USBPORTSC1 16 -#define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ -#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ -#define USBPORTSC_PE 0x0004 /* Port Enable */ -#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_LS 0x0030 /* Line Status */ -#define USBPORTSC_RD 0x0040 /* Resume Detect */ -#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ -#define USBPORTSC_PR 0x0200 /* Port Reset */ -#define USBPORTSC_OC 0x0400 /* Over Current condition */ -#define USBPORTSC_SUSP 0x1000 /* Suspend */ - -/* Legacy support register */ -#define USBLEGSUP 0xc0 -#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ - -#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ - -#define UHCI_PTR_BITS cpu_to_le32(0x000F) -#define UHCI_PTR_TERM cpu_to_le32(0x0001) -#define UHCI_PTR_QH cpu_to_le32(0x0002) -#define UHCI_PTR_DEPTH cpu_to_le32(0x0004) -#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) - -#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ -#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ -#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ - -struct uhci_frame_list { - __u32 frame[UHCI_NUMFRAMES]; - - void *frame_cpu[UHCI_NUMFRAMES]; - - dma_addr_t dma_handle; -}; - -struct urb_priv; - -/* - * One role of a QH is to hold a queue of TDs for some endpoint. Each QH is - * used with one URB, and qh->element (updated by the HC) is either: - * - the next unprocessed TD for the URB, or - * - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or - * - the QH for the next URB queued to the same endpoint. - * - * The other role of a QH is to serve as a "skeleton" framelist entry, so we - * can easily splice a QH for some endpoint into the schedule at the right - * place. Then qh->element is UHCI_PTR_TERM. - * - * In the frame list, qh->link maintains a list of QHs seen by the HC: - * skel1 --> ep1-qh --> ep2-qh --> ... --> skel2 --> ... - */ -struct uhci_qh { - /* Hardware fields */ - __u32 link; /* Next queue */ - __u32 element; /* Queue element pointer */ - - /* Software fields */ - dma_addr_t dma_handle; - - struct usb_device *dev; - struct urb_priv *urbp; - - struct list_head list; /* P: uhci->frame_list_lock */ - struct list_head remove_list; /* P: uhci->remove_list_lock */ -} __attribute__((aligned(16))); - -/* - * for TD : - */ -#define td_status(td) le32_to_cpu((td)->status) -#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ -#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ -#define TD_CTRL_C_ERR_SHIFT 27 -#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ -#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ -#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ -#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ -#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ -#define TD_CTRL_NAK (1 << 19) /* NAK Received */ -#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ -#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ -#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ - -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) - -#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) -#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xFE0000) -#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ - -/* - * for TD : (a.k.a. Token) - */ -#define td_token(td) le32_to_cpu((td)->token) -#define TD_TOKEN_DEVADDR_SHIFT 8 -#define TD_TOKEN_TOGGLE_SHIFT 19 -#define TD_TOKEN_TOGGLE (1 << 19) -#define TD_TOKEN_EXPLEN_SHIFT 21 -#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */ -#define TD_TOKEN_PID_MASK 0xFF - -#define uhci_explen(len) ((len) << TD_TOKEN_EXPLEN_SHIFT) - -#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK) -#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1) -#define uhci_endpoint(token) (((token) >> 15) & 0xf) -#define uhci_devaddr(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f) -#define uhci_devep(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7ff) -#define uhci_packetid(token) ((token) & TD_TOKEN_PID_MASK) -#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) -#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) - -/* - * The documentation says "4 words for hardware, 4 words for software". - * - * That's silly, the hardware doesn't care. The hardware only cares that - * the hardware words are 16-byte aligned, and we can have any amount of - * sw space after the TD entry as far as I can tell. - * - * But let's just go with the documentation, at least for 32-bit machines. - * On 64-bit machines we probably want to take advantage of the fact that - * hw doesn't really care about the size of the sw-only area. - * - * Alas, not anymore, we have more than 4 words for software, woops. - * Everything still works tho, surprise! -jerdfelt - * - * td->link points to either another TD (not necessarily for the same urb or - * even the same endpoint), or nothing (PTR_TERM), or a QH (for queued urbs) - */ -struct uhci_td { - /* Hardware fields */ - __u32 link; - __u32 status; - __u32 token; - __u32 buffer; - - /* Software fields */ - dma_addr_t dma_handle; - - struct usb_device *dev; - struct urb *urb; - - struct list_head list; /* P: urb->lock */ - - int frame; /* for iso: what frame? */ - struct list_head fl_list; /* P: uhci->frame_list_lock */ -} __attribute__((aligned(16))); - -/* - * The UHCI driver places Interrupt, Control and Bulk into QH's both - * to group together TD's for one transfer, and also to faciliate queuing - * of URB's. To make it easy to insert entries into the schedule, we have - * a skeleton of QH's for each predefined Interrupt latency, low speed - * control, high speed control and terminating QH (see explanation for - * the terminating QH below). - * - * When we want to add a new QH, we add it to the end of the list for the - * skeleton QH. - * - * For instance, the queue can look like this: - * - * skel int128 QH - * dev 1 interrupt QH - * dev 5 interrupt QH - * skel int64 QH - * skel int32 QH - * ... - * skel int1 QH - * skel low speed control QH - * dev 5 control QH - * skel high speed control QH - * skel bulk QH - * dev 1 bulk QH - * dev 2 bulk QH - * skel terminating QH - * - * The terminating QH is used for 2 reasons: - * - To place a terminating TD which is used to workaround a PIIX bug - * (see Intel errata for explanation) - * - To loop back to the high speed control queue for full speed bandwidth - * reclamation - * - * Isochronous transfers are stored before the start of the skeleton - * schedule and don't use QH's. While the UHCI spec doesn't forbid the - * use of QH's for Isochronous, it doesn't use them either. Since we don't - * need to use them either, we follow the spec diagrams in hope that it'll - * be more compatible with future UHCI implementations. - */ - -#define UHCI_NUM_SKELQH 12 -#define skel_int128_qh skelqh[0] -#define skel_int64_qh skelqh[1] -#define skel_int32_qh skelqh[2] -#define skel_int16_qh skelqh[3] -#define skel_int8_qh skelqh[4] -#define skel_int4_qh skelqh[5] -#define skel_int2_qh skelqh[6] -#define skel_int1_qh skelqh[7] -#define skel_ls_control_qh skelqh[8] -#define skel_hs_control_qh skelqh[9] -#define skel_bulk_qh skelqh[10] -#define skel_term_qh skelqh[11] - -/* - * Search tree for determining where fits in the skelqh[] - * skeleton. - * - * An interrupt request should be placed into the slowest skelqh[] - * which meets the interval/period/frequency requirement. - * An interrupt request is allowed to be faster than but not slower. - * - * For a given , this function returns the appropriate/matching - * skelqh[] index value. - */ -static inline int __interval_to_skel(int interval) -{ - if (interval < 16) { - if (interval < 4) { - if (interval < 2) - return 7; /* int1 for 0-1 ms */ - return 6; /* int2 for 2-3 ms */ - } - if (interval < 8) - return 5; /* int4 for 4-7 ms */ - return 4; /* int8 for 8-15 ms */ - } - if (interval < 64) { - if (interval < 32) - return 3; /* int16 for 16-31 ms */ - return 2; /* int32 for 32-63 ms */ - } - if (interval < 128) - return 1; /* int64 for 64-127 ms */ - return 0; /* int128 for 128-255 ms (Max.) */ -} - -/* - * Device states for the host controller. - * - * To prevent "bouncing" in the presence of electrical noise, - * we insist on a 1-second "grace" period, before switching to - * the RUNNING or SUSPENDED states, during which the state is - * not allowed to change. - * - * The resume process is divided into substates in order to avoid - * potentially length delays during the timer handler. - * - * States in which the host controller is halted must have values <= 0. - */ -enum uhci_state { - UHCI_RESET, - UHCI_RUNNING_GRACE, /* Before RUNNING */ - UHCI_RUNNING, /* The normal state */ - UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */ - UHCI_SUSPENDED = -10, /* When no devices are attached */ - UHCI_RESUMING_1, - UHCI_RESUMING_2 -}; - -#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd) - -/* - * This describes the full uhci information. - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. - */ -struct uhci_hcd { - struct usb_hcd hcd; - -#ifdef CONFIG_PROC_FS - /* procfs */ - struct proc_dir_entry *proc_entry; -#endif - - /* Grabbed from PCI */ - unsigned long io_addr; - - struct pci_pool *qh_pool; - struct pci_pool *td_pool; - - struct usb_bus *bus; - - struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ - struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ - - spinlock_t frame_list_lock; - struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */ - int fsbr; /* Full speed bandwidth reclamation */ - unsigned long fsbrtimeout; /* FSBR delay */ - - enum uhci_state state; /* FIXME: needs a spinlock */ - unsigned long state_end; /* Time of next transition */ - int resume_detect; /* Need a Global Resume */ - - /* Main list of URB's currently controlled by this HC */ - spinlock_t urb_list_lock; - struct list_head urb_list; /* P: uhci->urb_list_lock */ - - /* List of QH's that are done, but waiting to be unlinked (race) */ - spinlock_t qh_remove_list_lock; - struct list_head qh_remove_list; /* P: uhci->qh_remove_list_lock */ - - /* List of asynchronously unlinked URB's */ - spinlock_t urb_remove_list_lock; - struct list_head urb_remove_list; /* P: uhci->urb_remove_list_lock */ - - /* List of URB's awaiting completion callback */ - spinlock_t complete_list_lock; - struct list_head complete_list; /* P: uhci->complete_list_lock */ - - int rh_numports; - - struct timer_list stall_timer; -}; - -struct urb_priv { - struct list_head urb_list; - - struct urb *urb; - struct usb_device *dev; - - struct uhci_qh *qh; /* QH for this URB */ - struct list_head td_list; /* P: urb->lock */ - - int fsbr : 1; /* URB turned on FSBR */ - int fsbr_timeout : 1; /* URB timed out on FSBR */ - int queued : 1; /* QH was queued (not linked in) */ - int short_control_packet : 1; /* If we get a short packet during */ - /* a control transfer, retrigger */ - /* the status phase */ - - int status; /* Final status */ - - unsigned long inserttime; /* In jiffies */ - unsigned long fsbrtime; /* In jiffies */ - - struct list_head queue_list; /* P: uhci->frame_list_lock */ - struct list_head complete_list; /* P: uhci->complete_list_lock */ -}; - -/* - * Locking in uhci.c - * - * spinlocks are used extensively to protect the many lists and data - * structures we have. It's not that pretty, but it's necessary. We - * need to be done with all of the locks (except complete_list_lock) when - * we call urb->complete. I've tried to make it simple enough so I don't - * have to spend hours racking my brain trying to figure out if the - * locking is safe. - * - * Here's the safe locking order to prevent deadlocks: - * - * #1 uhci->urb_list_lock - * #2 urb->lock - * #3 uhci->urb_remove_list_lock, uhci->frame_list_lock, - * uhci->qh_remove_list_lock - * #4 uhci->complete_list_lock - * - * If you're going to grab 2 or more locks at once, ALWAYS grab the lock - * at the lowest level FIRST and NEVER grab locks at the same level at the - * same time. - * - * So, if you need uhci->urb_list_lock, grab it before you grab urb->lock - */ - -#endif - diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci-hub.c b/reactos/drivers/usb/miniport/usbuhci/uhci-hub.c deleted file mode 100644 index f5d16cc7039..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci-hub.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Universal Host Controller Interface driver for USB. - * - * Maintainer: Johannes Erdfelt - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com - * (C) Copyright 1999 Randy Dunlap - * (C) Copyright 1999 Georg Acher, acher@in.tum.de - * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de - * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch - */ - -static __u8 root_hub_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x02, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - unsigned int io_addr = uhci->io_addr; - int i, len = 1; - - *buf = 0; - for (i = 0; i < uhci->rh_numports; i++) { - *buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); - len = (i + 1) / 8 + 1; - } - - return !!*buf; -} - -#define OK(x) len = (x); break - -#define CLR_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ - status = (status & 0xfff5) & ~(x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) - -#define SET_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ - status = (status & 0xfff5) | (x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) - - -/* size of returned buffer is part of USB spec */ -static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, - u16 wIndex, u8 *buf, u16 wLength) -{ - struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int i, status, retval = 0, len = 0; - unsigned int io_addr = uhci->io_addr; - __u16 cstatus; - char c_p_r[8]; - - for (i = 0; i < 8; i++) - c_p_r[i] = 0; - - switch (typeReq) { - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case GetHubStatus: - *(__u32 *)buf = cpu_to_le32(0); - OK(4); /* hub power */ - case GetPortStatus: - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1)); - cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | - ((status & USBPORTSC_PEC) >> (3 - 1)) | - (c_p_r[wIndex - 1] << (0 + 4)); - status = (status & USBPORTSC_CCS) | - ((status & USBPORTSC_PE) >> (2 - 1)) | - ((status & USBPORTSC_SUSP) >> (12 - 2)) | - ((status & USBPORTSC_PR) >> (9 - 4)) | - (1 << 8) | /* power on */ - ((status & USBPORTSC_LSDA) << (-8 + 9)); - - *(__u16 *)buf = cpu_to_le16(status); - *(__u16 *)(buf + 2) = cpu_to_le16(cstatus); - OK(4); - case SetHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - case C_HUB_LOCAL_POWER: - break; - default: - goto err; - } - break; - case ClearHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - OK(0); /* hub power over current */ - default: - goto err; - } - break; - case SetPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) - goto err; - - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - SET_RH_PORTSTAT(USBPORTSC_SUSP); - OK(0); - case USB_PORT_FEAT_RESET: - SET_RH_PORTSTAT(USBPORTSC_PR); - mdelay(50); /* USB v1.1 7.1.7.3 */ - c_p_r[wIndex - 1] = 1; - CLR_RH_PORTSTAT(USBPORTSC_PR); - udelay(10); - SET_RH_PORTSTAT(USBPORTSC_PE); - mdelay(10); - SET_RH_PORTSTAT(0xa); - OK(0); - case USB_PORT_FEAT_POWER: - OK(0); /* port power ** */ - case USB_PORT_FEAT_ENABLE: - SET_RH_PORTSTAT(USBPORTSC_PE); - OK(0); - default: - goto err; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > uhci->rh_numports) - goto err; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - CLR_RH_PORTSTAT(USBPORTSC_PE); - OK(0); - case USB_PORT_FEAT_C_ENABLE: - SET_RH_PORTSTAT(USBPORTSC_PEC); - OK(0); - case USB_PORT_FEAT_SUSPEND: - CLR_RH_PORTSTAT(USBPORTSC_SUSP); - OK(0); - case USB_PORT_FEAT_C_SUSPEND: - /*** WR_RH_PORTSTAT(RH_PS_PSSC); */ - OK(0); - case USB_PORT_FEAT_POWER: - OK(0); /* port power */ - case USB_PORT_FEAT_C_CONNECTION: - SET_RH_PORTSTAT(USBPORTSC_CSC); - OK(0); - case USB_PORT_FEAT_C_OVER_CURRENT: - OK(0); /* port power over current */ - case USB_PORT_FEAT_C_RESET: - c_p_r[wIndex - 1] = 0; - OK(0); - default: - goto err; - } - break; - case GetHubDescriptor: - len = min_t(unsigned int, wLength, - min_t(unsigned int, sizeof(root_hub_hub_des), wLength)); - memcpy(buf, root_hub_hub_des, len); - if (len > 2) - buf[2] = uhci->rh_numports; - OK(len); - default: -err: - retval = -EPIPE; - } - - return retval; -} - diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci.c b/reactos/drivers/usb/miniport/usbuhci/uhci.c deleted file mode 100644 index 27171032f66..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - ReactOS specific functions for UHCI module - by Aleksey Bragin (aleksey@reactos.com) - and Hervé Poussineau (hpoussin@reactos.org) - Some parts of code are inspired (or even just copied) from ReactOS Videoport driver -*/ -#define NDEBUG -#include "uhci.h" - -extern struct pci_driver uhci_pci_driver; -extern struct pci_device_id uhci_pci_ids[]; -struct pci_device_id* pci_ids = &uhci_pci_ids[0]; - -NTSTATUS -InitLinuxWrapper(PDEVICE_OBJECT DeviceObject) -{ - NTSTATUS Status; - PUSBMP_DEVICE_EXTENSION DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - /* Create generic linux structure */ - struct pci_dev *dev; - dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_UHCI_TAG); - DeviceExtension->pdev = dev; - - /* Initialize generic linux structure */ - dev->irq = DeviceExtension->InterruptVector; - dev->dev_ext = (PVOID)DeviceExtension; - dev->dev.dev_ext = DeviceObject; - dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name - - /* Init wrapper */ - init_wrapper(dev); - - strcpy(dev->dev.name, "UnivHCI PCI-USB Controller"); - strcpy(dev->slot_name, "UHCD PCI Slot"); - - /* Init the HCD. Probe will be called automatically, but will fail because id=NULL */ - Status = uhci_hcd_init(); - if (!NT_SUCCESS(Status)) - { - DPRINT("UHCI: uhci_hcd_init() failed with status 0x%08lx\n", Status); - /* FIXME: deinitialize linux wrapper */ - ExFreePoolWithTag(dev, USB_UHCI_TAG); - return Status; - } - - /* Init core usb */ - usb_init(); - - /* Probe device with real id now */ - uhci_pci_driver.probe(dev, uhci_pci_ids); - - return STATUS_SUCCESS; -} - -VOID STDCALL -DriverUnload(PDRIVER_OBJECT DriverObject) -{ - PUSBMP_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT DeviceObject; - struct pci_dev *dev; - - DeviceObject = DriverObject->DeviceObject; - DeviceExtension = (PUSBMP_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - dev = DeviceExtension->pdev; - - DPRINT1("UHCI: DriverUnload()\n"); - - // Exit usb device - usb_exit(); - - // Remove device (uhci_pci_driver.remove) - uhci_pci_driver.remove(dev); - - ExFreePool(dev->slot_name); - ExFreePool(dev); - - // Perform some cleanup - uhci_hcd_cleanup(); -} diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci.h b/reactos/drivers/usb/miniport/usbuhci/uhci.h deleted file mode 100644 index 54fbe6d01ff..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "usbcommon.h" - -#define USB_UHCI_TAG TAG('u','s','b','u') - -/* declare basic init functions and structures */ -int uhci_hcd_init(void); -void uhci_hcd_cleanup(void); -int STDCALL usb_init(void); -void STDCALL usb_exit(void); diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci.rc b/reactos/drivers/usb/miniport/usbuhci/uhci.rc deleted file mode 100644 index 5acdfd37517..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USB UHCI Device Driver\0" -#define REACTOS_STR_INTERNAL_NAME "uhci\0" -#define REACTOS_STR_ORIGINAL_FILENAME "uhci.sys\0" -#include diff --git a/reactos/drivers/usb/miniport/usbuhci/uhci_config.h b/reactos/drivers/usb/miniport/usbuhci/uhci_config.h deleted file mode 100644 index 207aa328174..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/uhci_config.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * Configs for UHCI - */ - -#define CONFIG_PCI diff --git a/reactos/drivers/usb/miniport/usbuhci/usbuhci.rbuild b/reactos/drivers/usb/miniport/usbuhci/usbuhci.rbuild deleted file mode 100644 index f2e9ae16fb6..00000000000 --- a/reactos/drivers/usb/miniport/usbuhci/usbuhci.rbuild +++ /dev/null @@ -1,13 +0,0 @@ - - - ../linux - - sys_base - usbminiportcommon - usbport - ntoskrnl - hal - uhci.c - uhci-hcd.c - uhci.rc - diff --git a/reactos/drivers/usb/usbport/buffer_simple.c b/reactos/drivers/usb/usbport/buffer_simple.c deleted file mode 100644 index c69586ff5c0..00000000000 --- a/reactos/drivers/usb/usbport/buffer_simple.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * buffer_simple.c -- replacement for usb/core/buffer.c - * - * (c) Georg Acher, georg@acher.org - * - */ - -#include "../miniport/usb_wrapper.h" -#define __KERNEL__ -#define CONFIG_PCI -#include "hcd.h" - -/*------------------------------------------------------------------------*/ -int hcd_buffer_create (struct usb_hcd *hcd) -{ - return 0; -} -/*------------------------------------------------------------------------*/ -void hcd_buffer_destroy (struct usb_hcd *hcd) -{ -} -/*------------------------------------------------------------------------*/ -void *hcd_buffer_alloc ( - struct usb_bus *bus, - size_t size, - int mem_flags, - dma_addr_t *dma -) -{ - return kmalloc(size,0); -} -/*------------------------------------------------------------------------*/ -void hcd_buffer_free ( - struct usb_bus *bus, - size_t size, - void *addr, - dma_addr_t dma -) -{ - kfree(addr); -} - diff --git a/reactos/drivers/usb/usbport/config.c b/reactos/drivers/usb/usbport/config.c deleted file mode 100644 index 8d2e937c180..00000000000 --- a/reactos/drivers/usb/usbport/config.c +++ /dev/null @@ -1,509 +0,0 @@ -#if 0 -#include -#include -#include -#include -#include -#else -#include "../miniport/usb_wrapper.h" -#endif - -#define USB_MAXALTSETTING 128 /* Hard limit */ -#define USB_MAXENDPOINTS 30 /* Hard limit */ - -/* these maximums are arbitrary */ -#define USB_MAXCONFIG 8 -#define USB_ALTSETTINGALLOC 4 -#define USB_MAXINTERFACES 32 - -static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, char *buffer, int size) -{ - struct usb_descriptor_header *header; - char *begin; - int parsed = 0, len, numskipped; - - header = (struct usb_descriptor_header *)buffer; - - /* Everything should be fine being passed into here, but we sanity */ - /* check JIC */ - if (header->bLength > size) { - err("ran out of descriptors parsing"); - return -1; - } - - if (header->bDescriptorType != USB_DT_ENDPOINT) { - warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X", - header->bDescriptorType, USB_DT_ENDPOINT); - return parsed; - } - - if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) - memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); - else - memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE); - - le16_to_cpus(&endpoint->desc.wMaxPacketSize); - - buffer += header->bLength; - size -= header->bLength; - parsed += header->bLength; - - /* Skip over the rest of the Class Specific or Vendor Specific */ - /* descriptors */ - begin = buffer; - numskipped = 0; - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength < 2) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header->bDescriptorType == USB_DT_ENDPOINT) || - (header->bDescriptorType == USB_DT_INTERFACE) || - (header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE)) - break; - - dbg("skipping descriptor 0x%X", - header->bDescriptorType); - numskipped++; - - buffer += header->bLength; - size -= header->bLength; - parsed += header->bLength; - } - if (numskipped) - dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); - - /* Copy any unknown descriptors into a storage area for drivers */ - /* to later parse */ - len = (int)(buffer - begin); - if (!len) { - endpoint->extra = NULL; - endpoint->extralen = 0; - return parsed; - } - - endpoint->extra = kmalloc(len, GFP_KERNEL); - - if (!endpoint->extra) { - err("couldn't allocate memory for endpoint extra descriptors"); - endpoint->extralen = 0; - return parsed; - } - - memcpy(endpoint->extra, begin, len); - endpoint->extralen = len; - - return parsed; -} - -static int usb_parse_interface(struct usb_interface *interface, char *buffer, int size) -{ - int i, len, numskipped, retval, parsed = 0; - struct usb_descriptor_header *header; - struct usb_host_interface *ifp; - char *begin; - - interface->act_altsetting = 0; - interface->num_altsetting = 0; - interface->max_altsetting = USB_ALTSETTINGALLOC; - device_initialize(&interface->dev); - - interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, - GFP_KERNEL); - - if (!interface->altsetting) { - err("couldn't kmalloc interface->altsetting"); - return -1; - } - - while (size > 0) { - struct usb_interface_descriptor *d; - - if (interface->num_altsetting >= interface->max_altsetting) { - struct usb_host_interface *ptr; - int oldmas; - - oldmas = interface->max_altsetting; - interface->max_altsetting += USB_ALTSETTINGALLOC; - if (interface->max_altsetting > USB_MAXALTSETTING) { - warn("too many alternate settings (incr %d max %d)\n", - USB_ALTSETTINGALLOC, USB_MAXALTSETTING); - return -1; - } - - ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); - if (ptr == NULL) { - err("couldn't kmalloc interface->altsetting"); - return -1; - } - memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); - kfree(interface->altsetting); - interface->altsetting = ptr; - } - - ifp = interface->altsetting + interface->num_altsetting; - ifp->endpoint = NULL; - ifp->extra = NULL; - ifp->extralen = 0; - interface->num_altsetting++; - - memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); - - /* Skip over the interface */ - buffer += ifp->desc.bLength; - parsed += ifp->desc.bLength; - size -= ifp->desc.bLength; - - begin = buffer; - numskipped = 0; - - /* Skip over any interface, class or vendor descriptors */ - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength < 2) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header->bDescriptorType == USB_DT_INTERFACE) || - (header->bDescriptorType == USB_DT_ENDPOINT) || - (header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE)) - break; - - numskipped++; - - buffer += header->bLength; - parsed += header->bLength; - size -= header->bLength; - } - - if (numskipped) - dbg("skipped %d class/vendor specific interface descriptors", numskipped); - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - ifp->extra = kmalloc(len, GFP_KERNEL); - - if (!ifp->extra) { - err("couldn't allocate memory for interface extra descriptors"); - ifp->extralen = 0; - return -1; - } - memcpy(ifp->extra, begin, len); - ifp->extralen = len; - } - - /* Did we hit an unexpected descriptor? */ - header = (struct usb_descriptor_header *)buffer; - if ((size >= sizeof(struct usb_descriptor_header)) && - ((header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE))) - return parsed; - - if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) { - warn("too many endpoints"); - return -1; - } - - ifp->endpoint = (struct usb_host_endpoint *) - kmalloc(ifp->desc.bNumEndpoints * - sizeof(struct usb_host_endpoint), GFP_KERNEL); - if (!ifp->endpoint) { - err("out of memory"); - return -1; - } - - memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints * - sizeof(struct usb_host_endpoint)); - - for (i = 0; i < ifp->desc.bNumEndpoints; i++) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength > size) { - err("ran out of descriptors parsing"); - return -1; - } - - retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); - if (retval < 0) - return retval; - - buffer += retval; - parsed += retval; - size -= retval; - } - - /* We check to see if it's an alternate to this one */ - d = (struct usb_interface_descriptor *)buffer; - if (size < USB_DT_INTERFACE_SIZE - || d->bDescriptorType != USB_DT_INTERFACE - || !d->bAlternateSetting) - return parsed; - } - - return parsed; -} - -int usb_parse_configuration(struct usb_host_config *config, char *buffer) -{ - int i, retval, size; - struct usb_descriptor_header *header; - - memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); - le16_to_cpus(&config->desc.wTotalLength); - size = config->desc.wTotalLength; - - if (config->desc.bNumInterfaces > USB_MAXINTERFACES) { - warn("too many interfaces"); - return -1; - } - - config->interface = (struct usb_interface *) - kmalloc(config->desc.bNumInterfaces * - sizeof(struct usb_interface), GFP_KERNEL); - dbg("kmalloc IF %p, numif %i", config->interface, config->desc.bNumInterfaces); - if (!config->interface) { - err("out of memory"); - return -1; - } - - memset(config->interface, 0, - config->desc.bNumInterfaces * sizeof(struct usb_interface)); - - buffer += config->desc.bLength; - size -= config->desc.bLength; - - config->extra = NULL; - config->extralen = 0; - - for (i = 0; i < config->desc.bNumInterfaces; i++) { - int numskipped, len; - char *begin; - - /* Skip over the rest of the Class Specific or Vendor */ - /* Specific descriptors */ - begin = buffer; - numskipped = 0; - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if ((header->bLength > size) || (header->bLength < 2)) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - /* If we find another "proper" descriptor then we're done */ - if ((header->bDescriptorType == USB_DT_ENDPOINT) || - (header->bDescriptorType == USB_DT_INTERFACE) || - (header->bDescriptorType == USB_DT_CONFIG) || - (header->bDescriptorType == USB_DT_DEVICE)) - break; - - dbg("skipping descriptor 0x%X", header->bDescriptorType); - numskipped++; - - buffer += header->bLength; - size -= header->bLength; - } - if (numskipped) - dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); - - /* Copy any unknown descriptors into a storage area for */ - /* drivers to later parse */ - len = (int)(buffer - begin); - if (len) { - if (config->extralen) { - warn("extra config descriptor"); - } else { - config->extra = kmalloc(len, GFP_KERNEL); - if (!config->extra) { - err("couldn't allocate memory for config extra descriptors"); - config->extralen = 0; - return -1; - } - - memcpy(config->extra, begin, len); - config->extralen = len; - } - } - - retval = usb_parse_interface(config->interface + i, buffer, size); - if (retval < 0) - return retval; - - buffer += retval; - size -= retval; - } - - return size; -} - -// hub-only!! ... and only exported for reset/reinit path. -// otherwise used internally on disconnect/destroy path -void usb_destroy_configuration(struct usb_device *dev) -{ - int c, i, j, k; - - if (!dev->config) - return; - - if (dev->rawdescriptors) { - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) - kfree(dev->rawdescriptors[i]); - - kfree(dev->rawdescriptors); - } - - for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { - struct usb_host_config *cf = &dev->config[c]; - - if (!cf->interface) - break; - - for (i = 0; i < cf->desc.bNumInterfaces; i++) { - struct usb_interface *ifp = - &cf->interface[i]; - - if (!ifp->altsetting) - break; - - for (j = 0; j < ifp->num_altsetting; j++) { - struct usb_host_interface *as = - &ifp->altsetting[j]; - - if(as->extra) { - kfree(as->extra); - } - - if (!as->endpoint) - break; - - for(k = 0; k < as->desc.bNumEndpoints; k++) { - if(as->endpoint[k].extra) { - kfree(as->endpoint[k].extra); - } - } - kfree(as->endpoint); - } - - kfree(ifp->altsetting); - } - kfree(cf->interface); - } - kfree(dev->config); -} - - -// hub-only!! ... and only in reset path, or usb_new_device() -// (used by real hubs and virtual root hubs) -int usb_get_configuration(struct usb_device *dev) -{ - int result; - unsigned int cfgno, length; - char *buffer; - char *bigbuffer; - struct usb_config_descriptor *desc; - - if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { - warn("too many configurations"); - return -EINVAL; - } - - if (dev->descriptor.bNumConfigurations < 1) { - warn("not enough configurations"); - return -EINVAL; - } - - dev->config = (struct usb_host_config *) - kmalloc(dev->descriptor.bNumConfigurations * - sizeof(struct usb_host_config), GFP_KERNEL); - if (!dev->config) { - err("out of memory"); - return -ENOMEM; - } - memset(dev->config, 0, dev->descriptor.bNumConfigurations * - sizeof(struct usb_host_config)); - - dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * - dev->descriptor.bNumConfigurations, GFP_KERNEL); - if (!dev->rawdescriptors) { - err("out of memory"); - return -ENOMEM; - } - - buffer = kmalloc(8, GFP_KERNEL); - if (!buffer) { - err("unable to allocate memory for configuration descriptors"); - return -ENOMEM; - } - desc = (struct usb_config_descriptor *)buffer; - - for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { - /* We grab the first 8 bytes so we know how long the whole */ - /* configuration is */ - result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); - if (result < 8) { - if (result < 0) { - err("unable to get descriptor"); - } - else { - err("config descriptor too short (expected %i, got %i)", 8, result); - result = -EINVAL; - } - goto err; - } - - /* Get the full buffer */ - length = le16_to_cpu(desc->wTotalLength); - - bigbuffer = kmalloc(length, GFP_KERNEL); - if (!bigbuffer) { - err("unable to allocate memory for configuration descriptors"); - result = -ENOMEM; - goto err; - } - - /* Now that we know the length, get the whole thing */ - result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); - if (result < 0) { - err("couldn't get all of config descriptors"); - kfree(bigbuffer); - goto err; - } - - if (result < length) { - err("config descriptor too short (expected %i, got %i)", length, result); - result = -EINVAL; - kfree(bigbuffer); - goto err; - } - - dev->rawdescriptors[cfgno] = bigbuffer; - - result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); - if (result > 0) - dbg("descriptor data left"); - else if (result < 0) { - result = -EINVAL; - goto err; - } - } - - kfree(buffer); - return 0; -err: - kfree(buffer); - dev->descriptor.bNumConfigurations = cfgno; - return result; -} - diff --git a/reactos/drivers/usb/usbport/core_drivers/usbkey.c b/reactos/drivers/usb/usbport/core_drivers/usbkey.c deleted file mode 100644 index 811187a24f7..00000000000 --- a/reactos/drivers/usb/usbport/core_drivers/usbkey.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - This driver is based on Cromwell's usbkey driver - and also includes stuff from Linux 2.5 usbkey driver by Vojtech Pavlik -*/ - -#define NDEBUG -#include "../../miniport/usb_wrapper.h" - -#define keyboarddebug 0 - -#if keyboarddebug -//extern int printk(const char *szFormat, ...); -#endif - -unsigned int current_keyboard_key; - -extern USBPORT_INTERFACE UsbPortInterface; - -static unsigned char usb_kbd_keycode[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95, - 120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114, 0, 0, 0,124, 0,181,182,183,184,185,186,187,188,189, - 190,191,192,193,194,195,196,197,198, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140 -}; - -struct usb_kbd_info { - struct urb *urb; - unsigned char kbd_pkt[8]; - unsigned char old[8]; - - /* - struct input_dev dev; - struct usb_device *usbdev; - struct urb irq, led; - struct usb_ctrlrequest dr; - unsigned char leds, newleds; - char name[128]; - int open; - */ -}; - -/** - * memscan - Find a character in an area of memory. - * @addr: The memory area - * @c: The byte to search for - * @size: The size of the area. - * - * returns the address of the first occurrence of @c, or 1 byte past - * the area if @c is not found - */ -void * memscan(void * addr, int c, size_t size) -{ - unsigned char * p = (unsigned char *) addr; - - while (size) { - if (*p == c) - return (void *) p; - p++; - size--; - } - return (void *) p; -} - -void input_report_key(unsigned int code, int value) -{ - KEYBOARD_INPUT_DATA KeyboardInputData; - ULONG InputDataConsumed; - - KeyboardInputData.MakeCode = code; - KeyboardInputData.Flags = (value == 1) ? KEY_MAKE : KEY_BREAK; - - if (UsbPortInterface.KbdConnectData->ClassService) - { - KIRQL OldIrql; - - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - (*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.KbdConnectData->ClassService)( - UsbPortInterface.KbdConnectData->ClassDeviceObject, - &KeyboardInputData, - (&KeyboardInputData)+1, - &InputDataConsumed); - KeLowerIrql(OldIrql); - } -} - -static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_kbd_info *kbd = urb->context; - int i; - - if (urb->status) return; - - memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8); - - //for (i = 0; i < 8; i++) - // input_report_key(usb_kbd_keycode[i + 224], (kbd->kbd_pkt[0] >> i) & 1); - - for (i = 2; i < 8; i++) { - - if (kbd->old[i] > 3 && memscan(kbd->kbd_pkt + 2, kbd->old[i], 6) == kbd->kbd_pkt + 8) { - if (usb_kbd_keycode[kbd->old[i]]) - input_report_key(usb_kbd_keycode[kbd->old[i]], 0); - else - info("Unknown key (scancode %#x) released.", kbd->old[i]); - } - - if (kbd->kbd_pkt[i] > 3 && memscan(kbd->old + 2, kbd->kbd_pkt[i], 6) == kbd->old + 8) { - if (usb_kbd_keycode[kbd->kbd_pkt[i]]) - input_report_key(usb_kbd_keycode[kbd->kbd_pkt[i]], 1); - else - info("Unknown key (scancode %#x) pressed.", kbd->kbd_pkt[i]); - } - } - - memcpy(kbd->old, kbd->kbd_pkt, 8); - -#if 0 - //memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8); - //current_keyboard_key = kbd->kbd_pkt[2]; - { - KEYBOARD_INPUT_DATA KeyboardInputData; - ULONG InputDataConsumed; - - KeyboardInputData.MakeCode = current_keyboard_key & ~0x80; - KeyboardInputData.Flags = (current_keyboard_key & 0x80) ? KEY_MAKE : KEY_BREAK; - - if (UsbPortInterface.KbdConnectData->ClassService) - { - KIRQL OldIrql; - - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - (*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.KbdConnectData->ClassService)( - UsbPortInterface.KbdConnectData->ClassDeviceObject, - &KeyboardInputData, - (&KeyboardInputData)+1, - &InputDataConsumed); - KeLowerIrql(OldIrql); - } - } -#endif - - - #if keyboarddebug - printk(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]); - #endif - - usb_submit_urb(urb,GFP_ATOMIC); - -} - -static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct urb *urb; - struct usb_device *udev = interface_to_usbdev (intf); - struct usb_endpoint_descriptor *ep_irq_in; - //struct usb_endpoint_descriptor *ep_irq_out; - struct usb_kbd_info *usbk; - - //int i, pipe, maxp; - //char *buf; - - usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0); - if (!usbk) return -1; - memset(usbk, 0, sizeof(struct usb_kbd_info)); - - urb=usb_alloc_urb(0,0); - if (!urb) return -1; - - usbk->urb=urb; - - ep_irq_in = &intf->altsetting[0].endpoint[0].desc; - usb_fill_int_urb(urb, udev, - usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), - usbk->kbd_pkt, 8, usb_kbd_irq, - usbk, 8); - - usb_submit_urb(urb,GFP_ATOMIC); - usb_set_intfdata(intf,usbk); - #if keyboarddebug - printk("USB Keyboard Connected\n"); - #endif - - return 0; -} - - -static void usb_kbd_disconnect(struct usb_interface *intf) -{ - struct usb_kbd_info *usbk = usb_get_intfdata (intf); - usbprintk("Keyboard disconnected\n "); - usb_unlink_urb(usbk->urb); - usb_free_urb(usbk->urb); - kfree(usbk); -} - -static struct usb_device_id usb_kbd_id_table [] = { - { USB_INTERFACE_INFO(3, 1, 1) }, - { } /* Terminating entry */ -}; - - -static struct usb_driver usb_kbd_driver = { - .owner = THIS_MODULE, - .name = "keyboard", - .probe = usb_kbd_probe, - .disconnect = usb_kbd_disconnect, - .id_table = usb_kbd_id_table, -}; - -void UsbKeyBoardInit(void) -{ - //current_remote_key=0; - //sbprintk("Keyboard probe %p ",xremote_probe); - if (usb_register(&usb_kbd_driver) < 0) { - #if keyboarddebug - printk("Unable to register Keyboard driver"); - #endif - return; - } -} - -void UsbKeyBoardRemove(void) { - usb_deregister(&usb_kbd_driver); -} diff --git a/reactos/drivers/usb/usbport/core_drivers/usbmouse.c b/reactos/drivers/usb/usbport/core_drivers/usbmouse.c deleted file mode 100644 index 3e8ed4eabaf..00000000000 --- a/reactos/drivers/usb/usbport/core_drivers/usbmouse.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - This driver is based on Linux 2.5.75 usbmouse driver by Vojtech Pavlik -*/ - -#define NDEBUG -#include "../../miniport/usb_wrapper.h" - -extern USBPORT_INTERFACE UsbPortInterface; - -struct usb_mouse { - char name[128]; - char phys[64]; - struct usb_device *usbdev; - char btn_old; - //struct input_dev dev; - struct urb *irq; - int open; - - signed char *data; - dma_addr_t data_dma; -}; - -static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_mouse *mouse = urb->context; - signed char *data = mouse->data; - int status; - - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } -/* - input_regs(dev, regs); - - input_report_key(dev, BTN_LEFT, data[0] & 0x01); - input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); - input_report_key(dev, BTN_SIDE, data[0] & 0x08); - input_report_key(dev, BTN_EXTRA, data[0] & 0x10); - - input_report_rel(dev, REL_X, data[1]); - input_report_rel(dev, REL_Y, data[2]); - input_report_rel(dev, REL_WHEEL, data[3]); - - input_sync(dev); -*/ - - { - MOUSE_INPUT_DATA MouseInputData; - ULONG InputDataConsumed; - - MouseInputData.Flags = MOUSE_MOVE_RELATIVE; - MouseInputData.LastX = data[1]; - MouseInputData.LastY = data[2]; - - MouseInputData.ButtonFlags = 0; - MouseInputData.ButtonData = 0; - - if ((data[0] & 0x01) && ((mouse->btn_old & 0x01) != (data[0] & 0x01))) - MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN; - else if (!(data[0] & 0x01) && ((mouse->btn_old & 0x01) != (data[0] & 0x01))) - MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP; - - if ((data[0] & 0x02) && ((mouse->btn_old & 0x02) != (data[0] & 0x02))) - MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN; - else if (!(data[0] & 0x02) && ((mouse->btn_old & 0x02) != (data[0] & 0x02))) - MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP; - - if ((data[0] & 0x04) && ((mouse->btn_old & 0x04) != (data[0] & 0x04))) - MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN; - else if (!(data[0] & 0x04) && ((mouse->btn_old & 0x04) != (data[0] & 0x04))) - MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP; - - if ((data[0] & 0x08) && ((mouse->btn_old & 0x08) != (data[0] & 0x08))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_DOWN; - else if (!(data[0] & 0x08) && ((mouse->btn_old & 0x08) != (data[0] & 0x08))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_UP; - - if ((data[0] & 0x10) && ((mouse->btn_old & 0x10) != (data[0] & 0x10))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_DOWN; - else if (!(data[0] & 0x10) && ((mouse->btn_old & 0x10) != (data[0] & 0x10))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_UP; - - if (data[3]) - { - MouseInputData.ButtonFlags |= MOUSE_WHEEL; - MouseInputData.ButtonData = data[3]; - } - - if (UsbPortInterface.MouseConnectData->ClassService) - { - KIRQL OldIrql; - - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - (*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.MouseConnectData->ClassService)( - UsbPortInterface.MouseConnectData->ClassDeviceObject, - &MouseInputData, - (&MouseInputData)+1, - &InputDataConsumed); - KeLowerIrql(OldIrql); - } - - mouse->btn_old = data[0]; - - // debug info - printk("MouseInputData.Buttons=0x%03x\n", MouseInputData.Buttons); - } - - printk("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data[1], data[2], data[3], data[0]); - -resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", - mouse->usbdev->bus->bus_name, - mouse->usbdev->devpath, status); -} -/* -static int usb_mouse_open(struct input_dev *dev) -{ - struct usb_mouse *mouse = dev->private; - - if (mouse->open++) - return 0; - - mouse->irq->dev = mouse->usbdev; - if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { - mouse->open--; - return -EIO; - } - - return 0; -} - -static void usb_mouse_close(struct input_dev *dev) -{ - struct usb_mouse *mouse = dev->private; - - if (!--mouse->open) - usb_unlink_urb(mouse->irq); -} -*/ - -static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) -{ - struct usb_device * dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct usb_mouse *mouse; - int pipe, maxp; - char path[64]; - char *buf; - - interface = &intf->altsetting[intf->act_altsetting]; - - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) - return -ENODEV; - if ((endpoint->bmAttributes & 3) != 3) - return -ENODEV; - - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) - return -ENOMEM; - memset(mouse, 0, sizeof(struct usb_mouse)); - - mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma); - if (!mouse->data) { - kfree(mouse); - return -ENOMEM; - } - - mouse->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mouse->irq) { - usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); - kfree(mouse); - return -ENODEV; - } - - mouse->usbdev = dev; - - usb_make_path(dev, path, 64); - sprintf(mouse->phys, "%s/input0", path); - - if (!(buf = kmalloc(63, GFP_KERNEL))) { - usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); - kfree(mouse); - return -ENOMEM; - } - - if (dev->descriptor.iManufacturer && - usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0) - strcat(mouse->name, buf); - if (dev->descriptor.iProduct && - usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0) - sprintf(mouse->name, "%s %s", mouse->name, buf); - - if (!strlen(mouse->name)) - sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x", - dev->descriptor.idVendor, dev->descriptor.idProduct); - - kfree(buf); - - usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, - (maxp > 8 ? 8 : maxp), - usb_mouse_irq, mouse, endpoint->bInterval); - //mouse->irq->transfer_dma = mouse->data_dma; - //mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - printk(KERN_INFO "input: %s on %s\n", mouse->name, path); - - usb_set_intfdata(intf, mouse); - - // Open device - mouse->irq->dev = mouse->usbdev; - if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { - return -EIO; - } - - mouse->btn_old = 0; - - return 0; -} - -static void usb_mouse_disconnect(struct usb_interface *intf) -{ - struct usb_mouse *mouse = usb_get_intfdata (intf); - - usb_set_intfdata(intf, NULL); - usbprintk("Mouse disconnected\n "); - if (mouse) { - usb_unlink_urb(mouse->irq); - usb_free_urb(mouse->irq); - usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); - kfree(mouse); - } -} - -static struct usb_device_id usb_mouse_id_table [] = { - { USB_INTERFACE_INFO(3, 1, 2) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); - -static struct usb_driver usb_mouse_driver = { - .owner = THIS_MODULE, - .name = "usbmouse", - .probe = usb_mouse_probe, - .disconnect = usb_mouse_disconnect, - .id_table = usb_mouse_id_table, -}; - -void UsbMouseInit(void) -{ - if (usb_register(&usb_mouse_driver) < 0) { - #if mousedebug - printk("Unable to register Mouse driver"); - #endif - return; - } -} - -void UsbMouseRemove(void) { - usb_deregister(&usb_mouse_driver); -} diff --git a/reactos/drivers/usb/usbport/hcd-pci.c b/reactos/drivers/usb/usbport/hcd-pci.c deleted file mode 100644 index 5e666551406..00000000000 --- a/reactos/drivers/usb/usbport/hcd-pci.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * (C) Copyright David Brownell 2000-2002 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if 0 -#include - -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - -#include -#include -#include -#include -#include -#include -#include "hcd.h" -#else - -#include "../miniport/usb_wrapper.h" -#include "hcd.h" -#endif - - -/* PCI-based HCs are normal, but custom bus glue should be ok */ - - -/*-------------------------------------------------------------------------*/ - -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ - -/** - * usb_hcd_pci_probe - initialize PCI-based HCDs - * @dev: USB Host Controller being probed - * @id: pci hotplug id connecting controller to HCD framework - * Context: !in_interrupt() - * - * Allocates basic PCI resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - * - * Store this function in the HCD's struct pci_driver as probe(). - */ -int STDCALL -usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) -{ - struct hc_driver *driver; - PHYSICAL_ADDRESS resource; - unsigned long len; - void *base; - struct usb_hcd *hcd; - int retval, region; - char buf [8]; - //char *bufp = buf; - - printk("usbcore: usb_hcd_pci_probe() called\n"); - - if (usb_disabled()) - return -ENODEV; - - if (!id || !(driver = (struct hc_driver *) id->driver_data)) - return -EINVAL; - - if (pci_enable_device (dev) < 0) - return -ENODEV; - - if (!dev->irq) { - err ("Found HC with no IRQ. Check BIOS/PCI %s setup!", - dev->slot_name); - return -ENODEV; - } - - if (driver->flags & HCD_MEMORY) { // EHCI, OHCI - region = 0; - resource = pci_resource_start (dev, 0); - len = pci_resource_len (dev, 0); - if (!request_mem_region (resource, len, driver->description)) { - dbg ("controller already in use"); - return -EBUSY; - } - base = ioremap_nocache (resource, len); - if (base == NULL) { - dbg ("error mapping memory"); - retval = -EFAULT; -clean_1: - release_mem_region (resource, len); - err ("init %s fail, %d", dev->slot_name, retval); - return retval; - } - - } else { // UHCI - //resource = 0; - len = 0; - for (region = 0; region < PCI_ROM_RESOURCE; region++) { - if (!(pci_resource_flags (dev, region) & IORESOURCE_IO)) - continue; - - resource = pci_resource_start (dev, region); - len = pci_resource_len (dev, region); - if (request_region (resource, len, - driver->description)) - break; - } - if (region == PCI_ROM_RESOURCE) { - dbg ("no i/o regions available"); - return -EBUSY; - } - base = (void *) (ULONG_PTR)resource.u.LowPart; - } - - // driver->start(), later on, will transfer device from - // control by SMM/BIOS to control by Linux (if needed) - - pci_set_master (dev); - - hcd = driver->hcd_alloc (); - if (hcd == NULL){ - dbg ("hcd alloc fail"); - retval = -ENOMEM; -clean_2: - if (driver->flags & HCD_MEMORY) { - iounmap (base); - goto clean_1; - } else { - release_region (resource, len); - err ("init %s fail, %d", dev->slot_name, retval); - return retval; - } - } - pci_set_drvdata (dev, hcd); - hcd->driver = driver; - hcd->description = driver->description; - hcd->pdev = dev; - hcd->self.bus_name = dev->slot_name; - hcd->product_desc = dev->dev.name; - hcd->self.controller = &dev->dev; - hcd->controller = hcd->self.controller; - - if ((retval = hcd_buffer_create (hcd)) != 0) { -clean_3: - driver->hcd_free (hcd); - goto clean_2; - } - - dev_info (hcd->controller, "%s\n", hcd->product_desc); - -#ifndef __sparc__ - sprintf (buf, "%d", dev->irq); -#else - bufp = __irq_itoa(dev->irq); -#endif - if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd) - != 0) { - dev_err (hcd->controller, - "request interrupt %s failed\n", buf); - retval = -EBUSY; - goto clean_3; - } - hcd->irq = dev->irq; - - hcd->regs = base; - hcd->region = region; - dev_info (hcd->controller, "irq %s, %s %p\n", buf, - (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", - base); - - usb_bus_init (&hcd->self); - hcd->self.op = &usb_hcd_operations; - hcd->self.hcpriv = (void *) hcd; - - INIT_LIST_HEAD (&hcd->dev_list); - - usb_register_bus (&hcd->self); - - if ((retval = driver->start (hcd)) < 0) - usb_hcd_pci_remove (dev); - - //ReactOS-specific: Init core drivers here - UsbKeyBoardInit(); - UsbMouseInit(); - - return retval; -} -EXPORT_SYMBOL (usb_hcd_pci_probe); - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -/** - * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs - * @dev: USB Host Controller being removed - * Context: !in_interrupt() - * - * Reverses the effect of usb_hcd_pci_probe(), first invoking - * the HCD's stop() method. It is always called from a thread - * context, normally "rmmod", "apmd", or something similar. - * - * Store this function in the HCD's struct pci_driver as remove(). - */ -void STDCALL usb_hcd_pci_remove (struct pci_dev *dev) -{ - struct usb_hcd *hcd; - struct usb_device *hub; - - hcd = pci_get_drvdata(dev); - if (!hcd) - return; - dev_info (hcd->controller, "remove, state %x\n", hcd->state); - - if (in_interrupt ()) - BUG (); - - hub = hcd->self.root_hub; - hcd->state = USB_STATE_QUIESCING; - - dev_dbg (hcd->controller, "roothub graceful disconnect\n"); - usb_disconnect (&hub); - - hcd->driver->stop (hcd); - hcd_buffer_destroy (hcd); - hcd->state = USB_STATE_HALT; - pci_set_drvdata (dev, 0); - - free_irq (hcd->irq, hcd); - if (hcd->driver->flags & HCD_MEMORY) { - iounmap (hcd->regs); - release_mem_region (pci_resource_start (dev, 0), - pci_resource_len (dev, 0)); - } else { - release_region (pci_resource_start (dev, hcd->region), - pci_resource_len (dev, hcd->region)); - } - - usb_deregister_bus (&hcd->self); - if (atomic_read (&hcd->self.refcnt) != 1) { - dev_warn (hcd->controller, - "dangling refs (%d) to bus %d!\n", - atomic_read (&hcd->self.refcnt) - 1, - hcd->self.busnum); - } - hcd->driver->hcd_free (hcd); -} -EXPORT_SYMBOL (usb_hcd_pci_remove); - - -#ifdef CONFIG_PM - -/* - * Some "sleep" power levels imply updating struct usb_driver - * to include a callback asking hcds to do their bit by checking - * if all the drivers can suspend. Gets involved with remote wakeup. - * - * If there are pending urbs, then HCs will need to access memory, - * causing extra power drain. New sleep()/wakeup() PM calls might - * be needed, beyond PCI suspend()/resume(). The root hub timer - * still be accessing memory though ... - * - * FIXME: USB should have some power budgeting support working with - * all kinds of hubs. - * - * FIXME: This assumes only D0->D3 suspend and D3->D0 resume. - * D1 and D2 states should do something, yes? - * - * FIXME: Should provide generic enable_wake(), calling pci_enable_wake() - * for all supported states, so that USB remote wakeup can work for any - * devices that support it (and are connected via powered hubs). - * - * FIXME: resume doesn't seem to work right any more... - */ - - -// 2.4 kernels have issued concurrent resumes (w/APM) -// we defend against that error; PCI doesn't yet. - -/** - * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD - * @dev: USB Host Controller being suspended - * - * Store this function in the HCD's struct pci_driver as suspend(). - */ -int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) -{ - struct usb_hcd *hcd; - int retval; - - hcd = pci_get_drvdata(dev); - dev_info (hcd->controller, "suspend to state %d\n", state); - - pci_save_state (dev, hcd->pci_state); - - // FIXME for all connected devices, leaf-to-root: - // driver->suspend() - // proposed "new 2.5 driver model" will automate that - - /* driver may want to disable DMA etc */ - retval = hcd->driver->suspend (hcd, state); - hcd->state = USB_STATE_SUSPENDED; - - pci_set_power_state (dev, state); - return retval; -} -EXPORT_SYMBOL (usb_hcd_pci_suspend); - -/** - * usb_hcd_pci_resume - power management resume of a PCI-based HCD - * @dev: USB Host Controller being resumed - * - * Store this function in the HCD's struct pci_driver as resume(). - */ -int usb_hcd_pci_resume (struct pci_dev *dev) -{ - struct usb_hcd *hcd; - int retval; - - hcd = pci_get_drvdata(dev); - dev_info (hcd->controller, "resume\n"); - - /* guard against multiple resumes (APM bug?) */ - atomic_inc (&hcd->resume_count); - if (atomic_read (&hcd->resume_count) != 1) { - dev_err (hcd->controller, "concurrent PCI resumes\n"); - retval = 0; - goto done; - } - - retval = -EBUSY; - if (hcd->state != USB_STATE_SUSPENDED) { - dev_dbg (hcd->controller, "can't resume, not suspended!\n"); - goto done; - } - hcd->state = USB_STATE_RESUMING; - - pci_set_power_state (dev, 0); - pci_restore_state (dev, hcd->pci_state); - - retval = hcd->driver->resume (hcd); - if (!HCD_IS_RUNNING (hcd->state)) { - dev_dbg (hcd->controller, "resume fail, retval %d\n", retval); - usb_hc_died (hcd); -// FIXME: recover, reset etc. - } else { - // FIXME for all connected devices, root-to-leaf: - // driver->resume (); - // proposed "new 2.5 driver model" will automate that - } - -done: - atomic_dec (&hcd->resume_count); - return retval; -} -EXPORT_SYMBOL (usb_hcd_pci_resume); - -#endif /* CONFIG_PM */ - - diff --git a/reactos/drivers/usb/usbport/hcd.c b/reactos/drivers/usb/usbport/hcd.c deleted file mode 100644 index a0697185447..00000000000 --- a/reactos/drivers/usb/usbport/hcd.c +++ /dev/null @@ -1,1503 +0,0 @@ -/* - * (C) Copyright Linus Torvalds 1999 - * (C) Copyright Johannes Erdfelt 1999-2001 - * (C) Copyright Andreas Gal 1999 - * (C) Copyright Gregory P. Smith 1999 - * (C) Copyright Deti Fliegl 1999 - * (C) Copyright Randy Dunlap 2000 - * (C) Copyright David Brownell 2000-2002 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if 0 -#include - -#ifdef CONFIG_USB_DEBUG -#define DEBUG -#endif - -#include -#include -#include -#include -#include -#include /* for UTS_SYSNAME */ -#include /* for hcd->pdev and dma addressing */ -#include -#include - -#include -#else -#include "../miniport/usb_wrapper.h" -//#define DEBUG -#endif - -#include "hcd.h" - -// #define USB_BANDWIDTH_MESSAGES - -/*-------------------------------------------------------------------------*/ - -/* - * USB Host Controller Driver framework - * - * Plugs into usbcore (usb_bus) and lets HCDs share code, minimizing - * HCD-specific behaviors/bugs. - * - * This does error checks, tracks devices and urbs, and delegates to a - * "hc_driver" only for code (and data) that really needs to know about - * hardware differences. That includes root hub registers, i/o queues, - * and so on ... but as little else as possible. - * - * Shared code includes most of the "root hub" code (these are emulated, - * though each HC's hardware works differently) and PCI glue, plus request - * tracking overhead. The HCD code should only block on spinlocks or on - * hardware handshaking; blocking on software events (such as other kernel - * threads releasing resources, or completing actions) is all generic. - * - * Happens the USB 2.0 spec says this would be invisible inside the "USBD", - * and includes mostly a "HCDI" (HCD Interface) along with some APIs used - * only by the hub driver ... and that neither should be seen or used by - * usb client device drivers. - * - * Contributors of ideas or unattributed patches include: David Brownell, - * Roman Weissgaerber, Rory Bolt, Greg Kroah-Hartman, ... - * - * HISTORY: - * 2002-02-21 Pull in most of the usb_bus support from usb.c; some - * associated cleanup. "usb_hcd" still != "usb_bus". - * 2001-12-12 Initial patch version for Linux 2.5.1 kernel. - */ - -/*-------------------------------------------------------------------------*/ - -/* host controllers we manage */ -LIST_HEAD (usb_bus_list); -EXPORT_SYMBOL_GPL (usb_bus_list); - -/* used when allocating bus numbers */ -#define USB_MAXBUS 64 -struct usb_busmap { - unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))]; -}; -static struct usb_busmap busmap; - -/* used when updating list of hcds */ -DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */ -EXPORT_SYMBOL_GPL (usb_bus_list_lock); - -/* used when updating hcd data */ -static spinlock_t hcd_data_lock;// = SPIN_LOCK_UNLOCKED; - -/*-------------------------------------------------------------------------*/ - -/* - * Sharable chunks of root hub code. - */ - -/*-------------------------------------------------------------------------*/ - -#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff) -#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff) - -/* usb 2.0 root hub device descriptor */ -static const u8 usb2_rh_dev_descriptor [18] = { - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, 0x02, /* __u16 bcdUSB; v2.0 */ - - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - - 0x00, 0x00, /* __u16 idVendor; */ - 0x00, 0x00, /* __u16 idProduct; */ - KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ - - 0x03, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* no usb 2.0 root hub "device qualifier" descriptor: one speed only */ - -/* usb 1.1 root hub device descriptor */ -static const u8 usb11_rh_dev_descriptor [18] = { - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x10, 0x01, /* __u16 bcdUSB; v1.1 */ - - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - - 0x00, 0x00, /* __u16 idVendor; */ - 0x00, 0x00, /* __u16 idProduct; */ - KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */ - - 0x03, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - - -/*-------------------------------------------------------------------------*/ - -/* Configuration descriptors for our root hubs */ - -static const u8 fs_rh_config_descriptor [] = { - - /* one configuration */ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, 0x00, /* __u16 wTotalLength; */ - 0x01, /* __u8 bNumInterfaces; (1) */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, - 6: Self-powered, - 5 Remote-wakwup, - 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* USB 1.1: - * USB 2.0, single TT organization (mandatory): - * one interface, protocol 0 - * - * USB 2.0, multiple TT organization (optional): - * two interfaces, protocols 1 (like single TT) - * and 2 (multiple TT mode) ... config is - * sometimes settable - * NOT IMPLEMENTED - */ - - /* one interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ - 0x00, /* __u8 if_iInterface; */ - - /* one endpoint (status change endpoint) */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ - 0xff /* __u8 ep_bInterval; (255ms -- usb 2.0 spec) */ -}; - -static const u8 hs_rh_config_descriptor [] = { - - /* one configuration */ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, 0x00, /* __u16 wTotalLength; */ - 0x01, /* __u8 bNumInterfaces; (1) */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; - Bit 7: Bus-powered, - 6: Self-powered, - 5 Remote-wakwup, - 4..0: resvd */ - 0x00, /* __u8 MaxPower; */ - - /* USB 1.1: - * USB 2.0, single TT organization (mandatory): - * one interface, protocol 0 - * - * USB 2.0, multiple TT organization (optional): - * two interfaces, protocols 1 (like single TT) - * and 2 (multiple TT mode) ... config is - * sometimes settable - * NOT IMPLEMENTED - */ - - /* one interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ - 0x00, /* __u8 if_iInterface; */ - - /* one endpoint (status change endpoint) */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ - 0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ -}; - -/*-------------------------------------------------------------------------*/ - -/* - * helper routine for returning string descriptors in UTF-16LE - * input can actually be ISO-8859-1; ASCII is its 7-bit subset - */ -static int ascii2utf (char *s, u8 *utf, int utfmax) -{ - int retval; - - for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { - *utf++ = *s++; - *utf++ = 0; - } - return retval; -} - -/* - * rh_string - provides manufacturer, product and serial strings for root hub - * @id: the string ID number (1: serial number, 2: product, 3: vendor) - * @hcd: the host controller for this root hub - * @type: string describing our driver - * @data: return packet in UTF-16 LE - * @len: length of the return packet - * - * Produces either a manufacturer, product or serial number string for the - * virtual root hub device. - */ -static int rh_string ( - int id, - struct usb_hcd *hcd, - u8 *data, - int len -) { - char buf [100]; - - // language ids - if (id == 0) { - *data++ = 4; *data++ = 3; /* 4 bytes string data */ - *data++ = 0x09; *data++ = 0x04; /* MSFT-speak for "en-us" */ - return 4; - - // serial number - } else if (id == 1) { - strcpy (buf, hcd->self.bus_name); - - // product description - } else if (id == 2) { - strcpy (buf, hcd->product_desc); - - // id 3 == vendor description - } else if (id == 3) { - sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, - hcd->description); - - // unsupported IDs --> "protocol stall" - } else - return 0; - - data [0] = 2 * (strlen (buf) + 1); - data [1] = 3; /* type == string */ - return 2 + ascii2utf (buf, data + 2, len - 2); -} - - -/* Root hub control transfers execute synchronously */ -static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) -{ - struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; - u16 typeReq, wValue, wIndex, wLength; - const u8 *bufp = 0; - u8 *ubuf = urb->transfer_buffer; - int len = 0; - //unsigned long flags; - - typeReq = (cmd->bRequestType << 8) | cmd->bRequest; - wValue = le16_to_cpu (cmd->wValue); - wIndex = le16_to_cpu (cmd->wIndex); - wLength = le16_to_cpu (cmd->wLength); - - if (wLength > urb->transfer_buffer_length) - goto error; - - /* set up for success */ - urb->status = 0; - urb->actual_length = wLength; - switch (typeReq) { - - /* DEVICE REQUESTS */ - - case DeviceRequest | USB_REQ_GET_STATUS: - // DEVICE_REMOTE_WAKEUP - ubuf [0] = 1; // selfpowered - ubuf [1] = 0; - /* FALLTHROUGH */ - case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: - case DeviceOutRequest | USB_REQ_SET_FEATURE: - dev_dbg (hcd->controller, "no device features yet yet\n"); - break; - case DeviceRequest | USB_REQ_GET_CONFIGURATION: - ubuf [0] = 1; - /* FALLTHROUGH */ - case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: - break; - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - switch (wValue & 0xff00) { - case USB_DT_DEVICE << 8: - if (hcd->driver->flags & HCD_USB2) - bufp = usb2_rh_dev_descriptor; - else if (hcd->driver->flags & HCD_USB11) - bufp = usb11_rh_dev_descriptor; - else - goto error; - len = 18; - break; - case USB_DT_CONFIG << 8: - if (hcd->driver->flags & HCD_USB2) { - bufp = hs_rh_config_descriptor; - len = sizeof hs_rh_config_descriptor; - } else { - bufp = fs_rh_config_descriptor; - len = sizeof fs_rh_config_descriptor; - } - break; - case USB_DT_STRING << 8: - urb->actual_length = rh_string ( - wValue & 0xff, hcd, - ubuf, wLength); - break; - default: - goto error; - } - break; - case DeviceRequest | USB_REQ_GET_INTERFACE: - ubuf [0] = 0; - /* FALLTHROUGH */ - case DeviceOutRequest | USB_REQ_SET_INTERFACE: - break; - case DeviceOutRequest | USB_REQ_SET_ADDRESS: - // wValue == urb->dev->devaddr - dev_dbg (hcd->controller, "root hub device address %d\n", - wValue); - break; - - /* INTERFACE REQUESTS (no defined feature/status flags) */ - - /* ENDPOINT REQUESTS */ - - case EndpointRequest | USB_REQ_GET_STATUS: - // ENDPOINT_HALT flag - ubuf [0] = 0; - ubuf [1] = 0; - /* FALLTHROUGH */ - case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: - case EndpointOutRequest | USB_REQ_SET_FEATURE: - dev_dbg (hcd->controller, "no endpoint features yet\n"); - break; - - /* CLASS REQUESTS (and errors) */ - - default: - /* non-generic request */ - urb->status = hcd->driver->hub_control (hcd, - typeReq, wValue, wIndex, - ubuf, wLength); - break; -error: - /* "protocol stall" on error */ - urb->status = -EPIPE; - dev_dbg (hcd->controller, "unsupported hub control message (maxchild %d)\n", - urb->dev->maxchild); - } - if (urb->status) { - urb->actual_length = 0; - dev_dbg (hcd->controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n", - typeReq, wValue, wIndex, wLength, urb->status); - } - if (bufp) { - if (urb->transfer_buffer_length < len) - len = urb->transfer_buffer_length; - urb->actual_length = len; - // always USB_DIR_IN, toward host - memcpy (ubuf, bufp, len); - } - - /* any errors get returned through the urb completion */ - local_irq_save (flags); - usb_hcd_giveback_urb (hcd, urb, NULL); - local_irq_restore (flags); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* - * Root Hub interrupt transfers are synthesized with a timer. - * Completions are called in_interrupt() but not in_irq(). - */ - -static void rh_report_status (unsigned long ptr); - -static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb) -{ - int len = 1 + (urb->dev->maxchild / 8); - - /* rh_timer protected by hcd_data_lock */ - if (hcd->rh_timer.data - || urb->status != -EINPROGRESS - || urb->transfer_buffer_length < len) { - dev_dbg (hcd->controller, - "not queuing rh status urb, stat %d\n", - urb->status); - return -EINVAL; - } - - init_timer (&hcd->rh_timer); - - hcd->rh_timer.function = rh_report_status; - hcd->rh_timer.data = (unsigned long) urb; - /* USB 2.0 spec says 256msec; this is close enough */ - hcd->rh_timer.expires = HZ/4; - add_timer (&hcd->rh_timer); - urb->hcpriv = hcd; /* nonzero to indicate it's queued */ - return 0; -} - -/* timer callback */ - -static void rh_report_status (unsigned long ptr) -{ - struct urb *urb; - struct usb_hcd *hcd; - int length; - //unsigned long flags; - - urb = (struct urb *) ptr; - local_irq_save (flags); - spin_lock (&urb->lock); - - /* do nothing if the hc is gone or the urb's been unlinked */ - if (!urb->dev - || urb->status != -EINPROGRESS - || (hcd = urb->dev->bus->hcpriv) == 0 - || !HCD_IS_RUNNING (hcd->state)) { - spin_unlock (&urb->lock); - local_irq_restore (flags); - return; - } - - length = hcd->driver->hub_status_data (hcd, urb->transfer_buffer); - - /* complete the status urb, or retrigger the timer */ - spin_lock (&hcd_data_lock); - if (length > 0) { - hcd->rh_timer.data = 0; - urb->actual_length = length; - urb->status = 0; - urb->hcpriv = 0; - } else - mod_timer (&hcd->rh_timer, HZ/4); - spin_unlock (&hcd_data_lock); - spin_unlock (&urb->lock); - - /* local irqs are always blocked in completions */ - if (length > 0) - usb_hcd_giveback_urb (hcd, urb, NULL); - local_irq_restore (flags); -} - -/*-------------------------------------------------------------------------*/ - -static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb) -{ - if (usb_pipeint (urb->pipe)) { - int retval; - unsigned long flags; - - spin_lock_irqsave (&hcd_data_lock, flags); - retval = rh_status_urb (hcd, urb); - spin_unlock_irqrestore (&hcd_data_lock, flags); - return retval; - } - if (usb_pipecontrol (urb->pipe)) - return rh_call_control (hcd, urb); - else - return -EINVAL; -} - -/*-------------------------------------------------------------------------*/ - -void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb) -{ - //unsigned long flags; - - /* note: always a synchronous unlink */ - del_timer_sync (&hcd->rh_timer); - hcd->rh_timer.data = 0; - - local_irq_save (flags); - urb->hcpriv = 0; - usb_hcd_giveback_urb (hcd, urb, NULL); - local_irq_restore (flags); -} - -/*-------------------------------------------------------------------------*/ - -/* exported only within usbcore */ -void usb_bus_get (struct usb_bus *bus) -{ - atomic_inc (&bus->refcnt); -} - -/* exported only within usbcore */ -void usb_bus_put (struct usb_bus *bus) -{ - if (atomic_dec_and_test (&bus->refcnt)) - kfree (bus); -} - -/*-------------------------------------------------------------------------*/ - -/** - * usb_bus_init - shared initialization code - * @bus: the bus structure being initialized - * - * This code is used to initialize a usb_bus structure, memory for which is - * separately managed. - */ -void STDCALL usb_bus_init (struct usb_bus *bus) -{ - memset (&bus->devmap, 0, sizeof(struct usb_devmap)); - - bus->devnum_next = 1; - - bus->root_hub = NULL; - bus->hcpriv = NULL; - bus->busnum = -1; - bus->bandwidth_allocated = 0; - bus->bandwidth_int_reqs = 0; - bus->bandwidth_isoc_reqs = 0; - - INIT_LIST_HEAD (&bus->bus_list); - - atomic_set (&bus->refcnt, 1); -} - -/** - * usb_alloc_bus - creates a new USB host controller structure - * @op: pointer to a struct usb_operations that this bus structure should use - * Context: !in_interrupt() - * - * Creates a USB host controller bus structure with the specified - * usb_operations and initializes all the necessary internal objects. - * - * If no memory is available, NULL is returned. - * - * The caller should call usb_free_bus() when it is finished with the structure. - */ -struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *op) -{ - struct usb_bus *bus; - - bus = kmalloc (sizeof *bus, GFP_KERNEL); - if (!bus) - return NULL; - usb_bus_init (bus); - bus->op = op; - return bus; -} - -/** - * usb_free_bus - frees the memory used by a bus structure - * @bus: pointer to the bus to free - * - * To be invoked by a HCD, only as the last step of decoupling from - * hardware. It is an error to call this if the reference count is - * anything but one. That would indicate that some system component - * did not correctly shut down, and thought the hardware was still - * accessible. - */ -void STDCALL usb_free_bus (struct usb_bus *bus) -{ - if (!bus) - return; - if (atomic_read (&bus->refcnt) != 1) - err ("usb_free_bus #%d, count != 1", bus->busnum); - usb_bus_put (bus); -} - -/*-------------------------------------------------------------------------*/ - -/** - * usb_register_bus - registers the USB host controller with the usb core - * @bus: pointer to the bus to register - * Context: !in_interrupt() - * - * Assigns a bus number, and links the controller into usbcore data - * structures so that it can be seen by scanning the bus list. - */ -void STDCALL usb_register_bus(struct usb_bus *bus) -{ - int busnum; - - down (&usb_bus_list_lock); - busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1); - if (busnum < USB_MAXBUS) { - set_bit (busnum, busmap.busmap); - bus->busnum = busnum; - } else - warn ("too many buses"); - - usb_bus_get (bus); - - /* Add it to the list of buses */ - list_add (&bus->bus_list, &usb_bus_list); - up (&usb_bus_list_lock); - - usbfs_add_bus (bus); - - dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum); -} - -/** - * usb_deregister_bus - deregisters the USB host controller - * @bus: pointer to the bus to deregister - * Context: !in_interrupt() - * - * Recycles the bus number, and unlinks the controller from usbcore data - * structures so that it won't be seen by scanning the bus list. - */ -void STDCALL usb_deregister_bus (struct usb_bus *bus) -{ - dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum); - - /* - * NOTE: make sure that all the devices are removed by the - * controller code, as well as having it call this when cleaning - * itself up - */ - down (&usb_bus_list_lock); - list_del (&bus->bus_list); - up (&usb_bus_list_lock); - - usbfs_remove_bus (bus); - - clear_bit (bus->busnum, busmap.busmap); - - usb_bus_put (bus); -} - -/** - * usb_register_root_hub - called by HCD to register its root hub - * @usb_dev: the usb root hub device to be registered. - * @parent_dev: the parent device of this root hub. - * - * The USB host controller calls this function to register the root hub - * properly with the USB subsystem. It sets up the device properly in - * the driverfs tree, and then calls usb_new_device() to register the - * usb device. - */ -int STDCALL usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev) -{ - int retval; - - sprintf (&usb_dev->dev.bus_id[0], "usb%d", usb_dev->bus->busnum); - usb_dev->state = USB_STATE_DEFAULT; - retval = usb_new_device (usb_dev, parent_dev); - if (retval) - dev_err (parent_dev, "can't register root hub for %s, %d\n", - usb_dev->dev.bus_id, retval); - return retval; -} - - -/*-------------------------------------------------------------------------*/ - -/** - * usb_calc_bus_time - approximate periodic transaction time in nanoseconds - * @speed: from dev->speed; USB_SPEED_{LOW,FULL,HIGH} - * @is_input: true iff the transaction sends data to the host - * @isoc: true for isochronous transactions, false for interrupt ones - * @bytecount: how many bytes in the transaction. - * - * Returns approximate bus time in nanoseconds for a periodic transaction. - * See USB 2.0 spec section 5.11.3; only periodic transfers need to be - * scheduled in software, this function is only used for such scheduling. - */ -long STDCALL usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount) -{ - unsigned long tmp; - - switch (speed) { - case USB_SPEED_LOW: /* INTR only */ - if (is_input) { - tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } else { - tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } - case USB_SPEED_FULL: /* ISOC or INTR */ - if (isoc) { - tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); - } else { - tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L; - return (9107L + BW_HOST_DELAY + tmp); - } - case USB_SPEED_HIGH: /* ISOC or INTR */ - // FIXME adjust for input vs output - if (isoc) - tmp = HS_USECS (bytecount); - else - tmp = HS_USECS_ISO (bytecount); - return tmp; - default: - dbg ("bogus device speed!"); - return -1; - } -} - -/* - * usb_check_bandwidth(): - * - * old_alloc is from host_controller->bandwidth_allocated in microseconds; - * bustime is from calc_bus_time(), but converted to microseconds. - * - * returns if successful, - * or -ENOSPC if bandwidth request fails. - * - * FIXME: - * This initial implementation does not use Endpoint.bInterval - * in managing bandwidth allocation. - * It probably needs to be expanded to use Endpoint.bInterval. - * This can be done as a later enhancement (correction). - * - * This will also probably require some kind of - * frame allocation tracking...meaning, for example, - * that if multiple drivers request interrupts every 10 USB frames, - * they don't all have to be allocated at - * frame numbers N, N+10, N+20, etc. Some of them could be at - * N+11, N+21, N+31, etc., and others at - * N+12, N+22, N+32, etc. - * - * Similarly for isochronous transfers... - * - * Individual HCDs can schedule more directly ... this logic - * is not correct for high speed transfers. - */ -int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb) -{ - unsigned int pipe = urb->pipe; - long bustime; - int is_in = usb_pipein (pipe); - int is_iso = usb_pipeisoc (pipe); - int old_alloc = dev->bus->bandwidth_allocated; - int new_alloc; - - - bustime = NS_TO_US (usb_calc_bus_time (dev->speed, is_in, is_iso, - usb_maxpacket (dev, pipe, !is_in))); - if (is_iso) - bustime /= urb->number_of_packets; - - new_alloc = old_alloc + (int) bustime; - if (new_alloc > FRAME_TIME_MAX_USECS_ALLOC) { -#ifdef DEBUG_MODE -#ifdef DEBUG - char *mode = -#ifdef CONFIG_USB_BANDWIDTH - ""; -#else - "would have "; -#endif - dev_dbg (&dev->dev, "usb_check_bandwidth %sFAILED: %d + %ld = %d usec\n", - mode, old_alloc, bustime, new_alloc); -#endif -#endif -#ifdef CONFIG_USB_BANDWIDTH - bustime = -ENOSPC; /* report error */ -#endif - } - - return bustime; -} - - -/** - * usb_claim_bandwidth - records bandwidth for a periodic transfer - * @dev: source/target of request - * @urb: request (urb->dev == dev) - * @bustime: bandwidth consumed, in (average) microseconds per frame - * @isoc: true iff the request is isochronous - * - * Bus bandwidth reservations are recorded purely for diagnostic purposes. - * HCDs are expected not to overcommit periodic bandwidth, and to record such - * reservations whenever endpoints are added to the periodic schedule. - * - * FIXME averaging per-frame is suboptimal. Better to sum over the HCD's - * entire periodic schedule ... 32 frames for OHCI, 1024 for UHCI, settable - * for EHCI (256/512/1024 frames, default 1024) and have the bus expose how - * large its periodic schedule is. - */ -void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc) -{ - dev->bus->bandwidth_allocated += bustime; - if (isoc) - dev->bus->bandwidth_isoc_reqs++; - else - dev->bus->bandwidth_int_reqs++; - urb->bandwidth = bustime; - -#ifdef USB_BANDWIDTH_MESSAGES - dev_dbg (&dev->dev, "bandwidth alloc increased by %d (%s) to %d for %d requesters\n", - bustime, - isoc ? "ISOC" : "INTR", - dev->bus->bandwidth_allocated, - dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); -#endif -} - - -/** - * usb_release_bandwidth - reverses effect of usb_claim_bandwidth() - * @dev: source/target of request - * @urb: request (urb->dev == dev) - * @isoc: true iff the request is isochronous - * - * This records that previously allocated bandwidth has been released. - * Bandwidth is released when endpoints are removed from the host controller's - * periodic schedule. - */ -void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb, int isoc) -{ - dev->bus->bandwidth_allocated -= urb->bandwidth; - if (isoc) - dev->bus->bandwidth_isoc_reqs--; - else - dev->bus->bandwidth_int_reqs--; - -#ifdef USB_BANDWIDTH_MESSAGES - dev_dbg (&dev->dev, "bandwidth alloc reduced by %d (%s) to %d for %d requesters\n", - urb->bandwidth, - isoc ? "ISOC" : "INTR", - dev->bus->bandwidth_allocated, - dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); -#endif - urb->bandwidth = 0; -} - - -/*-------------------------------------------------------------------------*/ - -/* - * Generic HC operations. - */ - -/*-------------------------------------------------------------------------*/ - -/* called from khubd, or root hub init threads for hcd-private init */ -static int hcd_alloc_dev (struct usb_device *udev) -{ - struct hcd_dev *dev; - struct usb_hcd *hcd; - unsigned long flags; - - if (!udev || udev->hcpriv) - return -EINVAL; - if (!udev->bus || !udev->bus->hcpriv) - return -ENODEV; - hcd = udev->bus->hcpriv; - if (hcd->state == USB_STATE_QUIESCING) - return -ENOLINK; - - dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; - memset (dev, 0, sizeof *dev); - - INIT_LIST_HEAD (&dev->dev_list); - INIT_LIST_HEAD (&dev->urb_list); - - spin_lock_irqsave (&hcd_data_lock, flags); - list_add (&dev->dev_list, &hcd->dev_list); - // refcount is implicit - udev->hcpriv = dev; - spin_unlock_irqrestore (&hcd_data_lock, flags); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static void urb_unlink (struct urb *urb) -{ - unsigned long flags; - struct usb_device *dev; - - /* Release any periodic transfer bandwidth */ - if (urb->bandwidth) - usb_release_bandwidth (urb->dev, urb, - usb_pipeisoc (urb->pipe)); - - /* clear all state linking urb to this dev (and hcd) */ - - spin_lock_irqsave (&hcd_data_lock, flags); - list_del_init (&urb->urb_list); - dev = urb->dev; - spin_unlock_irqrestore (&hcd_data_lock, flags); - usb_put_dev (dev); -} - - -/* may be called in any context with a valid urb->dev usecount - * caller surrenders "ownership" of urb - * expects usb_submit_urb() to have sanity checked and conditioned all - * inputs in the urb - */ -static int hcd_submit_urb (struct urb *urb, int mem_flags) -{ - int status; - struct usb_hcd *hcd = urb->dev->bus->hcpriv; - struct hcd_dev *dev = urb->dev->hcpriv; - unsigned long flags; - - - if (!hcd || !dev) - return -ENODEV; - //printk("submit_urb %p, # %i, t %i\n",urb,urb->dev->devnum,usb_pipetype(urb->pipe)); - /* - * FIXME: make urb timeouts be generic, keeping the HCD cores - * as simple as possible. - */ - - // NOTE: a generic device/urb monitoring hook would go here. - // hcd_monitor_hook(MONITOR_URB_SUBMIT, urb) - // It would catch submission paths for all urbs. - - /* - * Atomically queue the urb, first to our records, then to the HCD. - * Access to urb->status is controlled by urb->lock ... changes on - * i/o completion (normal or fault) or unlinking. - */ - - // FIXME: verify that quiescing hc works right (RH cleans up) - - spin_lock_irqsave (&hcd_data_lock, flags); - if (HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_QUIESCING) { - usb_get_dev (urb->dev); - list_add_tail (&urb->urb_list, &dev->urb_list); - status = 0; - } else { - INIT_LIST_HEAD (&urb->urb_list); - status = -ESHUTDOWN; - } - spin_unlock_irqrestore (&hcd_data_lock, flags); - if (status) - return status; - - /* increment urb's reference count as part of giving it to the HCD - * (which now controls it). HCD guarantees that it either returns - * an error or calls giveback(), but not both. - */ - - urb = usb_get_urb (urb); - if (urb->dev == hcd->self.root_hub) { - /* NOTE: requirement on hub callers (usbfs and the hub - * driver, for now) that URBs' urb->transfer_buffer be - * valid and usb_buffer_{sync,unmap}() not be needed, since - * they could clobber root hub response data. - */ - urb->transfer_flags |= URB_NO_DMA_MAP; - status = rh_urb_enqueue (hcd, urb); - goto done; - } - - /* lower level hcd code should use *_dma exclusively, - * unless it uses pio or talks to another transport. - */ - if (!(urb->transfer_flags & URB_NO_DMA_MAP) - && hcd->controller->dma_mask) { - if (usb_pipecontrol (urb->pipe)) - urb->setup_dma = dma_map_single ( - hcd->controller, - urb->setup_packet, - sizeof (struct usb_ctrlrequest), - DMA_TO_DEVICE); - if (urb->transfer_buffer_length != 0) - urb->transfer_dma = dma_map_single ( - hcd->controller, - urb->transfer_buffer, - urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? DMA_FROM_DEVICE - : DMA_TO_DEVICE); - } - - status = hcd->driver->urb_enqueue (hcd, urb, mem_flags); -done: - - if (status) { - usb_put_urb (urb); - urb_unlink (urb); - } - - return status; -} - -/*-------------------------------------------------------------------------*/ - -/* called in any context */ -static int hcd_get_frame_number (struct usb_device *udev) -{ - struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv; - return hcd->driver->get_frame_number (hcd); -} - -/*-------------------------------------------------------------------------*/ - -/* this makes the hcd giveback() the urb more quickly, by kicking it - * off hardware queues (which may take a while) and returning it as - * soon as practical. we've already set up the urb's return status, - * but we can't know if the callback completed already. - */ -static void -unlink1 (struct usb_hcd *hcd, struct urb *urb) -{ - if (urb == (struct urb *) hcd->rh_timer.data) - usb_rh_status_dequeue (hcd, urb); - else { - int value; - - /* failures "should" be harmless */ - value = hcd->driver->urb_dequeue (hcd, urb); - if (value != 0) - dev_dbg (hcd->controller, - "dequeue %p --> %d\n", - urb, value); - } -} - -struct completion_splice { // modified urb context: - /* did we complete? */ - struct completion done; - - /* original urb data */ - usb_complete_t complete; - void *context; -}; - -static void unlink_complete (struct urb *urb, struct pt_regs *regs) -{ - struct completion_splice *splice; - - splice = (struct completion_splice *) urb->context; - - /* issue original completion call */ - urb->complete = splice->complete; - urb->context = splice->context; - urb->complete (urb, regs); - - /* then let the synchronous unlink call complete */ - complete (&splice->done); -} - -/* - * called in any context; note ASYNC_UNLINK restrictions - * - * caller guarantees urb won't be recycled till both unlink() - * and the urb's completion function return - */ -static int hcd_unlink_urb (struct urb *urb) -{ - struct hcd_dev *dev; - struct usb_hcd *hcd = 0; - struct device *sys = 0; - unsigned long flags; - struct completion_splice splice; - int retval; - - if (!urb) - return -EINVAL; - - /* - * we contend for urb->status with the hcd core, - * which changes it while returning the urb. - * - * Caller guaranteed that the urb pointer hasn't been freed, and - * that it was submitted. But as a rule it can't know whether or - * not it's already been unlinked ... so we respect the reversed - * lock sequence needed for the usb_hcd_giveback_urb() code paths - * (urb lock, then hcd_data_lock) in case some other CPU is now - * unlinking it. - */ - spin_lock_irqsave (&urb->lock, flags); - spin_lock (&hcd_data_lock); - - if (!urb->dev || !urb->dev->bus) { - retval = -ENODEV; - goto done; - } - - dev = urb->dev->hcpriv; - sys = &urb->dev->dev; - hcd = urb->dev->bus->hcpriv; - if (!dev || !hcd) { - retval = -ENODEV; - goto done; - } - - if (!urb->hcpriv) { - retval = -EINVAL; - goto done; - } - - /* Any status except -EINPROGRESS means something already started to - * unlink this URB from the hardware. So there's no more work to do. - * - * FIXME use better explicit urb state - */ - if (urb->status != -EINPROGRESS) { - retval = -EBUSY; - goto done; - } - - /* maybe set up to block until the urb's completion fires. the - * lower level hcd code is always async, locking on urb->status - * updates; an intercepted completion unblocks us. - */ - if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { - if (in_interrupt ()) { - dev_dbg (hcd->controller, "non-async unlink in_interrupt"); - retval = -EWOULDBLOCK; - goto done; - } - /* synchronous unlink: block till we see the completion */ - init_completion (&splice.done); - splice.complete = urb->complete; - splice.context = urb->context; - urb->complete = unlink_complete; - urb->context = &splice; - urb->status = -ENOENT; - } else { - /* asynchronous unlink */ - urb->status = -ECONNRESET; - } - spin_unlock (&hcd_data_lock); - spin_unlock_irqrestore (&urb->lock, flags); - - // FIXME remove splicing, so this becomes unlink1 (hcd, urb); - if (urb == (struct urb *) hcd->rh_timer.data) { - usb_rh_status_dequeue (hcd, urb); - retval = 0; - } else { - retval = hcd->driver->urb_dequeue (hcd, urb); - - /* hcds shouldn't really fail these calls, but... */ - if (retval) { - dev_dbg (sys, "dequeue %p --> %d\n", urb, retval); - if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { - spin_lock_irqsave (&urb->lock, flags); - urb->complete = splice.complete; - urb->context = splice.context; - spin_unlock_irqrestore (&urb->lock, flags); - } - goto bye; - } - } - - /* block till giveback, if needed */ - if (urb->transfer_flags & URB_ASYNC_UNLINK) - return -EINPROGRESS; - - wait_for_completion (&splice.done); - return 0; - -done: - spin_unlock (&hcd_data_lock); - spin_unlock_irqrestore (&urb->lock, flags); -bye: - if (retval && sys && sys->driver) - dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); - return retval; -} - -/*-------------------------------------------------------------------------*/ - -/* disables the endpoint: cancels any pending urbs, then synchronizes with - * the hcd to make sure all endpoint state is gone from hardware. use for - * set_configuration, set_interface, driver removal, physical disconnect. - * - * example: a qh stored in hcd_dev.ep[], holding state related to endpoint - * type, maxpacket size, toggle, halt status, and scheduling. - */ -static void hcd_endpoint_disable (struct usb_device *udev, int endpoint) -{ - unsigned long flags; - struct hcd_dev *dev; - struct usb_hcd *hcd; - struct urb *urb; - unsigned epnum = endpoint & USB_ENDPOINT_NUMBER_MASK; - - dev = udev->hcpriv; - hcd = udev->bus->hcpriv; - -rescan: - /* (re)block new requests, as best we can */ - if (endpoint & USB_DIR_IN) { - usb_endpoint_halt (udev, epnum, 0); - udev->epmaxpacketin [epnum] = 0; - } else { - usb_endpoint_halt (udev, epnum, 1); - udev->epmaxpacketout [epnum] = 0; - } - - /* then kill any current requests */ - spin_lock_irqsave (&hcd_data_lock, flags); - list_for_each_entry (urb, &dev->urb_list, urb_list) { - int tmp = urb->pipe; - - /* ignore urbs for other endpoints */ - if (usb_pipeendpoint (tmp) != epnum) - continue; - if ((tmp ^ endpoint) & USB_DIR_IN) - continue; - - /* another cpu may be in hcd, spinning on hcd_data_lock - * to giveback() this urb. the races here should be - * small, but a full fix needs a new "can't submit" - * urb state. - */ - if (urb->status != -EINPROGRESS) - continue; - usb_get_urb (urb); - spin_unlock_irqrestore (&hcd_data_lock, flags); - - spin_lock_irqsave (&urb->lock, flags); - tmp = urb->status; - if (tmp == -EINPROGRESS) - urb->status = -ESHUTDOWN; - spin_unlock_irqrestore (&urb->lock, flags); - - /* kick hcd unless it's already returning this */ - if (tmp == -EINPROGRESS) { - tmp = urb->pipe; - unlink1 (hcd, urb); - dev_dbg (hcd->controller, - "shutdown urb %p pipe %08x ep%d%s%s\n", - urb, tmp, usb_pipeendpoint (tmp), - (tmp & USB_DIR_IN) ? "in" : "out", - ({ char *s; \ - switch (usb_pipetype (tmp)) { \ - case PIPE_CONTROL: s = ""; break; \ - case PIPE_BULK: s = "-bulk"; break; \ - case PIPE_INTERRUPT: s = "-intr"; break; \ - default: s = "-iso"; break; \ - }; s;})); - } - usb_put_urb (urb); - - /* list contents may have changed */ - goto rescan; - } - spin_unlock_irqrestore (&hcd_data_lock, flags); - - /* synchronize with the hardware, so old configuration state - * clears out immediately (and will be freed). - */ - might_sleep (); - if (hcd->driver->endpoint_disable) - hcd->driver->endpoint_disable (hcd, dev, endpoint); -} - -/*-------------------------------------------------------------------------*/ - -/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup. - * we're guaranteed that the device is fully quiesced. also, that each - * endpoint has been hcd_endpoint_disabled. - */ - -static int hcd_free_dev (struct usb_device *udev) -{ - struct hcd_dev *dev; - struct usb_hcd *hcd; - unsigned long flags; - - if (!udev || !udev->hcpriv) - return -EINVAL; - - if (!udev->bus || !udev->bus->hcpriv) - return -ENODEV; - - // should udev->devnum == -1 ?? - - dev = udev->hcpriv; - hcd = udev->bus->hcpriv; - - /* device driver problem with refcounts? */ - if (!list_empty (&dev->urb_list)) { - dev_dbg (hcd->controller, "free busy dev, %s devnum %d (bug!)\n", - hcd->self.bus_name, udev->devnum); - return -EINVAL; - } - - spin_lock_irqsave (&hcd_data_lock, flags); - list_del (&dev->dev_list); - udev->hcpriv = NULL; - spin_unlock_irqrestore (&hcd_data_lock, flags); - - kfree (dev); - return 0; -} - -/* - * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue) - * - * When registering a USB bus through the HCD framework code, use this - * usb_operations vector. The PCI glue layer does so automatically; only - * bus glue for non-PCI system busses will need to use this. - */ -struct usb_operations usb_hcd_operations = { - .allocate = hcd_alloc_dev, - .get_frame_number = hcd_get_frame_number, - .submit_urb = hcd_submit_urb, - .unlink_urb = hcd_unlink_urb, - .deallocate = hcd_free_dev, - .buffer_alloc = hcd_buffer_alloc, - .buffer_free = hcd_buffer_free, - .disable = hcd_endpoint_disable, -}; -EXPORT_SYMBOL (usb_hcd_operations); - -/*-------------------------------------------------------------------------*/ - -/** - * usb_hcd_giveback_urb - return URB from HCD to device driver - * @hcd: host controller returning the URB - * @urb: urb being returned to the USB device driver. - * @regs: pt_regs, passed down to the URB completion handler - * Context: in_interrupt() - * - * This hands the URB from HCD to its USB device driver, using its - * completion function. The HCD has freed all per-urb resources - * (and is done using urb->hcpriv). It also released all HCD locks; - * the device driver won't cause problems if it frees, modifies, - * or resubmits this URB. - */ -void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) -{ - urb_unlink (urb); - - // NOTE: a generic device/urb monitoring hook would go here. - // hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev) - // It would catch exit/unlink paths for all urbs. - - /* lower level hcd code should use *_dma exclusively */ - if (!(urb->transfer_flags & URB_NO_DMA_MAP)) { - if (usb_pipecontrol (urb->pipe)) - pci_unmap_single (hcd->pdev, urb->setup_dma, - sizeof (struct usb_ctrlrequest), - PCI_DMA_TODEVICE); - if (urb->transfer_buffer_length != 0) - pci_unmap_single (hcd->pdev, urb->transfer_dma, - urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? PCI_DMA_FROMDEVICE - : PCI_DMA_TODEVICE); - } - - /* pass ownership to the completion handler */ - urb->complete (urb, regs); - usb_put_urb (urb); -} - -/*-------------------------------------------------------------------------*/ - -/** - * usb_hcd_irq - hook IRQs to HCD framework (bus glue) - * @irq: the IRQ being raised - * @__hcd: pointer to the HCD whose IRQ is beinng signaled - * @r: saved hardware registers - * - * When registering a USB bus through the HCD framework code, use this - * to handle interrupts. The PCI glue layer does so automatically; only - * bus glue for non-PCI system busses will need to use this. - */ -irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) -{ - struct usb_hcd *hcd = __hcd; - int start = hcd->state; - - if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */ - return IRQ_NONE; - - hcd->driver->irq (hcd, r); - if (hcd->state != start && hcd->state == USB_STATE_HALT) - usb_hc_died (hcd); - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -static void hcd_panic (void *_hcd) -{ - struct usb_hcd *hcd = _hcd; - hcd->driver->stop (hcd); -} - -/** - * usb_hc_died - report abnormal shutdown of a host controller (bus glue) - * @hcd: pointer to the HCD representing the controller - * - * This is called by bus glue to report a USB host controller that died - * while operations may still have been pending. It's called automatically - * by the PCI glue, so only glue for non-PCI busses should need to call it. - */ -void STDCALL usb_hc_died (struct usb_hcd *hcd) -{ - struct list_head *devlist, *urblist; - struct hcd_dev *dev; - struct urb *urb; - unsigned long flags; - - /* flag every pending urb as done */ - spin_lock_irqsave (&hcd_data_lock, flags); - list_for_each (devlist, &hcd->dev_list) { - dev = list_entry (devlist, struct hcd_dev, dev_list); - list_for_each (urblist, &dev->urb_list) { - urb = list_entry (urblist, struct urb, urb_list); - dev_dbg (hcd->controller, "shutdown %s urb %p pipe %x, current status %d\n", - hcd->self.bus_name, urb, urb->pipe, urb->status); - if (urb->status == -EINPROGRESS) - urb->status = -ESHUTDOWN; - } - } - urb = (struct urb *) hcd->rh_timer.data; - if (urb) - urb->status = -ESHUTDOWN; - spin_unlock_irqrestore (&hcd_data_lock, flags); - - /* hcd->stop() needs a task context */ - INIT_WORK (&hcd->work, hcd_panic, hcd); - (void) schedule_work (&hcd->work); -} - diff --git a/reactos/drivers/usb/usbport/hcd.h b/reactos/drivers/usb/usbport/hcd.h deleted file mode 100644 index 593ef5d3755..00000000000 --- a/reactos/drivers/usb/usbport/hcd.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#ifdef __KERNEL__ - -/* This file contains declarations of usbcore internals that are mostly - * used or exposed by Host Controller Drivers. - */ - -/* - * USB Packet IDs (PIDs) - */ -#define USB_PID_UNDEF_0 0xf0 -#define USB_PID_OUT 0xe1 -#define USB_PID_ACK 0xd2 -#define USB_PID_DATA0 0xc3 -#define USB_PID_PING 0xb4 /* USB 2.0 */ -#define USB_PID_SOF 0xa5 -#define USB_PID_NYET 0x96 /* USB 2.0 */ -#define USB_PID_DATA2 0x87 /* USB 2.0 */ -#define USB_PID_SPLIT 0x78 /* USB 2.0 */ -#define USB_PID_IN 0x69 -#define USB_PID_NAK 0x5a -#define USB_PID_DATA1 0x4b -#define USB_PID_PREAMBLE 0x3c /* Token mode */ -#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ -#define USB_PID_SETUP 0x2d -#define USB_PID_STALL 0x1e -#define USB_PID_MDATA 0x0f /* USB 2.0 */ - -/*-------------------------------------------------------------------------*/ - -/* - * USB Host Controller Driver (usb_hcd) framework - * - * Since "struct usb_bus" is so thin, you can't share much code in it. - * This framework is a layer over that, and should be more sharable. - */ - -/*-------------------------------------------------------------------------*/ - -struct usb_hcd { /* usb_bus.hcpriv points to this */ - - /* - * housekeeping - */ - struct usb_bus self; /* hcd is-a bus */ - - const char *product_desc; /* product/vendor string */ - const char *description; /* "ehci-hcd" etc */ - - struct timer_list rh_timer; /* drives root hub */ - struct list_head dev_list; /* devices on this bus */ - struct work_struct work; - - /* - * hardware info/state - */ - struct hc_driver *driver; /* hw-specific hooks */ - int irq; /* irq allocated */ - void *regs; /* device memory/io */ - struct device *controller; /* handle to hardware */ - - /* a few non-PCI controllers exist, mostly for OHCI */ - struct pci_dev *pdev; /* pci is typical */ -#ifdef CONFIG_PCI - int region; /* pci region for regs */ - u32 pci_state [16]; /* for PM state save */ - atomic_t resume_count; /* multiple resumes issue */ -#endif - -#define HCD_BUFFER_POOLS 4 - struct pci_pool *pool [HCD_BUFFER_POOLS]; - - int state; -# define __ACTIVE 0x01 -# define __SLEEPY 0x02 -# define __SUSPEND 0x04 -# define __TRANSIENT 0x80 - -# define USB_STATE_HALT 0 -# define USB_STATE_RUNNING (__ACTIVE) -# define USB_STATE_READY (__ACTIVE|__SLEEPY) -# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) -# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT) -# define USB_STATE_SUSPENDED (__SUSPEND) - -#define HCD_IS_RUNNING(state) ((state) & __ACTIVE) -#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND) - - /* more shared queuing code would be good; it should support - * smarter scheduling, handle transaction translators, etc; - * input size of periodic table to an interrupt scheduler. - * (ohci 32, uhci 1024, ehci 256/512/1024). - */ -}; - -/* 2.4 does this a bit differently ... */ -static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) -{ - return &hcd->self; -} - - -struct hcd_dev { /* usb_device.hcpriv points to this */ - struct list_head dev_list; /* on this hcd */ - struct list_head urb_list; /* pending on this dev */ - - /* per-configuration HC/HCD state, such as QH or ED */ - void *ep[32]; -}; - -// urb.hcpriv is really hardware-specific - -struct hcd_timeout { /* timeouts we allocate */ - struct list_head timeout_list; - struct timer_list timer; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * FIXME usb_operations should vanish or become hc_driver, - * when usb_bus and usb_hcd become the same thing. - */ - -struct usb_operations { - int (*allocate)(struct usb_device *); - int (*deallocate)(struct usb_device *); - int (*get_frame_number) (struct usb_device *usb_dev); - int (*submit_urb) (struct urb *urb, int mem_flags); - int (*unlink_urb) (struct urb *urb); - - /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */ - void *(*buffer_alloc)(struct usb_bus *bus, size_t size, - int mem_flags, - dma_addr_t *dma); - void (*buffer_free)(struct usb_bus *bus, size_t size, - void *addr, dma_addr_t dma); - - void (*disable)(struct usb_device *udev, int bEndpointAddress); -}; - -/* each driver provides one of these, and hardware init support */ - -struct pt_regs; - -// new struct from 2.6 -struct hc_driver { - const char *description; /* "ehci-hcd" etc */ - - /* irq handler */ - irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs); - - int flags; -#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ -#define HCD_USB11 0x0010 /* USB 1.1 */ -#define HCD_USB2 0x0020 /* USB 2.0 */ - - /* called to init HCD and root hub */ - int (*reset) (struct usb_hcd *hcd); - int (*start) (struct usb_hcd *hcd); - - /* called after all devices were suspended */ - int (*suspend) (struct usb_hcd *hcd, u32 state); - - /* called before any devices get resumed */ - int (*resume) (struct usb_hcd *hcd); - - /* cleanly make HCD stop writing memory and doing I/O */ - void (*stop) (struct usb_hcd *hcd); - - /* return current frame number */ - int (*get_frame_number) (struct usb_hcd *hcd); - - /* memory lifecycle */ - struct usb_hcd *(*hcd_alloc) (void); - void (*hcd_free) (struct usb_hcd *hcd); - - /* manage i/o requests, device state */ - int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb, - int mem_flags); - int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); - - /* hw synch, freeing endpoint resources that urb_dequeue can't */ - void (*endpoint_disable)(struct usb_hcd *hcd, - struct hcd_dev *dev, int bEndpointAddress); - - /* root hub support */ - int (*hub_status_data) (struct usb_hcd *hcd, char *buf); - int (*hub_control) (struct usb_hcd *hcd, - u16 typeReq, u16 wValue, u16 wIndex, - u8 *buf, u16 wLength); -}; - -// old version, "just in case" -#if 0 -struct hc_driver { - const char *description; /* "ehci-hcd" etc */ - - /* irq handler */ - int (*irq) (struct usb_hcd *hcd, struct pt_regs *regs); - - int flags; -#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ -#define HCD_USB11 0x0010 /* USB 1.1 */ -#define HCD_USB2 0x0020 /* USB 2.0 */ - - /* called to init HCD and root hub */ - int (*start) (struct usb_hcd *hcd); - - /* called after all devices were suspended */ - int (*suspend) (struct usb_hcd *hcd, u32 state); - - /* called before any devices get resumed */ - int (*resume) (struct usb_hcd *hcd); - - /* cleanly make HCD stop writing memory and doing I/O */ - void (*stop) (struct usb_hcd *hcd); - - /* return current frame number */ - int (*get_frame_number) (struct usb_hcd *hcd); - - /* memory lifecycle */ - struct usb_hcd *(*hcd_alloc) (void); - void (*hcd_free) (struct usb_hcd *hcd); - - /* manage i/o requests, device state */ - int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb, - int mem_flags); - int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); - - /* hw synch, freeing endpoint resources that urb_dequeue can't */ - void (*endpoint_disable)(struct usb_hcd *hcd, - struct hcd_dev *dev, int bEndpointAddress); - - /* root hub support */ - int (*hub_status_data) (struct usb_hcd *hcd, char *buf); - int (*hub_control) (struct usb_hcd *hcd, - u16 typeReq, u16 wValue, u16 wIndex, - char *buf, u16 wLength); -}; -#endif - -extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); -extern void STDCALL usb_bus_init (struct usb_bus *bus); -extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb); - -#ifdef CONFIG_PCI -struct pci_dev; -struct pci_device_id; -extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev, - const struct pci_device_id *id); -extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev); - -#ifdef CONFIG_PM -// FIXME: see Documentation/power/pci.txt (2.4.6 and later?) -// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state); -extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state); -extern int usb_hcd_pci_resume (struct pci_dev *dev); -// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg); -#endif /* CONFIG_PM */ - -#endif /* CONFIG_PCI */ - -/* pci-ish (pdev null is ok) buffer alloc/mapping support */ -int hcd_buffer_create (struct usb_hcd *hcd); -void hcd_buffer_destroy (struct usb_hcd *hcd); - -void *hcd_buffer_alloc (struct usb_bus *bus, size_t size, - int mem_flags, dma_addr_t *dma); -void hcd_buffer_free (struct usb_bus *bus, size_t size, - void *addr, dma_addr_t dma); - -/* generic bus glue, needed for host controllers that don't use PCI */ -extern struct usb_operations usb_hcd_operations; -extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); -extern void STDCALL usb_hc_died (struct usb_hcd *hcd); - -/* -------------------------------------------------------------------------- */ - -/* Enumeration is only for the hub driver, or HCD virtual root hubs */ -extern int usb_new_device(struct usb_device *dev, struct device *parent); -extern void STDCALL usb_connect(struct usb_device *dev); -extern void usb_disconnect(struct usb_device **); - -/* exported to hub driver ONLY to support usb_reset_device () */ -extern int usb_get_configuration(struct usb_device *dev); -extern void usb_set_maxpacket(struct usb_device *dev); -extern void usb_destroy_configuration(struct usb_device *dev); -extern int usb_set_address(struct usb_device *dev); - -/* use these only before the device's address has been set */ -#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30)) -#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN) - -/*-------------------------------------------------------------------------*/ - -/* - * HCD Root Hub support - */ - -#include "hub.h" - -/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ -#define DeviceRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) -#define DeviceOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) - -#define InterfaceRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) - -#define EndpointRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -#define EndpointOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) - -/* table 9.6 standard features */ -#define DEVICE_REMOTE_WAKEUP 1 -#define ENDPOINT_HALT 0 - -/* class requests from the USB 2.0 hub spec, table 11-15 */ -/* GetBusState and SetHubDescriptor are optional, omitted */ -#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) -#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) -#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) -#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) -#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) -#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) -#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) - - -/*-------------------------------------------------------------------------*/ - -/* - * Generic bandwidth allocation constants/support - */ -#define FRAME_TIME_USECS 1000L -#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ - /* Trying not to use worst-case bit-stuffing - of (7/6 * 8 * bytecount) = 9.33 * bytecount */ - /* bytecount = data payload byte count */ - -#define NS_TO_US(ns) ((ns + 500L) / 1000L) - /* convert & round nanoseconds to microseconds */ - -extern void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, - int bustime, int isoc); -extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb, - int isoc); - -/* - * Full/low speed bandwidth allocation constants/support. - */ -#define BW_HOST_DELAY 1000L /* nanoseconds */ -#define BW_HUB_LS_SETUP 333L /* nanoseconds */ - /* 4 full-speed bit times (est.) */ - -#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ -#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) -#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) - -extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb); - -/* - * Ceiling microseconds (typical) for that many bytes at high speed - * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed - * to preallocate bandwidth) - */ -#define USB2_HOST_DELAY 5 /* nsec, guess */ -#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ - + ((2083UL * (3167 + BitTime (bytes)))/1000) \ - + USB2_HOST_DELAY) -#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \ - + ((2083UL * (3167 + BitTime (bytes)))/1000) \ - + USB2_HOST_DELAY) - -extern long STDCALL usb_calc_bus_time (int speed, int is_input, - int isoc, int bytecount); - -/*-------------------------------------------------------------------------*/ - -extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *); -extern void STDCALL usb_free_bus (struct usb_bus *); - -extern void STDCALL usb_register_bus (struct usb_bus *); -extern void STDCALL usb_deregister_bus (struct usb_bus *); - -extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev, - struct device *parent_dev); - -/* for portability to 2.4, hcds should call this */ -static inline int hcd_register_root (struct usb_hcd *hcd) -{ - return usb_register_root_hub ( - hcd_to_bus (hcd)->root_hub, hcd->controller); -} - -/*-------------------------------------------------------------------------*/ - -/* exported only within usbcore */ - -extern struct list_head usb_bus_list; -extern struct semaphore usb_bus_list_lock; - -extern void usb_bus_get (struct usb_bus *bus); -extern void usb_bus_put (struct usb_bus *bus); - -extern int usb_find_interface_driver (struct usb_device *dev, - struct usb_interface *interface); - -#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) - -#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) - -/* - * USB device fs stuff - */ - -#ifdef CONFIG_USB_DEVICEFS - -/* - * these are expected to be called from the USB core/hub thread - * with the kernel lock held - */ -extern void usbfs_add_bus(struct usb_bus *bus); -extern void usbfs_remove_bus(struct usb_bus *bus); -extern void usbfs_add_device(struct usb_device *dev); -extern void usbfs_remove_device(struct usb_device *dev); -extern void usbfs_update_special (void); - -extern int usbfs_init(void); -extern void usbfs_cleanup(void); - -#else /* CONFIG_USB_DEVICEFS */ - -static inline void usbfs_add_bus(struct usb_bus *bus) {} -static inline void usbfs_remove_bus(struct usb_bus *bus) {} -static inline void usbfs_add_device(struct usb_device *dev) -{ - if (dev->parent) - { - PDEVICE_OBJECT Pdo = (PDEVICE_OBJECT)dev->parent->dev.dev_ext; - if (Pdo) - IoInvalidateDeviceRelations(Pdo, BusRelations); - else - DPRINT1("Pdo == NULL, not sending IoInvalidateDeviceRelations()!"); - } -} -static inline void usbfs_remove_device(struct usb_device *dev) {} -static inline void usbfs_update_special (void) {} - -static inline int usbfs_init(void) { return 0; } -static inline void usbfs_cleanup(void) { } - -#endif /* CONFIG_USB_DEVICEFS */ - -/*-------------------------------------------------------------------------*/ - -/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ -// bleech -- resurfaced in 2.4.11 or 2.4.12 -#define bitmap DeviceRemovable - - -/*-------------------------------------------------------------------------*/ - -/* random stuff */ - -#define RUN_CONTEXT (in_irq () ? "in_irq" \ - : (in_interrupt () ? "in_interrupt" : "can sleep")) - - -#endif /* __KERNEL__ */ - diff --git a/reactos/drivers/usb/usbport/hub.c b/reactos/drivers/usb/usbport/hub.c deleted file mode 100644 index 05a3903eb62..00000000000 --- a/reactos/drivers/usb/usbport/hub.c +++ /dev/null @@ -1,1494 +0,0 @@ -/* - * USB hub driver. - * - * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999 Johannes Erdfelt - * (C) Copyright 1999 Gregory P. Smith - * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au) - * - */ -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif -#include -#include -#include - -#include -#include -#include - -#include "hcd.h" -#include "hub.h" - -#else - -#include "../miniport/usb_wrapper.h" -#include "hcd.h" -#include "hub.h" - -#endif - -/* Wakes up khubd */ -static spinlock_t hub_event_lock; -//static DECLARE_MUTEX(usb_address0_sem); - -static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */ -static LIST_HEAD(hub_list); /* List of all hubs (for cleanup) */ - -static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); -static pid_t khubd_pid = 0; /* PID of khubd */ -static DECLARE_COMPLETION(khubd_exited); - -#ifdef DEBUG -static inline char *portspeed (int portstatus) -{ - if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) - return "480 Mb/s"; - else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) - return "1.5 Mb/s"; - else - return "12 Mb/s"; -} -#endif - -/* for dev_info, dev_dbg, etc */ -static inline struct device *hubdev (struct usb_device *dev) -{ - return &dev->actconfig->interface [0].dev; -} - -/* USB 2.0 spec Section 11.24.4.5 */ -static int get_hub_descriptor(struct usb_device *dev, void *data, int size) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - USB_DT_HUB << 8, 0, data, size, HZ * USB_CTRL_GET_TIMEOUT); -} - -/* - * USB 2.0 spec Section 11.24.2.1 - */ -static int clear_hub_feature(struct usb_device *dev, int feature) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ); -} - -/* - * USB 2.0 spec Section 11.24.2.2 - * BUG: doesn't handle port indicator selector in high byte of wIndex - */ -static int clear_port_feature(struct usb_device *dev, int port, int feature) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ); -} - -/* - * USB 2.0 spec Section 11.24.2.13 - * BUG: doesn't handle port indicator selector in high byte of wIndex - */ -static int set_port_feature(struct usb_device *dev, int port, int feature) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ); -} - -/* - * USB 2.0 spec Section 11.24.2.6 - */ -static int get_hub_status(struct usb_device *dev, - struct usb_hub_status *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, - data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); -} - -/* - * USB 2.0 spec Section 11.24.2.7 - */ -static int get_port_status(struct usb_device *dev, int port, - struct usb_port_status *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, - data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT); -} - -/* completion function, fires on port status changes and various faults */ -static void hub_irq(struct urb *urb, struct pt_regs *regs) -{ - struct usb_hub *hub = (struct usb_hub *)urb->context; - unsigned long flags; - int status; - - switch (urb->status) { - case -ENOENT: /* synchronous unlink */ - case -ECONNRESET: /* async unlink */ - case -ESHUTDOWN: /* hardware going away */ - return; - case -EOVERFLOW: - if (hub->RestCounter>0) { - // we already resetted one time ... - hub->error = 0; - hub->nerrors = 0; - break; - } - hub->RestCounter++; - - default: /* presumably an error */ - /* Cause a hub reset after 10 consecutive errors */ - printk("hub_irq got ...: error %d URB: %d",hub->error,urb->status); - - dev_dbg (&hub->intf->dev, "transfer --> %d\n", urb->status); - if ((++hub->nerrors < 10) || hub->error) - goto resubmit; - hub->error = urb->status; - - /* FALL THROUGH */ - - /* let khubd handle things */ - case 0: /* we got data: port status changed */ - break; - } - - - hub->nerrors = 0; - - /* Something happened, let khubd figure it out */ - spin_lock_irqsave(&hub_event_lock, flags); - if (list_empty(&hub->event_list)) { - list_add(&hub->event_list, &hub_event_list); - wake_up(&khubd_wait); - } - spin_unlock_irqrestore(&hub_event_lock, flags); - -resubmit: - if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 - /* ENODEV means we raced disconnect() */ - && status != -ENODEV) - dev_err (&hub->intf->dev, "resubmit --> %d\n", urb->status); -} - -/* USB 2.0 spec Section 11.24.2.3 */ -static inline int -hub_clear_tt_buffer (struct usb_device *hub, u16 devinfo, u16 tt) -{ - return usb_control_msg (hub, usb_rcvctrlpipe (hub, 0), - HUB_CLEAR_TT_BUFFER, USB_DIR_IN | USB_RECIP_OTHER, - devinfo, tt, 0, 0, HZ); -} - -/* - * enumeration blocks khubd for a long time. we use keventd instead, since - * long blocking there is the exception, not the rule. accordingly, HCDs - * talking to TTs must queue control transfers (not just bulk and iso), so - * both can talk to the same hub concurrently. - */ -static void hub_tt_kevent (void *arg) -{ - struct usb_hub *hub = arg; - unsigned long flags; - - spin_lock_irqsave (&hub->tt.lock, flags); - while (!list_empty (&hub->tt.clear_list)) { - struct list_head *temp; - struct usb_tt_clear *clear; - struct usb_device *dev; - int status; - - temp = hub->tt.clear_list.next; - clear = list_entry (temp, struct usb_tt_clear, clear_list); - list_del (&clear->clear_list); - - /* drop lock so HCD can concurrently report other TT errors */ - spin_unlock_irqrestore (&hub->tt.lock, flags); - dev = interface_to_usbdev (hub->intf); - status = hub_clear_tt_buffer (dev, clear->devinfo, clear->tt); - spin_lock_irqsave (&hub->tt.lock, flags); - - if (status) - err ("usb-%s-%s clear tt %d (%04x) error %d", - dev->bus->bus_name, dev->devpath, - clear->tt, clear->devinfo, status); - kfree (clear); - } - spin_unlock_irqrestore (&hub->tt.lock, flags); -} - -/** - * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub - * @dev: the device whose split transaction failed - * @pipe: identifies the endpoint of the failed transaction - * - * High speed HCDs use this to tell the hub driver that some split control or - * bulk transaction failed in a way that requires clearing internal state of - * a transaction translator. This is normally detected (and reported) from - * interrupt context. - * - * It may not be possible for that hub to handle additional full (or low) - * speed transactions until that state is fully cleared out. - */ -void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe) -{ - struct usb_tt *tt = dev->tt; - unsigned long flags; - struct usb_tt_clear *clear; - - /* we've got to cope with an arbitrary number of pending TT clears, - * since each TT has "at least two" buffers that can need it (and - * there can be many TTs per hub). even if they're uncommon. - */ - if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == 0) { - err ("can't save CLEAR_TT_BUFFER state for hub at usb-%s-%s", - dev->bus->bus_name, tt->hub->devpath); - /* FIXME recover somehow ... RESET_TT? */ - return; - } - - /* info that CLEAR_TT_BUFFER needs */ - clear->tt = tt->multi ? dev->ttport : 1; - clear->devinfo = usb_pipeendpoint (pipe); - clear->devinfo |= dev->devnum << 4; - clear->devinfo |= usb_pipecontrol (pipe) - ? (USB_ENDPOINT_XFER_CONTROL << 11) - : (USB_ENDPOINT_XFER_BULK << 11); - if (usb_pipein (pipe)) - clear->devinfo |= 1 << 15; - - /* tell keventd to clear state for this TT */ - spin_lock_irqsave (&tt->lock, flags); - list_add_tail (&clear->clear_list, &tt->clear_list); - schedule_work (&tt->kevent); - spin_unlock_irqrestore (&tt->lock, flags); -} - -static void hub_power_on(struct usb_hub *hub) -{ - struct usb_device *dev; - int i; - int DelayPerPort; - int DelayAfterPort; - - DelayAfterPort = hub->descriptor->bPwrOn2PwrGood * 2; - DelayPerPort = 0; - - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { - case 0x00: - DelayAfterPort = hub->descriptor->bPwrOn2PwrGood * 2; - DelayPerPort = 0; - break; - case 0x01: - DelayAfterPort = hub->descriptor->bPwrOn2PwrGood; - DelayPerPort = hub->descriptor->bPwrOn2PwrGood /4; - break; - case 0x02: - case 0x03: - //dev_dbg(hub_dev, "unknown reserved power switching mode\n"); - break; - } - - - /* Enable power to the ports */ - dev_dbg(hubdev(interface_to_usbdev(hub->intf)), - "enabling power on all ports\n"); - dev = interface_to_usbdev(hub->intf); - - for (i = 0; i < hub->descriptor->bNbrPorts; i++) { - set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); - wait_ms(DelayPerPort); - } - - /* Wait for power to be enabled */ - wait_ms(DelayAfterPort); -} - -static int hub_hub_status(struct usb_hub *hub, - u16 *status, u16 *change) -{ - struct usb_device *dev = interface_to_usbdev (hub->intf); - int ret; - - ret = get_hub_status(dev, &hub->status->hub); - if (ret < 0) { - dev_err (hubdev (dev), - "%s failed (err = %d)\n", __FUNCTION__, ret); - } - else { - *status = le16_to_cpu(hub->status->hub.wHubStatus); - *change = le16_to_cpu(hub->status->hub.wHubChange); - ret = 0; - } - return ret; -} - -static int hub_configure(struct usb_hub *hub, - struct usb_endpoint_descriptor *endpoint) -{ - struct usb_device *dev = interface_to_usbdev (hub->intf); - struct device *hub_dev; - u16 hubstatus, hubchange; - unsigned int pipe; - int maxp, ret; - char *message; - - hub->buffer = usb_buffer_alloc(dev, sizeof(*hub->buffer), GFP_KERNEL, - &hub->buffer_dma); - if (!hub->buffer) { - message = "can't allocate hub irq buffer"; - ret = -ENOMEM; - goto fail; - } - - hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); - if (!hub->status) { - message = "can't kmalloc hub status buffer"; - ret = -ENOMEM; - goto fail; - } - - hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); - if (!hub->descriptor) { - message = "can't kmalloc hub descriptor"; - ret = -ENOMEM; - goto fail; - } - - /* Request the entire hub descriptor. - * hub->descriptor can handle USB_MAXCHILDREN ports, - * but the hub can/will return fewer bytes here. - */ - ret = get_hub_descriptor(dev, hub->descriptor, - sizeof(*hub->descriptor)); - if (ret < 0) { - message = "can't read hub descriptor"; - goto fail; - } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { - message = "hub has too many ports!"; - // XBOX PATCH hub->descriptor->bNbrPorts = 4; //ret = -ENODEV; - //goto fail; - } - - hub_dev = hubdev(dev); - dev->maxchild = hub->descriptor->bNbrPorts; - dev_info (hub_dev, "%d port%s detected\n", dev->maxchild, - (dev->maxchild == 1) ? "" : "s"); - - le16_to_cpus(&hub->descriptor->wHubCharacteristics); - - if (hub->descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND) { - int i; - char portstr [USB_MAXCHILDREN + 1]; - - for (i = 0; i < dev->maxchild; i++) - portstr[i] = hub->descriptor->DeviceRemovable - [((i + 1) / 8)] & (1 << ((i + 1) % 8)) - ? 'F' : 'R'; - portstr[dev->maxchild] = 0; - dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr); - } else - dev_dbg(hub_dev, "standalone hub\n"); - - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { - case 0x00: - dev_dbg(hub_dev, "ganged power switching\n"); - break; - case 0x01: - dev_dbg(hub_dev, "individual port power switching\n"); - break; - case 0x02: - case 0x03: - dev_dbg(hub_dev, "unknown reserved power switching mode\n"); - break; - } - - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { - case 0x00: - dev_dbg(hub_dev, "global over-current protection\n"); - break; - case 0x08: - dev_dbg(hub_dev, "individual port over-current protection\n"); - break; - case 0x10: - case 0x18: - dev_dbg(hub_dev, "no over-current protection\n"); - break; - } - - spin_lock_init (&hub->tt.lock); - INIT_LIST_HEAD (&hub->tt.clear_list); - INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); - switch (dev->descriptor.bDeviceProtocol) { - case 0: - break; - case 1: - dev_dbg(hub_dev, "Single TT\n"); - hub->tt.hub = dev; - break; - case 2: - dev_dbg(hub_dev, "TT per port\n"); - hub->tt.hub = dev; - hub->tt.multi = 1; - break; - default: - dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", - dev->descriptor.bDeviceProtocol); - break; - } - - switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { - case 0x00: - if (dev->descriptor.bDeviceProtocol != 0) - dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n"); - break; - case 0x20: - dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n"); - break; - case 0x40: - dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n"); - break; - case 0x60: - dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n"); - break; - } - - dev_dbg(hub_dev, "Port indicators are %s supported\n", - (hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND) - ? "" : "not"); - - if (hub->descriptor->bPwrOn2PwrGood<3) hub->descriptor->bPwrOn2PwrGood = 3; - if (hub->descriptor->bPwrOn2PwrGood>20) hub->descriptor->bPwrOn2PwrGood = 20; - - dev_dbg(hub_dev, "power on to power good time: %dms\n", - hub->descriptor->bPwrOn2PwrGood * 2); - dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", - hub->descriptor->bHubContrCurrent); - - ret = hub_hub_status(hub, &hubstatus, &hubchange); - if (ret < 0) { - message = "can't get hub status"; - goto fail; - } - - dev_dbg(hub_dev, "local power source is %s\n", - (hubstatus & HUB_STATUS_LOCAL_POWER) - ? "lost (inactive)" : "good"); - - dev_dbg(hub_dev, "%sover-current condition exists\n", - (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); - - /* Start the interrupt endpoint */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - if (maxp > sizeof(*hub->buffer)) - maxp = sizeof(*hub->buffer); - - hub->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!hub->urb) { - message = "couldn't allocate interrupt urb"; - ret = -ENOMEM; - goto fail; - } - - usb_fill_int_urb(hub->urb, dev, pipe, *hub->buffer, maxp, hub_irq, - hub, endpoint->bInterval); - hub->urb->transfer_dma = hub->buffer_dma; - hub->urb->transfer_flags |= URB_NO_DMA_MAP; - ret = usb_submit_urb(hub->urb, GFP_KERNEL); - if (ret) { - message = "couldn't submit status urb"; - goto fail; - } - - /* Wake up khubd */ - wake_up(&khubd_wait); - printk("hub_thread should woke up\n"); - - hub_power_on(hub); - - return 0; - -fail: - dev_err (&hub->intf->dev, "config failed, %s (err %d)\n", - message, ret); - /* hub_disconnect() frees urb and descriptor */ - return ret; -} - -static void hub_disconnect(struct usb_interface *intf) -{ - struct usb_hub *hub = usb_get_intfdata (intf); - unsigned long flags; - - if (!hub) - return; - - usb_set_intfdata (intf, NULL); - spin_lock_irqsave(&hub_event_lock, flags); - - /* Delete it and then reset it */ - list_del(&hub->event_list); - INIT_LIST_HEAD(&hub->event_list); - list_del(&hub->hub_list); - INIT_LIST_HEAD(&hub->hub_list); - - spin_unlock_irqrestore(&hub_event_lock, flags); - - down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */ - up(&hub->khubd_sem); - - /* assuming we used keventd, it must quiesce too */ - if (hub->tt.hub) - flush_scheduled_work (); - - if (hub->urb) { - usb_unlink_urb(hub->urb); - usb_free_urb(hub->urb); - hub->urb = NULL; - } - - if (hub->descriptor) { - kfree(hub->descriptor); - hub->descriptor = NULL; - } - - if (hub->status) { - kfree(hub->status); - hub->status = NULL; - } - - if (hub->buffer) { - usb_buffer_free(interface_to_usbdev(intf), - sizeof(*hub->buffer), hub->buffer, - hub->buffer_dma); - hub->buffer = NULL; - } - - /* Free the memory */ - kfree(hub); -} - -static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_host_interface *desc; - struct usb_endpoint_descriptor *endpoint; - struct usb_device *dev; - struct usb_hub *hub; - unsigned long flags; - - desc = intf->altsetting + intf->act_altsetting; - dev = interface_to_usbdev(intf); - - /* Some hubs have a subclass of 1, which AFAICT according to the */ - /* specs is not defined, but it works */ - if ((desc->desc.bInterfaceSubClass != 0) && - (desc->desc.bInterfaceSubClass != 1)) { -//descriptor_error: - desc->desc.bInterfaceSubClass =0; - dev_err (&intf->dev, "bad descriptor, ignoring hub\n"); - //return -EIO; - } - - /* Multiple endpoints? What kind of mutant ninja-hub is this? */ - if (desc->desc.bNumEndpoints != 1) { - desc->desc.bNumEndpoints = 1; - //goto descriptor_error; - } - - endpoint = &desc->endpoint[0].desc; - - /* Output endpoint? Curiouser and curiouser.. */ - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { - //goto descriptor_error; - endpoint->bEndpointAddress |= USB_DIR_IN; - } - - /* If it's not an interrupt endpoint, we'd better punt! */ - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) { - endpoint->bmAttributes |= USB_ENDPOINT_XFER_INT; - //goto descriptor_error; - //return -EIO; - } - - /* We found a hub */ - dev_info (hubdev (dev), "USB hub found\n"); - - hub = kmalloc(sizeof(*hub), GFP_KERNEL); - if (!hub) { - err("couldn't kmalloc hub struct"); - return -ENOMEM; - } - - memset(hub, 0, sizeof(*hub)); - - hub->RestCounter = 0; - - INIT_LIST_HEAD(&hub->event_list); - hub->intf = intf; - init_MUTEX(&hub->khubd_sem); - - /* Record the new hub's existence */ - spin_lock_irqsave(&hub_event_lock, flags); - INIT_LIST_HEAD(&hub->hub_list); - list_add(&hub->hub_list, &hub_list); - spin_unlock_irqrestore(&hub_event_lock, flags); - - usb_set_intfdata (intf, hub); - - if (hub_configure(hub, endpoint) >= 0) - { - strcpy (intf->dev.name, "Hub"); - return 0; - } - - //hub_disconnect (intf); - return -ENODEV; -} - -static int -hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) -{ - struct usb_device *hub = interface_to_usbdev (intf); - - /* assert ifno == 0 (part of hub spec) */ - switch (code) { - case USBDEVFS_HUB_PORTINFO: { - struct usbdevfs_hub_portinfo *info = user_data; - unsigned long flags; - int i; - - spin_lock_irqsave(&hub_event_lock, flags); - if (hub->devnum <= 0) - info->nports = 0; - else { - info->nports = hub->maxchild; - for (i = 0; i < info->nports; i++) { - if (hub->children[i] == NULL) - info->port[i] = 0; - else - info->port[i] = - hub->children[i]->devnum; - } - } - spin_unlock_irqrestore(&hub_event_lock, flags); - - return info->nports + 1; - } - - default: - return -ENOSYS; - } -} - -static int hub_reset(struct usb_hub *hub) -{ - struct usb_device *dev = interface_to_usbdev(hub->intf); - int i; - - /* Disconnect any attached devices */ - for (i = 0; i < hub->descriptor->bNbrPorts; i++) { - if (dev->children[i]) - usb_disconnect(&dev->children[i]); - } - - /* Attempt to reset the hub */ - if (hub->urb) - usb_unlink_urb(hub->urb); - else - return -1; - - if (usb_reset_device(dev)) - return -1; - - hub->urb->dev = dev; - if (usb_submit_urb(hub->urb, GFP_KERNEL)) - return -1; - - hub_power_on(hub); - - return 0; -} - -static void hub_start_disconnect(struct usb_device *dev) -{ - struct usb_device *parent = dev->parent; - int i; - - /* Find the device pointer to disconnect */ - if (parent) { - for (i = 0; i < parent->maxchild; i++) { - if (parent->children[i] == dev) { - usb_disconnect(&parent->children[i]); - return; - } - } - } - - err("cannot disconnect hub %s", dev->devpath); -} - -static int hub_port_status(struct usb_device *dev, int port, - u16 *status, u16 *change) -{ - struct usb_hub *hub = usb_get_intfdata (dev->actconfig->interface); - int ret; - - if (!hub) - return -ENODEV; - - ret = get_port_status(dev, port + 1, &hub->status->port); - if (ret < 0) { - dev_err (hubdev (dev), - "%s failed (err = %d)\n", __FUNCTION__, ret); - } - else { - *status = le16_to_cpu(hub->status->port.wPortStatus); - *change = le16_to_cpu(hub->status->port.wPortChange); - ret = 0; - } - return ret; -} - -#define HUB_RESET_TRIES 5 -#define HUB_PROBE_TRIES 5 -#define HUB_ROOT_RESET_TIME 40 -#define HUB_SHORT_RESET_TIME 10 -#define HUB_LONG_RESET_TIME 70 -#define HUB_RESET_TIMEOUT 500 - -/* return: -1 on error, 0 on success, 1 on disconnect. */ -static int hub_port_wait_reset(struct usb_device *hub, int port, - struct usb_device *dev, unsigned int delay) -{ - int delay_time, ret; - u16 portstatus; - u16 portchange; - - for (delay_time = 0; - delay_time < HUB_RESET_TIMEOUT; - delay_time += delay) { - /* wait to give the device a chance to reset */ - wait_ms(delay); - - /* read and decode port status */ - ret = hub_port_status(hub, port, &portstatus, &portchange); - if (ret < 0) { - return -1; - } - - /* Device went away? */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return 1; - - /* bomb out completely if something weird happened */ - if ((portchange & USB_PORT_STAT_C_CONNECTION)) - return -1; - - /* if we`ve finished resetting, then break out of the loop */ - if (!(portstatus & USB_PORT_STAT_RESET) && - (portstatus & USB_PORT_STAT_ENABLE)) { - if (portstatus & USB_PORT_STAT_HIGH_SPEED) - dev->speed = USB_SPEED_HIGH; - else if (portstatus & USB_PORT_STAT_LOW_SPEED) - dev->speed = USB_SPEED_LOW; - else - dev->speed = USB_SPEED_FULL; - return 0; - } - - /* switch to the long delay after two short delay failures */ - if (delay_time >= 2 * HUB_SHORT_RESET_TIME) - delay = HUB_LONG_RESET_TIME; - - dev_dbg (hubdev (hub), - "port %d not reset yet, waiting %dms\n", - port + 1, delay); - } - - return -1; -} - -/* return: -1 on error, 0 on success, 1 on disconnect. */ -static int hub_port_reset(struct usb_device *hub, int port, - struct usb_device *dev, unsigned int delay) -{ - int i, status; - - /* Reset the port */ - for (i = 0; i < HUB_RESET_TRIES; i++) { - set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET); - - /* return on disconnect or reset */ - status = hub_port_wait_reset(hub, port, dev, delay); - if (status != -1) { - clear_port_feature(hub, - port + 1, USB_PORT_FEAT_C_RESET); - dev->state = status - ? USB_STATE_NOTATTACHED - : USB_STATE_DEFAULT; - return status; - } - - dev_dbg (hubdev (hub), - "port %d not enabled, trying reset again...\n", - port + 1); - delay = HUB_LONG_RESET_TIME; - } - - dev_err (hubdev (hub), - "Cannot enable port %i. Maybe the USB cable is bad?\n", - port + 1); - - return -1; -} - -int hub_port_disable(struct usb_device *hub, int port) -{ - int ret; - - ret = clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE); - if (ret) - dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n", - port + 1, ret); - - return ret; -} - -/* USB 2.0 spec, 7.1.7.3 / fig 7-29: - * - * Between connect detection and reset signaling there must be a delay - * of 100ms at least for debounce and power-settling. The corresponding - * timer shall restart whenever the downstream port detects a disconnect. - * - * Apparently there are some bluetooth and irda-dongles and a number - * of low-speed devices which require longer delays of about 200-400ms. - * Not covered by the spec - but easy to deal with. - * - * This implementation uses 400ms minimum debounce timeout and checks - * every 25ms for transient disconnects to restart the delay. - */ - -#define HUB_DEBOUNCE_TIMEOUT 400 -#define HUB_DEBOUNCE_STEP 5 -#define HUB_DEBOUNCE_STABLE 3 - -/* return: -1 on error, 0 on success, 1 on disconnect. */ -static int hub_port_debounce(struct usb_device *hub, int port) -{ - int ret; - int delay_time, stable_count; - u16 portchange, portstatus; - unsigned connection; - - connection = 0; - stable_count = 0; - for (delay_time = 0; delay_time < HUB_DEBOUNCE_TIMEOUT; delay_time += HUB_DEBOUNCE_STEP) { - wait_ms(HUB_DEBOUNCE_STEP); - - ret = hub_port_status(hub, port, &portstatus, &portchange); - if (ret < 0) - return -1; - - if ((portstatus & USB_PORT_STAT_CONNECTION) == connection) { - if (connection) { - if (++stable_count == HUB_DEBOUNCE_STABLE) - break; - } - } else { - stable_count = 0; - } - connection = portstatus & USB_PORT_STAT_CONNECTION; - - if ((portchange & USB_PORT_STAT_C_CONNECTION)) { - clear_port_feature(hub, port+1, USB_PORT_FEAT_C_CONNECTION); - } - } - - /* XXX Replace this with dbg() when 2.6 is about to ship. */ - dev_dbg (hubdev (hub), - "debounce: port %d: delay %dms stable %d status 0x%x\n", - port + 1, delay_time, stable_count, portstatus); - - return ((portstatus&USB_PORT_STAT_CONNECTION)) ? 0 : 1; -} - -static void hub_port_connect_change(struct usb_hub *hubstate, int port, - u16 portstatus, u16 portchange) -{ - struct usb_device *hub = interface_to_usbdev(hubstate->intf); - struct usb_device *dev; - unsigned int delay = HUB_SHORT_RESET_TIME; - int i; - int DevcoosenAdress = 0; - - //printe("port %d, status %x, change %x,\n",port + 1, portstatus, portchange); - - - dev_dbg (&hubstate->intf->dev, - "port %d, status %x, change %x, %s\n", - port + 1, portstatus, portchange, portspeed (portstatus)); - - /* Clear the connection change status */ - clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION); - - /* Disconnect any existing devices under this port */ - if (hub->children[port]) - usb_disconnect(&hub->children[port]); - - /* Return now if nothing is connected */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) { - if (portstatus & USB_PORT_STAT_ENABLE) - hub_port_disable(hub, port); - - return; - } - - if (hub_port_debounce(hub, port)) { - dev_err (&hubstate->intf->dev, - "connect-debounce failed, port %d disabled\n", - port+1); - //printe("connect-debounce failed, port %d disabled\n", port+1); - hub_port_disable(hub, port); - return; - } - - /* root hub ports have a slightly longer reset period - * (from USB 2.0 spec, section 7.1.7.5) - */ - if (!hub->parent) - delay = HUB_ROOT_RESET_TIME; - - /* Some low speed devices have problems with the quick delay, so */ - /* be a bit pessimistic with those devices. RHbug #23670 */ - if (portstatus & USB_PORT_STAT_LOW_SPEED) - delay = HUB_LONG_RESET_TIME; - - down(&usb_address0_sem); - - for (i = 0; i < HUB_PROBE_TRIES; i++) { - struct usb_device *pdev; - int len; - - /* Allocate a new device struct */ - dev = usb_alloc_dev(hub, hub->bus); - if (!dev) { - dev_err (&hubstate->intf->dev, - "couldn't allocate usb_device\n"); - break; - } - - - dev->state = USB_STATE_POWERED; - - /* Reset the device, and detect its speed */ - if (hub_port_reset(hub, port, dev, delay)) { - usb_put_dev(dev); - break; - } - - /* Find a new address for it */ - if (DevcoosenAdress==0) { - usb_choose_address(dev); - DevcoosenAdress = dev->devnum; - } - dev->devnum = DevcoosenAdress ; - - /* Set up TT records, if needed */ - if (hub->tt) { - dev->tt = hub->tt; - dev->ttport = hub->ttport; - } else if (dev->speed != USB_SPEED_HIGH - && hub->speed == USB_SPEED_HIGH) { - dev->tt = &hubstate->tt; - dev->ttport = port + 1; - } - - /* Save readable and stable topology id, distinguishing - * devices by location for diagnostics, tools, etc. The - * string is a path along hub ports, from the root. Each - * device's id will be stable until USB is re-cabled, and - * hubs are often labeled with these port numbers. - * - * Initial size: ".NN" times five hubs + NUL = 16 bytes max - * (quite rare, since most hubs have 4-6 ports). - */ - pdev = dev->parent; - if (pdev->devpath [0] != '0') /* parent not root? */ - len = snprintf (dev->devpath, sizeof dev->devpath, - "%s.%d", pdev->devpath, port + 1); - /* root == "0", root port 2 == "2", port 3 that hub "2.3" */ - else - len = snprintf (dev->devpath, sizeof dev->devpath, - "%d", port + 1); - if (len == sizeof dev->devpath) - dev_err (&hubstate->intf->dev, - "devpath size! usb/%03d/%03d path %s\n", - dev->bus->busnum, dev->devnum, dev->devpath); - dev_info (&hubstate->intf->dev, - "new USB device on port %d, assigned address %d\n", - port + 1, dev->devnum); - - /* put the device in the global device tree. the hub port - * is the "bus_id"; hubs show in hierarchy like bridges - */ - dev->dev.parent = dev->parent->dev.parent->parent; - - /* Run it through the hoops (find a driver, etc) */ - if (!usb_new_device(dev, &hub->dev)) { - hub->children[port] = dev; - usbfs_add_device(dev); - goto done; - } - - /* Free the configuration if there was an error */ - usb_put_dev(dev); - - /* Switch to a long reset time */ - delay = HUB_LONG_RESET_TIME; - } - - - hub_port_disable(hub, port); -done: - up(&usb_address0_sem); -} - -static void hub_events(void) -{ - unsigned long flags; - struct list_head *tmp; - struct usb_device *dev; - struct usb_hub *hub; - u16 hubstatus; - u16 hubchange; - u16 portstatus; - u16 portchange; - int i, ret; - int m=0; - /* - * We restart the list every time to avoid a deadlock with - * deleting hubs downstream from this one. This should be - * safe since we delete the hub from the event list. - * Not the most efficient, but avoids deadlocks. - */ - //DPRINT1("hub_events() called\n"); - - while (m<5) { - m++; - spin_lock_irqsave(&hub_event_lock, flags); - - if (list_empty(&hub_event_list)) - break; - - /* Grab the next entry from the beginning of the list */ - tmp = hub_event_list.next; - - hub = list_entry(tmp, struct usb_hub, event_list); - dev = interface_to_usbdev(hub->intf); - - list_del_init(tmp); - - if (unlikely(down_trylock(&hub->khubd_sem))) - BUG(); /* never blocks, we were on list */ - - spin_unlock_irqrestore(&hub_event_lock, flags); - - if (hub->error) { - dev_dbg (&hub->intf->dev, "resetting for error %d\n", - hub->error); - - if (hub_reset(hub)) { - dev_dbg (&hub->intf->dev, - "can't reset; disconnecting\n"); - up(&hub->khubd_sem); - hub_start_disconnect(dev); - continue; - } - - hub->nerrors = 0; - hub->error = 0; - } - - for (i = 0; i < hub->descriptor->bNbrPorts; i++) { - ret = hub_port_status(dev, i, &portstatus, &portchange); - if (ret < 0) { - continue; - } - - if (portchange & USB_PORT_STAT_C_CONNECTION) { - hub_port_connect_change(hub, i, portstatus, portchange); - } else if (portchange & USB_PORT_STAT_C_ENABLE) { - dev_dbg (hubdev (dev), - "port %d enable change, status %x\n", - i + 1, portstatus); - clear_port_feature(dev, - i + 1, USB_PORT_FEAT_C_ENABLE); - - /* - * EM interference sometimes causes badly - * shielded USB devices to be shutdown by - * the hub, this hack enables them again. - * Works at least with mouse driver. - */ - if (!(portstatus & USB_PORT_STAT_ENABLE) - && (portstatus & USB_PORT_STAT_CONNECTION) - && (dev->children[i])) { - dev_err (&hub->intf->dev, - "port %i " - "disabled by hub (EMI?), " - "re-enabling...", - i + 1); - hub_port_connect_change(hub, - i, portstatus, portchange); - } - } - - if (portchange & USB_PORT_STAT_C_SUSPEND) { - dev_dbg (&hub->intf->dev, - "suspend change on port %d\n", - i + 1); - clear_port_feature(dev, - i + 1, USB_PORT_FEAT_C_SUSPEND); - } - - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - dev_err (&hub->intf->dev, - "over-current change on port %d\n", - i + 1); - clear_port_feature(dev, - i + 1, USB_PORT_FEAT_C_OVER_CURRENT); - hub_power_on(hub); - } - - if (portchange & USB_PORT_STAT_C_RESET) { - dev_dbg (&hub->intf->dev, - "reset change on port %d\n", - i + 1); - clear_port_feature(dev, - i + 1, USB_PORT_FEAT_C_RESET); - } - } /* end for i */ - - /* deal with hub status changes */ - if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) { - dev_err (&hub->intf->dev, "get_hub_status failed\n"); - } - else { - if (hubchange & HUB_CHANGE_LOCAL_POWER) { - dev_dbg (&hub->intf->dev, "power change\n"); - clear_hub_feature(dev, C_HUB_LOCAL_POWER); - } - if (hubchange & HUB_CHANGE_OVERCURRENT) { - dev_dbg (&hub->intf->dev, "overcurrent change\n"); - wait_ms(500); /* Cool down */ - clear_hub_feature(dev, C_HUB_OVER_CURRENT); - hub_power_on(hub); - } - } - up(&hub->khubd_sem); - } /* end while (1) */ - - spin_unlock_irqrestore(&hub_event_lock, flags); -} - -// ReactOS: STDCALL is needed here -static int STDCALL hub_thread(void *__hub) -{ - //LARGE_INTEGER delay; - - /* - * This thread doesn't need any user-level access, - * so get rid of all our resources - */ - - daemonize("khubd"); - allow_signal(SIGKILL); - - // Initialize khubd spinlock - KeInitializeSpinLock((PKSPIN_LOCK)&hub_event_lock); - - //delay.QuadPart = -10000000*5; // wait 5 seconds before powering up - //KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1); - - printk("hub_thread starting"); - - /* Send me a signal to get me die (for debugging) */ - do { - LARGE_INTEGER delay; - - /* The following is just for debug */ - inc_jiffies(1); - do_all_timers(); - //handle_irqs(-1); - /* End of debug hack*/ - hub_events(); - /* The following is just for debug */ - handle_irqs(-1); - /* End of debug hack*/ - - //FIXME: Correct this - //wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); // interruptable_sleep_on analog - below - //while (!list_empty(&hub_event_list)) { - // interruptible_sleep_on(&khubd_wait); - //} - - delay.QuadPart = -10000*100; // convert to 100ns units - KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1); - - if (current->flags & PF_FREEZE) - refrigerator(PF_IOTHREAD); - - } while (!signal_pending(current)); - - dbg("hub_thread exiting"); - complete_and_exit(&khubd_exited, 0); -} - -static struct usb_device_id hub_id_table [] = { - { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, - .bDeviceClass = USB_CLASS_HUB}, - { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, - .bInterfaceClass = USB_CLASS_HUB}, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, hub_id_table); - -static struct usb_driver hub_driver = { - .owner = THIS_MODULE, - .name = "hub", - .probe = hub_probe, - .disconnect = hub_disconnect, - .ioctl = hub_ioctl, - .id_table = hub_id_table, -}; - -/* - * This should be a separate module. - */ -int usb_hub_init(void) -{ - pid_t pid; - - // ReactOS-specific - // Create Event object, initialize other sync events - KeInitializeEvent(&khubd_wait, NotificationEvent, TRUE); // signalled state - - if (usb_register(&hub_driver) < 0) { - err("Unable to register USB hub driver"); - return -1; - } - - pid = kernel_thread((void*)hub_thread, NULL, - (CLONE_FS | CLONE_FILES | CLONE_SIGHAND)); - if (pid >= 0) { - khubd_pid = pid; - return 0; - } - - /* Fall through if kernel_thread failed */ - usb_deregister(&hub_driver); - err("failed to start hub_thread"); - - return -1; -} - -void usb_hub_cleanup(void) -{ - int ret; - - /* Kill the thread */ - ret = kill_proc(khubd_pid, SIGKILL, 1); - - wait_for_completion(&khubd_exited); - - /* - * Hub resources are freed for us by usb_deregister. It calls - * usb_driver_purge on every device which in turn calls that - * devices disconnect function if it is using this driver. - * The hub_disconnect function takes care of releasing the - * individual hub resources. -greg - */ - usb_deregister(&hub_driver); -} /* usb_hub_cleanup() */ - -/* - * WARNING - If a driver calls usb_reset_device, you should simulate a - * disconnect() and probe() for other interfaces you doesn't claim. This - * is left up to the driver writer right now. This insures other drivers - * have a chance to re-setup their interface. - * - * Take a look at proc_resetdevice in devio.c for some sample code to - * do this. - * Use this only from within your probe function, otherwise use - * usb_reset_device() below, which ensure proper locking - */ -int usb_physical_reset_device(struct usb_device *dev) -{ - struct usb_device *parent = dev->parent; - struct usb_device_descriptor *descriptor; - int i, ret, port = -1; - - if (!parent) { - err("attempting to reset root hub!"); - return -EINVAL; - } - - for (i = 0; i < parent->maxchild; i++) - if (parent->children[i] == dev) { - port = i; - break; - } - - if (port < 0) - return -ENOENT; - - descriptor = kmalloc(sizeof *descriptor, GFP_NOIO); - if (!descriptor) { - return -ENOMEM; - } - - down(&usb_address0_sem); - - /* Send a reset to the device */ - if (hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { - hub_port_disable(parent, port); - up(&usb_address0_sem); - kfree(descriptor); - return(-ENODEV); - } - - /* Reprogram the Address */ - ret = usb_set_address(dev); - if (ret < 0) { - err("USB device not accepting new address (error=%d)", ret); - hub_port_disable(parent, port); - up(&usb_address0_sem); - kfree(descriptor); - return ret; - } - - /* Let the SET_ADDRESS settle */ - wait_ms(10); - - up(&usb_address0_sem); - - /* - * Now we fetch the configuration descriptors for the device and - * see if anything has changed. If it has, we dump the current - * parsed descriptors and reparse from scratch. Then we leave - * the device alone for the caller to finish setting up. - * - * If nothing changed, we reprogram the configuration and then - * the alternate settings. - */ - - ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor, - sizeof(*descriptor)); - if (ret < 0) { - kfree(descriptor); - return ret; - } - - le16_to_cpus(&descriptor->bcdUSB); - le16_to_cpus(&descriptor->idVendor); - le16_to_cpus(&descriptor->idProduct); - le16_to_cpus(&descriptor->bcdDevice); - - if (RtlCompareMemory(&dev->descriptor, descriptor, sizeof(*descriptor)) != sizeof(*descriptor)) { - kfree(descriptor); - usb_destroy_configuration(dev); - - ret = usb_get_device_descriptor(dev); - if (ret < sizeof(dev->descriptor)) { - if (ret < 0) { - err("unable to get device %s descriptor " - "(error=%d)", dev->devpath, ret); - } - else { - err("USB device %s descriptor short read " - "(expected %Zi, got %i)", - dev->devpath, - sizeof(dev->descriptor), ret); - } - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - dev->devnum = -1; - return -EIO; - } - - ret = usb_get_configuration(dev); - if (ret < 0) { - err("unable to get configuration (error=%d)", ret); - usb_destroy_configuration(dev); - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - dev->devnum = -1; - return 1; - } - - usb_set_configuration(dev, dev->config[0].desc.bConfigurationValue); - - - return 1; - } - - kfree(descriptor); - - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, - dev->actconfig->desc.bConfigurationValue, 0, - NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); - if (ret < 0) { - err("failed to set dev %s active configuration (error=%d)", - dev->devpath, ret); - return ret; - } - dev->state = USB_STATE_CONFIGURED; - - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf = &dev->actconfig->interface[i]; - struct usb_interface_descriptor *as; - - as = &intf->altsetting[intf->act_altsetting].desc; - ret = usb_set_interface(dev, as->bInterfaceNumber, - as->bAlternateSetting); - if (ret < 0) { - err("failed to set active alternate setting " - "for dev %s interface %d (error=%d)", - dev->devpath, i, ret); - return ret; - } - } - - return 0; -} - -int usb_reset_device(struct usb_device *udev) -{ - //struct device *gdev = &udev->dev; - int r; - - down_read(&gdev->bus->subsys.rwsem); - r = usb_physical_reset_device(udev); - up_read(&gdev->bus->subsys.rwsem); - - return r; -} - - diff --git a/reactos/drivers/usb/usbport/hub.h b/reactos/drivers/usb/usbport/hub.h deleted file mode 100644 index e52f0df8caa..00000000000 --- a/reactos/drivers/usb/usbport/hub.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef __LINUX_HUB_H -#define __LINUX_HUB_H - -/* - * Hub protocol and driver data structures. - * - * Some of these are known to the "virtual root hub" code - * in host controller drivers. - */ -#if 0 -#include -#include -#include /* likely()/unlikely() */ -#endif -/* - * Hub request types - */ - -#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) -#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) - -/* - * Hub class requests - * See USB 2.0 spec Table 11-16 - */ -#define HUB_CLEAR_TT_BUFFER 8 -#define HUB_RESET_TT 9 -#define HUB_GET_TT_STATE 10 -#define HUB_STOP_TT 11 - -/* - * Hub Class feature numbers - * See USB 2.0 spec Table 11-17 - */ -#define C_HUB_LOCAL_POWER 0 -#define C_HUB_OVER_CURRENT 1 - -/* - * Port feature numbers - * See USB 2.0 spec Table 11-17 - */ -#define USB_PORT_FEAT_CONNECTION 0 -#define USB_PORT_FEAT_ENABLE 1 -#define USB_PORT_FEAT_SUSPEND 2 -#define USB_PORT_FEAT_OVER_CURRENT 3 -#define USB_PORT_FEAT_RESET 4 -#define USB_PORT_FEAT_POWER 8 -#define USB_PORT_FEAT_LOWSPEED 9 -#define USB_PORT_FEAT_HIGHSPEED 10 -#define USB_PORT_FEAT_C_CONNECTION 16 -#define USB_PORT_FEAT_C_ENABLE 17 -#define USB_PORT_FEAT_C_SUSPEND 18 -#define USB_PORT_FEAT_C_OVER_CURRENT 19 -#define USB_PORT_FEAT_C_RESET 20 -#define USB_PORT_FEAT_TEST 21 -#define USB_PORT_FEAT_INDICATOR 22 - -/* - * Hub Status and Hub Change results - * See USB 2.0 spec Table 11-19 and Table 11-20 - */ -struct usb_port_status { - __u16 wPortStatus; - __u16 wPortChange; -} __attribute__ ((packed)); - -/* - * wPortStatus bit field - * See USB 2.0 spec Table 11-21 - */ -#define USB_PORT_STAT_CONNECTION 0x0001 -#define USB_PORT_STAT_ENABLE 0x0002 -#define USB_PORT_STAT_SUSPEND 0x0004 -#define USB_PORT_STAT_OVERCURRENT 0x0008 -#define USB_PORT_STAT_RESET 0x0010 -/* bits 5 to 7 are reserved */ -#define USB_PORT_STAT_POWER 0x0100 -#define USB_PORT_STAT_LOW_SPEED 0x0200 -#define USB_PORT_STAT_HIGH_SPEED 0x0400 -#define USB_PORT_STAT_TEST 0x0800 -#define USB_PORT_STAT_INDICATOR 0x1000 -/* bits 13 to 15 are reserved */ - -/* - * wPortChange bit field - * See USB 2.0 spec Table 11-22 - * Bits 0 to 4 shown, bits 5 to 15 are reserved - */ -#define USB_PORT_STAT_C_CONNECTION 0x0001 -#define USB_PORT_STAT_C_ENABLE 0x0002 -#define USB_PORT_STAT_C_SUSPEND 0x0004 -#define USB_PORT_STAT_C_OVERCURRENT 0x0008 -#define USB_PORT_STAT_C_RESET 0x0010 - -/* - * wHubCharacteristics (masks) - * See USB 2.0 spec Table 11-13, offset 3 - */ -#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ -#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ -#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ -#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ -#define HUB_CHAR_PORTIND 0x0080 /* D7 */ - -struct usb_hub_status { - __u16 wHubStatus; - __u16 wHubChange; -} __attribute__ ((packed)); - -/* - * Hub Status & Hub Change bit masks - * See USB 2.0 spec Table 11-19 and Table 11-20 - * Bits 0 and 1 for wHubStatus and wHubChange - * Bits 2 to 15 are reserved for both - */ -#define HUB_STATUS_LOCAL_POWER 0x0001 -#define HUB_STATUS_OVERCURRENT 0x0002 -#define HUB_CHANGE_LOCAL_POWER 0x0001 -#define HUB_CHANGE_OVERCURRENT 0x0002 - - -/* - * Hub descriptor - * See USB 2.0 spec Table 11-13 - */ - -#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) -#define USB_DT_HUB_NONVAR_SIZE 7 - -struct usb_hub_descriptor { - __u8 bDescLength; - __u8 bDescriptorType; - __u8 bNbrPorts; - __u16 wHubCharacteristics; - __u8 bPwrOn2PwrGood; - __u8 bHubContrCurrent; - /* add 1 bit for hub status change; round to bytes */ - __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; - __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; -} __attribute__ ((packed)); - -struct usb_device; - -/* - * As of USB 2.0, full/low speed devices are segregated into trees. - * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). - * The other type grows from high speed hubs when they connect to - * full/low speed devices using "Transaction Translators" (TTs). - * - * TTs should only be known to the hub driver, and high speed bus - * drivers (only EHCI for now). They affect periodic scheduling and - * sometimes control/bulk error recovery. - */ -struct usb_tt { - struct usb_device *hub; /* upstream highspeed hub */ - int multi; /* true means one TT per port */ - - /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ - spinlock_t lock; - struct list_head clear_list; /* of usb_tt_clear */ - struct work_struct kevent; -}; - -struct usb_tt_clear { - struct list_head clear_list; - unsigned tt; - u16 devinfo; -}; - -extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); - -struct usb_hub { - struct usb_interface *intf; /* the "real" device */ - struct urb *urb; /* for interrupt polling pipe */ - - /* buffer for urb ... 1 bit each for hub and children, rounded up */ - char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8]; - dma_addr_t buffer_dma; /* DMA address for buffer */ - union { - struct usb_hub_status hub; - struct usb_port_status port; - } *status; /* buffer for status reports */ - - int error; /* last reported error */ - int nerrors; /* track consecutive errors */ - int RestCounter; - struct list_head hub_list; /* all hubs */ - struct list_head event_list; /* hubs w/data or errs ready */ - - struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct semaphore khubd_sem; - struct usb_tt tt; /* Transaction Translator */ -}; - -#endif /* __LINUX_HUB_H */ diff --git a/reactos/drivers/usb/usbport/makefile.crom b/reactos/drivers/usb/usbport/makefile.crom deleted file mode 100644 index dd6262ccaaa..00000000000 --- a/reactos/drivers/usb/usbport/makefile.crom +++ /dev/null @@ -1,6 +0,0 @@ - -O_TARGET := message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o buffer_simple.o urb.o usb-debug.o - -#O_TARGET := urb.o - -include $(TOPDIR)/Rules.make diff --git a/reactos/drivers/usb/usbport/message.c b/reactos/drivers/usb/usbport/message.c deleted file mode 100644 index a7fe455cae9..00000000000 --- a/reactos/drivers/usb/usbport/message.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * message.c - synchronous message handling - */ -#if 0 -#include /* for scatterlist macros */ -#include -#include -#include -#include -#include -#include -#else -#include "../miniport/usb_wrapper.h" -#endif - -#include "hcd.h" /* for usbcore internals */ - -// ReactOS specific: No WAITQUEUEs here -#undef wake_up -#define wake_up(a) do {} while(0) - -struct usb_api_data { - wait_queue_head_t wqh; - int done; -}; - -static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) -{ - struct usb_api_data *awd = (struct usb_api_data *)urb->context; - - awd->done = 1; - wmb(); - wake_up(&awd->wqh); -} - -// Starts urb and waits for completion or timeout -static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) -{ - //DECLARE_WAITQUEUE(wait, current); // Fireball, 24Jan05 - silent gcc complaining about unused wait variable - struct usb_api_data awd; - int status; - - //printk("usb_start_wait_urb(): urb devnum=%d, timeout=%d, urb->actual_length=%d\n", urb->dev->devnum, timeout, urb->actual_length); - - init_waitqueue_head((PKEVENT)&awd.wqh); - awd.done = 0; - - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&awd.wqh, &wait); - - urb->context = &awd; - status = usb_submit_urb(urb, GFP_ATOMIC); - - if (status) { - // something went wrong - usb_free_urb(urb); - set_current_state(TASK_RUNNING); - remove_wait_queue(&awd.wqh, &wait); - return status; - } - //printk("TRACE 3.1, timeout=%d, awd.done=%d\n", timeout, awd.done); - while (timeout && !awd.done) - { - timeout = schedule_timeout(timeout); - set_current_state(TASK_UNINTERRUPTIBLE); - rmb(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&awd.wqh, &wait); - - if (!timeout && !awd.done) { - if (urb->status != -EINPROGRESS) { /* No callback?!! */ - printk(KERN_ERR "usb: raced timeout, " - "pipe 0x%x status %d time left %d\n", - urb->pipe, urb->status, timeout); - status = urb->status; - } else { - warn("usb_control/bulk_msg: timeout"); - usb_unlink_urb(urb); // remove urb safely - status = -ETIMEDOUT; - } - } else - status = urb->status; - - if (actual_length) - *actual_length = urb->actual_length; - - usb_free_urb(urb); - - return status; -} - -/*-------------------------------------------------------------------*/ -// returns status (negative) or length (positive) -int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, - struct usb_ctrlrequest *cmd, void *data, int len, int timeout) -{ - struct urb *urb; - int retv; - int length; - - urb = usb_alloc_urb(0, GFP_NOIO); - if (!urb) - return -ENOMEM; - - usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, - usb_api_blocking_completion, 0); - - retv = usb_start_wait_urb(urb, timeout, &length); - - if (retv < 0) - return retv; - else - return length; -} - -/** - * usb_control_msg - Builds a control urb, sends it off and waits for completion - * @dev: pointer to the usb device to send the message to - * @pipe: endpoint "pipe" to send the message to - * @request: USB message request value - * @requesttype: USB message request type value - * @value: USB message value - * @index: USB message index value - * @data: pointer to the data to send - * @size: length in bytes of the data to send - * @timeout: time in jiffies to wait for the message to complete before - * timing out (if 0 the wait is forever) - * Context: !in_interrupt () - * - * This function sends a simple control message to a specified endpoint - * and waits for the message to complete, or timeout. - * - * If successful, it returns the number of bytes transferred, otherwise a negative error number. - * - * Don't use this function from within an interrupt context, like a - * bottom half handler. If you need an asynchronous message, or need to send - * a message from within interrupt context, use usb_submit_urb() - * If a thread in your driver uses this call, make sure your disconnect() - * method can wait for it to complete. Since you don't have a handle on - * the URB used, you can't cancel the request. - */ -int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, - __u16 value, __u16 index, void *data, __u16 size, int timeout) -{ - struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); - int ret; - - if (!dr) - return -ENOMEM; - - dr->bRequestType= requesttype; - dr->bRequest = request; - dr->wValue = cpu_to_le16p(&value); - dr->wIndex = cpu_to_le16p(&index); - dr->wLength = cpu_to_le16p(&size); - - //printk("usb_control_msg: devnum=%d, size=%d, timeout=%d\n", dev->devnum, size, timeout); - - ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); - kfree(dr); - return ret; -} - - -/** - * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion - * @usb_dev: pointer to the usb device to send the message to - * @pipe: endpoint "pipe" to send the message to - * @data: pointer to the data to send - * @len: length in bytes of the data to send - * @actual_length: pointer to a location to put the actual length transferred in bytes - * @timeout: time in jiffies to wait for the message to complete before - * timing out (if 0 the wait is forever) - * Context: !in_interrupt () - * - * This function sends a simple bulk message to a specified endpoint - * and waits for the message to complete, or timeout. - * - * If successful, it returns 0, otherwise a negative error number. - * The number of actual bytes transferred will be stored in the - * actual_length paramater. - * - * Don't use this function from within an interrupt context, like a - * bottom half handler. If you need an asynchronous message, or need to - * send a message from within interrupt context, use usb_submit_urb() - * If a thread in your driver uses this call, make sure your disconnect() - * method can wait for it to complete. Since you don't have a handle on - * the URB used, you can't cancel the request. - */ -int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, - void *data, int len, int *actual_length, int timeout) -{ - struct urb *urb; - - if (len < 0) - return -EINVAL; - - urb=usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return -ENOMEM; - - usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, 0); - - return usb_start_wait_urb(urb,timeout,actual_length); -} - -/*-------------------------------------------------------------------*/ -//#warning "Scatter-gather stuff disabled" -#if 0 -static void sg_clean (struct usb_sg_request *io) -{ - if (io->urbs) { - while (io->entries--) - usb_free_urb (io->urbs [io->entries]); - kfree (io->urbs); - io->urbs = 0; - } - if (io->dev->dev.dma_mask != 0) - usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents); - io->dev = 0; -} - -static void sg_complete (struct urb *urb, struct pt_regs *regs) -{ - struct usb_sg_request *io = (struct usb_sg_request *) urb->context; - unsigned long flags; - - spin_lock_irqsave (&io->lock, flags); - - /* In 2.5 we require hcds' endpoint queues not to progress after fault - * reports, until the completion callback (this!) returns. That lets - * device driver code (like this routine) unlink queued urbs first, - * if it needs to, since the HC won't work on them at all. So it's - * not possible for page N+1 to overwrite page N, and so on. - * - * That's only for "hard" faults; "soft" faults (unlinks) sometimes - * complete before the HCD can get requests away from hardware, - * though never during cleanup after a hard fault. - */ - if (io->status - && (io->status != -ECONNRESET - || urb->status != -ECONNRESET) - && urb->actual_length) { - dev_err (io->dev->bus->controller, - "dev %s ep%d%s scatterlist error %d/%d\n", - io->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - urb->status, io->status); - // BUG (); - } - - if (urb->status && urb->status != -ECONNRESET) { - int i, found, status; - - io->status = urb->status; - - /* the previous urbs, and this one, completed already. - * unlink the later ones so they won't rx/tx bad data, - * - * FIXME don't bother unlinking urbs that haven't yet been - * submitted; those non-error cases shouldn't be syslogged - */ - for (i = 0, found = 0; i < io->entries; i++) { - if (found) { - status = usb_unlink_urb (io->urbs [i]); - if (status && status != -EINPROGRESS) - err ("sg_complete, unlink --> %d", - status); - } else if (urb == io->urbs [i]) - found = 1; - } - } - - /* on the last completion, signal usb_sg_wait() */ - io->bytes += urb->actual_length; - io->count--; - if (!io->count) - complete (&io->complete); - - spin_unlock_irqrestore (&io->lock, flags); -} - - -/** - * usb_sg_init - initializes scatterlist-based bulk/interrupt I/O request - * @io: request block being initialized. until usb_sg_wait() returns, - * treat this as a pointer to an opaque block of memory, - * @dev: the usb device that will send or receive the data - * @pipe: endpoint "pipe" used to transfer the data - * @period: polling rate for interrupt endpoints, in frames or - * (for high speed endpoints) microframes; ignored for bulk - * @sg: scatterlist entries - * @nents: how many entries in the scatterlist - * @length: how many bytes to send from the scatterlist, or zero to - * send every byte identified in the list. - * @mem_flags: SLAB_* flags affecting memory allocations in this call - * - * Returns zero for success, else a negative errno value. This initializes a - * scatter/gather request, allocating resources such as I/O mappings and urb - * memory (except maybe memory used by USB controller drivers). - * - * The request must be issued using usb_sg_wait(), which waits for the I/O to - * complete (or to be canceled) and then cleans up all resources allocated by - * usb_sg_init(). - * - * The request may be canceled with usb_sg_cancel(), either before or after - * usb_sg_wait() is called. - */ -int usb_sg_init ( - struct usb_sg_request *io, - struct usb_device *dev, - unsigned pipe, - unsigned period, - struct scatterlist *sg, - int nents, - size_t length, - int mem_flags -) -{ - int i; - int urb_flags; - int dma; - - if (!io || !dev || !sg - || usb_pipecontrol (pipe) - || usb_pipeisoc (pipe) - || nents <= 0) - return -EINVAL; - - spin_lock_init (&io->lock); - io->dev = dev; - io->pipe = pipe; - io->sg = sg; - io->nents = nents; - - /* not all host controllers use DMA (like the mainstream pci ones); - * they can use PIO (sl811) or be software over another transport. - */ - dma = (dev->dev.dma_mask != 0); - if (dma) - io->entries = usb_buffer_map_sg (dev, pipe, sg, nents); - else - io->entries = nents; - - /* initialize all the urbs we'll use */ - if (io->entries <= 0) - return io->entries; - - io->count = 0; - io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags); - if (!io->urbs) - goto nomem; - - urb_flags = URB_ASYNC_UNLINK | URB_NO_DMA_MAP | URB_NO_INTERRUPT; - if (usb_pipein (pipe)) - urb_flags |= URB_SHORT_NOT_OK; - - for (i = 0; i < io->entries; i++, io->count = i) { - unsigned len; - - io->urbs [i] = usb_alloc_urb (0, mem_flags); - if (!io->urbs [i]) { - io->entries = i; - goto nomem; - } - - io->urbs [i]->dev = dev; - io->urbs [i]->pipe = pipe; - io->urbs [i]->interval = period; - io->urbs [i]->transfer_flags = urb_flags; - - io->urbs [i]->complete = sg_complete; - io->urbs [i]->context = io; - io->urbs [i]->status = -EINPROGRESS; - io->urbs [i]->actual_length = 0; - - if (dma) { - /* hc may use _only_ transfer_dma */ - io->urbs [i]->transfer_dma = sg_dma_address (sg + i); - len = sg_dma_len (sg + i); - } else { - /* hc may use _only_ transfer_buffer */ - io->urbs [i]->transfer_buffer = - page_address (sg [i].page) + sg [i].offset; - len = sg [i].length; - } - - if (length) { - len = min_t (unsigned, len, length); - length -= len; - if (length == 0) - io->entries = i + 1; - } - io->urbs [i]->transfer_buffer_length = len; - } - io->urbs [--i]->transfer_flags &= ~URB_NO_INTERRUPT; - - /* transaction state */ - io->status = 0; - io->bytes = 0; - init_completion (&io->complete); - return 0; - -nomem: - sg_clean (io); - return -ENOMEM; -} - - -/** - * usb_sg_wait - synchronously execute scatter/gather request - * @io: request block handle, as initialized with usb_sg_init(). - * some fields become accessible when this call returns. - * Context: !in_interrupt () - * - * This function blocks until the specified I/O operation completes. It - * leverages the grouping of the related I/O requests to get good transfer - * rates, by queueing the requests. At higher speeds, such queuing can - * significantly improve USB throughput. - * - * There are three kinds of completion for this function. - * (1) success, where io->status is zero. The number of io->bytes - * transferred is as requested. - * (2) error, where io->status is a negative errno value. The number - * of io->bytes transferred before the error is usually less - * than requested, and can be nonzero. - * (3) cancelation, a type of error with status -ECONNRESET that - * is initiated by usb_sg_cancel(). - * - * When this function returns, all memory allocated through usb_sg_init() or - * this call will have been freed. The request block parameter may still be - * passed to usb_sg_cancel(), or it may be freed. It could also be - * reinitialized and then reused. - * - * Data Transfer Rates: - * - * Bulk transfers are valid for full or high speed endpoints. - * The best full speed data rate is 19 packets of 64 bytes each - * per frame, or 1216 bytes per millisecond. - * The best high speed data rate is 13 packets of 512 bytes each - * per microframe, or 52 KBytes per millisecond. - * - * The reason to use interrupt transfers through this API would most likely - * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond - * could be transferred. That capability is less useful for low or full - * speed interrupt endpoints, which allow at most one packet per millisecond, - * of at most 8 or 64 bytes (respectively). - */ -void usb_sg_wait (struct usb_sg_request *io) -{ - int i; - unsigned long flags; - - /* queue the urbs. */ - spin_lock_irqsave (&io->lock, flags); - for (i = 0; i < io->entries && !io->status; i++) { - int retval; - - retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC); - - /* after we submit, let completions or cancelations fire; - * we handshake using io->status. - */ - spin_unlock_irqrestore (&io->lock, flags); - switch (retval) { - /* maybe we retrying will recover */ - case -ENXIO: // hc didn't queue this one - case -EAGAIN: - case -ENOMEM: - retval = 0; - i--; - // FIXME: should it usb_sg_cancel() on INTERRUPT? - yield (); - break; - - /* no error? continue immediately. - * - * NOTE: to work better with UHCI (4K I/O buffer may - * need 3K of TDs) it may be good to limit how many - * URBs are queued at once; N milliseconds? - */ - case 0: - cpu_relax (); - break; - - /* fail any uncompleted urbs */ - default: - io->urbs [i]->status = retval; - dbg ("usb_sg_msg, submit --> %d", retval); - usb_sg_cancel (io); - } - spin_lock_irqsave (&io->lock, flags); - if (retval && io->status == -ECONNRESET) - io->status = retval; - } - spin_unlock_irqrestore (&io->lock, flags); - - /* OK, yes, this could be packaged as non-blocking. - * So could the submit loop above ... but it's easier to - * solve neither problem than to solve both! - */ - wait_for_completion (&io->complete); - - sg_clean (io); -} - -/** - * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait() - * @io: request block, initialized with usb_sg_init() - * - * This stops a request after it has been started by usb_sg_wait(). - * It can also prevents one initialized by usb_sg_init() from starting, - * so that call just frees resources allocated to the request. - */ -void usb_sg_cancel (struct usb_sg_request *io) -{ - unsigned long flags; - - spin_lock_irqsave (&io->lock, flags); - - /* shut everything down, if it didn't already */ - if (!io->status) { - int i; - - io->status = -ECONNRESET; - for (i = 0; i < io->entries; i++) { - int retval; - - if (!io->urbs [i]->dev) - continue; - retval = usb_unlink_urb (io->urbs [i]); - if (retval && retval != -EINPROGRESS) - warn ("usb_sg_cancel, unlink --> %d", retval); - // FIXME don't warn on "not yet submitted" error - } - } - spin_unlock_irqrestore (&io->lock, flags); -} -#endif -/*-------------------------------------------------------------------*/ - -/** - * usb_get_descriptor - issues a generic GET_DESCRIPTOR request - * @dev: the device whose descriptor is being retrieved - * @type: the descriptor type (USB_DT_*) - * @index: the number of the descriptor - * @buf: where to put the descriptor - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * Gets a USB descriptor. Convenience functions exist to simplify - * getting some types of descriptors. Use - * usb_get_device_descriptor() for USB_DT_DEVICE, - * and usb_get_string() or usb_string() for USB_DT_STRING. - * Configuration descriptors (USB_DT_CONFIG) are part of the device - * structure, at least for the current configuration. - * In addition to a number of USB-standard descriptors, some - * devices also use class-specific or vendor-specific descriptors. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size) -{ - int i = 5; - int result = 0; - - memset(buf,0,size); // Make sure we parse really received data - - while (i--) { - /* retries if the returned length was 0; flakey device */ - if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (type << 8) + index, 0, buf, size, - HZ * USB_CTRL_GET_TIMEOUT)) > 0 - || result == -EPIPE) - break; - } - return result; -} - -/** - * usb_get_string - gets a string descriptor - * @dev: the device whose string descriptor is being retrieved - * @langid: code for language chosen (from string descriptor zero) - * @index: the number of the descriptor - * @buf: where to put the string - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character, - * in little-endian byte order). - * The usb_string() function will often be a convenient way to turn - * these strings into kernel-printable form. - * - * Strings may be referenced in device, configuration, interface, or other - * descriptors, and could also be used in vendor-specific ways. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (USB_DT_STRING << 8) + index, langid, buf, size, - HZ * USB_CTRL_GET_TIMEOUT); -} - -/** - * usb_get_device_descriptor - (re)reads the device descriptor - * @dev: the device whose device descriptor is being updated - * Context: !in_interrupt () - * - * Updates the copy of the device descriptor stored in the device structure, - * which dedicates space for this purpose. Note that several fields are - * converted to the host CPU's byte order: the USB version (bcdUSB), and - * vendors product and version fields (idVendor, idProduct, and bcdDevice). - * That lets device drivers compare against non-byteswapped constants. - * - * There's normally no need to use this call, although some devices - * will change their descriptors after events like updating firmware. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_device_descriptor(struct usb_device *dev) -{ - int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, - sizeof(dev->descriptor)); - if (ret >= 0) { - le16_to_cpus(&dev->descriptor.bcdUSB); - le16_to_cpus(&dev->descriptor.idVendor); - le16_to_cpus(&dev->descriptor.idProduct); - le16_to_cpus(&dev->descriptor.bcdDevice); - } - return ret; -} - -/** - * usb_get_status - issues a GET_STATUS call - * @dev: the device whose status is being checked - * @type: USB_RECIP_*; for device, interface, or endpoint - * @target: zero (for device), else interface or endpoint number - * @data: pointer to two bytes of bitmap data - * Context: !in_interrupt () - * - * Returns device, interface, or endpoint status. Normally only of - * interest to see if the device is self powered, or has enabled the - * remote wakeup facility; or whether a bulk or interrupt endpoint - * is halted ("stalled"). - * - * Bits in these status bitmaps are set using the SET_FEATURE request, - * and cleared using the CLEAR_FEATURE request. The usb_clear_halt() - * function should be used to clear halt ("stall") status. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. - */ -int usb_get_status(struct usb_device *dev, int type, int target, void *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, - HZ * USB_CTRL_GET_TIMEOUT); -} - - -// hub-only!! ... and only exported for reset/reinit path. -// otherwise used internally, when setting up a config -void usb_set_maxpacket(struct usb_device *dev) -{ - int i, b; - - /* NOTE: affects all endpoints _except_ ep0 */ - for (i=0; iactconfig->desc.bNumInterfaces; i++) { - struct usb_interface *ifp = dev->actconfig->interface + i; - struct usb_host_interface *as = ifp->altsetting + ifp->act_altsetting; - struct usb_host_endpoint *ep = as->endpoint; - int e; - - for (e=0; edesc.bNumEndpoints; e++) { - struct usb_endpoint_descriptor *d; - d = &ep [e].desc; - b = d->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if ((d->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ - dev->epmaxpacketout[b] = d->wMaxPacketSize; - dev->epmaxpacketin [b] = d->wMaxPacketSize; - } - else if (usb_endpoint_out(d->bEndpointAddress)) { - if (d->wMaxPacketSize > dev->epmaxpacketout[b]) - dev->epmaxpacketout[b] = d->wMaxPacketSize; - } - else { - if (d->wMaxPacketSize > dev->epmaxpacketin [b]) - dev->epmaxpacketin [b] = d->wMaxPacketSize; - } - } - } -} - -/** - * usb_clear_halt - tells device to clear endpoint halt/stall condition - * @dev: device whose endpoint is halted - * @pipe: endpoint "pipe" being cleared - * Context: !in_interrupt () - * - * This is used to clear halt conditions for bulk and interrupt endpoints, - * as reported by URB completion status. Endpoints that are halted are - * sometimes referred to as being "stalled". Such endpoints are unable - * to transmit or receive data until the halt status is cleared. Any URBs - * queued for such an endpoint should normally be unlinked by the driver - * before clearing the halt condition, as described in sections 5.7.5 - * and 5.8.5 of the USB 2.0 spec. - * - * Note that control and isochronous endpoints don't halt, although control - * endpoints report "protocol stall" (for unsupported requests) using the - * same status code used to report a true stall. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns zero on success, or else the status code returned by the - * underlying usb_control_msg() call. - */ -int usb_clear_halt(struct usb_device *dev, int pipe) -{ - int result; - int endp = usb_pipeendpoint(pipe); - - if (usb_pipein (pipe)) - endp |= USB_DIR_IN; - - /* we don't care if it wasn't halted first. in fact some devices - * (like some ibmcam model 1 units) seem to expect hosts to make - * this request for iso endpoints, which can't halt! - */ - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, - HZ * USB_CTRL_SET_TIMEOUT); - - /* don't un-halt or force to DATA0 except on success */ - if (result < 0) - return result; - - /* NOTE: seems like Microsoft and Apple don't bother verifying - * the clear "took", so some devices could lock up if you check... - * such as the Hagiwara FlashGate DUAL. So we won't bother. - * - * NOTE: make sure the logic here doesn't diverge much from - * the copy in usb-storage, for as long as we need two copies. - */ - - /* toggle was reset by the clear, then ep was reactivated */ - usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); - usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); - - return 0; -} - -/** - * usb_set_interface - Makes a particular alternate setting be current - * @dev: the device whose interface is being updated - * @interface: the interface being updated - * @alternate: the setting being chosen. - * Context: !in_interrupt () - * - * This is used to enable data transfers on interfaces that may not - * be enabled by default. Not all devices support such configurability. - * Only the driver bound to an interface may change its setting. - * - * Within any given configuration, each interface may have several - * alternative settings. These are often used to control levels of - * bandwidth consumption. For example, the default setting for a high - * speed interrupt endpoint may not send more than 64 bytes per microframe, - * while interrupt transfers of up to 3KBytes per microframe are legal. - * Also, isochronous endpoints may never be part of an - * interface's default setting. To access such bandwidth, alternate - * interface settings must be made current. - * - * Note that in the Linux USB subsystem, bandwidth associated with - * an endpoint in a given alternate setting is not reserved until an URB - * is submitted that needs that bandwidth. Some other operating systems - * allocate bandwidth early, when a configuration is chosen. - * - * This call is synchronous, and may not be used in an interrupt context. - * Also, drivers must not change altsettings while urbs are scheduled for - * endpoints in that interface; all such urbs must first be completed - * (perhaps forced by unlinking). - * - * Returns zero on success, or else the status code returned by the - * underlying usb_control_msg() call. - */ -int usb_set_interface(struct usb_device *dev, int interface, int alternate) -{ - struct usb_interface *iface; - struct usb_host_interface *iface_as; - int i, ret; - void (*disable)(struct usb_device *, int) = dev->bus->op->disable; - - iface = usb_ifnum_to_if(dev, interface); - if (!iface) { - warn("selecting invalid interface %d", interface); - return -EINVAL; - } - - /* 9.4.10 says devices don't need this, if the interface - only has one alternate setting */ - if (iface->num_altsetting == 1) { - dbg("ignoring set_interface for dev %d, iface %d, alt %d", - dev->devnum, interface, alternate); - return 0; - } - - if (alternate < 0 || alternate >= iface->num_altsetting) - return -EINVAL; - - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, - iface->altsetting[alternate] - .desc.bAlternateSetting, - interface, NULL, 0, HZ * 5)) < 0) - return ret; - - /* FIXME drivers shouldn't need to replicate/bugfix the logic here - * when they implement async or easily-killable versions of this or - * other "should-be-internal" functions (like clear_halt). - * should hcd+usbcore postprocess control requests? - */ - - /* prevent submissions using previous endpoint settings */ - iface_as = iface->altsetting + iface->act_altsetting; - for (i = 0; i < iface_as->desc.bNumEndpoints; i++) { - u8 ep = iface_as->endpoint [i].desc.bEndpointAddress; - int out = !(ep & USB_DIR_IN); - - /* clear out hcd state, then usbcore state */ - if (disable) - disable (dev, ep); - ep &= USB_ENDPOINT_NUMBER_MASK; - (out ? dev->epmaxpacketout : dev->epmaxpacketin ) [ep] = 0; - } - iface->act_altsetting = alternate; - - /* 9.1.1.5: reset toggles for all endpoints affected by this iface-as - * - * Note: - * Despite EP0 is always present in all interfaces/AS, the list of - * endpoints from the descriptor does not contain EP0. Due to its - * omnipresence one might expect EP0 being considered "affected" by - * any SetInterface request and hence assume toggles need to be reset. - * However, EP0 toggles are re-synced for every individual transfer - * during the SETUP stage - hence EP0 toggles are "don't care" here. - * (Likewise, EP0 never "halts" on well designed devices.) - */ - - iface_as = &iface->altsetting[alternate]; - for (i = 0; i < iface_as->desc.bNumEndpoints; i++) { - u8 ep = iface_as->endpoint[i].desc.bEndpointAddress; - int out = !(ep & USB_DIR_IN); - - ep &= USB_ENDPOINT_NUMBER_MASK; - usb_settoggle (dev, ep, out, 0); - (out ? dev->epmaxpacketout : dev->epmaxpacketin) [ep] - = iface_as->endpoint [i].desc.wMaxPacketSize; - usb_endpoint_running (dev, ep, out); - } - - return 0; -} - -/** - * usb_set_configuration - Makes a particular device setting be current - * @dev: the device whose configuration is being updated - * @configuration: the configuration being chosen. - * Context: !in_interrupt () - * - * This is used to enable non-default device modes. Not all devices - * support this kind of configurability. By default, configuration - * zero is selected after enumeration; many devices only have a single - * configuration. - * - * USB devices may support one or more configurations, which affect - * power consumption and the functionality available. For example, - * the default configuration is limited to using 100mA of bus power, - * so that when certain device functionality requires more power, - * and the device is bus powered, that functionality will be in some - * non-default device configuration. Other device modes may also be - * reflected as configuration options, such as whether two ISDN - * channels are presented as independent 64Kb/s interfaces or as one - * bonded 128Kb/s interface. - * - * Note that USB has an additional level of device configurability, - * associated with interfaces. That configurability is accessed using - * usb_set_interface(). - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns zero on success, or else the status code returned by the - * underlying usb_control_msg() call. - */ -int usb_set_configuration(struct usb_device *dev, int configuration) -{ - int i, ret; - struct usb_host_config *cp = NULL; - void (*disable)(struct usb_device *, int) = dev->bus->op->disable; - - for (i=0; idescriptor.bNumConfigurations; i++) { - if (dev->config[i].desc.bConfigurationValue == configuration) { - cp = &dev->config[i]; - break; - } - } - if ((!cp && configuration != 0) || (cp && configuration == 0)) { - warn("selecting invalid configuration %d", configuration); - return -EINVAL; - } - - /* if it's already configured, clear out old state first. */ - if (dev->state != USB_STATE_ADDRESS && disable) { - for (i = 1 /* skip ep0 */; i < 15; i++) { - disable (dev, i); - disable (dev, USB_DIR_IN | i); - } - } - dev->toggle[0] = dev->toggle[1] = 0; - dev->halted[0] = dev->halted[1] = 0; - dev->state = USB_STATE_ADDRESS; - - if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, configuration, 0, - NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) - return ret; - if (configuration) - dev->state = USB_STATE_CONFIGURED; - dev->actconfig = cp; - - /* reset more hc/hcd endpoint state */ - usb_set_maxpacket(dev); - - return 0; -} - - -/** - * usb_string - returns ISO 8859-1 version of a string descriptor - * @dev: the device whose string descriptor is being retrieved - * @index: the number of the descriptor - * @buf: where to put the string - * @size: how big is "buf"? - * Context: !in_interrupt () - * - * This converts the UTF-16LE encoded strings returned by devices, from - * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones - * that are more usable in most kernel contexts. Note that all characters - * in the chosen descriptor that can't be encoded using ISO-8859-1 - * are converted to the question mark ("?") character, and this function - * chooses strings in the first language supported by the device. - * - * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit - * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode, - * and is appropriate for use many uses of English and several other - * Western European languages. (But it doesn't include the "Euro" symbol.) - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Returns length of the string (>= 0) or usb_control_msg status (< 0). - */ -int usb_string(struct usb_device *dev, int index, char *buf, size_t size) -{ - unsigned char *tbuf; - int err, len; - unsigned int u, idx; - - if (size <= 0 || !buf || !index) - return -EINVAL; - buf[0] = 0; - tbuf = kmalloc(256, GFP_KERNEL); - if (!tbuf) - return -ENOMEM; - - /* get langid for strings if it's not yet known */ - if (!dev->have_langid) { - err = usb_get_string(dev, 0, 0, tbuf, 4); - if (err < 0) { - err("error getting string descriptor 0 (error=%d)", err); - goto errout; - } else if (tbuf[0] < 4) { - err("string descriptor 0 too short"); - err = -EINVAL; - goto errout; - } else { - dev->have_langid = -1; - dev->string_langid = tbuf[2] | (tbuf[3]<< 8); - /* always use the first langid listed */ - dbg("USB device number %d default language ID 0x%x", - dev->devnum, dev->string_langid); - } - } - - /* - * ask for the length of the string - */ - - err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); - if(err<2) - goto errout; - len=tbuf[0]; - - err = usb_get_string(dev, dev->string_langid, index, tbuf, len); - if (err < 0) - goto errout; - - size--; /* leave room for trailing NULL char in output buffer */ - for (idx = 0, u = 2; u < err; u += 2) { - if (idx >= size) - break; - if (tbuf[u+1]) /* high byte */ - buf[idx++] = '?'; /* non ISO-8859-1 character */ - else - buf[idx++] = tbuf[u]; - } - buf[idx] = 0; - err = idx; - - errout: - kfree(tbuf); - return err; -} - -// synchronous request completion model -EXPORT_SYMBOL(usb_control_msg); -EXPORT_SYMBOL(usb_bulk_msg); - -EXPORT_SYMBOL(usb_sg_init); -EXPORT_SYMBOL(usb_sg_cancel); -EXPORT_SYMBOL(usb_sg_wait); - -// synchronous control message convenience routines -EXPORT_SYMBOL(usb_get_descriptor); -EXPORT_SYMBOL(usb_get_device_descriptor); -EXPORT_SYMBOL(usb_get_status); -EXPORT_SYMBOL(usb_get_string); -EXPORT_SYMBOL(usb_string); -EXPORT_SYMBOL(usb_clear_halt); -EXPORT_SYMBOL(usb_set_configuration); -EXPORT_SYMBOL(usb_set_interface); - diff --git a/reactos/drivers/usb/usbport/urb.c b/reactos/drivers/usb/usbport/urb.c deleted file mode 100644 index ef945d016c0..00000000000 --- a/reactos/drivers/usb/usbport/urb.c +++ /dev/null @@ -1,398 +0,0 @@ -#include "../miniport/usb_wrapper.h" -#include "hcd.h" - -/** - * usb_init_urb - initializes a urb so that it can be used by a USB driver - * @urb: pointer to the urb to initialize - * - * Initializes a urb so that the USB subsystem can use it properly. - * - * If a urb is created with a call to usb_alloc_urb() it is not - * necessary to call this function. Only use this if you allocate the - * space for a struct urb on your own. If you call this function, be - * careful when freeing the memory for your urb that it is no longer in - * use by the USB core. - * - * Only use this function if you _really_ understand what you are doing. - */ -void STDCALL usb_init_urb(struct urb *urb) -{ - if (urb) { - memset(urb, 0, sizeof(*urb)); - urb->count = (atomic_t)ATOMIC_INIT(1); - spin_lock_init(&urb->lock); - } -} - -/** - * usb_alloc_urb - creates a new urb for a USB driver to use - * @iso_packets: number of iso packets for this urb - * @mem_flags: the type of memory to allocate, see kmalloc() for a list of - * valid options for this. - * - * Creates an urb for the USB driver to use, initializes a few internal - * structures, incrementes the usage counter, and returns a pointer to it. - * - * If no memory is available, NULL is returned. - * - * If the driver want to use this urb for interrupt, control, or bulk - * endpoints, pass '0' as the number of iso packets. - * - * The driver must call usb_free_urb() when it is finished with the urb. - */ -struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags) -{ - struct urb *urb; - - urb = (struct urb *)kmalloc(sizeof(struct urb) + - iso_packets * sizeof(struct usb_iso_packet_descriptor), - mem_flags); - if (!urb) { - err("alloc_urb: kmalloc failed"); - return NULL; - } - usb_init_urb(urb); - return urb; -} - -/** - * usb_free_urb - frees the memory used by a urb when all users of it are finished - * @urb: pointer to the urb to free - * - * Must be called when a user of a urb is finished with it. When the last user - * of the urb calls this function, the memory of the urb is freed. - * - * Note: The transfer buffer associated with the urb is not freed, that must be - * done elsewhere. - */ -void STDCALL usb_free_urb(struct urb *urb) -{ - if (urb) - if (atomic_dec_and_test(&urb->count)) - { - kfree(urb); - } -} - -/** - * usb_get_urb - increments the reference count of the urb - * @urb: pointer to the urb to modify - * - * This must be called whenever a urb is transferred from a device driver to a - * host controller driver. This allows proper reference counting to happen - * for urbs. - * - * A pointer to the urb with the incremented reference counter is returned. - */ -struct urb STDCALL * usb_get_urb(struct urb *urb) -{ - if (urb) { - atomic_inc(&urb->count); - return urb; - } else - return NULL; -} - - -/*-------------------------------------------------------------------*/ - -/** - * usb_submit_urb - issue an asynchronous transfer request for an endpoint - * @urb: pointer to the urb describing the request - * @mem_flags: the type of memory to allocate, see kmalloc() for a list - * of valid options for this. - * - * This submits a transfer request, and transfers control of the URB - * describing that request to the USB subsystem. Request completion will - * be indicated later, asynchronously, by calling the completion handler. - * The three types of completion are success, error, and unlink - * (also called "request cancellation"). - * URBs may be submitted in interrupt context. - * - * The caller must have correctly initialized the URB before submitting - * it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are - * available to ensure that most fields are correctly initialized, for - * the particular kind of transfer, although they will not initialize - * any transfer flags. - * - * Successful submissions return 0; otherwise this routine returns a - * negative error number. If the submission is successful, the complete() - * callback from the urb will be called exactly once, when the USB core and - * host controller driver are finished with the urb. When the completion - * function is called, control of the URB is returned to the device - * driver which issued the request. The completion handler may then - * immediately free or reuse that URB. - * - * For control endpoints, the synchronous usb_control_msg() call is - * often used (in non-interrupt context) instead of this call. - * That is often used through convenience wrappers, for the requests - * that are standardized in the USB 2.0 specification. For bulk - * endpoints, a synchronous usb_bulk_msg() call is available. - * - * Request Queuing: - * - * URBs may be submitted to endpoints before previous ones complete, to - * minimize the impact of interrupt latencies and system overhead on data - * throughput. This is required for continuous isochronous data streams, - * and may also be required for some kinds of interrupt transfers. Such - * queueing also maximizes bandwidth utilization by letting USB controllers - * start work on later requests before driver software has finished the - * completion processing for earlier requests. - * - * Bulk and Isochronous URBs may always be queued. At this writing, all - * mainstream host controller drivers support queueing for control and - * interrupt transfer requests. - * - * Reserved Bandwidth Transfers: - * - * Periodic transfers (interrupt or isochronous) are performed repeatedly, - * using the interval specified in the urb. Submitting the first urb to - * the endpoint reserves the bandwidth necessary to make those transfers. - * If the USB subsystem can't allocate sufficient bandwidth to perform - * the periodic request, submitting such a periodic request should fail. - * - * Device drivers must explicitly request that repetition, by ensuring that - * some URB is always on the endpoint's queue (except possibly for short - * periods during completion callacks). When there is no longer an urb - * queued, the endpoint's bandwidth reservation is canceled. This means - * drivers can use their completion handlers to ensure they keep bandwidth - * they need, by reinitializing and resubmitting the just-completed urb - * until the driver longer needs that periodic bandwidth. - * - * Memory Flags: - * - * The general rules for how to decide which mem_flags to use - * are the same as for kmalloc. There are four - * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and - * GFP_ATOMIC. - * - * GFP_NOFS is not ever used, as it has not been implemented yet. - * - * GFP_ATOMIC is used when - * (a) you are inside a completion handler, an interrupt, bottom half, - * tasklet or timer, or - * (b) you are holding a spinlock or rwlock (does not apply to - * semaphores), or - * (c) current->state != TASK_RUNNING, this is the case only after - * you've changed it. - * - * GFP_NOIO is used in the block io path and error handling of storage - * devices. - * - * All other situations use GFP_KERNEL. - * - * Some more specific rules for mem_flags can be inferred, such as - * (1) start_xmit, timeout, and receive methods of network drivers must - * use GFP_ATOMIC (they are called with a spinlock held); - * (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also - * called with a spinlock held); - * (3) If you use a kernel thread with a network driver you must use - * GFP_NOIO, unless (b) or (c) apply; - * (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c) - * apply or your are in a storage driver's block io path; - * (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and - * (6) changing firmware on a running storage or net device uses - * GFP_NOIO, unless b) or c) apply - * - */ -int STDCALL usb_submit_urb(struct urb *urb, int mem_flags) -{ - int pipe, temp, max; - struct usb_device *dev; - struct usb_operations *op; - int is_out; - //printk("sub dev %p bus %p num %i op %p sub %p\n", - // urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb); - if (!urb || urb->hcpriv || !urb->complete) - return -EINVAL; - if (!(dev = urb->dev) || - (dev->state < USB_STATE_DEFAULT) || - (!dev->bus) || (dev->devnum <= 0)) - return -ENODEV; - if (!(op = dev->bus->op) || !op->submit_urb) - return -ENODEV; - - urb->status = -EINPROGRESS; - urb->actual_length = 0; - urb->bandwidth = 0; - - /* Lots of sanity checks, so HCDs can rely on clean data - * and don't need to duplicate tests - */ - pipe = urb->pipe; - temp = usb_pipetype (pipe); - is_out = usb_pipeout (pipe); - - if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) - return -ENODEV; - - /* (actually HCDs may need to duplicate this, endpoint might yet - * stall due to queued bulk/intr transactions that complete after - * we check) - */ - if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out)) - return -EPIPE; - - /* FIXME there should be a sharable lock protecting us against - * config/altsetting changes and disconnects, kicking in here. - * (here == before maxpacket, and eventually endpoint type, - * checks get made.) - */ - - max = usb_maxpacket (dev, pipe, is_out); - if (max <= 0) { - dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)", - __FUNCTION__, - usb_pipeendpoint (pipe), is_out ? "OUT" : "IN", - dev->bus->bus_name, dev->devpath, - max); - return -EMSGSIZE; - } - - /* periodic transfers limit size per frame/uframe, - * but drivers only control those sizes for ISO. - * while we're checking, initialize return status. - */ - if (temp == PIPE_ISOCHRONOUS) { - int n, len; - - /* "high bandwidth" mode, 1-3 packets/uframe? */ - if (dev->speed == USB_SPEED_HIGH) { - int mult = 1 + ((max >> 11) & 0x03); - max &= 0x03ff; - max *= mult; - } - - if (urb->number_of_packets <= 0) - return -EINVAL; - for (n = 0; n < urb->number_of_packets; n++) { - len = urb->iso_frame_desc [n].length; - if (len < 0 || len > max) - return -EMSGSIZE; - urb->iso_frame_desc [n].status = -EXDEV; - urb->iso_frame_desc [n].actual_length = 0; - } - } - - /* the I/O buffer must be mapped/unmapped, except when length=0 */ - if (urb->transfer_buffer_length < 0) - return -EMSGSIZE; - -#ifdef DEBUG - /* stuff that drivers shouldn't do, but which shouldn't - * cause problems in HCDs if they get it wrong. - */ - { - unsigned int orig_flags = urb->transfer_flags; - unsigned int allowed; - - /* enforce simple/standard policy */ - allowed = URB_ASYNC_UNLINK; // affects later unlinks - allowed |= URB_NO_DMA_MAP; - allowed |= URB_NO_INTERRUPT; - switch (temp) { - case PIPE_BULK: - if (is_out) - allowed |= URB_ZERO_PACKET; - /* FALLTHROUGH */ - case PIPE_CONTROL: - allowed |= URB_NO_FSBR; /* only affects UHCI */ - /* FALLTHROUGH */ - default: /* all non-iso endpoints */ - if (!is_out) - allowed |= URB_SHORT_NOT_OK; - break; - case PIPE_ISOCHRONOUS: - allowed |= URB_ISO_ASAP; - break; - } - urb->transfer_flags &= allowed; - - /* fail if submitter gave bogus flags */ - if (urb->transfer_flags != orig_flags) { - err ("BOGUS urb flags, %x --> %x", - orig_flags, urb->transfer_flags); - return -EINVAL; - } - } -#endif - /* - * Force periodic transfer intervals to be legal values that are - * a power of two (so HCDs don't need to). - * - * FIXME want bus->{intr,iso}_sched_horizon values here. Each HC - * supports different values... this uses EHCI/UHCI defaults (and - * EHCI can use smaller non-default values). - */ - switch (temp) { - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - /* too small? */ - if (urb->interval <= 0) - return -EINVAL; - /* too big? */ - switch (dev->speed) { - case USB_SPEED_HIGH: /* units are microframes */ - // NOTE usb handles 2^15 - if (urb->interval > (1024 * 8)) - urb->interval = 1024 * 8; - temp = 1024 * 8; - break; - case USB_SPEED_FULL: /* units are frames/msec */ - case USB_SPEED_LOW: - if (temp == PIPE_INTERRUPT) { - if (urb->interval > 255) - return -EINVAL; - // NOTE ohci only handles up to 32 - temp = 128; - } else { - if (urb->interval > 1024) - urb->interval = 1024; - // NOTE usb and ohci handle up to 2^15 - temp = 1024; - } - break; - default: - return -EINVAL; - } - /* power of two? */ - while (temp > urb->interval) - temp >>= 1; - urb->interval = temp; - } - - return op->submit_urb (urb, mem_flags); -} - -/*-------------------------------------------------------------------*/ - -/** - * usb_unlink_urb - abort/cancel a transfer request for an endpoint - * @urb: pointer to urb describing a previously submitted request - * - * This routine cancels an in-progress request. The requests's - * completion handler will be called with a status code indicating - * that the request has been canceled, and that control of the URB - * has been returned to that device driver. - * - * When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this - * request is synchronous. Success is indicated by returning zero, - * at which time the urb will have been unlinked, - * and the completion function will see status -ENOENT. Failure is - * indicated by any other return value. This mode may not be used - * when unlinking an urb from an interrupt context, such as a bottom - * half or a completion handler, - * - * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this - * request is asynchronous. Success is indicated by returning -EINPROGRESS, - * at which time the urb will normally not have been unlinked, - * and the completion function will see status -ECONNRESET. Failure is - * indicated by any other return value. - */ -int STDCALL usb_unlink_urb(struct urb *urb) -{ - if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) - return urb->dev->bus->op->unlink_urb(urb); - else - return -ENODEV; -} diff --git a/reactos/drivers/usb/usbport/usb-debug.c b/reactos/drivers/usb/usbport/usb-debug.c deleted file mode 100644 index b8742ad67dc..00000000000 --- a/reactos/drivers/usb/usbport/usb-debug.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * debug.c - USB debug helper routines. - * - * I just want these out of the way where they aren't in your - * face, but so that you can still use them.. - */ -#define CONFIG_USB_DEBUG -#if 0 -#include -#include -#include -#include -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif -#include -#else -#include "../miniport/usb_wrapper.h" -#endif - -static void usb_show_endpoint(struct usb_host_endpoint *endpoint) -{ - usb_show_endpoint_descriptor(&endpoint->desc); -} - -static void usb_show_interface(struct usb_host_interface *altsetting) -{ - int i; - - usb_show_interface_descriptor(&altsetting->desc); - - for (i = 0; i < altsetting->desc.bNumEndpoints; i++) - usb_show_endpoint(altsetting->endpoint + i); -} - -static void usb_show_config(struct usb_host_config *config) -{ - int i, j; - struct usb_interface *ifp; - - usb_show_config_descriptor(&config->desc); - for (i = 0; i < config->desc.bNumInterfaces; i++) { - ifp = config->interface + i; - - if (!ifp) - break; - - printk("\n Interface: %d\n", i); - for (j = 0; j < ifp->num_altsetting; j++) - usb_show_interface(ifp->altsetting + j); - } -} - -void usb_show_device(struct usb_device *dev) -{ - int i; - - usb_show_device_descriptor(&dev->descriptor); - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) - usb_show_config(dev->config + i); -} - -/* - * Parse and show the different USB descriptors. - */ -void usb_show_device_descriptor(struct usb_device_descriptor *desc) -{ - if (!desc) - { - printk("Invalid USB device descriptor (NULL POINTER)\n"); - return; - } - printk(" Length = %2d%s\n", desc->bLength, - desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)"); - printk(" DescriptorType = %02x\n", desc->bDescriptorType); - - printk(" USB version = %x.%02x\n", - desc->bcdUSB >> 8, desc->bcdUSB & 0xff); - printk(" Vendor:Product = %04x:%04x\n", - desc->idVendor, desc->idProduct); - printk(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0); - printk(" NumConfigurations = %d\n", desc->bNumConfigurations); - printk(" Device version = %x.%02x\n", - desc->bcdDevice >> 8, desc->bcdDevice & 0xff); - - printk(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n", - desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol); - switch (desc->bDeviceClass) { - case 0: - printk(" Per-interface classes\n"); - break; - case USB_CLASS_AUDIO: - printk(" Audio device class\n"); - break; - case USB_CLASS_COMM: - printk(" Communications class\n"); - break; - case USB_CLASS_HID: - printk(" Human Interface Devices class\n"); - break; - case USB_CLASS_PRINTER: - printk(" Printer device class\n"); - break; - case USB_CLASS_MASS_STORAGE: - printk(" Mass Storage device class\n"); - break; - case USB_CLASS_HUB: - printk(" Hub device class\n"); - break; - case USB_CLASS_VENDOR_SPEC: - printk(" Vendor class\n"); - break; - default: - printk(" Unknown class\n"); - } -} - -void usb_show_config_descriptor(struct usb_config_descriptor *desc) -{ - printk("Configuration:\n"); - printk(" bLength = %4d%s\n", desc->bLength, - desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)"); - printk(" bDescriptorType = %02x\n", desc->bDescriptorType); - printk(" wTotalLength = %04x\n", desc->wTotalLength); - printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces); - printk(" bConfigurationValue = %02x\n", desc->bConfigurationValue); - printk(" iConfiguration = %02x\n", desc->iConfiguration); - printk(" bmAttributes = %02x\n", desc->bmAttributes); - printk(" bMaxPower = %4dmA\n", desc->bMaxPower * 2); -} - -void usb_show_interface_descriptor(struct usb_interface_descriptor *desc) -{ - printk(" Alternate Setting: %2d\n", desc->bAlternateSetting); - printk(" bLength = %4d%s\n", desc->bLength, - desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)"); - printk(" bDescriptorType = %02x\n", desc->bDescriptorType); - printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber); - printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting); - printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints); - printk(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n", - desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol); - printk(" iInterface = %02x\n", desc->iInterface); -} - -void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc) -{ - char *LengthCommentString = (desc->bLength == - USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength == - USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)"; - char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" }; - - printk(" Endpoint:\n"); - printk(" bLength = %4d%s\n", - desc->bLength, LengthCommentString); - printk(" bDescriptorType = %02x\n", desc->bDescriptorType); - printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress, - (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL ? "i/o" : - (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out"); - printk(" bmAttributes = %02x (%s)\n", desc->bmAttributes, - EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]); - printk(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize); - printk(" bInterval = %02x\n", desc->bInterval); - - /* Audio extensions to the endpoint descriptor */ - if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) { - printk(" bRefresh = %02x\n", desc->bRefresh); - printk(" bSynchAddress = %02x\n", desc->bSynchAddress); - } -} - -void usb_show_string(struct usb_device *dev, char *id, int index) -{ - char *buf; - - if (!index) - return; - if (!(buf = kmalloc(256, GFP_KERNEL))) - return; - if (usb_string(dev, index, buf, 256) > 0) - dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf); - kfree(buf); -} - -void usb_dump_urb (struct urb *urb) -{ - printk ("urb :%p\n", urb); - printk ("dev :%p\n", urb->dev); - printk ("pipe :%08X\n", urb->pipe); - printk ("status :%d\n", urb->status); - printk ("transfer_flags :%08X\n", urb->transfer_flags); - printk ("transfer_buffer :%p\n", urb->transfer_buffer); - printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length); - printk ("actual_length :%d\n", urb->actual_length); - printk ("setup_packet :%p\n", urb->setup_packet); - printk ("start_frame :%d\n", urb->start_frame); - printk ("number_of_packets :%d\n", urb->number_of_packets); - printk ("interval :%d\n", urb->interval); - printk ("error_count :%d\n", urb->error_count); - printk ("context :%p\n", urb->context); - printk ("complete :%p\n", urb->complete); -} - diff --git a/reactos/drivers/usb/usbport/usb.c b/reactos/drivers/usb/usbport/usb.c deleted file mode 100644 index f9b936f0b48..00000000000 --- a/reactos/drivers/usb/usbport/usb.c +++ /dev/null @@ -1,1627 +0,0 @@ -/* - * drivers/usb/usb.c - * - * (C) Copyright Linus Torvalds 1999 - * (C) Copyright Johannes Erdfelt 1999-2001 - * (C) Copyright Andreas Gal 1999 - * (C) Copyright Gregory P. Smith 1999 - * (C) Copyright Deti Fliegl 1999 (new USB architecture) - * (C) Copyright Randy Dunlap 2000 - * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id, - more docs, etc) - * (C) Copyright Yggdrasil Computing, Inc. 2000 - * (usb_device_id matching changes by Adam J. Richter) - * (C) Copyright Greg Kroah-Hartman 2002-2003 - * - * NOTE! This is not actually a driver at all, rather this is - * just a collection of helper routines that implement the - * generic USB things that the real drivers can use.. - * - * Think of this as a "USB library" rather than anything else. - * It should be considered a slave, with no callbacks. Callbacks - * are evil. - */ - -#if 0 -#include - -#ifdef CONFIG_USB_DEBUG - #define DEBUG -#else - #undef DEBUG -#endif - -#include -#include -#include -#include -#include /* for in_interrupt() */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "hcd.h" -#include "usb.h" -#else -#include "../miniport/usb_wrapper.h" -#include "hcd.h" -#endif - -extern int usb_hub_init(void); -extern void usb_hub_cleanup(void); -extern int usb_major_init(void); -extern void usb_major_cleanup(void); - - -int nousb; /* Disable USB when built into kernel image */ - /* Not honored on modular build */ - - -static int generic_probe (struct device *dev) -{ - return 0; -} -static int generic_remove (struct device *dev) -{ - return 0; -} - -static struct device_driver usb_generic_driver = { - .name = "usb", - .bus = &usb_bus_type, - .probe = generic_probe, - .remove = generic_remove, -}; - -static int usb_generic_driver_data; - -/* needs to be called with BKL held */ -int usb_device_probe(struct device *dev) -{ - struct usb_interface * intf = to_usb_interface(dev); - struct usb_driver * driver = to_usb_driver(dev->driver); - const struct usb_device_id *id; - int error = -ENODEV; - - dev_dbg(dev, "%s\n", __FUNCTION__); - - if (!driver->probe) - return error; - /* driver claim() doesn't yet affect dev->driver... */ - if (intf->driver) - return error; - - id = usb_match_id (intf, driver->id_table); - if (id) { - dev_dbg (dev, "%s - got id\n", __FUNCTION__); - down (&driver->serialize); - error = driver->probe (intf, id); - up (&driver->serialize); - } - if (!error) - intf->driver = driver; - - return error; -} - -int usb_device_remove(struct device *dev) -{ - struct usb_interface *intf; - struct usb_driver *driver; - - intf = list_entry(dev,struct usb_interface,dev); - driver = to_usb_driver(dev->driver); - - down(&driver->serialize); - - if (intf->driver && intf->driver->disconnect) - intf->driver->disconnect(intf); - - /* if driver->disconnect didn't release the interface */ - if (intf->driver) - usb_driver_release_interface(driver, intf); - - up(&driver->serialize); - - return 0; -} - -/** - * usb_register - register a USB driver - * @new_driver: USB operations for the driver - * - * Registers a USB driver with the USB core. The list of unattached - * interfaces will be rescanned whenever a new driver is added, allowing - * the new driver to attach to any recognized devices. - * Returns a negative error code on failure and 0 on success. - * - * NOTE: if you want your driver to use the USB major number, you must call - * usb_register_dev() to enable that functionality. This function no longer - * takes care of that. - */ -int usb_register(struct usb_driver *new_driver) -{ - int retval = 0; - - if (nousb) - return -ENODEV; - - new_driver->driver.name = (char *)new_driver->name; - new_driver->driver.bus = &usb_bus_type; - new_driver->driver.probe = usb_device_probe; - new_driver->driver.remove = usb_device_remove; - - init_MUTEX(&new_driver->serialize); - - retval = driver_register(&new_driver->driver); - - if (!retval) { - info("registered new driver %s", new_driver->name); - usbfs_update_special(); - } else { - err("problem %d when registering driver %s", - retval, new_driver->name); - } - - return retval; -} - -/** - * usb_deregister - unregister a USB driver - * @driver: USB operations of the driver to unregister - * Context: !in_interrupt (), must be called with BKL held - * - * Unlinks the specified driver from the internal USB driver list. - * - * NOTE: If you called usb_register_dev(), you still need to call - * usb_deregister_dev() to clean up your driver's allocated minor numbers, - * this * call will no longer do it for you. - */ -void usb_deregister(struct usb_driver *driver) -{ - info("deregistering driver %s", driver->name); - - driver_unregister (&driver->driver); - - usbfs_update_special(); -} - -/** - * usb_ifnum_to_if - get the interface object with a given interface number (usbcore-internal) - * @dev: the device whose current configuration is considered - * @ifnum: the desired interface - * - * This walks the device descriptor for the currently active configuration - * and returns a pointer to the interface with that particular interface - * number, or null. - * - * Note that configuration descriptors are not required to assign interface - * numbers sequentially, so that it would be incorrect to assume that - * the first interface in that descriptor corresponds to interface zero. - * This routine helps device drivers avoid such mistakes. - * However, you should make sure that you do the right thing with any - * alternate settings available for this interfaces. - */ -struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) -{ - int i; - - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) - if (dev->actconfig->interface[i].altsetting[0] - .desc.bInterfaceNumber == ifnum) - return &dev->actconfig->interface[i]; - - return NULL; -} - -/** - * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number - * @dev: the device whose current configuration is considered - * @epnum: the desired endpoint - * - * This walks the device descriptor for the currently active configuration, - * and returns a pointer to the endpoint with that particular endpoint - * number, or null. - * - * Note that interface descriptors are not required to assign endpont - * numbers sequentially, so that it would be incorrect to assume that - * the first endpoint in that descriptor corresponds to interface zero. - * This routine helps device drivers avoid such mistakes. - */ -struct usb_endpoint_descriptor * -usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) -{ - int i, j, k; - - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) - for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++) - for (k = 0; k < dev->actconfig->interface[i] - .altsetting[j].desc.bNumEndpoints; k++) - if (epnum == dev->actconfig->interface[i] - .altsetting[j].endpoint[k] - .desc.bEndpointAddress) - return &dev->actconfig->interface[i] - .altsetting[j].endpoint[k] - .desc; - - return NULL; -} - -/** - * usb_driver_claim_interface - bind a driver to an interface - * @driver: the driver to be bound - * @iface: the interface to which it will be bound - * @priv: driver data associated with that interface - * - * This is used by usb device drivers that need to claim more than one - * interface on a device when probing (audio and acm are current examples). - * No device driver should directly modify internal usb_interface or - * usb_device structure members. - * - * Few drivers should need to use this routine, since the most natural - * way to bind to an interface is to return the private data from - * the driver's probe() method. Any driver that does use this must - * first be sure that no other driver has claimed the interface, by - * checking with usb_interface_claimed(). - */ -void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv) -{ - if (!iface || !driver) - return; - - // FIXME change API to report an error in this case - if (iface->driver) { - err ("%s driver booted %s off interface %p", - driver->name, iface->driver->name, iface); - } - else { - dbg("%s driver claimed interface %p", driver->name, iface); - } - iface->driver = driver; - usb_set_intfdata(iface, priv); -} - -/** - * usb_interface_claimed - returns true iff an interface is claimed - * @iface: the interface being checked - * - * This should be used by drivers to check other interfaces to see if - * they are available or not. If another driver has claimed the interface, - * they may not claim it. Otherwise it's OK to claim it using - * usb_driver_claim_interface(). - * - * Returns true (nonzero) iff the interface is claimed, else false (zero). - */ -int usb_interface_claimed(struct usb_interface *iface) -{ - if (!iface) - return 0; - - return (iface->driver != NULL); -} /* usb_interface_claimed() */ - -/** - * usb_driver_release_interface - unbind a driver from an interface - * @driver: the driver to be unbound - * @iface: the interface from which it will be unbound - * - * This should be used by drivers to release their claimed interfaces. - * It is normally called in their disconnect() methods, and only for - * drivers that bound to more than one interface in their probe(). - * - * When the USB subsystem disconnect()s a driver from some interface, - * it automatically invokes this method for that interface. That - * means that even drivers that used usb_driver_claim_interface() - * usually won't need to call this. - */ -void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface) -{ - /* this should never happen, don't release something that's not ours */ - if (!iface || iface->driver != driver) - return; - - iface->driver = NULL; - usb_set_intfdata(iface, NULL); -} - -/** - * usb_match_id - find first usb_device_id matching device or interface - * @interface: the interface of interest - * @id: array of usb_device_id structures, terminated by zero entry - * - * usb_match_id searches an array of usb_device_id's and returns - * the first one matching the device or interface, or null. - * This is used when binding (or rebinding) a driver to an interface. - * Most USB device drivers will use this indirectly, through the usb core, - * but some layered driver frameworks use it directly. - * These device tables are exported with MODULE_DEVICE_TABLE, through - * modutils and "modules.usbmap", to support the driver loading - * functionality of USB hotplugging. - * - * What Matches: - * - * The "match_flags" element in a usb_device_id controls which - * members are used. If the corresponding bit is set, the - * value in the device_id must match its corresponding member - * in the device or interface descriptor, or else the device_id - * does not match. - * - * "driver_info" is normally used only by device drivers, - * but you can create a wildcard "matches anything" usb_device_id - * as a driver's "modules.usbmap" entry if you provide an id with - * only a nonzero "driver_info" field. If you do this, the USB device - * driver's probe() routine should use additional intelligence to - * decide whether to bind to the specified interface. - * - * What Makes Good usb_device_id Tables: - * - * The match algorithm is very simple, so that intelligence in - * driver selection must come from smart driver id records. - * Unless you have good reasons to use another selection policy, - * provide match elements only in related groups, and order match - * specifiers from specific to general. Use the macros provided - * for that purpose if you can. - * - * The most specific match specifiers use device descriptor - * data. These are commonly used with product-specific matches; - * the USB_DEVICE macro lets you provide vendor and product IDs, - * and you can also match against ranges of product revisions. - * These are widely used for devices with application or vendor - * specific bDeviceClass values. - * - * Matches based on device class/subclass/protocol specifications - * are slightly more general; use the USB_DEVICE_INFO macro, or - * its siblings. These are used with single-function devices - * where bDeviceClass doesn't specify that each interface has - * its own class. - * - * Matches based on interface class/subclass/protocol are the - * most general; they let drivers bind to any interface on a - * multiple-function device. Use the USB_INTERFACE_INFO - * macro, or its siblings, to match class-per-interface style - * devices (as recorded in bDeviceClass). - * - * Within those groups, remember that not all combinations are - * meaningful. For example, don't give a product version range - * without vendor and product IDs; or specify a protocol without - * its associated class and subclass. - */ -const struct usb_device_id * -usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_host_interface *intf; - struct usb_device *dev; - struct usb_device_id *save_id; - int firsttime; - - firsttime = 1; - - save_id = (struct usb_device_id*)id; - id = (struct usb_device_id*)save_id; - - /* proc_connectinfo in devio.c may call us with id == NULL. */ - if (id == NULL) - return NULL; - - intf = &interface->altsetting [interface->act_altsetting]; - dev = interface_to_usbdev(interface); - - /* It is important to check that id->driver_info is nonzero, - since an entry that is all zeroes except for a nonzero - id->driver_info is the way to create an entry that - indicates that the driver want to examine every - device and interface. */ - for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || - id->driver_info; id++) { - - if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - id->idVendor != dev->descriptor.idVendor) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - id->idProduct != dev->descriptor.idProduct) - continue; - - /* No need to test id->bcdDevice_lo != 0, since 0 is never - greater than any unsigned number. */ - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && - (id->bcdDevice_lo > dev->descriptor.bcdDevice)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && - (id->bcdDevice_hi < dev->descriptor.bcdDevice)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && - (id->bDeviceClass != dev->descriptor.bDeviceClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && - (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && - (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && - (id->bInterfaceClass != intf->desc.bInterfaceClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && - (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) - continue; - - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && - (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) - continue; - - return id; - } - - return NULL; -} - -/** - * usb_find_interface - find usb_interface pointer for driver and device - * @drv: the driver whose current configuration is considered - * @minor: the minor number of the desired device - * - * This walks the driver device list and returns a pointer to the interface - * with the matching minor. Note, this only works for devices that share the - * USB major number. - */ -struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) -{ - struct list_head *entry; - struct device *dev; - struct usb_interface *intf; - - list_for_each(entry, &drv->driver.devices) { - dev = container_of(entry, struct device, driver_list); - - /* can't look at usb devices, only interfaces */ - if (dev->driver == &usb_generic_driver) - continue; - - intf = to_usb_interface(dev); - if (intf->minor == -1) - continue; - if (intf->minor == minor) - return intf; - } - - /* no device found that matches */ - return NULL; -} - -static int usb_device_match (struct device *dev, struct device_driver *drv) -{ - struct usb_interface *intf; - struct usb_driver *usb_drv; - const struct usb_device_id *id; - - /* check for generic driver, which we don't match any device with */ - if (drv == &usb_generic_driver) - return 0; - - intf = to_usb_interface(dev); - - usb_drv = to_usb_driver(drv); - id = usb_drv->id_table; - - id = usb_match_id (intf, usb_drv->id_table); - if (id) - return 1; - - return 0; -} - - -#ifdef CONFIG_HOTPLUG - -/* - * USB hotplugging invokes what /proc/sys/kernel/hotplug says - * (normally /sbin/hotplug) when USB devices get added or removed. - * - * This invokes a user mode policy agent, typically helping to load driver - * or other modules, configure the device, and more. Drivers can provide - * a MODULE_DEVICE_TABLE to help with module loading subtasks. - * - * We're called either from khubd (the typical case) or from root hub - * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle - * delays in event delivery. Use sysfs (and DEVPATH) to make sure the - * device (and this configuration!) are still present. - */ -static int usb_hotplug (struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct usb_interface *intf; - struct usb_device *usb_dev; - char *scratch; - int i = 0; - int length = 0; - - dbg ("%s", __FUNCTION__); - - if (!dev) - return -ENODEV; - - /* Must check driver_data here, as on remove driver is always NULL */ - if ((dev->driver == &usb_generic_driver) || - (dev->driver_data == &usb_generic_driver_data)) - return 0; - - intf = to_usb_interface(dev); - usb_dev = interface_to_usbdev (intf); - - if (usb_dev->devnum < 0) { - dbg ("device already deleted ??"); - return -ENODEV; - } - if (!usb_dev->bus) { - dbg ("bus already removed?"); - return -ENODEV; - } - - scratch = buffer; - -#ifdef CONFIG_USB_DEVICEFS - /* If this is available, userspace programs can directly read - * all the device descriptors we don't tell them about. Or - * even act as usermode drivers. - * - * FIXME reduce hardwired intelligence here - */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, - "DEVICE=/proc/bus/usb/%03d/%03d", - usb_dev->bus->busnum, usb_dev->devnum); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; -#endif - - /* per-device configurations are common */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, "PRODUCT=%x/%x/%x", - usb_dev->descriptor.idVendor, - usb_dev->descriptor.idProduct, - usb_dev->descriptor.bcdDevice); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; - - /* class-based driver binding models */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, "TYPE=%d/%d/%d", - usb_dev->descriptor.bDeviceClass, - usb_dev->descriptor.bDeviceSubClass, - usb_dev->descriptor.bDeviceProtocol); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; - - if (usb_dev->descriptor.bDeviceClass == 0) { - int alt = intf->act_altsetting; - - /* 2.4 only exposed interface zero. in 2.5, hotplug - * agents are called for all interfaces, and can use - * $DEVPATH/bInterfaceNumber if necessary. - */ - envp [i++] = scratch; - length += snprintf (scratch, buffer_size - length, - "INTERFACE=%d/%d/%d", - intf->altsetting[alt].desc.bInterfaceClass, - intf->altsetting[alt].desc.bInterfaceSubClass, - intf->altsetting[alt].desc.bInterfaceProtocol); - if ((buffer_size - length <= 0) || (i >= num_envp)) - return -ENOMEM; - ++length; - scratch += length; - - } - envp [i++] = 0; - - return 0; -} - -#else - -static int usb_hotplug (struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - return -ENODEV; -} - -#endif /* CONFIG_HOTPLUG */ - -/** - * usb_alloc_dev - allocate a usb device structure (usbcore-internal) - * @parent: hub to which device is connected - * @bus: bus used to access the device - * Context: !in_interrupt () - * - * Only hub drivers (including virtual root hub drivers for host - * controllers) should ever call this. - * - * This call is synchronous, and may not be used in an interrupt context. - */ -struct usb_device STDCALL *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus) -{ - struct usb_device *dev; - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - - memset(dev, 0, sizeof(*dev)); - - device_initialize(&dev->dev); - dev->state = USB_STATE_ATTACHED; - - usb_bus_get(bus); - - if (!parent) - dev->devpath [0] = '0'; - dev->bus = bus; - dev->parent = parent; - INIT_LIST_HEAD(&dev->filelist); - - init_MUTEX(&dev->serialize); - - if (dev->bus->op->allocate) - dev->bus->op->allocate(dev); - - return dev; -} - -/** - * usb_get_dev - increments the reference count of the usb device structure - * @dev: the device being referenced - * - * Each live reference to a device should be refcounted. - * - * Drivers for USB interfaces should normally record such references in - * their probe() methods, when they bind to an interface, and release - * them by calling usb_put_dev(), in their disconnect() methods. - * - * A pointer to the device with the incremented reference counter is returned. - */ -struct usb_device STDCALL *usb_get_dev (struct usb_device *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - - tmp = get_device(&dev->dev); - if (tmp) - return to_usb_device(tmp); - else - return NULL; -} - -/** - * usb_put_dev - release a use of the usb device structure - * @dev: device that's been disconnected - * - * Must be called when a user of a device is finished with it. When the last - * user of the device calls this function, the memory of the device is freed. - */ -void STDCALL usb_put_dev(struct usb_device *dev) -{ - if (dev) - put_device(&dev->dev); -} - -/** - * usb_release_dev - free a usb device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this usb device are - * done. - */ -static void usb_release_dev(struct device *dev) -{ - struct usb_device *udev; - - udev = to_usb_device(dev); - - if (udev->bus && udev->bus->op && udev->bus->op->deallocate) - udev->bus->op->deallocate(udev); - usb_destroy_configuration (udev); - usb_bus_put (udev->bus); - kfree (udev); -} - - -static struct usb_device *match_device(struct usb_device *dev, - u16 vendor_id, u16 product_id) -{ - struct usb_device *ret_dev = NULL; - int child; - - dbg("looking at vendor %d, product %d", - dev->descriptor.idVendor, - dev->descriptor.idProduct); - - /* see if this device matches */ - if ((dev->descriptor.idVendor == vendor_id) && - (dev->descriptor.idProduct == product_id)) { - dbg ("found the device!"); - ret_dev = usb_get_dev(dev); - goto exit; - } - - /* look through all of the children of this device */ - for (child = 0; child < dev->maxchild; ++child) { - if (dev->children[child]) { - ret_dev = match_device(dev->children[child], - vendor_id, product_id); - if (ret_dev) - goto exit; - } - } -exit: - return ret_dev; -} - -/** - * usb_find_device - find a specific usb device in the system - * @vendor_id: the vendor id of the device to find - * @product_id: the product id of the device to find - * - * Returns a pointer to a struct usb_device if such a specified usb - * device is present in the system currently. The usage count of the - * device will be incremented if a device is found. Make sure to call - * usb_put_dev() when the caller is finished with the device. - * - * If a device with the specified vendor and product id is not found, - * NULL is returned. - */ -struct usb_device *usb_find_device(u16 vendor_id, u16 product_id) -{ - struct list_head *buslist; - struct usb_bus *bus; - struct usb_device *dev = NULL; - - down(&usb_bus_list_lock); - for (buslist = usb_bus_list.next; - buslist != &usb_bus_list; - buslist = buslist->next) { - bus = container_of(buslist, struct usb_bus, bus_list); - dev = match_device(bus->root_hub, vendor_id, product_id); - if (dev) - goto exit; - } -exit: - up(&usb_bus_list_lock); - return dev; -} - -/** - * usb_get_current_frame_number - return current bus frame number - * @dev: the device whose bus is being queried - * - * Returns the current frame number for the USB host controller - * used with the given USB device. This can be used when scheduling - * isochronous requests. - * - * Note that different kinds of host controller have different - * "scheduling horizons". While one type might support scheduling only - * 32 frames into the future, others could support scheduling up to - * 1024 frames into the future. - */ -int usb_get_current_frame_number(struct usb_device *dev) -{ - return dev->bus->op->get_frame_number (dev); -} - -/*-------------------------------------------------------------------*/ -/* - * __usb_get_extra_descriptor() finds a descriptor of specific type in the - * extra field of the interface and endpoint descriptor structs. - */ - -int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr) -{ - struct usb_descriptor_header *header; - - while (size >= sizeof(struct usb_descriptor_header)) { - header = (struct usb_descriptor_header *)buffer; - - if (header->bLength < 2) { - err("invalid descriptor length of %d", header->bLength); - return -1; - } - - if (header->bDescriptorType == type) { - *ptr = header; - return 0; - } - - buffer += header->bLength; - size -= header->bLength; - } - return -1; -} - -/** - * usb_disconnect - disconnect a device (usbcore-internal) - * @pdev: pointer to device being disconnected - * Context: !in_interrupt () - * - * Something got disconnected. Get rid of it, and all of its children. - * - * Only hub drivers (including virtual root hub drivers for host - * controllers) should ever call this. - * - * This call is synchronous, and may not be used in an interrupt context. - */ -void usb_disconnect(struct usb_device **pdev) -{ - struct usb_device *dev = *pdev; - struct usb_bus *bus; - struct usb_operations *ops; - int i; - - might_sleep (); - - if (!dev) { -// pr_debug ("%s nodev\n", __FUNCTION__); - DPRINT ("%s nodev\n", __FUNCTION__); - return; - } - bus = dev->bus; - if (!bus) { -// pr_debug ("%s nobus\n", __FUNCTION__); - DPRINT ("%s nobus\n", __FUNCTION__); - return; - } - ops = bus->op; - - *pdev = NULL; - - /* mark the device as inactive, so any further urb submissions for - * this device will fail. - */ - dev->state = USB_STATE_NOTATTACHED; - - dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum); - - /* Free up all the children before we remove this device */ - for (i = 0; i < USB_MAXCHILDREN; i++) { - struct usb_device **child = dev->children + i; - if (*child) - usb_disconnect(child); - } - - /* disconnect() drivers from interfaces (a key side effect) */ - dev_dbg (&dev->dev, "unregistering interfaces\n"); - if (dev->actconfig) { - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *interface; - - /* remove this interface */ - interface = &dev->actconfig->interface[i]; - device_unregister(&interface->dev); - } - } - - /* deallocate hcd/hardware state */ - if (ops->disable) { - void (*disable)(struct usb_device *, int) = ops->disable; - - for (i = 0; i < 15; i++) { - disable (dev, i); - disable (dev, USB_DIR_IN | i); - } - } - - dev_dbg (&dev->dev, "unregistering device\n"); - /* Free the device number and remove the /proc/bus/usb entry */ - if (dev->devnum > 0) { - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - usbfs_remove_device(dev); - } - device_unregister(&dev->dev); - - /* Decrement the reference count, it'll auto free everything when */ - /* it hits 0 which could very well be now */ - usb_put_dev(dev); -} - -/** - * usb_connect - pick device address (usbcore-internal) - * @dev: newly detected device (in DEFAULT state) - * - * Picks a device address. It's up to the hub (or root hub) driver - * to handle and manage enumeration, starting from the DEFAULT state. - * Only hub drivers (including virtual root hub drivers for host - * controllers) should ever call this. - */ -void STDCALL usb_connect(struct usb_device *dev) -{ - int devnum; - // FIXME needs locking for SMP!! - /* why? this is called only from the hub thread, - * which hopefully doesn't run on multiple CPU's simultaneously 8-) - * ... it's also called from modprobe/rmmod/apmd threads as part - * of virtual root hub init/reinit. In the init case, the hub code - * won't have seen this, but not so for reinit ... - */ - dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ - - /* Try to allocate the next devnum beginning at bus->devnum_next. */ - devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next); - if (devnum >= 128) - devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); - - dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); - - if (devnum < 128) { - set_bit(devnum, dev->bus->devmap.devicemap); - dev->devnum = devnum; - } -} - -/** - * usb_choose_address - pick device address (usbcore-internal) - * @dev: newly detected device (in DEFAULT state) - * - * Picks a device address. It's up to the hub (or root hub) driver - * to handle and manage enumeration, starting from the DEFAULT state. - * Only hub drivers (but not virtual root hub drivers for host - * controllers) should ever call this. - */ -void usb_choose_address(struct usb_device *dev) -{ - int devnum; - // FIXME needs locking for SMP!! - /* why? this is called only from the hub thread, - * which hopefully doesn't run on multiple CPU's simultaneously 8-) - */ - - /* Try to allocate the next devnum beginning at bus->devnum_next. */ - devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next); - if (devnum >= 128) - devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1); - - dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); - - if (devnum < 128) { - set_bit(devnum, dev->bus->devmap.devicemap); - dev->devnum = devnum; - } -} - -// hub-only!! ... and only exported for reset/reinit path. -// otherwise used internally, for usb_new_device() -int usb_set_address(struct usb_device *dev) -{ - int retval; - - if (dev->devnum == 0) - return -EINVAL; - if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS) - return -EINVAL; - retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, - 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); - if (retval == 0) - dev->state = USB_STATE_ADDRESS; - return retval; -} - - -/* improve on the default device description, if we can ... and - * while we're at it, maybe show the vendor and product strings. - */ -static void set_device_description (struct usb_device *dev) -{ - void *buf; - int mfgr = dev->descriptor.iManufacturer; - int prod = dev->descriptor.iProduct; - int vendor_id = dev->descriptor.idVendor; - int product_id = dev->descriptor.idProduct; - char *mfgr_str, *prod_str; - - /* set default; keep it if there are no strings, or kmalloc fails */ - sprintf (dev->dev.name, "USB device %04x:%04x", - vendor_id, product_id); - - if (!(buf = kmalloc(256 * 2, GFP_KERNEL))) - return; - - prod_str = (char *) buf; - mfgr_str = (char *) buf + 256; - - if (prod && usb_string (dev, prod, prod_str, 256) > 0) { -#ifdef DEBUG - dev_printk (KERN_INFO, &dev->dev, "Product: %s\n", prod_str); -#endif - } else { - prod_str = 0; - } - - if (mfgr && usb_string (dev, mfgr, mfgr_str, 256) > 0) { -#ifdef DEBUG - dev_printk (KERN_INFO, &dev->dev, "Manufacturer: %s\n", mfgr_str); -#endif - } else { - mfgr_str = 0; - } - - /* much like pci ... describe as either: - * - both strings: 'product descr (vendor descr)' - * - product only: 'product descr (USB device vvvv:pppp)' - * - vendor only: 'USB device vvvv:pppp (vendor descr)' - * - neither string: 'USB device vvvv:pppp' - */ - - if (prod_str && mfgr_str) { - - snprintf(dev->dev.name, sizeof dev->dev.name, - "%s (%s)", prod_str, mfgr_str); - } else if (prod_str) { - snprintf(dev->dev.name, sizeof dev->dev.name, - "%s (USB device %04x:%04x)", - prod_str, vendor_id, product_id); - - } else if (mfgr_str) { - snprintf(dev->dev.name, sizeof dev->dev.name, - "USB device %04x:%04x (%s)", - vendor_id, product_id, mfgr_str); - } - usbprintk("USB connected: %s\n",dev->dev.name); - kfree(buf); -} - -/* - * By the time we get here, we chose a new device address - * and is in the default state. We need to identify the thing and - * get the ball rolling.. - * - * Returns 0 for success, != 0 for error. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Only hub drivers (including virtual root hub drivers for host - * controllers) should ever call this. - */ -#define NEW_DEVICE_RETRYS 2 -#define SET_ADDRESS_RETRYS 20 -int usb_new_device(struct usb_device *dev, struct device *parent) -{ - int err = -EINVAL; - int i; - int j; - - /* - * Set the driver for the usb device to point to the "generic" driver. - * This prevents the main usb device from being sent to the usb bus - * probe function. Yes, it's a hack, but a nice one :) - * - * Do it asap, so more driver model stuff (like the device.h message - * utilities) can be used in hcd submit/unlink code paths. - */ - usb_generic_driver.bus = &usb_bus_type; - dev->dev.parent = parent; - dev->dev.driver = &usb_generic_driver; - dev->dev.bus = &usb_bus_type; - dev->dev.release = usb_release_dev; - dev->dev.driver_data = &usb_generic_driver_data; - usb_get_dev(dev); - if (dev->dev.bus_id[0] == 0) - sprintf (&dev->dev.bus_id[0], "%d-%s", - dev->bus->busnum, dev->devpath); - - /* dma masks come from the controller; readonly, except to hcd */ - dev->dev.dma_mask = parent->dma_mask; - - /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... - * it's fixed size except for full speed devices. - */ - switch (dev->speed) { - case USB_SPEED_HIGH: /* fixed at 64 */ - i = 64; - break; - case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ - /* to determine the ep0 maxpacket size, read the first 8 - * bytes from the device descriptor to get bMaxPacketSize0; - * then correct our initial (small) guess. - */ - // FALLTHROUGH - case USB_SPEED_LOW: /* fixed at 8 */ - i = 8; - break; - default: - goto fail; - } - dev->epmaxpacketin [0] = i; - dev->epmaxpacketout[0] = i; - - for (i = 0; i < NEW_DEVICE_RETRYS; ++i) { - - for (j = 0; j < SET_ADDRESS_RETRYS; ++j) { - err = usb_set_address(dev); - if (err >= 0) - break; - wait_ms(5); - } - if (err < 0) { - dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n", - dev->devnum, err); - goto fail; - } - - wait_ms(10); /* Let the SET_ADDRESS settle */ - - /* high and low speed devices don't need this... */ - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); - if (err >= 8) - break; - wait_ms(100); - } - - if (err < 8) { - dev_err(&dev->dev, "device descriptor read/8, error %d\n", err); - goto fail; - } - if (dev->speed == USB_SPEED_FULL) { - //usb_disable_endpoint(dev, 0); - usb_endpoint_running(dev, 0, 1); - usb_endpoint_running(dev, 0, 0); - dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; - dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; - } - - /* USB device state == addressed ... still not usable */ - - err = usb_get_device_descriptor(dev); - if (err < (signed)sizeof(dev->descriptor)) { - dev_err(&dev->dev, "device descriptor read/all, error %d\n", err); - goto fail; - } - - err = usb_get_configuration(dev); - if (err < 0) { - dev_err(&dev->dev, "can't read configurations, error %d\n", - err); - goto fail; - } - - /* we set the default configuration here */ - err = usb_set_configuration(dev, dev->config[0].desc.bConfigurationValue); - if (err) { - dev_err(&dev->dev, "failed to set device %d default configuration (error=%d)\n", - dev->devnum, err); - goto fail; - } - - /* USB device state == configured ... tell the world! */ - - dev_dbg(&dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", - dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); - set_device_description (dev); - -#ifdef DEBUG - if (dev->descriptor.iSerialNumber) - usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber); -#endif - /* put into sysfs, with device and config specific files */ - err = device_add (&dev->dev); - if (err) - return err; - usb_create_driverfs_dev_files (dev); - - /* Register all of the interfaces for this device with the driver core. - * Remember, interfaces get bound to drivers, not devices. */ - for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *interface = &dev->actconfig->interface[i]; - struct usb_interface_descriptor *desc; - - desc = &interface->altsetting [interface->act_altsetting].desc; - interface->dev.parent = &dev->dev; - interface->dev.driver = NULL; - interface->dev.bus = &usb_bus_type; - interface->dev.dma_mask = parent->dma_mask; - sprintf (&interface->dev.bus_id[0], "%d-%s:%d", - dev->bus->busnum, dev->devpath, - desc->bInterfaceNumber); - if (!desc->iInterface - || usb_string (dev, desc->iInterface, - interface->dev.name, - sizeof interface->dev.name) <= 0) { - /* typically devices won't bother with interface - * descriptions; this is the normal case. an - * interface's driver might describe it better. - * (also: iInterface is per-altsetting ...) - */ - sprintf (&interface->dev.name[0], - "usb-%s-%s interface %d", - dev->bus->bus_name, dev->devpath, - desc->bInterfaceNumber); - DPRINT1(".........................usb_new_device: %s\n", interface->dev.name); - } - dev_dbg (&dev->dev, "%s - registering interface %s\n", __FUNCTION__, interface->dev.bus_id); - device_add (&interface->dev); - usb_create_driverfs_intf_files (interface); - } - /* add a /proc/bus/usb entry */ - //usbfs_add_device(dev); - - return 0; -fail: - dev->state = USB_STATE_DEFAULT; - clear_bit(dev->devnum, dev->bus->devmap.devicemap); - dev->devnum = -1; - return err; -} - -/** - * usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_DMA_MAP - * @dev: device the buffer will be used with - * @size: requested buffer size - * @mem_flags: affect whether allocation may block - * @dma: used to return DMA address of buffer - * - * Return value is either null (indicating no buffer could be allocated), or - * the cpu-space pointer to a buffer that may be used to perform DMA to the - * specified device. Such cpu-space buffers are returned along with the DMA - * address (through the pointer provided). - * - * These buffers are used with URB_NO_DMA_MAP set in urb->transfer_flags to - * avoid behaviors like using "DMA bounce buffers", or tying down I/O mapping - * hardware for long idle periods. The implementation varies between - * platforms, depending on details of how DMA will work to this device. - * Using these buffers also helps prevent cacheline sharing problems on - * architectures where CPU caches are not DMA-coherent. - * - * When the buffer is no longer used, free it with usb_buffer_free(). - */ -void *usb_buffer_alloc ( - struct usb_device *dev, - size_t size, - int mem_flags, - dma_addr_t *dma -) -{ - if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc) - return 0; - return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma); -} - -/** - * usb_buffer_free - free memory allocated with usb_buffer_alloc() - * @dev: device the buffer was used with - * @size: requested buffer size - * @addr: CPU address of buffer - * @dma: DMA address of buffer - * - * This reclaims an I/O buffer, letting it be reused. The memory must have - * been allocated using usb_buffer_alloc(), and the parameters must match - * those provided in that allocation request. - */ -void usb_buffer_free ( - struct usb_device *dev, - size_t size, - void *addr, - dma_addr_t dma -) -{ - if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free) - return; - dev->bus->op->buffer_free (dev->bus, size, addr, dma); -} - -/** - * usb_buffer_map - create DMA mapping(s) for an urb - * @urb: urb whose transfer_buffer will be mapped - * - * Return value is either null (indicating no buffer could be mapped), or - * the parameter. URB_NO_DMA_MAP is added to urb->transfer_flags if the - * operation succeeds. If the device is connected to this system through - * a non-DMA controller, this operation always succeeds. - * - * This call would normally be used for an urb which is reused, perhaps - * as the target of a large periodic transfer, with usb_buffer_dmasync() - * calls to synchronize memory and dma state. It may not be used for - * control requests. - * - * Reverse the effect of this call with usb_buffer_unmap(). - */ -struct urb *usb_buffer_map (struct urb *urb) -{ - struct usb_bus *bus; - struct device *controller; - - if (!urb - || usb_pipecontrol (urb->pipe) - || !urb->dev - || !(bus = urb->dev->bus) - || !(controller = bus->controller)) - return 0; - - if (controller->dma_mask) { - urb->transfer_dma = dma_map_single (controller, - urb->transfer_buffer, urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - // FIXME generic api broken like pci, can't report errors - // if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; - } else - urb->transfer_dma = ~0; - urb->transfer_flags |= URB_NO_DMA_MAP; - return urb; -} - -/** - * usb_buffer_dmasync - synchronize DMA and CPU view of buffer(s) - * @urb: urb whose transfer_buffer will be synchronized - */ -void usb_buffer_dmasync (struct urb *urb) -{ - struct usb_bus *bus; - struct device *controller; - - if (!urb - || !(urb->transfer_flags & URB_NO_DMA_MAP) - || !urb->dev - || !(bus = urb->dev->bus) - || !(controller = bus->controller)) - return; - - if (controller->dma_mask) - dma_sync_single (controller, - urb->transfer_dma, urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? DMA_FROM_DEVICE : DMA_TO_DEVICE); -} - -/** - * usb_buffer_unmap - free DMA mapping(s) for an urb - * @urb: urb whose transfer_buffer will be unmapped - * - * Reverses the effect of usb_buffer_map(). - */ -void usb_buffer_unmap (struct urb *urb) -{ - struct usb_bus *bus; - struct device *controller; - - if (!urb - || !(urb->transfer_flags & URB_NO_DMA_MAP) - || !urb->dev - || !(bus = urb->dev->bus) - || !(controller = bus->controller)) - return; - - if (controller->dma_mask) - dma_unmap_single (controller, - urb->transfer_dma, urb->transfer_buffer_length, - usb_pipein (urb->pipe) - ? DMA_FROM_DEVICE : DMA_TO_DEVICE); - urb->transfer_flags &= ~URB_NO_DMA_MAP; -} - -/** - * usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint - * @dev: device to which the scatterlist will be mapped - * @pipe: endpoint defining the mapping direction - * @sg: the scatterlist to map - * @nents: the number of entries in the scatterlist - * - * Return value is either < 0 (indicating no buffers could be mapped), or - * the number of DMA mapping array entries in the scatterlist. - * - * The caller is responsible for placing the resulting DMA addresses from - * the scatterlist into URB transfer buffer pointers, and for setting the - * URB_NO_DMA_MAP transfer flag in each of those URBs. - * - * Top I/O rates come from queuing URBs, instead of waiting for each one - * to complete before starting the next I/O. This is particularly easy - * to do with scatterlists. Just allocate and submit one URB for each DMA - * mapping entry returned, stopping on the first error or when all succeed. - * Better yet, use the usb_sg_*() calls, which do that (and more) for you. - * - * This call would normally be used when translating scatterlist requests, - * rather than usb_buffer_map(), since on some hardware (with IOMMUs) it - * may be able to coalesce mappings for improved I/O efficiency. - * - * Reverse the effect of this call with usb_buffer_unmap_sg(). - */ -int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int nents) -{ - struct usb_bus *bus; - struct device *controller; - - if (!dev - || usb_pipecontrol (pipe) - || !(bus = dev->bus) - || !(controller = bus->controller) - || !controller->dma_mask) - return -1; - - // FIXME generic api broken like pci, can't report errors - return dma_map_sg (controller, sg, nents, - usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); -} - -/** - * usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer(s) - * @dev: device to which the scatterlist will be mapped - * @pipe: endpoint defining the mapping direction - * @sg: the scatterlist to synchronize - * @n_hw_ents: the positive return value from usb_buffer_map_sg - * - * Use this when you are re-using a scatterlist's data buffers for - * another USB request. - */ -void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int n_hw_ents) -{ - struct usb_bus *bus; - struct device *controller; - - if (!dev - || !(bus = dev->bus) - || !(controller = bus->controller) - || !controller->dma_mask) - return; - - dma_sync_sg (controller, sg, n_hw_ents, - usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); -} - -/** - * usb_buffer_unmap_sg - free DMA mapping(s) for a scatterlist - * @dev: device to which the scatterlist will be mapped - * @pipe: endpoint defining the mapping direction - * @sg: the scatterlist to unmap - * @n_hw_ents: the positive return value from usb_buffer_map_sg - * - * Reverses the effect of usb_buffer_map_sg(). - */ -void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe, - struct scatterlist *sg, int n_hw_ents) -{ - struct usb_bus *bus; - struct device *controller; - - if (!dev - || !(bus = dev->bus) - || !(controller = bus->controller) - || !controller->dma_mask) - return; - - dma_unmap_sg (controller, sg, n_hw_ents, - usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE); -} - - -struct bus_type usb_bus_type = { - .name = "usb", - .match = usb_device_match, - .hotplug = usb_hotplug, -}; - -#ifndef MODULE - -static int __init usb_setup_disable(char *str) -{ - nousb = 1; - return 1; -} - -/* format to disable USB on kernel command line is: nousb */ -__setup("nousb", usb_setup_disable); - -#endif - -/* - * for external read access to - */ -int STDCALL usb_disabled(void) -{ - return nousb; -} - -/* - * Init - */ -int STDCALL __init usb_init(void) -{ - if (nousb) { - info("USB support disabled\n"); - return 0; - } - - bus_register(&usb_bus_type); - usb_major_init(); - usbfs_init(); - usb_hub_init(); - - driver_register(&usb_generic_driver); - - return 0; -} - -/* - * Cleanup - */ -void STDCALL __exit usb_exit(void) -{ - /* This will matter if shutdown/reboot does exitcalls. */ - if (nousb) - return; - - driver_unregister(&usb_generic_driver); - usb_major_cleanup(); - usbfs_cleanup(); - usb_hub_cleanup(); - bus_unregister(&usb_bus_type); -} - -subsys_initcall(usb_init); -module_exit(usb_exit); - -/* - * USB may be built into the kernel or be built as modules. - * These symbols are exported for device (or host controller) - * driver modules to use. - */ -EXPORT_SYMBOL(usb_epnum_to_ep_desc); - -EXPORT_SYMBOL(usb_register); -EXPORT_SYMBOL(usb_deregister); -EXPORT_SYMBOL(usb_disabled); - -EXPORT_SYMBOL(usb_device_probe); -EXPORT_SYMBOL(usb_device_remove); - -EXPORT_SYMBOL(usb_alloc_dev); -EXPORT_SYMBOL(usb_put_dev); -EXPORT_SYMBOL(usb_get_dev); -EXPORT_SYMBOL(usb_hub_tt_clear_buffer); - -EXPORT_SYMBOL(usb_driver_claim_interface); -EXPORT_SYMBOL(usb_interface_claimed); -EXPORT_SYMBOL(usb_driver_release_interface); -EXPORT_SYMBOL(usb_match_id); -EXPORT_SYMBOL(usb_find_interface); -EXPORT_SYMBOL(usb_ifnum_to_if); - -EXPORT_SYMBOL(usb_new_device); -EXPORT_SYMBOL(usb_reset_device); -EXPORT_SYMBOL(usb_connect); -EXPORT_SYMBOL(usb_disconnect); - -EXPORT_SYMBOL(__usb_get_extra_descriptor); - -EXPORT_SYMBOL(usb_find_device); -EXPORT_SYMBOL(usb_get_current_frame_number); - -EXPORT_SYMBOL (usb_buffer_alloc); -EXPORT_SYMBOL (usb_buffer_free); - -EXPORT_SYMBOL (usb_buffer_map); -EXPORT_SYMBOL (usb_buffer_dmasync); -EXPORT_SYMBOL (usb_buffer_unmap); - -EXPORT_SYMBOL (usb_buffer_map_sg); -EXPORT_SYMBOL (usb_buffer_dmasync_sg); -EXPORT_SYMBOL (usb_buffer_unmap_sg); - -MODULE_LICENSE("GPL"); diff --git a/reactos/drivers/usb/usbport/usb.h b/reactos/drivers/usb/usbport/usb.h deleted file mode 100644 index 09f459f67ac..00000000000 --- a/reactos/drivers/usb/usbport/usb.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Functions local to drivers/usb/core/ */ - -extern void usb_create_driverfs_dev_files (struct usb_device *dev); -extern void usb_create_driverfs_intf_files (struct usb_interface *intf); - diff --git a/reactos/drivers/usb/usbport/usbcore.c b/reactos/drivers/usb/usbport/usbcore.c deleted file mode 100644 index 9602186bf16..00000000000 --- a/reactos/drivers/usb/usbport/usbcore.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - ReactOS specific functions for usbcore module - by Aleksey Bragin (aleksey@reactos.com) -*/ - -#include -#include -#include "../miniport/usb_wrapper.h" - -USBPORT_INTERFACE UsbPortInterface; - -void STDCALL RegisterPortDriver(PDRIVER_OBJECT pDrvObj, PUSBPORT_INTERFACE pUsbPortIntf) -{ - // copy struct to global var - DPRINT("Miniport 0x%08X registered\n", (ULONG)pDrvObj); - memcpy(&UsbPortInterface.KbdConnectData, &pUsbPortIntf->KbdConnectData, sizeof(CONNECT_DATA)); - memcpy(&UsbPortInterface.MouseConnectData, &pUsbPortIntf->MouseConnectData, sizeof(CONNECT_DATA)); -} - -NTSTATUS STDCALL -AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo) -{ - DbgPrint("usbcore: AddDevice called\n"); - - /* we need to do kind of this stuff here (as usual) - PDEVICE_OBJECT fdo; - IoCreateDevice(..., &fdo); - pdx->LowerDeviceObject = - IoAttachDeviceToDeviceStack(fdo, pdo);*/ - - return STATUS_SUCCESS; -} - -VOID STDCALL -DriverUnload(PDRIVER_OBJECT DriverObject) -{ - // nothing to do here yet -} - -// Dispatch PNP -NTSTATUS STDCALL -DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp) -{ - ULONG fcn; - PIO_STACK_LOCATION stack; - - stack = IoGetCurrentIrpStackLocation(Irp); - fcn = stack->MinorFunction; - DbgPrint("IRP_MJ_PNP, fcn=%d\n", fcn); - - if (fcn == IRP_MN_REMOVE_DEVICE) - { - IoDeleteDevice(fdo); - } - - return STATUS_SUCCESS; -} - -NTSTATUS STDCALL -DispatchPower(PDEVICE_OBJECT fido, PIRP Irp) -{ - DbgPrint("IRP_MJ_POWER dispatch\n"); - return STATUS_SUCCESS; -} - -/* - * Standard DriverEntry method. - */ -NTSTATUS STDCALL -DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath) -{ - DriverObject->DriverUnload = DriverUnload; - DriverObject->DriverExtension->AddDevice = AddDevice; - DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; - DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; - - return STATUS_SUCCESS; -} diff --git a/reactos/drivers/usb/usbport/usbcore.rc b/reactos/drivers/usb/usbport/usbcore.rc deleted file mode 100644 index f12b4d6d391..00000000000 --- a/reactos/drivers/usb/usbport/usbcore.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0" -#define REACTOS_STR_INTERNAL_NAME "usbcore\0" -#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0" -#include diff --git a/reactos/drivers/usb/usbport/usbport.def b/reactos/drivers/usb/usbport/usbport.def deleted file mode 100644 index a784bc9ee89..00000000000 --- a/reactos/drivers/usb/usbport/usbport.def +++ /dev/null @@ -1,34 +0,0 @@ -; -; Exports definition file for usbcore.sys -; -EXPORTS -RegisterPortDriver@8 -usb_alloc_bus@4 -usb_alloc_dev@8 -usb_alloc_urb@8 -usb_bus_init@4 -usb_calc_bus_time@16 -usb_check_bandwidth@8 -usb_claim_bandwidth@16 -usb_connect@4 -usb_deregister_bus@4 -usb_disabled@0 -usb_exit@0 -usb_free_bus@4 -usb_free_urb@4 -usb_get_dev@4 -usb_get_string -usb_get_urb@4 -usb_hcd_giveback_urb@12 -;usb_hcd_irq@12 -usb_hcd_pci_probe@8 -usb_hcd_pci_remove@4 -usb_hc_died@4 -usb_init@0 -usb_init_urb@4 -usb_put_dev@4 -usb_release_bandwidth@12 -usb_register_bus@4 -usb_register_root_hub@8 -usb_submit_urb@8 -usb_unlink_urb@4 \ No newline at end of file diff --git a/reactos/drivers/usb/usbport/usbport.rbuild b/reactos/drivers/usb/usbport/usbport.rbuild deleted file mode 100644 index 0620cd22ef3..00000000000 --- a/reactos/drivers/usb/usbport/usbport.rbuild +++ /dev/null @@ -1,21 +0,0 @@ - - - - sys_base - ntoskrnl - hal - message.c - hcd.c - hcd-pci.c - hub.c - usb.c - config.c - urb.c - buffer_simple.c - usb-debug.c - usbcore.c - core_drivers/usbkey.c - core_drivers/usbmouse.c - - usbcore.rc -