diff --git a/reactos/drivers/usb/cromwell/uhci/close.c b/reactos/drivers/usb/cromwell/uhci/close.c new file mode 100644 index 00000000000..0c5c08a5e2a --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/close.c @@ -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; +} diff --git a/reactos/drivers/usb/cromwell/uhci/create.c b/reactos/drivers/usb/cromwell/uhci/create.c new file mode 100644 index 00000000000..c832a954902 --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/create.c @@ -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; +} diff --git a/reactos/drivers/usb/cromwell/uhci/fdo.c b/reactos/drivers/usb/cromwell/uhci/fdo.c new file mode 100644 index 00000000000..46163303c89 --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/fdo.c @@ -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; +} diff --git a/reactos/drivers/usb/cromwell/uhci/misc.c b/reactos/drivers/usb/cromwell/uhci/misc.c new file mode 100644 index 00000000000..db16b3bdc51 --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/misc.c @@ -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 + +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; +} diff --git a/reactos/drivers/usb/cromwell/uhci/pdo.c b/reactos/drivers/usb/cromwell/uhci/pdo.c new file mode 100644 index 00000000000..dd65d873fbd --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/pdo.c @@ -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; +} + diff --git a/reactos/drivers/usb/cromwell/uhci/uhci.c b/reactos/drivers/usb/cromwell/uhci/uhci.c new file mode 100644 index 00000000000..dd16dbc80b4 --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/uhci.c @@ -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; +} diff --git a/reactos/drivers/usb/cromwell/uhci/uhci.def b/reactos/drivers/usb/cromwell/uhci/uhci.def deleted file mode 100644 index 320634a6a47..00000000000 --- a/reactos/drivers/usb/cromwell/uhci/uhci.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY uhci.sys -EXPORTS diff --git a/reactos/drivers/usb/cromwell/uhci/uhci.h b/reactos/drivers/usb/cromwell/uhci/uhci.h new file mode 100644 index 00000000000..a9227189f52 --- /dev/null +++ b/reactos/drivers/usb/cromwell/uhci/uhci.h @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +// 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); diff --git a/reactos/drivers/usb/cromwell/uhci/uhci.xml b/reactos/drivers/usb/cromwell/uhci/uhci.xml index c7acd5a0603..0bb83f5a290 100644 --- a/reactos/drivers/usb/cromwell/uhci/uhci.xml +++ b/reactos/drivers/usb/cromwell/uhci/uhci.xml @@ -1,5 +1,4 @@ - - + include @@ -8,7 +7,12 @@ ntoskrnl hal usbcore + close.c + create.c + fdo.c + misc.c + pdo.c + uhci.c uhci-hcd.c - uhci_main.c uhci.rc diff --git a/reactos/drivers/usb/cromwell/uhci/uhci_main.c b/reactos/drivers/usb/cromwell/uhci/uhci_main.c deleted file mode 100644 index 394bf65f24c..00000000000 --- a/reactos/drivers/usb/cromwell/uhci/uhci_main.c +++ /dev/null @@ -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 -#define DEBUG -#include - -// 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; -}