Enumerate root hub connected to UHCI controller

Use Cromwell USB stack to initialize UHCI controller

svn path=/trunk/; revision=15905
This commit is contained in:
Hervé Poussineau 2005-06-14 12:31:51 +00:00
parent 2e0ff75066
commit 819d60094a
10 changed files with 1226 additions and 378 deletions

View file

@ -0,0 +1,28 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS UHCI controller driver (Cromwell type)
* FILE: drivers/usb/cromwell/uhci/close.c
* PURPOSE: IRP_MJ_CLOSE operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
#define NDEBUG
#include "uhci.h"
NTSTATUS STDCALL
UhciClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
POHCI_DEVICE_EXTENSION pDeviceExtension;
DPRINT("UHCI: IRP_MJ_CLOSE\n");
pDeviceExtension = (POHCI_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;
}

View file

@ -0,0 +1,41 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS UHCI controller driver (Cromwell type)
* FILE: drivers/usb/cromwell/uhci/create.c
* PURPOSE: IRP_MJ_CREATE operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
#define NDEBUG
#include "uhci.h"
NTSTATUS STDCALL
UhciCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
POHCI_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DPRINT("UHCI: IRP_MJ_CREATE\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = (POHCI_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;
}

View file

@ -0,0 +1,422 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS UHCI controller driver (Cromwell type)
* FILE: drivers/usb/cromwell/uhci/fdo.c
* PURPOSE: IRP_MJ_PNP/IRP_MJ_DEVICE_CONTROL operations for FDOs
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com),
* James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net)
*/
#define NDEBUG
#include "uhci.h"
/* declare basic init functions and structures */
int uhci_hcd_init(void);
int STDCALL usb_init(void);
extern struct pci_driver uhci_pci_driver;
extern struct pci_device_id uhci_pci_ids[];
static NTSTATUS
InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status = STATUS_SUCCESS;
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_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 */
init_wrapper(dev);
dev->irq = DeviceExtension->InterruptVector;
dev->dev_ext = (PVOID)DeviceExtension;
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name
strcpy(dev->dev.name, "UnivHCI PCI-USB Controller");
strcpy(dev->slot_name, "UHCD PCI Slot");
/* Init the OHCI 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);
// DPRINT1("UHCI :SysIoBusNumA %d\n",DeviceExtension->SystemIoBusNumber);
// DeviceExtension->SystemIoBusNumber = dev->bus->number;
// DPRINT1("UHCI: SysIoBusNumB %d\n",DeviceExtension->SystemIoBusNumber);
return Status;
}
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
static VOID
UhciGetUserBuffers(
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 STDCALL
UhciFdoStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PDRIVER_OBJECT DriverObject;
POHCI_DRIVER_EXTENSION DriverExtension;
POHCI_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST AllocatedResources;
/*
* Get the initialization data we saved in VideoPortInitialize.
*/
DriverObject = DeviceObject->DriverObject;
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
DeviceExtension = (POHCI_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 *)uhci_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 *)uhci_pci_ids->driver_data)->flags |= HCD_MEMORY;
}
}
}
}
/* Print assigned resources */
DPRINT("UHCI: Interrupt Vector 0x%lx, %S base 0x%lx, Length 0x%lx\n",
DeviceExtension->InterruptVector,
((struct hc_driver *)uhci_pci_ids->driver_data)->flags & HCD_MEMORY ? L"Memory" : L"I/O",
DeviceExtension->BaseAddress,
DeviceExtension->BaseAddrLength);
/* Init wrapper with this object */
return InitLinuxWrapper(DeviceObject);
}
static NTSTATUS
UhciFdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
POHCI_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
NTSTATUS Status = STATUS_SUCCESS;
DeviceExtension = (POHCI_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 STDCALL
UhciPnpFdo(
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:
{
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = UhciFdoStartDevice(DeviceObject, Irp);
break;
}
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_STOP_DEVICE:
{
Status = ForwardIrpAndWait(DeviceObject, Irp);
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:
case IRP_MN_CANCEL_STOP_DEVICE:
{
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
{
switch (IrpSp->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations;
DPRINT("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = UhciFdoQueryBusRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
case RemovalRelations:
{
DPRINT1("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
default:
DPRINT1("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
IrpSp->Parameters.QueryDeviceRelations.Type);
return ForwardIrpAndForget(DeviceObject, Irp);
}
break;
}
default:
{
DPRINT1("UHCI: 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
UhciDeviceControlFdo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
ULONG IoControlCode;
POHCI_DEVICE_EXTENSION DeviceExtension;
ULONG LengthIn, LengthOut;
ULONG_PTR Information = 0;
PVOID BufferIn, BufferOut;
NTSTATUS Status;
DPRINT("UHCI: UsbDeviceControlFdo() called\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
UhciGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut);
switch (IoControlCode)
{
case IOCTL_GET_HCD_DRIVERKEY_NAME:
{
DPRINT1("UHCI: IOCTL_GET_HCD_DRIVERKEY_NAME does not return correct string\n");
/* FIXME: should return sth like {36FC9E60-C465-11CF-8056-444553540000}\0000 */
if (LengthOut < sizeof(USB_HCD_DRIVERKEY_NAME))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
PUSB_HCD_DRIVERKEY_NAME StringDescriptor;
ULONG StringSize;
StringDescriptor = (PUSB_HCD_DRIVERKEY_NAME)BufferOut;
Status = IoGetDeviceProperty(
((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PhysicalDeviceObject,
DevicePropertyDeviceDescription,
LengthOut - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName),
StringDescriptor->DriverKeyName,
&StringSize);
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
{
DPRINT("UHCI: IOCTL_GET_HCD_DRIVERKEY_NAME returns '%S'\n", StringDescriptor->DriverKeyName);
StringDescriptor->ActualLength = StringSize + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName);
Information = LengthOut;
Status = STATUS_SUCCESS;
}
}
break;
}
case IOCTL_USB_GET_ROOT_HUB_NAME:
{
DPRINT("UHCI: IOCTL_USB_GET_ROOT_HUB_NAME\n");
if (LengthOut < sizeof(USB_HCD_DRIVERKEY_NAME))
{
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
PUSB_HCD_DRIVERKEY_NAME StringDescriptor;
PUNICODE_STRING RootHubInterfaceName;
StringDescriptor = (PUSB_HCD_DRIVERKEY_NAME)BufferOut;
DeviceObject = ((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->RootHubPdo;
RootHubInterfaceName = &((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->HcdInterfaceName;
StringDescriptor->ActualLength = RootHubInterfaceName->Length + sizeof(WCHAR) + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName);
if (StringDescriptor->ActualLength <= LengthOut)
{
/* Copy root hub name */
RtlCopyMemory(
StringDescriptor->DriverKeyName,
RootHubInterfaceName->Buffer,
RootHubInterfaceName->Length);
StringDescriptor->DriverKeyName[RootHubInterfaceName->Length / sizeof(WCHAR)] = '\0';
DPRINT("UHCI: IOCTL_USB_GET_ROOT_HUB_NAME returns '%S'\n", StringDescriptor->DriverKeyName);
Information = StringDescriptor->ActualLength;
}
else
Information = sizeof(USB_HCD_DRIVERKEY_NAME);
Status = STATUS_SUCCESS;
}
break;
}
/*case IOCTL_USB_GET_NODE_INFORMATION:
{
DPRINT1("UHCI: IOCTL_USB_GET_NODE_INFORMATION\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}*/
case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
{
DPRINT1("UHCI: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_USB_GET_NODE_CONNECTION_NAME:
{
DPRINT1("UHCI: IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
default:
{
/* Pass Irp to lower driver */
DPRINT1("UHCI: 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;
}

View file

@ -0,0 +1,166 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS UHCI controller driver (Cromwell type)
* FILE: drivers/usb/cromwell/uhci/misc.c
* PURPOSE: Misceallenous operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com),
*/
#define NDEBUG
#include "uhci.h"
#include <stdarg.h>
NTSTATUS STDCALL
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 = ((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NextDeviceObject;
KEVENT Event;
NTSTATUS Status;
ASSERT(LowerDevice);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
DPRINT("UHCI: 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 STDCALL
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice = ((POHCI_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
UhciInitMultiSzString(
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_UHCI_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_UHCI_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
UhciDuplicateUnicodeString(
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;
}

View file

@ -0,0 +1,196 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS UHCI controller driver (Cromwell type)
* FILE: drivers/usb/cromwell/uhci/pdo.c
* PURPOSE: IRP_MJ_PNP/IRP_MJ_DEVICE_CONTROL operations for PDOs
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com),
* James Tabor (jimtabor@adsl-64-217-116-74.dsl.hstntx.swbell.net)
*/
#define NDEBUG
#include "uhci.h"
extern struct usb_driver hub_driver;
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
NTSTATUS
UhciDeviceControlPdo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
NTSTATUS Status;
DPRINT("UHCI: UhciDeviceControlPdo() called\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
Status = Irp->IoStatus.Status;
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE:
{
POHCI_DEVICE_EXTENSION DeviceExtension;
DPRINT("UHCI: IOCTL_INTERNAL_USB_GET_ROOT_USB_DEVICE\n");
if (Irp->AssociatedIrp.SystemBuffer == NULL
|| Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
PVOID* pRootHubPointer;
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceExtension->FunctionalDeviceObject->DeviceExtension;
pRootHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
*pRootHubPointer = (PVOID)DeviceExtension->pdev->bus; /* struct usb_device* */
Information = sizeof(PVOID);
Status = STATUS_SUCCESS;
}
break;
}
default:
{
DPRINT1("UHCI: 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
UhciPdoQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT ULONG_PTR* Information)
{
POHCI_DEVICE_EXTENSION DeviceExtension;
ULONG IdType;
UNICODE_STRING SourceString;
UNICODE_STRING String;
NTSTATUS Status;
IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlInitUnicodeString(&String, NULL);
switch (IdType)
{
case BusQueryDeviceID:
{
DPRINT("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB");
break;
}
case BusQueryHardwareIDs:
{
DPRINT("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
/* FIXME: Should return
USB\ROOT_HUB&VID????&PID????&REV????
USB\ROOT_HUB&VID????&PID????
USB\ROOT_HUB
*/
UhciInitMultiSzString(&SourceString, "USB\\ROOT_HUB", NULL);
break;
}
case BusQueryCompatibleIDs:
DPRINT("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
/* No compatible ID */
*Information = 0;
return STATUS_NOT_SUPPORTED;
case BusQueryInstanceID:
{
DPRINT("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
RtlInitUnicodeString(&SourceString, L"0000"); /* FIXME */
break;
}
default:
DPRINT1("UHCI: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
return STATUS_NOT_SUPPORTED;
}
Status = UhciDuplicateUnicodeString(
&String,
&SourceString,
PagedPool);
*Information = (ULONG_PTR)String.Buffer;
return Status;
}
static NTSTATUS
UhciPnpStartDevice(
IN PDEVICE_OBJECT DeviceObject)
{
POHCI_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DeviceExtension = (POHCI_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("UHCI: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
return Status;
}
return Status;
}
NTSTATUS STDCALL
UhciPnpPdo(
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("UHCI: IRP_MJ_PNP/IRP_MN_START_DEVICE\n");
Status = UhciPnpStartDevice(DeviceObject);
break;
}
case IRP_MN_QUERY_ID: /* 0x13 */
{
Status = UhciPdoQueryId(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("UHCI: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -0,0 +1,297 @@
/*
ReactOS specific functions for UHCI module
by Aleksey Bragin (aleksey@reactos.com)
and Hervé Poussineau (hpoussin@reactos.com)
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
*/
#define NDEBUG
#define INITGUID
#include "uhci.h"
/* declare basic init functions and structures */
void uhci_hcd_cleanup(void);
void STDCALL usb_exit(void);
extern struct pci_driver uhci_pci_driver;
static ULONG DeviceNumber = 0; /* FIXME: what is that? */
static NTSTATUS
CreateRootHubPdo(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Fdo,
OUT PDEVICE_OBJECT* pPdo)
{
PDEVICE_OBJECT Pdo;
POHCI_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DPRINT("UHCI: CreateRootHubPdo()\n");
Status = IoCreateDevice(
DriverObject,
sizeof(OHCI_DEVICE_EXTENSION),
NULL, /* DeviceName */
FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status))
{
DPRINT("UHCI: 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 = (POHCI_DEVICE_EXTENSION)Pdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
DeviceExtension->IsFDO = false;
DeviceExtension->FunctionalDeviceObject = Fdo;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
*pPdo = Pdo;
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT pdo)
{
PDEVICE_OBJECT fdo;
NTSTATUS Status;
WCHAR DeviceBuffer[20];
WCHAR LinkDeviceBuffer[20];
UNICODE_STRING DeviceName;
UNICODE_STRING LinkDeviceName;
POHCI_DRIVER_EXTENSION DriverExtension;
POHCI_DEVICE_EXTENSION DeviceExtension;
DPRINT("UHCI: AddDevice called\n");
// Allocate driver extension now
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
if (DriverExtension == NULL)
{
Status = IoAllocateDriverObjectExtension(
DriverObject,
DriverObject,
sizeof(OHCI_DRIVER_EXTENSION),
(PVOID *)&DriverExtension);
if (!NT_SUCCESS(Status))
{
DPRINT("UHCI: Allocating DriverObjectExtension failed.\n");
return Status;
}
}
// Create a unicode device name
// DeviceNumber = 0; //TODO: Allocate new device number every time
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
Status = IoCreateDevice(DriverObject,
sizeof(OHCI_DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_BUS_EXTENDER,
0,
FALSE,
&fdo);
if (!NT_SUCCESS(Status))
{
DPRINT("UHCI: IoCreateDevice call failed with status 0x%08lx\n", Status);
return Status;
}
// zerofill device extension
DeviceExtension = (POHCI_DEVICE_EXTENSION)fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
/* Create root hub Pdo */
Status = CreateRootHubPdo(DriverObject, fdo, &DeviceExtension->RootHubPdo);
if (!NT_SUCCESS(Status))
{
DPRINT("UHCI: CreateRootHubPdo() failed with status 0x%08lx\n", Status);
IoDeleteDevice(fdo);
return Status;
}
/* Register device interface for controller */
Status = IoRegisterDeviceInterface(
pdo,
&GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
NULL,
&DeviceExtension->HcdInterfaceName);
if (!NT_SUCCESS(Status))
{
DPRINT("UHCI: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
IoDeleteDevice(DeviceExtension->RootHubPdo);
IoDeleteDevice(fdo);
return Status;
}
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
// Initialize device extension
DeviceExtension->IsFDO = TRUE;
DeviceExtension->DeviceNumber = DeviceNumber;
DeviceExtension->PhysicalDeviceObject = pdo;
DeviceExtension->FunctionalDeviceObject = fdo;
DeviceExtension->DriverExtension = DriverExtension;
/* FIXME: do a loop to find an available number */
swprintf(LinkDeviceBuffer, L"\\??\\HCD%lu", 0);
RtlInitUnicodeString(&LinkDeviceName, LinkDeviceBuffer);
Status = IoCreateSymbolicLink(&LinkDeviceName, &DeviceName);
if (!NT_SUCCESS(Status))
{
DPRINT("UHCI: IoCreateSymbolicLink call failed with status 0x%08x\n", Status);
IoDeleteDevice(DeviceExtension->RootHubPdo);
IoDeleteDevice(fdo);
return Status;
}
return STATUS_SUCCESS;
}
VOID STDCALL
DriverUnload(PDRIVER_OBJECT DriverObject)
{
POHCI_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT DeviceObject;
struct pci_dev *dev;
DeviceObject = DriverObject->DeviceObject;
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
dev = DeviceExtension->pdev;
DPRINT1("UHCI: DriverUnload()\n");
// Exit usb device
usb_exit();
// Remove device (ohci_pci_driver.remove)
uhci_pci_driver.remove(dev);
ExFreePool(dev->slot_name);
ExFreePool(dev);
// Perform some cleanup
uhci_hcd_cleanup();
}
NTSTATUS STDCALL
IrpStub(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status = STATUS_NOT_SUPPORTED;
if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
{
DPRINT1("UHCI: FDO stub for major function 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
#ifndef NDEBUG
DbgBreakPoint();
#endif
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("UHCI: PDO stub for major function 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
#ifndef NDEBUG
DbgBreakPoint();
#endif
}
Status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
static NTSTATUS STDCALL
DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return UhciCreate(DeviceObject, Irp);
else
return IrpStub(DeviceObject, Irp);
}
static NTSTATUS STDCALL
DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return UhciClose(DeviceObject, Irp);
else
return IrpStub(DeviceObject, Irp);
}
static NTSTATUS STDCALL
DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return UhciDeviceControlFdo(DeviceObject, Irp);
else
return UhciDeviceControlPdo(DeviceObject, Irp);
}
static NTSTATUS STDCALL
DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return UhciPnpFdo(DeviceObject, Irp);
else
return UhciPnpPdo(DeviceObject, Irp);
}
static NTSTATUS STDCALL
DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
{
DPRINT1("UHCI: IRP_MJ_POWER unimplemented\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*
* Standard DriverEntry method.
*/
NTSTATUS STDCALL
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
{
ULONG i;
DPRINT("********* Cromwell UHCI *********\n");
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_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
return STATUS_SUCCESS;
}

View file

@ -1,2 +0,0 @@
LIBRARY uhci.sys
EXPORTS

View file

@ -0,0 +1,69 @@
#include <ddk/ntddk.h>
#include <ddk/usbdi.h>
#include <ddk/usbiodef.h>
#include <initguid.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 "../core/hcd.h"
#include "../host/ohci_main.h"
#define USB_UHCI_TAG TAG('u','s','b','u')
/* create.c */
NTSTATUS STDCALL
UhciCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* close.c */
NTSTATUS STDCALL
UhciClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* fdo.c */
NTSTATUS STDCALL
UhciPnpFdo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
UhciDeviceControlFdo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* misc.c */
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
UhciDuplicateUnicodeString(
OUT PUNICODE_STRING Destination,
IN PUNICODE_STRING Source,
IN POOL_TYPE PoolType);
NTSTATUS
UhciInitMultiSzString(
OUT PUNICODE_STRING Destination,
... /* list of PCSZ */);
/* pdo.c */
NTSTATUS STDCALL
UhciPnpPdo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
UhciDeviceControlPdo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);

View file

@ -1,5 +1,4 @@
<module name="uhci" type="kernelmodedriver" installbase="system32/drivers" installname="uhci.sys" warnings="true">
<importlibrary definition="uhci.def" />
<module name="uhci" type="kernelmodedriver" installbase="system32/drivers" installname="usbuhci.sys" warnings="true">
<define name="__USE_W32API" />
<define name="DEBUG_MODE" />
<include base="ntoskrnl">include</include>
@ -8,7 +7,12 @@
<library>ntoskrnl</library>
<library>hal</library>
<library>usbcore</library>
<file>close.c</file>
<file>create.c</file>
<file>fdo.c</file>
<file>misc.c</file>
<file>pdo.c</file>
<file>uhci.c</file>
<file>uhci-hcd.c</file>
<file>uhci_main.c</file>
<file>uhci.rc</file>
</module>

View file

@ -1,373 +0,0 @@
/*
ReactOS specific functions for UHCI module
by Aleksey Bragin (aleksey@reactos.com)
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
*/
#include <ddk/ntddk.h>
#define DEBUG
#include <debug.h>
// config and include core/hcd.h, for hc_device struct
#include "../usb_wrapper.h"
#include "../core/hcd.h"
#include "../host/ohci_main.h"
// declare basic init funcs
void init_wrapper(struct pci_dev *probe_dev);
int uhci_hcd_init(void);
void uhci_hcd_cleanup(void);
int STDCALL usb_init(void);
void STDCALL usb_exit(void);
extern struct pci_driver uhci_pci_driver;
extern struct pci_device_id uhci_pci_ids[];
// This should be removed, but for testing purposes it's here
//struct pci_dev *dev;
//struct pci_device_id *dev_id;
#define USB_UHCI_TAG TAG('u','s','b','u')
NTSTATUS STDCALL
AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
{
PDEVICE_OBJECT fdo;
NTSTATUS Status;
WCHAR DeviceBuffer[20];
UNICODE_STRING DeviceName;
WCHAR LinkDeviceBuffer[20];
UNICODE_STRING LinkDeviceName;
POHCI_DRIVER_EXTENSION DriverExtension;
POHCI_DEVICE_EXTENSION DeviceExtension;
ULONG Size, DeviceNumber;
DPRINT1("uhci: AddDevice called\n");
// Allocate driver extension now
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
if (DriverExtension == NULL)
{
Status = IoAllocateDriverObjectExtension(
DriverObject,
DriverObject,
sizeof(OHCI_DRIVER_EXTENSION),
(PVOID *)&DriverExtension);
if (!NT_SUCCESS(Status))
{
DPRINT1("Allocating DriverObjectExtension failed.\n");
return Status;
}
}
// Create a unicode device name
DeviceNumber = 0; //TODO: Allocate new device number every time
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
Status = IoCreateDevice(DriverObject,
sizeof(OHCI_DEVICE_EXTENSION),
/* + DriverExtension->InitializationData.HwDeviceExtensionSize*/
&DeviceName,
FILE_DEVICE_CONTROLLER,
0,
FALSE,
&fdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateDevice call failed with status 0x%08x\n", Status);
return Status;
}
// zerofill device extension
DeviceExtension = (POHCI_DEVICE_EXTENSION)pdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
// Initialize device extension
DeviceExtension->DeviceNumber = DeviceNumber;
DeviceExtension->PhysicalDeviceObject = pdo;
DeviceExtension->FunctionalDeviceObject = fdo;
DeviceExtension->DriverExtension = DriverExtension;
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);
return Status;
}
/* Get bus number from the upper level bus driver. */
Size = sizeof(ULONG);
/* Status = IoGetDeviceProperty(
pdo,
DevicePropertyBusNumber,
Size,
&DeviceExtension->SystemIoBusNumber,
&Size);
if (!NT_SUCCESS(Status))
{
DPRINT1("Couldn't get an information from bus driver. Panic!!!\n");
return Status;
}
*/
DPRINT1("Done AddDevice\n");
return STATUS_SUCCESS;
}
VOID STDCALL
DriverUnload(PDRIVER_OBJECT DriverObject)
{
POHCI_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT DeviceObject;
struct pci_dev *dev;
DeviceObject = DriverObject->DeviceObject;
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
dev = DeviceExtension->pdev;
DPRINT1("DriverUnload()\n");
// Exit usb device
usb_exit();
// Remove device (ohci_pci_driver.remove)
uhci_pci_driver.remove(dev);
ExFreePool(dev->slot_name);
ExFreePool(dev);
// Perform some cleanup
uhci_hcd_cleanup();
}
NTSTATUS
InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
struct pci_dev *dev;
// Fill generic linux structs
dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_UHCI_TAG);
/* dev->data = (struct usb_hcd hcd) used in uhci-hub.c called from uhci-hcd.c */
DeviceExtension->pdev = dev;
init_wrapper(dev);
dev->irq = DeviceExtension->InterruptVector;
dev->dev_ext = (PVOID)DeviceExtension;
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name
strcpy(dev->dev.name, "UnivHCI PCI-USB Controller");
strcpy(dev->slot_name, "UHCD PCI Slot");
// Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL
Status = uhci_hcd_init();
//FIXME: Check status returned value
// Init core usb
usb_init();
// Probe device with real id now
uhci_pci_driver.probe(dev, uhci_pci_ids);
DPRINT1("InitLinuxWrapper() done\n");
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PDRIVER_OBJECT DriverObject;
POHCI_DRIVER_EXTENSION DriverExtension;
POHCI_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST AllocatedResources;
/*
* Get the initialization data we saved in VideoPortInitialize.
*/
DriverObject = DeviceObject->DriverObject;
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
DeviceExtension = (POHCI_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);*/
DPRINT1("AllocRess->Count: %d, PartResList.Count: %d\n",
AllocatedResources->Count, FullList->PartialResourceList.Count);
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;
DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
DeviceExtension->InterruptLevel,
DeviceExtension->InterruptVector);
}
else if (Descriptor->Type == CmResourceTypePort)
{
DeviceExtension->BaseAddress = Descriptor->u.Port.Start;
DeviceExtension->BaseAddrLength = Descriptor->u.Port.Length;
DeviceExtension->Flags = Descriptor->Flags;
((struct hc_driver *)uhci_pci_ids->driver_data)->flags &= ~HCD_MEMORY;
DPRINT1("I/O resource: start=0x%x, length=0x%x\n",
DeviceExtension->BaseAddress.u.LowPart, DeviceExtension->BaseAddrLength);
}
else if (Descriptor->Type == CmResourceTypeMemory)
{
DeviceExtension->BaseAddress = Descriptor->u.Memory.Start;
DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length;
DeviceExtension->Flags = Descriptor->Flags;
((struct hc_driver *)uhci_pci_ids->driver_data)->flags |= HCD_MEMORY;
DPRINT1("Memory resource: start=0x%x, length=0x%x\n",
DeviceExtension->BaseAddress.u.LowPart, DeviceExtension->BaseAddrLength);
}
else
DPRINT1("Get resource type: %d, Generic start=0x%x Generic length=0x%x\n",
Descriptor->Type, Descriptor->u.Generic.Start.u.LowPart, Descriptor->u.Generic.Length);
}
}
}
/*
* Init wrapper with this object
*/
return InitLinuxWrapper(DeviceObject);
}
// Dispatch PNP
NTSTATUS STDCALL
DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
// Status = ForwardIrpAndWait(DeviceObject, Irp);
// if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = OHCD_PnPStartDevice(DeviceObject, Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_STOP_DEVICE:
// Status = ForwardIrpAndWait(DeviceObject, Irp);
// if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoDeleteDevice(DeviceObject); // just delete device for now
break;
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
default:
return STATUS_NOT_IMPLEMENTED;
break;
}
return Status;
}
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)
{
DPRINT1("******************** Cromwell UHCI ********************\n");
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = AddDevice;
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
return STATUS_SUCCESS;
}