- Remove usbhub from the build.
svn path=/trunk/; revision=26625
-<directory name="miniport">
- <xi:include href="miniport/directory.rbuild" />
-</directory>
<directory name="nt4compat">
<xi:include href="nt4compat/directory.rbuild" />
</directory>
<!--directory name="usbd">
<xi:include href="usbd/usbd.rbuild" />
-</directory-->
+</directory>
<directory name="usbhub">
<xi:include href="usbhub/usbhub.rbuild" />
</directory>
-<directory name="usbport">
- <xi:include href="usbport/usbport.rbuild" />
-</directory>
-<!--directory name="usbstor">
+directory name="usbstor">
<xi:include href="usbstor/usbstor.rbuild" />
</directory-->
+++ /dev/null
-<module name="usbminiportcommon" type="objectlibrary">
- <define name="__USE_W32API" />
- <include>../linux</include>
- <include base="usbport">.</include>
- <file>fdo.c</file>
- <file>main.c</file>
- <file>misc.c</file>
- <file>pdo.c</file>
-</module>
+++ /dev/null
-/*
- * 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 <debug.h>
-
-#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;
-}
+++ /dev/null
-/*
- * 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 <debug.h>
-
-#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;
-}
+++ /dev/null
-/*
- * 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 <debug.h>
-
-#include "usbcommon.h"
-#include <stdarg.h>
-
-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;
-}
+++ /dev/null
-/*
- * 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 <debug.h>
-
-#include "usbcommon.h"
-#include <wdmguid.h>
-
-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;
-}
+++ /dev/null
-#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 <usbdi.h>
-#include <usbiodef.h>
-#include <initguid.h>
-#include <ntdd8042.h>
-
-#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
+++ /dev/null
-#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
+++ /dev/null
-<directory name="common">
- <xi:include href="common/common.rbuild" />
-</directory>
-<directory name="sys">
- <xi:include href="sys/sys.rbuild" />
-</directory>
-<!--directory name="usbehci">
- <xi:include href="usbehci/usbehci.rbuild" />
-</directory-->
-<directory name="usbohci">
- <xi:include href="usbohci/usbohci.rbuild" />
-</directory>
-<directory name="usbuhci">
- <xi:include href="usbuhci/usbuhci.rbuild" />
-</directory>
+++ /dev/null
-#ifndef _I386_BITOPS_H
-#define _I386_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-//#include <linux/config.h>
-
-/*
- * 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 */
+++ /dev/null
-#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
+++ /dev/null
-#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_
+++ /dev/null
-#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_
-
-
+++ /dev/null
-#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 */
+++ /dev/null
-#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
+++ /dev/null
-/*
- * 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 <standard-GPL-header.h>
- */
-
-/*------------------------------------------------------------------------*/
-/* 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 <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "consts.h"
-#include <string.h>
-#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;n<MAX_TIMERS;n++)
- if (main_timer_list[n]==0)
- {
- main_timer_list[n]=t;
- break;
- }
-}
-
-static void __inline__ del_timer(struct timer_list* t)
-{
- int n;
- for(n=0;n<MAX_TIMERS;n++)
- if (main_timer_list[n]==t)
- {
- main_timer_list[n]=0;
- break;
- }
-}
-static void __inline__ del_timer_sync(struct timer_list* t)
-{
- int n;
- for(n=0;n<MAX_TIMERS;n++)
- if (main_timer_list[n]==t)
- {
- main_timer_list[n]=0;
- break;
- }
-
-}
-static void __inline__ mod_timer(struct timer_list* t, int ex)
-{
- del_timer(t);
- t->expires=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);
+++ /dev/null
-#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
+++ /dev/null
-// 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;
-}
+++ /dev/null
-#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
-
+++ /dev/null
-#ifndef __LINUX_USB_H
-#define __LINUX_USB_H
-
-
-#include "usb_ch9.h"
-
-#define USB_MAJOR 180
-
-
-#ifdef __KERNEL__
-#if 0
-#include <linux/config.h>
-#include <linux/errno.h> /* for -ENODEV */
-#include <linux/delay.h> /* for mdelay() */
-#include <linux/interrupt.h> /* for in_interrupt() */
-#include <linux/list.h> /* for struct list_head */
-#include <linux/device.h> /* for struct device */
-#include <linux/fs.h> /* for struct file_operations */
-#include <linux/completion.h> /* for struct completion */
-#include <linux/sched.h> /* 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
+++ /dev/null
-/*
- * 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 <asm/types.h> /* __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 */
+++ /dev/null
-/*
- * 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);
-
-}
-/*------------------------------------------------------------------------*/
+++ /dev/null
-/*
- * 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;n<MAX_TIMERS;n++)
- {
- main_timer_list[n]=NULL;
- }
-
- my_jiffies=0;
- num_irqs=0;
- my_current=&act_cur;
- pci_probe_dev=probe_dev;
-
- for(n=0;n<MAX_IRQS;n++)
- {
- reg_irqs[n].handler=NULL;
- reg_irqs[n].irq=-1;
- }
- drvs_num=0;
- need_wakeup=0;
- for(n=0;n<MAX_DRVS;n++)
- m_drivers[n]=NULL;
-
- init_dma(probe_dev->dev_ext);
-}
-/*------------------------------------------------------------------------*/
-void handle_irqs(int irq)
-{
- int n;
- //printk("handle irqs\n");
- for(n=0;n<MAX_IRQS;n++)
- {
- if (reg_irqs[n].handler && (irq==reg_irqs[n].irq || irq==-1))
- reg_irqs[n].handler(reg_irqs[n].irq,reg_irqs[n].data,NULL);
- }
-}
-/*------------------------------------------------------------------------*/
-void inc_jiffies(int n)
-{
- my_jiffies+=n;
-}
-/*------------------------------------------------------------------------*/
-void do_all_timers(void)
-{
- int n;
- for(n=0;n<MAX_TIMERS;n++)
- {
- if (main_timer_list[n] && main_timer_list[n]->function)
- {
- 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;n<drvs_num;n++)
- {
- if (m_drivers[n]->probe)
- {
- 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_num<MAX_DRVS)
- {
- printk("driver_register %i: %p %p\n",drvs_num,driver,driver->probe);
-
- 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_irqs<MAX_IRQS)
- {
- reg_irqs[num_irqs].handler=handler;
- reg_irqs[num_irqs].irq=irq;
- reg_irqs[num_irqs].data=data;
- num_irqs++;
- return 0;
- }
-
- return 1;
-}
-/*------------------------------------------------------------------------*/
-int my_free_irq(int irq, void* p)
-{
- /* No free... */
- return 0;
-}
-/*------------------------------------------------------------------------*/
-// Lookaside funcs
-/*------------------------------------------------------------------------*/
-kmem_cache_t *my_kmem_cache_create(const char *tag, size_t alloc_size,
- size_t offset, unsigned long flags,
- void *ctor,
- void *dtor)
-{
- //TODO: Take in account ctor and dtor - callbacks for alloc/free, flags and offset
- //FIXME: We assume this cache is always NPaged
- PNPAGED_LOOKASIDE_LIST Lookaside;
- ULONG Tag=0x11223344; //FIXME: Make this from tag
-
- Lookaside = ExAllocatePool(NonPagedPool, sizeof(NPAGED_LOOKASIDE_LIST));
-
- ExInitializeNPagedLookasideList(
- Lookaside,
- NULL,
- NULL,
- 0,
- alloc_size,
- Tag,
- 0);
-
- return (kmem_cache_t *)Lookaside;
-}
-/*------------------------------------------------------------------------*/
-BOOLEAN my_kmem_cache_destroy(kmem_cache_t *co)
-{
- ExDeleteNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co);
-
- ExFreePool(co);
- return FALSE;
-}
-/*------------------------------------------------------------------------*/
-void *my_kmem_cache_alloc(kmem_cache_t *co, int flags)
-{
- return ExAllocateFromNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co);
-}
-/*------------------------------------------------------------------------*/
-void my_kmem_cache_free(kmem_cache_t *co, void *ptr)
-{
- ExFreeToNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co, ptr);
-}
-/*------------------------------------------------------------------------*/
-// DMA support routines
-/*------------------------------------------------------------------------*/
-#ifdef USB_DMA_SINGLE_SUPPORT
-static IO_ALLOCATION_ACTION NTAPI MapRegisterCallback(PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PVOID MapRegisterBase,
- PVOID Context);
-#endif
-
-NTSTATUS
-init_dma(PUSBMP_DEVICE_EXTENSION pDevExt)
-{
- // Prepare device descriptor structure
- DEVICE_DESCRIPTION dd;
-#ifdef USB_DMA_SINGLE_SUPPORT
- KEVENT DMAEvent;
- KIRQL OldIrql;
- NTSTATUS Status;
-#endif
-
- RtlZeroMemory( &dd, sizeof(dd) );
- dd.Version = DEVICE_DESCRIPTION_VERSION;
- dd.Master = TRUE;
- dd.ScatterGather = TRUE;
- dd.DemandMode = FALSE;
- dd.AutoInitialize = FALSE;
- dd.Dma32BitAddresses = TRUE;
- dd.InterfaceType = PCIBus;
- dd.DmaChannel = 0;//pDevExt->dmaChannel;
- 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; page<pool->pages_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; page<pool->pages_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);
-}
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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);
-}
+++ /dev/null
-<module name="sys_base" type="objectlibrary">
- <define name="__USE_W32API" />
- <define name="DEBUG_MODE" />
- <include base="ntoskrnl">include</include>
- <file>ros_wrapper.c</file>
- <file>linuxwrapper.c</file>
-</module>
\ No newline at end of file
+++ /dev/null
-#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);
-}
+++ /dev/null
-/*
- * Interface calls to BIOS
- *
- * 2003-06-21 Georg Acher (georg@acher.org)
- *
- */
-
-#include "boot.h"
-#include <stdarg.h>
-#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;
-}
-/*------------------------------------------------------------------------*/
+++ /dev/null
-/*
- * 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 <mfr@bmx-chemnitz.de>
- *
- */
-
-
-
-#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);
-}
-
-/*------------------------------------------------------------------------*/
-
-
-
+++ /dev/null
-/*
- * 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 <steve@toth.demon.co.uk>
- *
- * 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);
-}
+++ /dev/null
-//#include <stdlib.h>
-//#include <ntos/types.h>
-//#include <extypes.h>
-
-/*
- TODO: Do a major cleanup of this file!
- Lots of definitions should go to corresponding files
-*/
-
-#include <ntifs.h>
-#include <kbdmou.h>
-#include <debug.h>
-
-#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"
-
+++ /dev/null
-O_TARGET := ohci-hcd.o
-
-include $(TOPDIR)/Rules.make
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * 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
-
-/*-------------------------------------------------------------------------*/
-
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * [ 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 <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-# define DEBUG
-#else
-# undef DEBUG
-#endif
-
-
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h> /* for in_interrupt () */
-#include <linux/usb.h>
-#include "hcd.h"
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-#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
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * 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;
-}
-
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * 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);
-}
-
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * [ 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 <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
-#include <asm/prom.h>
-#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);*/
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * 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 <linux/jiffies.h> */
-#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);
-}
+++ /dev/null
-#define NDEBUG
-#include <debug.h>
-
-#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();
-}
+++ /dev/null
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
- * 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 <asm/io.h>) 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
-
+++ /dev/null
-#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 <reactos/version.rc>
+++ /dev/null
-/*
- * Configs for OHCI
- */
-
-#define CONFIG_PCI
+++ /dev/null
-<module name="usbohci" type="kernelmodedriver" installbase="system32/drivers" installname="usbohci.sys">
- <define name="__USE_W32API" />
- <include>../linux</include>
- <include base="usbminiportcommon"></include>
- <library>sys_base</library>
- <library>usbminiportcommon</library>
- <library>usbport</library>
- <library>ntoskrnl</library>
- <library>hal</library>
- <file>ohci.c</file>
- <file>ohci-hcd.c</file>
- <file>ohci.rc</file>
-</module>
+++ /dev/null
-/*
- * 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 <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
-#include <asm/io.h>
-#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
+++ /dev/null
-/*
- * Universal Host Controller Interface driver for USB.
- *
- * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
- *
- * (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 <linux/config.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/proc_fs.h>
-#endif
-
-//#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-//#else
-//#undef DEBUG
-//#endif
-
-#if 0
-#include <linux/usb.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#endif
-
-#include "uhci_config.h"
-#include "../usb_wrapper.h"
-#include "../../usbport/hcd.h"
-#include "uhci-hcd.h"
-
-#if 0
-#include <linux/pm.h>
-#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
- *
- * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
- * <dir_out> 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");
-
+++ /dev/null
-#ifndef __LINUX_UHCI_HCD_H
-#define __LINUX_UHCI_HCD_H
-
-#if 0
-#include <linux/list.h>
-#include <linux/usb.h>
-#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 <status>:
- */
-#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 <info>: (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 <interval> 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 <interval> but not slower.
- *
- * For a given <interval>, 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
-
+++ /dev/null
-/*
- * Universal Host Controller Interface driver for USB.
- *
- * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
- *
- * (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;
-}
-
+++ /dev/null
-/*
- 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();
-}
+++ /dev/null
-#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);
+++ /dev/null
-#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 <reactos/version.rc>
+++ /dev/null
-/*
- * Configs for UHCI
- */
-
-#define CONFIG_PCI
+++ /dev/null
-<module name="usbuhci" type="kernelmodedriver" installbase="system32/drivers" installname="usbuhci.sys">
- <define name="__USE_W32API" />
- <include>../linux</include>
- <include base="usbminiportcommon"></include>
- <library>sys_base</library>
- <library>usbminiportcommon</library>
- <library>usbport</library>
- <library>ntoskrnl</library>
- <library>hal</library>
- <file>uhci.c</file>
- <file>uhci-hcd.c</file>
- <file>uhci.rc</file>
-</module>
+++ /dev/null
-/*
- * 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);
-}
-
+++ /dev/null
-#if 0
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-#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;
-}
-
+++ /dev/null
-/*
- 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);
-}
+++ /dev/null
-/*\r
- This driver is based on Linux 2.5.75 usbmouse driver by Vojtech Pavlik\r
-*/\r
-
-#define NDEBUG
-#include "../../miniport/usb_wrapper.h"\r
-
-extern USBPORT_INTERFACE UsbPortInterface;\r
-
-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;\r
- ULONG InputDataConsumed;\r
-\r
- MouseInputData.Flags = MOUSE_MOVE_RELATIVE;\r
- MouseInputData.LastX = data[1];\r
- MouseInputData.LastY = data[2];\r
-\r
- MouseInputData.ButtonFlags = 0;\r
- MouseInputData.ButtonData = 0;\r
-\r
- if ((data[0] & 0x01) && ((mouse->btn_old & 0x01) != (data[0] & 0x01)))\r
- MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;\r
- else if (!(data[0] & 0x01) && ((mouse->btn_old & 0x01) != (data[0] & 0x01)))\r
- MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;\r
-\r
- if ((data[0] & 0x02) && ((mouse->btn_old & 0x02) != (data[0] & 0x02)))\r
- MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;\r
- else if (!(data[0] & 0x02) && ((mouse->btn_old & 0x02) != (data[0] & 0x02)))\r
- MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;\r
-\r
- if ((data[0] & 0x04) && ((mouse->btn_old & 0x04) != (data[0] & 0x04)))\r
- MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;\r
- else if (!(data[0] & 0x04) && ((mouse->btn_old & 0x04) != (data[0] & 0x04)))\r
- MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;\r
-\r
- if ((data[0] & 0x08) && ((mouse->btn_old & 0x08) != (data[0] & 0x08)))\r
- MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_DOWN;\r
- else if (!(data[0] & 0x08) && ((mouse->btn_old & 0x08) != (data[0] & 0x08)))\r
- MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_UP;\r
-\r
- if ((data[0] & 0x10) && ((mouse->btn_old & 0x10) != (data[0] & 0x10)))\r
- MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_DOWN;\r
- else if (!(data[0] & 0x10) && ((mouse->btn_old & 0x10) != (data[0] & 0x10)))\r
- MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_UP;\r
-\r
- if (data[3])\r
- {\r
- MouseInputData.ButtonFlags |= MOUSE_WHEEL;\r
- MouseInputData.ButtonData = data[3];\r
- }\r
- \r
- if (UsbPortInterface.MouseConnectData->ClassService)\r
- {\r
- KIRQL OldIrql;\r
-\r
- KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);\r
- (*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.MouseConnectData->ClassService)(\r
- UsbPortInterface.MouseConnectData->ClassDeviceObject,\r
- &MouseInputData,\r
- (&MouseInputData)+1,\r
- &InputDataConsumed);\r
- KeLowerIrql(OldIrql);\r
- }\r
-\r
- mouse->btn_old = data[0];\r
-\r
- // debug info\r
- printk("MouseInputData.Buttons=0x%03x\n", MouseInputData.Buttons);\r
- }\r
-
- 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 ");\r
- 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)\r
-{\r
- if (usb_register(&usb_mouse_driver) < 0) {\r
- #if mousedebug\r
- printk("Unable to register Mouse driver");\r
- #endif\r
- return;\r
- } \r
-}\r
-\r
-void UsbMouseRemove(void) {\r
- usb_deregister(&usb_mouse_driver);\r
-}\r
+++ /dev/null
-/*
- * (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 <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/usb.h>
-#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 */
-
-
+++ /dev/null
-/*
- * (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 <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/completion.h>
-#include <linux/uts.h> /* for UTS_SYSNAME */
-#include <linux/pci.h> /* for hcd->pdev and dma addressing */
-#include <linux/dma-mapping.h>
-#include <asm/byteorder.h>
-
-#include <linux/usb.h>
-#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 <bustime in us> 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);
-}
-
+++ /dev/null
-/*
- * 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__ */
-
+++ /dev/null
-/*
- * 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 <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/completion.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/ioctl.h>
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-#include <linux/usb.h>
-#include <linux/usbdevice_fs.h>
-#include <linux/suspend.h>
-
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-
-#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;
-}
-
-
+++ /dev/null
-#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 <linux/list.h>
-#include <linux/workqueue.h>
-#include <linux/compiler.h> /* 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 */
+++ /dev/null
-
-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
+++ /dev/null
-/*
- * message.c - synchronous message handling
- */
-#if 0
-#include <linux/pci.h> /* for scatterlist macros */
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <asm/byteorder.h>
-#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; i<dev->actconfig->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; e<as->desc.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; i<dev->descriptor.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);
-
+++ /dev/null
-#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;
-}
+++ /dev/null
-/*
- * 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 <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-#include <linux/usb.h>
-#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);
-}
-
+++ /dev/null
-/*
- * 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 <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h> /* for in_interrupt() */
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-
-#include <asm/io.h>
-#include <asm/scatterlist.h>
-#include <linux/mm.h>
-#include <linux/dma-mapping.h>
-#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 <nousb>
- */
-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");
+++ /dev/null
-/* 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);
-
+++ /dev/null
-/*
- ReactOS specific functions for usbcore module
- by Aleksey Bragin (aleksey@reactos.com)
-*/
-
-#include <ntddk.h>
-#include <debug.h>
-#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;
-}
+++ /dev/null
-#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 <reactos/version.rc>
+++ /dev/null
-;
-; 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
+++ /dev/null
-<module name="usbport" type="exportdriver" installbase="system32/drivers" installname="usbport.sys">
- <importlibrary definition="usbport.def" />
- <define name="__USE_W32API" />
- <library>sys_base</library>
- <library>ntoskrnl</library>
- <library>hal</library>
- <file>message.c</file>
- <file>hcd.c</file>
- <file>hcd-pci.c</file>
- <file>hub.c</file>
- <file>usb.c</file>
- <file>config.c</file>
- <file>urb.c</file>
- <file>buffer_simple.c</file>
- <file>usb-debug.c</file>
- <file>usbcore.c</file>
- <file>core_drivers/usbkey.c</file>
- <file>core_drivers/usbmouse.c</file>
-
- <file>usbcore.rc</file>
-</module>