- Delete cromwell-based usb drivers since they don't work with modern reactos kernel.

- Remove usbhub from the build.

svn path=/trunk/; revision=26625
This commit is contained in:
Aleksey Bragin
2007-05-02 11:37:29 +00:00
parent cff3ed531e
commit 80b680b6ae
71 changed files with 2 additions and 23522 deletions
+2 -8
View File
@@ -1,18 +1,12 @@
<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-->
@@ -1,9 +0,0 @@
<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>
-445
View File
@@ -1,445 +0,0 @@
/*
* PROJECT: ReactOS USB miniport driver (Cromwell type)
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/miniport/common/fdo.c
* PURPOSE: Operations on FDOs
* PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau ([email protected])
* Copyright James Tabor ([email protected])
*/
#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;
}
-453
View File
@@ -1,453 +0,0 @@
/*
* PROJECT: ReactOS USB miniport driver (Cromwell type)
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/miniport/common/main.c
* PURPOSE: Driver entry
* PROGRAMMERS: Copyright Aleksey Bragin ([email protected])
* Copyright 2005-2006 Hervé Poussineau ([email protected])
* Copyright James Tabor ([email protected])
*
* 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;
}
-167
View File
@@ -1,167 +0,0 @@
/*
* PROJECT: ReactOS USB miniport driver (Cromwell type)
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/miniport/common/misc.c
* PURPOSE: Misceallenous operations
* PROGRAMMERS: Copyright 2005 Hervé Poussineau ([email protected])
*/
#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;
}
-624
View File
@@ -1,624 +0,0 @@
/*
* PROJECT: ReactOS USB miniport driver (Cromwell type)
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/miniport/common/pdo.c
* PURPOSE: Operations on PDOs
* PROGRAMMERS: Copyright 2005-2006 Hervé Poussineau ([email protected])
* Copyright James Tabor ([email protected])
*/
#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;
}
@@ -1,114 +0,0 @@
#ifndef _USBMP_COMMON_H_
#define _USBMP_COMMON_H_
// config and include core/hcd.h, for hc_device struct struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
#include "../usb_wrapper.h"
#include <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
@@ -1,62 +0,0 @@
#ifndef _USBMP_COMMON_TYPES_H_
#define _USBMP_COMMON_TYPES_H_
typedef struct _USBMP_DRIVER_EXTENSION
{
//OHCI_HW_INITIALIZATION_DATA InitializationData;
//PVOID HwContext;
//UNICODE_STRING RegistryPath;
} USBMP_DRIVER_EXTENSION, *PUSBMP_DRIVER_EXTENSION;
typedef struct _USBMP_DEVICE_EXTENSTION
{
ULONG DeviceNumber;
PDEVICE_OBJECT PhysicalDeviceObject;
PDEVICE_OBJECT FunctionalDeviceObject;
PDEVICE_OBJECT NextDeviceObject;
//UNICODE_STRING RegistryPath;
UNICODE_STRING HcdInterfaceName;
//KSPIN_LOCK InterruptSpinLock;
PCM_RESOURCE_LIST AllocatedResources;
/* Interrupt-related info */
PKINTERRUPT InterruptObject;
ULONG InterruptVector;
ULONG InterruptLevel;
KINTERRUPT_MODE InterruptMode;
BOOLEAN InterruptShare;
KAFFINITY InterruptAffinity;
PHYSICAL_ADDRESS BaseAddress;
ULONG BaseAddrLength;
ULONG Flags;
//ULONG AdapterInterfaceType;
ULONG SystemIoBusNumber;
ULONG SystemIoSlotNumber;
//LIST_ENTRY AddressMappingListHead;
// DMA stuff, and buffers
PDMA_ADAPTER pDmaAdapter;
//PVOID MapRegisterBase;
ULONG mapRegisterCount;
#ifdef USB_DMA_SINGLE_SUPPORT
//PHYSICAL_ADDRESS Buffer;
//PVOID VirtualBuffer;
//ULONG BufferSize;
// Mdl used for single DMA transfers
//PMDL Mdl;
#endif
//KDPC DpcObject;
PUSBMP_DRIVER_EXTENSION DriverExtension;
ULONG DeviceOpened;
//KMUTEX DeviceLock;
//CHAR MiniPortDeviceExtension[1];
BOOLEAN IsFDO;
struct pci_dev * pdev;
PDEVICE_OBJECT RootHubPdo;
} USBMP_DEVICE_EXTENSION, *PUSBMP_DEVICE_EXTENSION;
#endif
@@ -1,15 +0,0 @@
<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>
@@ -1,384 +0,0 @@
#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 */
@@ -1,72 +0,0 @@
#ifndef _LINUX_BITOPS_H
#define _LINUX_BITOPS_H
/*
* ffs: find first bit set. This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
static inline int generic_ffs(int x)
{
int r = 1;
if (!x)
return 0;
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if (!(x & 1)) {
x >>= 1;
r += 1;
}
return r;
}
/*
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
static inline unsigned int generic_hweight32(unsigned int w)
{
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
}
static inline unsigned int generic_hweight16(unsigned int w)
{
unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
res = (res & 0x3333) + ((res >> 2) & 0x3333);
res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
}
static inline unsigned int generic_hweight8(unsigned int w)
{
unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
res = (res & 0x33) + ((res >> 2) & 0x33);
return (res & 0x0F) + ((res >> 4) & 0x0F);
}
#include "asm/bitops.h"
#endif
-337
View File
@@ -1,337 +0,0 @@
#ifndef _Boot_H_
#define _Boot_H_
#include "config.h"
/***************************************************************************
Includes used by XBox boot code
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/////////////////////////////////
// configuration
#include "consts.h"
#include "stdint.h"
#include "cromwell_types.h"
unsigned int cromwell_config;
unsigned int cromwell_retryload;
unsigned int cromwell_loadbank;
unsigned int cromwell_Biostype;
unsigned int xbox_ram;
#define XROMWELL 0
#define CROMWELL 1
#define ICON_WIDTH 64
#define ICON_HEIGHT 64
/*
static double min (double a, double b)
{
if (a < b) return a; else return b;
}
static inline double max (double a, double b)
{
if (a > b) return a; else return b;
}
*/
//#include "iso_fs.h"
//#include "BootVideo.h"
//#define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } }
#if 0
extern volatile CURRENT_VIDEO_MODE_DETAILS vmode;
unsigned int video_encoder;
volatile u32 VIDEO_CURSOR_POSX;
volatile u32 VIDEO_CURSOR_POSY;
volatile u32 VIDEO_ATTR;
volatile u32 VIDEO_LUMASCALING;
volatile u32 VIDEO_RSCALING;
volatile u32 VIDEO_BSCALING;
volatile u32 BIOS_TICK_COUNT;
volatile u32 VIDEO_VSYNC_POSITION;
volatile u32 VIDEO_VSYNC_DIR;
volatile u32 DVD_TRAY_STATE;
u8 VIDEO_AV_MODE ;
#define DVD_CLOSED 0
#define DVD_CLOSING 1
#define DVD_OPEN 2
#define DVD_OPENING 3
/////////////////////////////////
// Superfunky i386 internal structures
typedef struct gdt_t {
unsigned short m_wSize __attribute__ ((packed));
unsigned long m_dwBase32 __attribute__ ((packed));
unsigned short m_wDummy __attribute__ ((packed));
} ts_descriptor_pointer;
typedef struct { // inside an 8-byte protected mode interrupt vector
u16 m_wHandlerHighAddressLow16;
u16 m_wSelector;
u16 m_wType;
u16 m_wHandlerLinearAddressHigh16;
} ts_pm_interrupt;
typedef enum {
EDT_UNKNOWN= 0,
EDT_XBOXFS
} enumDriveType;
typedef struct tsHarddiskInfo { // this is the retained knowledge about an IDE device after init
unsigned short m_fwPortBase;
unsigned short m_wCountHeads;
unsigned short m_wCountCylinders;
unsigned short m_wCountSectorsPerTrack;
unsigned long m_dwCountSectorsTotal; /* total */
unsigned char m_bLbaMode; /* am i lba (0x40) or chs (0x00) */
unsigned char m_szIdentityModelNumber[40];
unsigned char term_space_1[2];
unsigned char m_szSerial[20];
unsigned char term_space_2[2];
char m_szFirmware[8];
unsigned char term_space_3[2];
unsigned char m_fDriveExists;
unsigned char m_fAtapi; // true if a CDROM, etc
enumDriveType m_enumDriveType;
unsigned char m_bCableConductors; // valid for device 0 if present
unsigned short m_wAtaRevisionSupported;
unsigned char s_length;
unsigned char m_length;
unsigned char m_fHasMbr;
unsigned short m_securitySettings; //This contains the contents of the ATA security regs
} tsHarddiskInfo;
/////////////////////////////////
// LED-flashing codes
// or these together as argument to I2cSetFrontpanelLed
enum {
I2C_LED_RED0 = 0x80,
I2C_LED_RED1 = 0x40,
I2C_LED_RED2 = 0x20,
I2C_LED_RED3 = 0x10,
I2C_LED_GREEN0 = 0x08,
I2C_LED_GREEN1 = 0x04,
I2C_LED_GREEN2 = 0x02,
I2C_LED_GREEN3 = 0x01
};
///////////////////////////////
/* BIOS-wide error codes all have b31 set */
enum {
ERR_SUCCESS = 0, // completed without error
ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time
ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error
ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test
};
/////////////////////////////////
// some Boot API prototypes
//////// BootPerformPicChallengeResponseAction.c
/* ---------------------------- IO primitives -----------------------------------------------------------
*/
static __inline void IoOutputByte(u16 wAds, u8 bValue) {
// __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) );
__asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds));
}
static __inline void IoOutputWord(u16 wAds, u16 wValue) {
// __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
__asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds));
}
static __inline void IoOutputDword(u16 wAds, u32 dwValue) {
// __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
__asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds));
}
static __inline u8 IoInputByte(u16 wAds) {
unsigned char _v;
__asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds));
return _v;
}
static __inline u16 IoInputWord(u16 wAds) {
u16 _v;
__asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds));
return _v;
}
static __inline u32 IoInputDword(u16 wAds) {
u32 _v;
__asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds));
return _v;
}
#define rdmsr(msr,val1,val2) \
__asm__ __volatile__("rdmsr" \
: "=a" (val1), "=d" (val2) \
: "c" (msr))
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
: /* no outputs */ \
: "c" (msr), "a" (val1), "d" (val2))
void BootPciInterruptEnable(void);
// boot process
int BootPerformPicChallengeResponseAction(void);
// LED control (see associated enum above)
int I2cSetFrontpanelLed(u8 b);
#define bprintf(...)
#if PRINT_TRACE
#define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__);
#else
#define TRACE
#endif
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *m_plistentryNext;
struct _LIST_ENTRY *m_plistentryPrevious;
} LIST_ENTRY;
void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew);
void ListEntryRemove(LIST_ENTRY *plistentryCurrent);
////////// BootPerformXCodeActions.c
int BootPerformXCodeActions(void);
#include "BootEEPROM.h"
#include "BootParser.h"
////////// BootStartBios.c
void StartBios(CONFIGENTRY *config,int nActivePartition, int nFATXPresent,int bootfrom);
int BootMenu(CONFIGENTRY *config,int nDrive,int nActivePartition, int nFATXPresent);
////////// BootResetActions.c
void ClearIDT (void);
void BootResetAction(void);
void BootCpuCache(bool fEnable) ;
int printk(const char *szFormat, ...);
void BiosCmosWrite(u8 bAds, u8 bData);
u8 BiosCmosRead(u8 bAds);
///////// BootPciPeripheralInitialization.c
void BootPciPeripheralInitialization(void);
void BootAGPBUSInitialization(void);
void BootDetectMemorySize(void);
extern void ReadPCIByte(unsigned int bus, unsigned int dev, unsigned intfunc, unsigned int reg_off, unsigned char *pbyteval);
extern void WritePCIByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval);
extern void ReadPCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int *pdwordval);
extern void WritePCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dwordval);
extern void ReadPCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
extern void WritePCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func,
unsigned int reg_off, unsigned char byteval);
u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw);
u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
///////// BootPerformPicChallengeResponseAction.c
int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite);
int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite);
bool I2CGetTemperature(int *, int *);
void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask);
///////// BootIde.c
extern tsHarddiskInfo tsaHarddiskInfo[]; // static struct stores data about attached drives
int BootIdeInit(void);
int BootIdeReadSector(int nDriveIndex, void * pbBuffer, unsigned int block, int byte_offset, int n_bytes);
int BootIdeBootSectorHddOrElTorito(int nDriveIndex, u8 * pbaResult);
int BootIdeAtapiAdditionalSenseCode(int nDrive, u8 * pba, int nLengthMaxReturn);
int BootIdeSetTransferMode(int nIndexDrive, int nMode);
int BootIdeWaitNotBusy(unsigned uIoBase);
bool BootIdeAtapiReportFriendlyError(int nDriveIndex, char * szErrorReturn, int nMaxLengthError);
void BootIdeAtapiPrintkFriendlyError(int nDriveIndex);
///////// BootUSB.c
void BootStopUSB(void);
void BootStartUSB(void);
void USBGetEvents(void);
#include "xpad.h"
extern struct xpad_data XPAD_current[4];
extern struct xpad_data XPAD_last[4];
extern void wait_ms(u32 ticks);
extern void wait_us(u32 ticks);
extern void wait_smalldelay(void);
void * memcpy(void *dest, const void *src, size_t size);
void * memset(void *dest, int data, size_t size);
int memcmp(const void *buffer1, const void *buffer2, size_t num);
int _strncmp(const char *sz1, const char *sz2, int nMax);
char * strcpy(char *sz, const char *szc);
char * _strncpy (char * dest, const char * src, size_t n);
void chrreplace(char *string, char search, char ch);
#define printf printk
#define sleep wait_ms
int tolower(int ch);
int isspace (int c);
void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength);
void * malloc(size_t size);
void free(void *);
extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde;
extern volatile bool fSeenPowerdown;
typedef enum {
ETS_OPEN_OR_OPENING=0,
ETS_CLOSING,
ETS_CLOSED
} TRAY_STATE;
extern volatile TRAY_STATE traystate;
extern void BootInterruptsWriteIdt(void);
#endif
int copy_swap_trim(unsigned char *dst, unsigned char *src, int len);
void HMAC_SHA1( unsigned char *result,
unsigned char *key, int key_length,
unsigned char *text1, int text1_length,
unsigned char *text2, int text2_length );
char *strrchr0(char *string, char ch);
#endif // _Boot_H_
@@ -1,70 +0,0 @@
#ifndef _Consts_H_
#define _Consts_H_
/*
*
* includes for startup code in a form usable by the .S files
*
*/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#define PCI_CFG_ADDR 0x0CF8
#define PCI_CFG_DATA 0x0CFC
#define I2C_IO_BASE 0xc000
#define BUS_0 0
#define BUS_1 1
#define DEV_0 0
#define DEV_1 1
#define DEV_2 2
#define DEV_3 3
#define DEV_4 4
#define DEV_5 5
#define DEV_6 6
#define DEV_7 7
#define DEV_8 8
#define DEV_9 9
#define DEV_a 0xa
#define DEV_b 0xb
#define DEV_c 0xc
#define DEV_d 0xd
#define DEV_e 0xe
#define DEV_f 0xf
#define DEV_10 0x10
#define DEV_11 0x11
#define DEV_12 0x12
#define DEV_13 0x13
#define DEV_14 0x14
#define DEV_15 0x15
#define DEV_16 0x16
#define DEV_17 0x17
#define DEV_18 0x18
#define DEV_19 0x19
#define DEV_1a 0x1a
#define DEV_1b 0x1b
#define DEV_1c 0x1c
#define DEV_1d 0x1d
#define DEV_1e 0x1e
#define DEV_1f 0x1f
#define FUNC_0 0
/*
#define boot_post_macro(value) \
movb $(value), %al ;\
outb %al, $0x80
*/
#endif // _Consts_H_
@@ -1,27 +0,0 @@
#ifndef cromwell_types_h
#define cromwell_types_h
/////////////////////////////////
// some typedefs to make for easy sizing
//typedef unsigned long ULONG;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
#ifndef bool_already_defined_
typedef int bool;
#endif
typedef unsigned long RGBA; // LSB=R -> MSB = A
//typedef long long __int64;
#define guint int
#define guint8 unsigned char
#define true 1
#define false 0
#ifndef NULL
#define NULL ((void *)0)
#endif
#endif /* #ifndef cromwell_types_h */
-132
View File
@@ -1,132 +0,0 @@
#ifndef _I386_ERRNO_H
#define _I386_ERRNO_H
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#endif
@@ -1,856 +0,0 @@
/*
* linux-wrapper.h
*
* Hard coded Linux kernel replacements for x86
*
* (c) 2003 Georg Acher ([email protected])
*
* Emulation of:
* typedefs
* structs
* macros
*
* All structs and prototypes are based on kernel source 2.5.72
*
* Modified by Aleksey Bragin ([email protected]) 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);
-224
View File
@@ -1,224 +0,0 @@
#ifndef _BOOT_LIST_H
#define _BOOT_LIST_H
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (void *) 0;
entry->prev = (void *) 0;
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(struct list_head *head)
{
return head->next == head;
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member) \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#endif
@@ -1,162 +0,0 @@
// PCI -> HAL interface
// this file is part of linux_wrapper.h
//FIXME: Move this file, make its definitions more general
#include "../common/usbcommon_types.h"
/*
Initialize device before it's used by a driver. Ask low-level code to enable I/O and memory.
Wake up the device if it was suspended. Beware, this function can fail.
*/
static int __inline__ pci_enable_device(struct pci_dev *dev)
{
DPRINT1("pci_enable_device() called...\n");
return 0;
}
// Get physical address where resource x resides
static PHYSICAL_ADDRESS __inline__ pci_resource_start (struct pci_dev *dev, int x)
{
PUSBMP_DEVICE_EXTENSION dev_ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
DPRINT1("pci_resource_start() called, x=0x%x\n", x);
//FIXME: Take x into account
return dev_ext->BaseAddress;
//return dev->base[x];
}
// ???
static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x)
{
PUSBMP_DEVICE_EXTENSION ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
DPRINT1("pci_resource_len() called, x=0x%x\n", x);
//FIXME: Take x into account
return ext->BaseAddrLength;
}
// ???
static int __inline__ pci_resource_flags(struct pci_dev *dev, int x)
{
PUSBMP_DEVICE_EXTENSION ext = (PUSBMP_DEVICE_EXTENSION)dev->dev_ext;
DPRINT1("pci_resource_flags() called, x=0x%x\n", x);
//FIXME: Take x into account
return ext->Flags;
}
/*
Enables bus-mastering for device dev
*/
static int __inline__ pci_set_master(struct pci_dev *dev) {return 0;}
// Store pointer to data for this device
static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d)
{
DPRINT1("pci_set_drvdata() called...\n");
dev->data=(void*)d;
return 0;
}
// Get pointer to previously saved data
static void __inline__ *pci_get_drvdata(struct pci_dev *dev)
{
DPRINT1("pci_get_drvdata() called...\n");
return dev->data;
}
/*
===========================================================================
I/O mem related stuff below
*/
/*
Allocate I/O memory region.
Parameters:
start begin of region
n length of region
name name of requester
*/
static int __inline__ request_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
{
DPRINT1("request_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
return ~0;
}
/*
Unmap I/O memory from kernel address space.
Parameters:
addr virtual start address
*/
static int __inline__ iounmap(void* p)
{
DPRINT1("iounmap(): p=0x%x. FIXME - how to obtain len of mapped region?\n", p);
//MmUnnapIoSpace(p);
return 0;
}
/*
Release I/O port region.
Parameters:
start begin of region
n length of region
*/
static int __inline__ release_region(PHYSICAL_ADDRESS addr, unsigned long len)
{
DPRINT1("release_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
return 0;
}
/*
Allocate I/O memory region.
Parameters:
start begin of region
n length of region
name name of requester
*/
static int __inline__ request_mem_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
{
DPRINT1("request_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
return 1;
}
/*
Remap I/O memory into kernel address space (no cache).
Parameters:
phys_addr begin of physical address range
size size of physical address range
Returns:
virtual start address of mapped range
*/
static void __inline__ *ioremap_nocache(PHYSICAL_ADDRESS addr, unsigned long len)
{
// MmMapIoSpace with NoCache param
DPRINT1("ioremap_nocache(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
return MmMapIoSpace(addr, len, MmNonCached);
}
/*
Release I/O memory region.
Parameters:
start begin of region
n length of region
*/
static int __inline__ release_mem_region(PHYSICAL_ADDRESS addr, unsigned long len)
{
DPRINT1("release_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
return 0;
}
@@ -1,16 +0,0 @@
#ifndef PCI_IDS__H
#define PCI_IDS__H
#define PCI_VENDOR_ID_NS 0x100b
#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_VENDOR_ID_OPTI 0x1045
#define PCI_VENDOR_ID_VIA 0x1106
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
#define PCI_CLASS_SERIAL_USB ((PCI_CLASS_SERIAL_BUS_CTLR << 8) + PCI_SUBCLASS_SB_USB)
#endif
File diff suppressed because it is too large Load Diff
@@ -1,315 +0,0 @@
/*
* This file holds USB constants and structures that are needed for USB
* device APIs. These are used by the USB device model, which is defined
* in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
* that need these:
*
* - the master/host side Linux-USB kernel driver API;
* - the "usbfs" user space API; and
* - (eventually) a Linux "gadget" slave/device side driver API.
*
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
* act either as a USB master/host or as a USB slave/device. That means
* the master and slave side APIs will benefit from working well together.
*/
#ifndef __LINUX_USB_CH9_H
#define __LINUX_USB_CH9_H
#if 0
#include <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 */
@@ -1,90 +0,0 @@
/*
* USB support for XBOX, based on Linux kernel source
*
* 2003-06-21 Georg Acher ([email protected])
*
*/
#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);
}
/*------------------------------------------------------------------------*/
@@ -1,906 +0,0 @@
/*
* USB support based on Linux kernel source
*
* 2003-06-21 Georg Acher ([email protected])
*
* 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);
}
-138
View File
@@ -1,138 +0,0 @@
#include "../usb_wrapper.h"
#include "config.h"
#include "xremote.h"
// This is for the Xpad
extern unsigned char xpad_button_history[7];
// This is for the Keyboard
extern unsigned int current_keyboard_key;
int risefall_xpad_BUTTON(unsigned char selected_Button) {
int xpad_id;
int match;
extern int xpad_num;
// USB keyboard section
match=0;
if (current_keyboard_key!=0) {
switch (selected_Button) {
case TRIGGER_XPAD_KEY_A :
if (current_keyboard_key == 0x28) match=1;
break;
case TRIGGER_XPAD_KEY_B :
if (current_keyboard_key == 0x29) match=1;
break;
case TRIGGER_XPAD_PAD_UP :
if (current_keyboard_key == 0x52) match=1;
break;
case TRIGGER_XPAD_PAD_DOWN :
if (current_keyboard_key == 0x51) match=1;
break;
case TRIGGER_XPAD_PAD_LEFT :
if (current_keyboard_key == 0x50) match=1;
break;
case TRIGGER_XPAD_PAD_RIGHT :
if (current_keyboard_key == 0x4f) match=1;
break;
}
if (match) {
//A match occurred, so the event has now been processed
//Clear it, and return success
current_keyboard_key=0;
return 1;
}
}
// Xbox IR remote section
match=0;
if (!remotekeyIsRepeat) {
/* We only grab the key event when the button is first pressed.
* If it's being held down, we ignore the multiple events this
* generates */
switch (selected_Button) {
case TRIGGER_XPAD_KEY_A:
if (current_remote_key == RC_KEY_SELECT) match=1;
break;
case TRIGGER_XPAD_PAD_UP:
if (current_remote_key == RC_KEY_UP) match=1;
break;
case TRIGGER_XPAD_PAD_DOWN:
if (current_remote_key == RC_KEY_DOWN) match=1;
break;
case TRIGGER_XPAD_PAD_LEFT:
if (current_remote_key == RC_KEY_LEFT) match=1;
break;
case TRIGGER_XPAD_PAD_RIGHT:
if (current_remote_key == RC_KEY_RIGHT) match=1;
break;
case TRIGGER_XPAD_KEY_BACK:
if (current_remote_key == RC_KEY_BACK) match=1;
break;
}
if (match) {
//A match occurred, so the event has now been processed
//Clear it, and return success
current_remote_key=0;
remotekeyIsRepeat=0;
return 1;
}
}
// Xbox controller section
if (selected_Button < 6) {
unsigned char Button;
Button = XPAD_current[0].keys[selected_Button];
if ((Button>0x30)&&(xpad_button_history[selected_Button]==0)) {
// Button Rising Edge
xpad_button_history[selected_Button] = 1;
return 1;
}
if ((Button==0x00)&&(xpad_button_history[selected_Button]==1)) {
// Button Falling Edge
xpad_button_history[selected_Button] = 0;
return -1;
}
}
if ((selected_Button > 5) & (selected_Button < 10) ) {
unsigned char Buttonmask;
switch (selected_Button) {
case TRIGGER_XPAD_PAD_UP :
Buttonmask = XPAD_PAD_UP;
break;
case TRIGGER_XPAD_PAD_DOWN :
Buttonmask = XPAD_PAD_DOWN;
break;
case TRIGGER_XPAD_PAD_LEFT :
Buttonmask = XPAD_PAD_LEFT;
break;
case TRIGGER_XPAD_PAD_RIGHT :
Buttonmask = XPAD_PAD_RIGHT;
break;
}
// Rising Edge
if (((XPAD_current[0].pad&Buttonmask) != 0) & ((xpad_button_history[6]&Buttonmask) == 0)) {
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
return 1;
}
// Falling Edge
if (((XPAD_current[0].pad&Buttonmask) == 0) & ((xpad_button_history[6]&Buttonmask) != 0)) {
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
return -1;
}
}
return 0;
}
@@ -1,24 +0,0 @@
#include "../usb_wrapper.h"
void wait_ms(int mils)
{
LARGE_INTEGER Interval;
DPRINT1("wait_ms(%d)\n", mils);
Interval.QuadPart = -(mils+1)*10000;
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
// schedule_timeout(1 + mils * HZ / 1000);
}
void my_udelay(int us)
{
LARGE_INTEGER Interval;
DPRINT1("udelay(%d)\n", us);
Interval.QuadPart = -us*10;
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
}
@@ -1,7 +0,0 @@
<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>
-124
View File
@@ -1,124 +0,0 @@
#include "../usb_wrapper.h"
#define keyboarddebug 1
#if keyboarddebug
//extern int printk(const char *szFormat, ...);
int ycoffset = 0;
#endif
unsigned int current_keyboard_key;
struct usb_kbd_info {
struct urb *urb;
unsigned char kbd_pkt[8];
unsigned char old[8];
/*
struct input_dev dev;
struct usb_device *usbdev;
struct urb irq, led;
struct usb_ctrlrequest dr;
unsigned char leds, newleds;
char name[128];
int open;
*/
};
static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_kbd_info *kbd = urb->context;
//int i;
if (urb->status) return;
memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8);
current_keyboard_key = kbd->kbd_pkt[2];
#if keyboarddebug
//ycoffset += 15;
//ycoffset = ycoffset % 600;
//VIDEO_CURSOR_POSX=20;
//VIDEO_CURSOR_POSY=ycoffset;
printk(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]);
#endif
usb_submit_urb(urb,GFP_ATOMIC);
}
static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct urb *urb;
struct usb_device *udev = interface_to_usbdev (intf);
struct usb_endpoint_descriptor *ep_irq_in;
//struct usb_endpoint_descriptor *ep_irq_out;
struct usb_kbd_info *usbk;
//int i, pipe, maxp;
//char *buf;
usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0);
if (!usbk) return -1;
urb=usb_alloc_urb(0,0);
if (!urb) return -1;
usbk->urb=urb;
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
usb_fill_int_urb(urb, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
usbk->kbd_pkt, 8, usb_kbd_irq,
usbk, 8);
usb_submit_urb(urb,GFP_ATOMIC);
usb_set_intfdata(intf,usbk);
#if keyboarddebug
printk("USB Keyboard Connected\n");
#endif
return 0;
}
static void usb_kbd_disconnect(struct usb_interface *intf)
{
struct usb_kbd_info *usbk = usb_get_intfdata (intf);
usbprintk("Keyboard disconnected\n ");
usb_unlink_urb(usbk->urb);
usb_free_urb(usbk->urb);
kfree(usbk);
}
static struct usb_device_id usb_kbd_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 1) },
{ } /* Terminating entry */
};
static struct usb_driver usb_kbd_driver = {
.owner = THIS_MODULE,
.name = "keyboard",
.probe = usb_kbd_probe,
.disconnect = usb_kbd_disconnect,
.id_table = usb_kbd_id_table,
};
void UsbKeyBoardInit(void)
{
//current_remote_key=0;
//sbprintk("Keyboard probe %p ",xremote_probe);
if (usb_register(&usb_kbd_driver) < 0) {
#if keyboarddebug
printk("Unable to register Keyboard driver");
#endif
return;
}
}
void UsbKeyBoardRemove(void) {
usb_deregister(&usb_kbd_driver);
}
@@ -1,65 +0,0 @@
/*
* Interface calls to BIOS
*
* 2003-06-21 Georg Acher ([email protected])
*
*/
#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;
}
/*------------------------------------------------------------------------*/
-183
View File
@@ -1,183 +0,0 @@
/*
* Simple XPAD driver for XBOX
*
* (c) 2003-07-04, Georg Acher ([email protected])
*
* Inspired by linux/drivers/usb/input/xpad.c
* by Marko Friedemann <[email protected]>
*
*/
#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);
}
/*------------------------------------------------------------------------*/
-142
View File
@@ -1,142 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* $Id$
*
* Copyright (c) 2002 Steven Toth <[email protected]>
*
* 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);
}
@@ -1,48 +0,0 @@
//#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"
@@ -1,3 +0,0 @@
O_TARGET := ohci-hcd.o
include $(TOPDIR)/Rules.make
@@ -1,666 +0,0 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <[email protected]>
* (C) Copyright 2000-2002 David Brownell <[email protected]>
*
* 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 (&regs->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 (&regs->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 (&regs->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 (&regs->intrstatus), next, size);
ohci_dump_intr_mask (controller, "intrenable",
readl (&regs->intrenable), next, size);
// intrdisable always same as intrenable
maybe_print_eds (controller, "ed_periodcurrent",
readl (&regs->ed_periodcurrent), next, size);
maybe_print_eds (controller, "ed_controlhead",
readl (&regs->ed_controlhead), next, size);
maybe_print_eds (controller, "ed_controlcurrent",
readl (&regs->ed_controlcurrent), next, size);
maybe_print_eds (controller, "ed_bulkhead",
readl (&regs->ed_bulkhead), next, size);
maybe_print_eds (controller, "ed_bulkcurrent",
readl (&regs->ed_bulkcurrent), next, size);
maybe_print_eds (controller, "donehead",
readl (&regs->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 (&regs->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 (&regs->fmremaining);
temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
rdata, (rdata >> 31) ? " FRT" : "",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->periodicstart);
temp = snprintf (next, size, "periodicstart 0x%04x\n",
rdata & 0x3fff);
size -= temp;
next += temp;
rdata = readl (&regs->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
/*-------------------------------------------------------------------------*/
@@ -1,722 +0,0 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <[email protected]>
* (C) Copyright 2000-2002 David Brownell <[email protected]>
*
* [ 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 (&regs->intrstatus)) == ~(u32)0) {
disable (ohci);
ohci_dbg (ohci, "device removed!\n");
return 0;
/* interrupt for some other device? */
} else if ((ints &= readl (&regs->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, &regs->intrdisable);
dl_done_list (ohci, dl_reverse_done_list (ohci), ptregs);
writel (OHCI_INTR_WDH, &regs->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, &regs->intrdisable);
spin_unlock (&ohci->lock);
writel (ints, &regs->intrstatus);
writel (OHCI_INTR_MIE, &regs->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
@@ -1,271 +0,0 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <[email protected]>
* (C) Copyright 2000-2002 David Brownell <[email protected]>
*
* 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;
}
@@ -1,146 +0,0 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <[email protected]>
* (C) Copyright 2000-2002 David Brownell <[email protected]>
*
* 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);
}
@@ -1,412 +0,0 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <[email protected]>
* (C) Copyright 2000-2002 David Brownell <[email protected]>
*
* [ 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);*/
File diff suppressed because it is too large Load Diff
@@ -1,76 +0,0 @@
#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();
}
-415
View File
@@ -1,415 +0,0 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <[email protected]>
* (C) Copyright 2000-2002 David Brownell <[email protected]>
*
* 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
@@ -1,5 +0,0 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "USB OHCI Device Driver\0"
#define REACTOS_STR_INTERNAL_NAME "ohci\0"
#define REACTOS_STR_ORIGINAL_FILENAME "ohci.sys\0"
#include <reactos/version.rc>
@@ -1,5 +0,0 @@
/*
* Configs for OHCI
*/
#define CONFIG_PCI
@@ -1,13 +0,0 @@
<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>
@@ -1,616 +0,0 @@
/*
* UHCI-specific debugging code. Invaluable when something
* goes wrong, but don't get in my face.
*
* Kernel visible pointers are surrounded in []'s and bus
* visible pointers are surrounded in ()'s
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2001 Johannes Erdfelt
*/
#if 0
#include <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
File diff suppressed because it is too large Load Diff
@@ -1,419 +0,0 @@
#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
@@ -1,184 +0,0 @@
/*
* Universal Host Controller Interface driver for USB.
*
* Maintainer: Johannes Erdfelt <[email protected]>
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2002 Johannes Erdfelt, [email protected]
* (C) Copyright 1999 Randy Dunlap
* (C) Copyright 1999 Georg Acher, [email protected]
* (C) Copyright 1999 Deti Fliegl, [email protected]
* (C) Copyright 1999 Thomas Sailer, [email protected]
*/
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;
}
@@ -1,81 +0,0 @@
/*
ReactOS specific functions for UHCI module
by Aleksey Bragin ([email protected])
and Hervé Poussineau ([email protected])
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();
}
@@ -1,9 +0,0 @@
#include "usbcommon.h"
#define USB_UHCI_TAG TAG('u','s','b','u')
/* declare basic init functions and structures */
int uhci_hcd_init(void);
void uhci_hcd_cleanup(void);
int STDCALL usb_init(void);
void STDCALL usb_exit(void);
@@ -1,5 +0,0 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "USB UHCI Device Driver\0"
#define REACTOS_STR_INTERNAL_NAME "uhci\0"
#define REACTOS_STR_ORIGINAL_FILENAME "uhci.sys\0"
#include <reactos/version.rc>
@@ -1,5 +0,0 @@
/*
* Configs for UHCI
*/
#define CONFIG_PCI
@@ -1,13 +0,0 @@
<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>
@@ -1,42 +0,0 @@
/*
* buffer_simple.c -- replacement for usb/core/buffer.c
*
* (c) Georg Acher, [email protected]
*
*/
#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);
}
-509
View File
@@ -1,509 +0,0 @@
#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;
}
@@ -1,236 +0,0 @@
/*
This driver is based on Cromwell's usbkey driver
and also includes stuff from Linux 2.5 usbkey driver by Vojtech Pavlik
*/
#define NDEBUG
#include "../../miniport/usb_wrapper.h"
#define keyboarddebug 0
#if keyboarddebug
//extern int printk(const char *szFormat, ...);
#endif
unsigned int current_keyboard_key;
extern USBPORT_INTERFACE UsbPortInterface;
static unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
115,114, 0, 0, 0,124, 0,181,182,183,184,185,186,187,188,189,
190,191,192,193,194,195,196,197,198, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
150,158,159,128,136,177,178,176,142,152,173,140
};
struct usb_kbd_info {
struct urb *urb;
unsigned char kbd_pkt[8];
unsigned char old[8];
/*
struct input_dev dev;
struct usb_device *usbdev;
struct urb irq, led;
struct usb_ctrlrequest dr;
unsigned char leds, newleds;
char name[128];
int open;
*/
};
/**
* memscan - Find a character in an area of memory.
* @addr: The memory area
* @c: The byte to search for
* @size: The size of the area.
*
* returns the address of the first occurrence of @c, or 1 byte past
* the area if @c is not found
*/
void * memscan(void * addr, int c, size_t size)
{
unsigned char * p = (unsigned char *) addr;
while (size) {
if (*p == c)
return (void *) p;
p++;
size--;
}
return (void *) p;
}
void input_report_key(unsigned int code, int value)
{
KEYBOARD_INPUT_DATA KeyboardInputData;
ULONG InputDataConsumed;
KeyboardInputData.MakeCode = code;
KeyboardInputData.Flags = (value == 1) ? KEY_MAKE : KEY_BREAK;
if (UsbPortInterface.KbdConnectData->ClassService)
{
KIRQL OldIrql;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
(*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.KbdConnectData->ClassService)(
UsbPortInterface.KbdConnectData->ClassDeviceObject,
&KeyboardInputData,
(&KeyboardInputData)+1,
&InputDataConsumed);
KeLowerIrql(OldIrql);
}
}
static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_kbd_info *kbd = urb->context;
int i;
if (urb->status) return;
memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8);
//for (i = 0; i < 8; i++)
// input_report_key(usb_kbd_keycode[i + 224], (kbd->kbd_pkt[0] >> i) & 1);
for (i = 2; i < 8; i++) {
if (kbd->old[i] > 3 && memscan(kbd->kbd_pkt + 2, kbd->old[i], 6) == kbd->kbd_pkt + 8) {
if (usb_kbd_keycode[kbd->old[i]])
input_report_key(usb_kbd_keycode[kbd->old[i]], 0);
else
info("Unknown key (scancode %#x) released.", kbd->old[i]);
}
if (kbd->kbd_pkt[i] > 3 && memscan(kbd->old + 2, kbd->kbd_pkt[i], 6) == kbd->old + 8) {
if (usb_kbd_keycode[kbd->kbd_pkt[i]])
input_report_key(usb_kbd_keycode[kbd->kbd_pkt[i]], 1);
else
info("Unknown key (scancode %#x) pressed.", kbd->kbd_pkt[i]);
}
}
memcpy(kbd->old, kbd->kbd_pkt, 8);
#if 0
//memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8);
//current_keyboard_key = kbd->kbd_pkt[2];
{
KEYBOARD_INPUT_DATA KeyboardInputData;
ULONG InputDataConsumed;
KeyboardInputData.MakeCode = current_keyboard_key & ~0x80;
KeyboardInputData.Flags = (current_keyboard_key & 0x80) ? KEY_MAKE : KEY_BREAK;
if (UsbPortInterface.KbdConnectData->ClassService)
{
KIRQL OldIrql;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
(*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.KbdConnectData->ClassService)(
UsbPortInterface.KbdConnectData->ClassDeviceObject,
&KeyboardInputData,
(&KeyboardInputData)+1,
&InputDataConsumed);
KeLowerIrql(OldIrql);
}
}
#endif
#if keyboarddebug
printk(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]);
#endif
usb_submit_urb(urb,GFP_ATOMIC);
}
static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct urb *urb;
struct usb_device *udev = interface_to_usbdev (intf);
struct usb_endpoint_descriptor *ep_irq_in;
//struct usb_endpoint_descriptor *ep_irq_out;
struct usb_kbd_info *usbk;
//int i, pipe, maxp;
//char *buf;
usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0);
if (!usbk) return -1;
memset(usbk, 0, sizeof(struct usb_kbd_info));
urb=usb_alloc_urb(0,0);
if (!urb) return -1;
usbk->urb=urb;
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
usb_fill_int_urb(urb, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
usbk->kbd_pkt, 8, usb_kbd_irq,
usbk, 8);
usb_submit_urb(urb,GFP_ATOMIC);
usb_set_intfdata(intf,usbk);
#if keyboarddebug
printk("USB Keyboard Connected\n");
#endif
return 0;
}
static void usb_kbd_disconnect(struct usb_interface *intf)
{
struct usb_kbd_info *usbk = usb_get_intfdata (intf);
usbprintk("Keyboard disconnected\n ");
usb_unlink_urb(usbk->urb);
usb_free_urb(usbk->urb);
kfree(usbk);
}
static struct usb_device_id usb_kbd_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 1) },
{ } /* Terminating entry */
};
static struct usb_driver usb_kbd_driver = {
.owner = THIS_MODULE,
.name = "keyboard",
.probe = usb_kbd_probe,
.disconnect = usb_kbd_disconnect,
.id_table = usb_kbd_id_table,
};
void UsbKeyBoardInit(void)
{
//current_remote_key=0;
//sbprintk("Keyboard probe %p ",xremote_probe);
if (usb_register(&usb_kbd_driver) < 0) {
#if keyboarddebug
printk("Unable to register Keyboard driver");
#endif
return;
}
}
void UsbKeyBoardRemove(void) {
usb_deregister(&usb_kbd_driver);
}
@@ -1,279 +0,0 @@
/*
This driver is based on Linux 2.5.75 usbmouse driver by Vojtech Pavlik
*/
#define NDEBUG
#include "../../miniport/usb_wrapper.h"
extern USBPORT_INTERFACE UsbPortInterface;
struct usb_mouse {
char name[128];
char phys[64];
struct usb_device *usbdev;
char btn_old;
//struct input_dev dev;
struct urb *irq;
int open;
signed char *data;
dma_addr_t data_dma;
};
static void usb_mouse_irq(struct urb *urb, struct pt_regs *regs)
{
struct usb_mouse *mouse = urb->context;
signed char *data = mouse->data;
int status;
switch (urb->status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
/* -EPIPE: should clear the halt */
default: /* error */
goto resubmit;
}
/*
input_regs(dev, regs);
input_report_key(dev, BTN_LEFT, data[0] & 0x01);
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
input_report_key(dev, BTN_SIDE, data[0] & 0x08);
input_report_key(dev, BTN_EXTRA, data[0] & 0x10);
input_report_rel(dev, REL_X, data[1]);
input_report_rel(dev, REL_Y, data[2]);
input_report_rel(dev, REL_WHEEL, data[3]);
input_sync(dev);
*/
{
MOUSE_INPUT_DATA MouseInputData;
ULONG InputDataConsumed;
MouseInputData.Flags = MOUSE_MOVE_RELATIVE;
MouseInputData.LastX = data[1];
MouseInputData.LastY = data[2];
MouseInputData.ButtonFlags = 0;
MouseInputData.ButtonData = 0;
if ((data[0] & 0x01) && ((mouse->btn_old & 0x01) != (data[0] & 0x01)))
MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
else if (!(data[0] & 0x01) && ((mouse->btn_old & 0x01) != (data[0] & 0x01)))
MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
if ((data[0] & 0x02) && ((mouse->btn_old & 0x02) != (data[0] & 0x02)))
MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
else if (!(data[0] & 0x02) && ((mouse->btn_old & 0x02) != (data[0] & 0x02)))
MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
if ((data[0] & 0x04) && ((mouse->btn_old & 0x04) != (data[0] & 0x04)))
MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
else if (!(data[0] & 0x04) && ((mouse->btn_old & 0x04) != (data[0] & 0x04)))
MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
if ((data[0] & 0x08) && ((mouse->btn_old & 0x08) != (data[0] & 0x08)))
MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_DOWN;
else if (!(data[0] & 0x08) && ((mouse->btn_old & 0x08) != (data[0] & 0x08)))
MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_UP;
if ((data[0] & 0x10) && ((mouse->btn_old & 0x10) != (data[0] & 0x10)))
MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_DOWN;
else if (!(data[0] & 0x10) && ((mouse->btn_old & 0x10) != (data[0] & 0x10)))
MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_UP;
if (data[3])
{
MouseInputData.ButtonFlags |= MOUSE_WHEEL;
MouseInputData.ButtonData = data[3];
}
if (UsbPortInterface.MouseConnectData->ClassService)
{
KIRQL OldIrql;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
(*(PSERVICE_CALLBACK_ROUTINE)UsbPortInterface.MouseConnectData->ClassService)(
UsbPortInterface.MouseConnectData->ClassDeviceObject,
&MouseInputData,
(&MouseInputData)+1,
&InputDataConsumed);
KeLowerIrql(OldIrql);
}
mouse->btn_old = data[0];
// debug info
printk("MouseInputData.Buttons=0x%03x\n", MouseInputData.Buttons);
}
printk("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data[1], data[2], data[3], data[0]);
resubmit:
status = usb_submit_urb (urb, SLAB_ATOMIC);
if (status)
err ("can't resubmit intr, %s-%s/input0, status %d",
mouse->usbdev->bus->bus_name,
mouse->usbdev->devpath, status);
}
/*
static int usb_mouse_open(struct input_dev *dev)
{
struct usb_mouse *mouse = dev->private;
if (mouse->open++)
return 0;
mouse->irq->dev = mouse->usbdev;
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
mouse->open--;
return -EIO;
}
return 0;
}
static void usb_mouse_close(struct input_dev *dev)
{
struct usb_mouse *mouse = dev->private;
if (!--mouse->open)
usb_unlink_urb(mouse->irq);
}
*/
static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id)
{
struct usb_device * dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_mouse *mouse;
int pipe, maxp;
char path[64];
char *buf;
interface = &intf->altsetting[intf->act_altsetting];
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80))
return -ENODEV;
if ((endpoint->bmAttributes & 3) != 3)
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL)))
return -ENOMEM;
memset(mouse, 0, sizeof(struct usb_mouse));
mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
if (!mouse->data) {
kfree(mouse);
return -ENOMEM;
}
mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!mouse->irq) {
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
kfree(mouse);
return -ENODEV;
}
mouse->usbdev = dev;
usb_make_path(dev, path, 64);
sprintf(mouse->phys, "%s/input0", path);
if (!(buf = kmalloc(63, GFP_KERNEL))) {
usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
kfree(mouse);
return -ENOMEM;
}
if (dev->descriptor.iManufacturer &&
usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
strcat(mouse->name, buf);
if (dev->descriptor.iProduct &&
usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
sprintf(mouse->name, "%s %s", mouse->name, buf);
if (!strlen(mouse->name))
sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
dev->descriptor.idVendor, dev->descriptor.idProduct);
kfree(buf);
usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
(maxp > 8 ? 8 : maxp),
usb_mouse_irq, mouse, endpoint->bInterval);
//mouse->irq->transfer_dma = mouse->data_dma;
//mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
usb_set_intfdata(intf, mouse);
// Open device
mouse->irq->dev = mouse->usbdev;
if (usb_submit_urb(mouse->irq, GFP_KERNEL)) {
return -EIO;
}
mouse->btn_old = 0;
return 0;
}
static void usb_mouse_disconnect(struct usb_interface *intf)
{
struct usb_mouse *mouse = usb_get_intfdata (intf);
usb_set_intfdata(intf, NULL);
usbprintk("Mouse disconnected\n ");
if (mouse) {
usb_unlink_urb(mouse->irq);
usb_free_urb(mouse->irq);
usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
kfree(mouse);
}
}
static struct usb_device_id usb_mouse_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 2) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
static struct usb_driver usb_mouse_driver = {
.owner = THIS_MODULE,
.name = "usbmouse",
.probe = usb_mouse_probe,
.disconnect = usb_mouse_disconnect,
.id_table = usb_mouse_id_table,
};
void UsbMouseInit(void)
{
if (usb_register(&usb_mouse_driver) < 0) {
#if mousedebug
printk("Unable to register Mouse driver");
#endif
return;
}
}
void UsbMouseRemove(void) {
usb_deregister(&usb_mouse_driver);
}
-374
View File
@@ -1,374 +0,0 @@
/*
* (C) Copyright David Brownell 2000-2002
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if 0
#include <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 */
File diff suppressed because it is too large Load Diff
-491
View File
@@ -1,491 +0,0 @@
/*
* Copyright (c) 2001-2002 by David Brownell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __KERNEL__
/* This file contains declarations of usbcore internals that are mostly
* used or exposed by Host Controller Drivers.
*/
/*
* USB Packet IDs (PIDs)
*/
#define USB_PID_UNDEF_0 0xf0
#define USB_PID_OUT 0xe1
#define USB_PID_ACK 0xd2
#define USB_PID_DATA0 0xc3
#define USB_PID_PING 0xb4 /* USB 2.0 */
#define USB_PID_SOF 0xa5
#define USB_PID_NYET 0x96 /* USB 2.0 */
#define USB_PID_DATA2 0x87 /* USB 2.0 */
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
#define USB_PID_IN 0x69
#define USB_PID_NAK 0x5a
#define USB_PID_DATA1 0x4b
#define USB_PID_PREAMBLE 0x3c /* Token mode */
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
#define USB_PID_SETUP 0x2d
#define USB_PID_STALL 0x1e
#define USB_PID_MDATA 0x0f /* USB 2.0 */
/*-------------------------------------------------------------------------*/
/*
* USB Host Controller Driver (usb_hcd) framework
*
* Since "struct usb_bus" is so thin, you can't share much code in it.
* This framework is a layer over that, and should be more sharable.
*/
/*-------------------------------------------------------------------------*/
struct usb_hcd { /* usb_bus.hcpriv points to this */
/*
* housekeeping
*/
struct usb_bus self; /* hcd is-a bus */
const char *product_desc; /* product/vendor string */
const char *description; /* "ehci-hcd" etc */
struct timer_list rh_timer; /* drives root hub */
struct list_head dev_list; /* devices on this bus */
struct work_struct work;
/*
* hardware info/state
*/
struct hc_driver *driver; /* hw-specific hooks */
int irq; /* irq allocated */
void *regs; /* device memory/io */
struct device *controller; /* handle to hardware */
/* a few non-PCI controllers exist, mostly for OHCI */
struct pci_dev *pdev; /* pci is typical */
#ifdef CONFIG_PCI
int region; /* pci region for regs */
u32 pci_state [16]; /* for PM state save */
atomic_t resume_count; /* multiple resumes issue */
#endif
#define HCD_BUFFER_POOLS 4
struct pci_pool *pool [HCD_BUFFER_POOLS];
int state;
# define __ACTIVE 0x01
# define __SLEEPY 0x02
# define __SUSPEND 0x04
# define __TRANSIENT 0x80
# define USB_STATE_HALT 0
# define USB_STATE_RUNNING (__ACTIVE)
# define USB_STATE_READY (__ACTIVE|__SLEEPY)
# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
# define USB_STATE_SUSPENDED (__SUSPEND)
#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
/* more shared queuing code would be good; it should support
* smarter scheduling, handle transaction translators, etc;
* input size of periodic table to an interrupt scheduler.
* (ohci 32, uhci 1024, ehci 256/512/1024).
*/
};
/* 2.4 does this a bit differently ... */
static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
{
return &hcd->self;
}
struct hcd_dev { /* usb_device.hcpriv points to this */
struct list_head dev_list; /* on this hcd */
struct list_head urb_list; /* pending on this dev */
/* per-configuration HC/HCD state, such as QH or ED */
void *ep[32];
};
// urb.hcpriv is really hardware-specific
struct hcd_timeout { /* timeouts we allocate */
struct list_head timeout_list;
struct timer_list timer;
};
/*-------------------------------------------------------------------------*/
/*
* FIXME usb_operations should vanish or become hc_driver,
* when usb_bus and usb_hcd become the same thing.
*/
struct usb_operations {
int (*allocate)(struct usb_device *);
int (*deallocate)(struct usb_device *);
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, int mem_flags);
int (*unlink_urb) (struct urb *urb);
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
int mem_flags,
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
void (*disable)(struct usb_device *udev, int bEndpointAddress);
};
/* each driver provides one of these, and hardware init support */
struct pt_regs;
// new struct from 2.6
struct hc_driver {
const char *description; /* "ehci-hcd" etc */
/* irq handler */
irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
int flags;
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
#define HCD_USB11 0x0010 /* USB 1.1 */
#define HCD_USB2 0x0020 /* USB 2.0 */
/* called to init HCD and root hub */
int (*reset) (struct usb_hcd *hcd);
int (*start) (struct usb_hcd *hcd);
/* called after all devices were suspended */
int (*suspend) (struct usb_hcd *hcd, u32 state);
/* called before any devices get resumed */
int (*resume) (struct usb_hcd *hcd);
/* cleanly make HCD stop writing memory and doing I/O */
void (*stop) (struct usb_hcd *hcd);
/* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd);
/* memory lifecycle */
struct usb_hcd *(*hcd_alloc) (void);
void (*hcd_free) (struct usb_hcd *hcd);
/* manage i/o requests, device state */
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
int mem_flags);
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
/* hw synch, freeing endpoint resources that urb_dequeue can't */
void (*endpoint_disable)(struct usb_hcd *hcd,
struct hcd_dev *dev, int bEndpointAddress);
/* root hub support */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
u8 *buf, u16 wLength);
};
// old version, "just in case"
#if 0
struct hc_driver {
const char *description; /* "ehci-hcd" etc */
/* irq handler */
int (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
int flags;
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
#define HCD_USB11 0x0010 /* USB 1.1 */
#define HCD_USB2 0x0020 /* USB 2.0 */
/* called to init HCD and root hub */
int (*start) (struct usb_hcd *hcd);
/* called after all devices were suspended */
int (*suspend) (struct usb_hcd *hcd, u32 state);
/* called before any devices get resumed */
int (*resume) (struct usb_hcd *hcd);
/* cleanly make HCD stop writing memory and doing I/O */
void (*stop) (struct usb_hcd *hcd);
/* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd);
/* memory lifecycle */
struct usb_hcd *(*hcd_alloc) (void);
void (*hcd_free) (struct usb_hcd *hcd);
/* manage i/o requests, device state */
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
int mem_flags);
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
/* hw synch, freeing endpoint resources that urb_dequeue can't */
void (*endpoint_disable)(struct usb_hcd *hcd,
struct hcd_dev *dev, int bEndpointAddress);
/* root hub support */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
int (*hub_control) (struct usb_hcd *hcd,
u16 typeReq, u16 wValue, u16 wIndex,
char *buf, u16 wLength);
};
#endif
extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
extern void STDCALL usb_bus_init (struct usb_bus *bus);
extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb);
#ifdef CONFIG_PCI
struct pci_dev;
struct pci_device_id;
extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev,
const struct pci_device_id *id);
extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
#ifdef CONFIG_PM
// FIXME: see Documentation/power/pci.txt (2.4.6 and later?)
// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
extern int usb_hcd_pci_resume (struct pci_dev *dev);
// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
#endif /* CONFIG_PM */
#endif /* CONFIG_PCI */
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
int hcd_buffer_create (struct usb_hcd *hcd);
void hcd_buffer_destroy (struct usb_hcd *hcd);
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
int mem_flags, dma_addr_t *dma);
void hcd_buffer_free (struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
/* generic bus glue, needed for host controllers that don't use PCI */
extern struct usb_operations usb_hcd_operations;
extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
extern void STDCALL usb_hc_died (struct usb_hcd *hcd);
/* -------------------------------------------------------------------------- */
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
extern int usb_new_device(struct usb_device *dev, struct device *parent);
extern void STDCALL usb_connect(struct usb_device *dev);
extern void usb_disconnect(struct usb_device **);
/* exported to hub driver ONLY to support usb_reset_device () */
extern int usb_get_configuration(struct usb_device *dev);
extern void usb_set_maxpacket(struct usb_device *dev);
extern void usb_destroy_configuration(struct usb_device *dev);
extern int usb_set_address(struct usb_device *dev);
/* use these only before the device's address has been set */
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
/*-------------------------------------------------------------------------*/
/*
* HCD Root Hub support
*/
#include "hub.h"
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
#define DeviceRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
#define DeviceOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
#define InterfaceRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
#define EndpointRequest \
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
#define EndpointOutRequest \
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
/* table 9.6 standard features */
#define DEVICE_REMOTE_WAKEUP 1
#define ENDPOINT_HALT 0
/* class requests from the USB 2.0 hub spec, table 11-15 */
/* GetBusState and SetHubDescriptor are optional, omitted */
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
/*-------------------------------------------------------------------------*/
/*
* Generic bandwidth allocation constants/support
*/
#define FRAME_TIME_USECS 1000L
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
/* Trying not to use worst-case bit-stuffing
of (7/6 * 8 * bytecount) = 9.33 * bytecount */
/* bytecount = data payload byte count */
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
/* convert & round nanoseconds to microseconds */
extern void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
int bustime, int isoc);
extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
int isoc);
/*
* Full/low speed bandwidth allocation constants/support.
*/
#define BW_HOST_DELAY 1000L /* nanoseconds */
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
/* 4 full-speed bit times (est.) */
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
/*
* Ceiling microseconds (typical) for that many bytes at high speed
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
* to preallocate bandwidth)
*/
#define USB2_HOST_DELAY 5 /* nsec, guess */
#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
+ USB2_HOST_DELAY)
#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
+ USB2_HOST_DELAY)
extern long STDCALL usb_calc_bus_time (int speed, int is_input,
int isoc, int bytecount);
/*-------------------------------------------------------------------------*/
extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *);
extern void STDCALL usb_free_bus (struct usb_bus *);
extern void STDCALL usb_register_bus (struct usb_bus *);
extern void STDCALL usb_deregister_bus (struct usb_bus *);
extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev,
struct device *parent_dev);
/* for portability to 2.4, hcds should call this */
static inline int hcd_register_root (struct usb_hcd *hcd)
{
return usb_register_root_hub (
hcd_to_bus (hcd)->root_hub, hcd->controller);
}
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
extern struct list_head usb_bus_list;
extern struct semaphore usb_bus_list_lock;
extern void usb_bus_get (struct usb_bus *bus);
extern void usb_bus_put (struct usb_bus *bus);
extern int usb_find_interface_driver (struct usb_device *dev,
struct usb_interface *interface);
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
/*
* USB device fs stuff
*/
#ifdef CONFIG_USB_DEVICEFS
/*
* these are expected to be called from the USB core/hub thread
* with the kernel lock held
*/
extern void usbfs_add_bus(struct usb_bus *bus);
extern void usbfs_remove_bus(struct usb_bus *bus);
extern void usbfs_add_device(struct usb_device *dev);
extern void usbfs_remove_device(struct usb_device *dev);
extern void usbfs_update_special (void);
extern int usbfs_init(void);
extern void usbfs_cleanup(void);
#else /* CONFIG_USB_DEVICEFS */
static inline void usbfs_add_bus(struct usb_bus *bus) {}
static inline void usbfs_remove_bus(struct usb_bus *bus) {}
static inline void usbfs_add_device(struct usb_device *dev)
{
if (dev->parent)
{
PDEVICE_OBJECT Pdo = (PDEVICE_OBJECT)dev->parent->dev.dev_ext;
if (Pdo)
IoInvalidateDeviceRelations(Pdo, BusRelations);
else
DPRINT1("Pdo == NULL, not sending IoInvalidateDeviceRelations()!");
}
}
static inline void usbfs_remove_device(struct usb_device *dev) {}
static inline void usbfs_update_special (void) {}
static inline int usbfs_init(void) { return 0; }
static inline void usbfs_cleanup(void) { }
#endif /* CONFIG_USB_DEVICEFS */
/*-------------------------------------------------------------------------*/
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
// bleech -- resurfaced in 2.4.11 or 2.4.12
#define bitmap DeviceRemovable
/*-------------------------------------------------------------------------*/
/* random stuff */
#define RUN_CONTEXT (in_irq () ? "in_irq" \
: (in_interrupt () ? "in_interrupt" : "can sleep"))
#endif /* __KERNEL__ */
File diff suppressed because it is too large Load Diff
-195
View File
@@ -1,195 +0,0 @@
#ifndef __LINUX_HUB_H
#define __LINUX_HUB_H
/*
* Hub protocol and driver data structures.
*
* Some of these are known to the "virtual root hub" code
* in host controller drivers.
*/
#if 0
#include <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 */
@@ -1,6 +0,0 @@
O_TARGET := message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o buffer_simple.o urb.o usb-debug.o
#O_TARGET := urb.o
include $(TOPDIR)/Rules.make
File diff suppressed because it is too large Load Diff
-398
View File
@@ -1,398 +0,0 @@
#include "../miniport/usb_wrapper.h"
#include "hcd.h"
/**
* usb_init_urb - initializes a urb so that it can be used by a USB driver
* @urb: pointer to the urb to initialize
*
* Initializes a urb so that the USB subsystem can use it properly.
*
* If a urb is created with a call to usb_alloc_urb() it is not
* necessary to call this function. Only use this if you allocate the
* space for a struct urb on your own. If you call this function, be
* careful when freeing the memory for your urb that it is no longer in
* use by the USB core.
*
* Only use this function if you _really_ understand what you are doing.
*/
void STDCALL usb_init_urb(struct urb *urb)
{
if (urb) {
memset(urb, 0, sizeof(*urb));
urb->count = (atomic_t)ATOMIC_INIT(1);
spin_lock_init(&urb->lock);
}
}
/**
* usb_alloc_urb - creates a new urb for a USB driver to use
* @iso_packets: number of iso packets for this urb
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of
* valid options for this.
*
* Creates an urb for the USB driver to use, initializes a few internal
* structures, incrementes the usage counter, and returns a pointer to it.
*
* If no memory is available, NULL is returned.
*
* If the driver want to use this urb for interrupt, control, or bulk
* endpoints, pass '0' as the number of iso packets.
*
* The driver must call usb_free_urb() when it is finished with the urb.
*/
struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
{
struct urb *urb;
urb = (struct urb *)kmalloc(sizeof(struct urb) +
iso_packets * sizeof(struct usb_iso_packet_descriptor),
mem_flags);
if (!urb) {
err("alloc_urb: kmalloc failed");
return NULL;
}
usb_init_urb(urb);
return urb;
}
/**
* usb_free_urb - frees the memory used by a urb when all users of it are finished
* @urb: pointer to the urb to free
*
* Must be called when a user of a urb is finished with it. When the last user
* of the urb calls this function, the memory of the urb is freed.
*
* Note: The transfer buffer associated with the urb is not freed, that must be
* done elsewhere.
*/
void STDCALL usb_free_urb(struct urb *urb)
{
if (urb)
if (atomic_dec_and_test(&urb->count))
{
kfree(urb);
}
}
/**
* usb_get_urb - increments the reference count of the urb
* @urb: pointer to the urb to modify
*
* This must be called whenever a urb is transferred from a device driver to a
* host controller driver. This allows proper reference counting to happen
* for urbs.
*
* A pointer to the urb with the incremented reference counter is returned.
*/
struct urb STDCALL * usb_get_urb(struct urb *urb)
{
if (urb) {
atomic_inc(&urb->count);
return urb;
} else
return NULL;
}
/*-------------------------------------------------------------------*/
/**
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
* @urb: pointer to the urb describing the request
* @mem_flags: the type of memory to allocate, see kmalloc() for a list
* of valid options for this.
*
* This submits a transfer request, and transfers control of the URB
* describing that request to the USB subsystem. Request completion will
* be indicated later, asynchronously, by calling the completion handler.
* The three types of completion are success, error, and unlink
* (also called "request cancellation").
* URBs may be submitted in interrupt context.
*
* The caller must have correctly initialized the URB before submitting
* it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
* available to ensure that most fields are correctly initialized, for
* the particular kind of transfer, although they will not initialize
* any transfer flags.
*
* Successful submissions return 0; otherwise this routine returns a
* negative error number. If the submission is successful, the complete()
* callback from the urb will be called exactly once, when the USB core and
* host controller driver are finished with the urb. When the completion
* function is called, control of the URB is returned to the device
* driver which issued the request. The completion handler may then
* immediately free or reuse that URB.
*
* For control endpoints, the synchronous usb_control_msg() call is
* often used (in non-interrupt context) instead of this call.
* That is often used through convenience wrappers, for the requests
* that are standardized in the USB 2.0 specification. For bulk
* endpoints, a synchronous usb_bulk_msg() call is available.
*
* Request Queuing:
*
* URBs may be submitted to endpoints before previous ones complete, to
* minimize the impact of interrupt latencies and system overhead on data
* throughput. This is required for continuous isochronous data streams,
* and may also be required for some kinds of interrupt transfers. Such
* queueing also maximizes bandwidth utilization by letting USB controllers
* start work on later requests before driver software has finished the
* completion processing for earlier requests.
*
* Bulk and Isochronous URBs may always be queued. At this writing, all
* mainstream host controller drivers support queueing for control and
* interrupt transfer requests.
*
* Reserved Bandwidth Transfers:
*
* Periodic transfers (interrupt or isochronous) are performed repeatedly,
* using the interval specified in the urb. Submitting the first urb to
* the endpoint reserves the bandwidth necessary to make those transfers.
* If the USB subsystem can't allocate sufficient bandwidth to perform
* the periodic request, submitting such a periodic request should fail.
*
* Device drivers must explicitly request that repetition, by ensuring that
* some URB is always on the endpoint's queue (except possibly for short
* periods during completion callacks). When there is no longer an urb
* queued, the endpoint's bandwidth reservation is canceled. This means
* drivers can use their completion handlers to ensure they keep bandwidth
* they need, by reinitializing and resubmitting the just-completed urb
* until the driver longer needs that periodic bandwidth.
*
* Memory Flags:
*
* The general rules for how to decide which mem_flags to use
* are the same as for kmalloc. There are four
* different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
* GFP_ATOMIC.
*
* GFP_NOFS is not ever used, as it has not been implemented yet.
*
* GFP_ATOMIC is used when
* (a) you are inside a completion handler, an interrupt, bottom half,
* tasklet or timer, or
* (b) you are holding a spinlock or rwlock (does not apply to
* semaphores), or
* (c) current->state != TASK_RUNNING, this is the case only after
* you've changed it.
*
* GFP_NOIO is used in the block io path and error handling of storage
* devices.
*
* All other situations use GFP_KERNEL.
*
* Some more specific rules for mem_flags can be inferred, such as
* (1) start_xmit, timeout, and receive methods of network drivers must
* use GFP_ATOMIC (they are called with a spinlock held);
* (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also
* called with a spinlock held);
* (3) If you use a kernel thread with a network driver you must use
* GFP_NOIO, unless (b) or (c) apply;
* (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c)
* apply or your are in a storage driver's block io path;
* (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and
* (6) changing firmware on a running storage or net device uses
* GFP_NOIO, unless b) or c) apply
*
*/
int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
{
int pipe, temp, max;
struct usb_device *dev;
struct usb_operations *op;
int is_out;
//printk("sub dev %p bus %p num %i op %p sub %p\n",
// urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb);
if (!urb || urb->hcpriv || !urb->complete)
return -EINVAL;
if (!(dev = urb->dev) ||
(dev->state < USB_STATE_DEFAULT) ||
(!dev->bus) || (dev->devnum <= 0))
return -ENODEV;
if (!(op = dev->bus->op) || !op->submit_urb)
return -ENODEV;
urb->status = -EINPROGRESS;
urb->actual_length = 0;
urb->bandwidth = 0;
/* Lots of sanity checks, so HCDs can rely on clean data
* and don't need to duplicate tests
*/
pipe = urb->pipe;
temp = usb_pipetype (pipe);
is_out = usb_pipeout (pipe);
if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
return -ENODEV;
/* (actually HCDs may need to duplicate this, endpoint might yet
* stall due to queued bulk/intr transactions that complete after
* we check)
*/
if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
return -EPIPE;
/* FIXME there should be a sharable lock protecting us against
* config/altsetting changes and disconnects, kicking in here.
* (here == before maxpacket, and eventually endpoint type,
* checks get made.)
*/
max = usb_maxpacket (dev, pipe, is_out);
if (max <= 0) {
dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
__FUNCTION__,
usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
dev->bus->bus_name, dev->devpath,
max);
return -EMSGSIZE;
}
/* periodic transfers limit size per frame/uframe,
* but drivers only control those sizes for ISO.
* while we're checking, initialize return status.
*/
if (temp == PIPE_ISOCHRONOUS) {
int n, len;
/* "high bandwidth" mode, 1-3 packets/uframe? */
if (dev->speed == USB_SPEED_HIGH) {
int mult = 1 + ((max >> 11) & 0x03);
max &= 0x03ff;
max *= mult;
}
if (urb->number_of_packets <= 0)
return -EINVAL;
for (n = 0; n < urb->number_of_packets; n++) {
len = urb->iso_frame_desc [n].length;
if (len < 0 || len > max)
return -EMSGSIZE;
urb->iso_frame_desc [n].status = -EXDEV;
urb->iso_frame_desc [n].actual_length = 0;
}
}
/* the I/O buffer must be mapped/unmapped, except when length=0 */
if (urb->transfer_buffer_length < 0)
return -EMSGSIZE;
#ifdef DEBUG
/* stuff that drivers shouldn't do, but which shouldn't
* cause problems in HCDs if they get it wrong.
*/
{
unsigned int orig_flags = urb->transfer_flags;
unsigned int allowed;
/* enforce simple/standard policy */
allowed = URB_ASYNC_UNLINK; // affects later unlinks
allowed |= URB_NO_DMA_MAP;
allowed |= URB_NO_INTERRUPT;
switch (temp) {
case PIPE_BULK:
if (is_out)
allowed |= URB_ZERO_PACKET;
/* FALLTHROUGH */
case PIPE_CONTROL:
allowed |= URB_NO_FSBR; /* only affects UHCI */
/* FALLTHROUGH */
default: /* all non-iso endpoints */
if (!is_out)
allowed |= URB_SHORT_NOT_OK;
break;
case PIPE_ISOCHRONOUS:
allowed |= URB_ISO_ASAP;
break;
}
urb->transfer_flags &= allowed;
/* fail if submitter gave bogus flags */
if (urb->transfer_flags != orig_flags) {
err ("BOGUS urb flags, %x --> %x",
orig_flags, urb->transfer_flags);
return -EINVAL;
}
}
#endif
/*
* Force periodic transfer intervals to be legal values that are
* a power of two (so HCDs don't need to).
*
* FIXME want bus->{intr,iso}_sched_horizon values here. Each HC
* supports different values... this uses EHCI/UHCI defaults (and
* EHCI can use smaller non-default values).
*/
switch (temp) {
case PIPE_ISOCHRONOUS:
case PIPE_INTERRUPT:
/* too small? */
if (urb->interval <= 0)
return -EINVAL;
/* too big? */
switch (dev->speed) {
case USB_SPEED_HIGH: /* units are microframes */
// NOTE usb handles 2^15
if (urb->interval > (1024 * 8))
urb->interval = 1024 * 8;
temp = 1024 * 8;
break;
case USB_SPEED_FULL: /* units are frames/msec */
case USB_SPEED_LOW:
if (temp == PIPE_INTERRUPT) {
if (urb->interval > 255)
return -EINVAL;
// NOTE ohci only handles up to 32
temp = 128;
} else {
if (urb->interval > 1024)
urb->interval = 1024;
// NOTE usb and ohci handle up to 2^15
temp = 1024;
}
break;
default:
return -EINVAL;
}
/* power of two? */
while (temp > urb->interval)
temp >>= 1;
urb->interval = temp;
}
return op->submit_urb (urb, mem_flags);
}
/*-------------------------------------------------------------------*/
/**
* usb_unlink_urb - abort/cancel a transfer request for an endpoint
* @urb: pointer to urb describing a previously submitted request
*
* This routine cancels an in-progress request. The requests's
* completion handler will be called with a status code indicating
* that the request has been canceled, and that control of the URB
* has been returned to that device driver.
*
* When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
* request is synchronous. Success is indicated by returning zero,
* at which time the urb will have been unlinked,
* and the completion function will see status -ENOENT. Failure is
* indicated by any other return value. This mode may not be used
* when unlinking an urb from an interrupt context, such as a bottom
* half or a completion handler,
*
* When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
* request is asynchronous. Success is indicated by returning -EINPROGRESS,
* at which time the urb will normally not have been unlinked,
* and the completion function will see status -ECONNRESET. Failure is
* indicated by any other return value.
*/
int STDCALL usb_unlink_urb(struct urb *urb)
{
if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
return urb->dev->bus->op->unlink_urb(urb);
else
return -ENODEV;
}
-206
View File
@@ -1,206 +0,0 @@
/*
* debug.c - USB debug helper routines.
*
* I just want these out of the way where they aren't in your
* face, but so that you can still use them..
*/
#define CONFIG_USB_DEBUG
#if 0
#include <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);
}
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,5 +0,0 @@
/* Functions local to drivers/usb/core/ */
extern void usb_create_driverfs_dev_files (struct usb_device *dev);
extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
-78
View File
@@ -1,78 +0,0 @@
/*
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;
}
-5
View File
@@ -1,5 +0,0 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0"
#define REACTOS_STR_INTERNAL_NAME "usbcore\0"
#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0"
#include <reactos/version.rc>
-34
View File
@@ -1,34 +0,0 @@
;
; Exports definition file for usbcore.sys
;
EXPORTS
RegisterPortDriver@8
usb_alloc_bus@4
usb_alloc_dev@8
usb_alloc_urb@8
usb_bus_init@4
usb_calc_bus_time@16
usb_check_bandwidth@8
usb_claim_bandwidth@16
usb_connect@4
usb_deregister_bus@4
usb_disabled@0
usb_exit@0
usb_free_bus@4
usb_free_urb@4
usb_get_dev@4
usb_get_string
usb_get_urb@4
usb_hcd_giveback_urb@12
;usb_hcd_irq@12
usb_hcd_pci_probe@8
usb_hcd_pci_remove@4
usb_hc_died@4
usb_init@0
usb_init_urb@4
usb_put_dev@4
usb_release_bandwidth@12
usb_register_bus@4
usb_register_root_hub@8
usb_submit_urb@8
usb_unlink_urb@4
@@ -1,21 +0,0 @@
<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>