Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: Parallel Port Function Driver * FILE: drivers/parallel/parport/fdo.c * PURPOSE: FDO functions */
#include "parport.h"#define NDEBUG#include <debug.h>
/* FUNCTIONS ****************************************************************/
NTSTATUSNTAPIAddDeviceInternal(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo, IN PULONG pLptPortNumber OPTIONAL, OUT PDEVICE_OBJECT* pFdo OPTIONAL){ PFDO_DEVICE_EXTENSION DeviceExtension = NULL; PDEVICE_OBJECT Fdo = NULL; WCHAR DeviceNameBuffer[32]; UNICODE_STRING DeviceName; NTSTATUS Status;
DPRINT("AddDeviceInternal()\n");
ASSERT(DriverObject); ASSERT(Pdo);
/* Create new device object */ swprintf(DeviceNameBuffer, L"\\Device\\ParallelPort%lu", IoGetConfigurationInformation()->ParallelCount); RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_PARALLEL_PORT, FILE_DEVICE_SECURE_OPEN, FALSE, &Fdo); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDevice() failed (Status 0x%08lx)\n", Status); Fdo = NULL; goto done; }
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->Common.IsFDO = TRUE; DeviceExtension->Common.PnpState = dsStopped;
DeviceExtension->PortNumber = IoGetConfigurationInformation()->ParallelCount++; DeviceExtension->Pdo = Pdo;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); if (!NT_SUCCESS(Status)) { DPRINT1("IoAttachDeviceToDeviceStackSafe() failed (Status 0x%08lx)\n", Status); goto done; }
if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE) Fdo->Flags |= DO_POWER_PAGABLE;
if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO) Fdo->Flags |= DO_BUFFERED_IO;
if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO) Fdo->Flags |= DO_DIRECT_IO;
/* Choose default strategy */ if ((Fdo->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) == 0) Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
if (pFdo) { *pFdo = Fdo; }
return STATUS_SUCCESS;
done: if (Fdo) { IoDeleteDevice(Fdo); }
return Status;}
NTSTATUSNTAPIFdoStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PCM_RESOURCE_LIST ResourceList, IN PCM_RESOURCE_LIST ResourceListTranslated){ PFDO_DEVICE_EXTENSION DeviceExtension; ULONG i;// ULONG Vector = 0;// KIRQL Dirql = 0;// KAFFINITY Affinity = 0;// KINTERRUPT_MODE InterruptMode = Latched;// BOOLEAN ShareInterrupt = TRUE;
DPRINT("FdoStartDevice ()\n");
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension); ASSERT(DeviceExtension->Common.IsFDO == TRUE);
if (!ResourceList) { DPRINT1("No allocated resources sent to driver\n"); return STATUS_INSUFFICIENT_RESOURCES; }
if (ResourceList->Count != 1) { DPRINT1("Wrong number of allocated resources sent to driver\n"); return STATUS_INSUFFICIENT_RESOURCES; }
if ((ResourceList->List[0].PartialResourceList.Version != 1) || (ResourceList->List[0].PartialResourceList.Revision != 1) || (ResourceListTranslated->List[0].PartialResourceList.Version != 1) || (ResourceListTranslated->List[0].PartialResourceList.Revision != 1)) { DPRINT1("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n", ResourceList->List[0].PartialResourceList.Version, ResourceList->List[0].PartialResourceList.Revision, ResourceListTranslated->List[0].PartialResourceList.Version, ResourceListTranslated->List[0].PartialResourceList.Revision); return STATUS_REVISION_MISMATCH; }
DeviceExtension->BaseAddress = 0;
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++) { PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i]; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[i];
switch (PartialDescriptor->Type) { case CmResourceTypePort: DPRINT("Port: BaseAddress 0x%lx Length %lu\n", PartialDescriptor->u.Port.Start.u.LowPart, PartialDescriptor->u.Port.Length);
if (DeviceExtension->BaseAddress == 0) { if (PartialDescriptor->u.Port.Length < 3) return STATUS_INSUFFICIENT_RESOURCES;
DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart; } break;
case CmResourceTypeInterrupt: DPRINT("Interrupt: Level %lu Vector %lu\n", PartialDescriptorTranslated->u.Interrupt.Level, PartialDescriptorTranslated->u.Interrupt.Vector);
(VOID)PartialDescriptorTranslated;// Dirql = (KIRQL)PartialDescriptorTranslated->u.Interrupt.Level;// Vector = PartialDescriptorTranslated->u.Interrupt.Vector;// Affinity = PartialDescriptorTranslated->u.Interrupt.Affinity;
// if (PartialDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)// InterruptMode = Latched;// else// InterruptMode = LevelSensitive;
// ShareInterrupt = (PartialDescriptorTranslated->ShareDisposition == CmResourceShareShared); break;
default: DPRINT1("Other resource: \n"); break; } }
DPRINT("New LPT port: Base 0x%lx\n", DeviceExtension->BaseAddress);
if (!DeviceExtension->BaseAddress) return STATUS_INSUFFICIENT_RESOURCES;
#if 0 if (!Dirql) return STATUS_INSUFFICIENT_RESOURCES;#endif
DeviceExtension->Common.PnpState = dsStarted;
/* We don't really care if the call succeeded or not... */
return STATUS_SUCCESS;}
staticNTSTATUSFdoCreateRawParallelPdo( IN PDEVICE_OBJECT DeviceObject){ PFDO_DEVICE_EXTENSION FdoDeviceExtension; PPDO_DEVICE_EXTENSION PdoDeviceExtension = NULL; PDEVICE_OBJECT Pdo = NULL; WCHAR DeviceNameBuffer[32]; WCHAR LinkNameBuffer[32]; WCHAR LptPortBuffer[32]; UNICODE_STRING DeviceName; UNICODE_STRING LinkName; UNICODE_STRING LptPort; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; HANDLE KeyHandle; NTSTATUS Status;
DPRINT("FdoCreateRawParallelPdo()\n");
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Create new device object */ swprintf(DeviceNameBuffer, L"\\Device\\Parallel%lu", FdoDeviceExtension->PortNumber); RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_CONTROLLER, 0, FALSE, &Pdo); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDevice() failed with status 0x%08x\n", Status); goto done; }
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; Pdo->Flags |= DO_POWER_PAGABLE;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension; RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
PdoDeviceExtension->Common.IsFDO = FALSE; PdoDeviceExtension->Common.PnpState = dsStopped;
Pdo->StackSize = DeviceObject->StackSize + 1;
FdoDeviceExtension->AttachedRawPdo = Pdo; PdoDeviceExtension->AttachedFdo = DeviceObject;
PdoDeviceExtension->PortNumber = FdoDeviceExtension->PortNumber; PdoDeviceExtension->LptPort = PdoDeviceExtension->PortNumber + 1;
/* Create link \DosDevices\LPTX -> \Device\ParallelY */ swprintf(LinkNameBuffer, L"\\DosDevices\\LPT%lu", PdoDeviceExtension->LptPort); RtlInitUnicodeString(&LinkName, LinkNameBuffer); Status = IoCreateSymbolicLink(&LinkName, &DeviceName); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateSymbolicLink() failed with status 0x%08x\n", Status); goto done; }
swprintf(LptPortBuffer, L"LPT%lu", PdoDeviceExtension->LptPort); RtlInitUnicodeString(&LptPort, LptPortBuffer);
/* Write an entry value under HKLM\HARDWARE\DeviceMap\PARALLEL PORTS. */ /* This step is not mandatory, so do not exit in case of error. */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\DeviceMap\\PARALLEL PORTS"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwCreateKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); if (NT_SUCCESS(Status)) { /* Key = \Device\Parallelx, Value = LPTx */ ZwSetValueKey(KeyHandle, &DeviceName, 0, REG_SZ, LptPortBuffer, LptPort.Length + sizeof(WCHAR)); ZwClose(KeyHandle); }
Pdo->Flags |= DO_BUFFERED_IO; Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
done: if (!NT_SUCCESS(Status)) { if (Pdo) { ASSERT(PdoDeviceExtension); IoDeleteDevice(Pdo); } }
return Status;}
staticNTSTATUSFdoQueryBusRelations( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, PIO_STACK_LOCATION IrpSp){ PFDO_DEVICE_EXTENSION DeviceExtension; PDEVICE_RELATIONS DeviceRelations; ULONG Size; ULONG i; ULONG PdoCount = 0; NTSTATUS Status;
UNREFERENCED_PARAMETER(IrpSp);
DPRINT("FdoQueryBusRelations()\n");
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ASSERT(DeviceExtension->Common.IsFDO);
/* TODO: Enumerate parallel devices and create their PDOs */
Status = FdoCreateRawParallelPdo(DeviceObject); if (!NT_SUCCESS(Status)) return Status;
PdoCount++;
/* Allocate a buffer for the device relations */ Size = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PdoCount - 1); DeviceRelations = ExAllocatePoolWithTag(PagedPool, Size, PARPORT_TAG); if (DeviceRelations == NULL) return STATUS_INSUFFICIENT_RESOURCES;
/* Fill the buffer */ i = 0; ObReferenceObject(DeviceExtension->AttachedRawPdo); DeviceRelations->Objects[i] = DeviceExtension->AttachedRawPdo; DeviceRelations->Count = 1;
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
DPRINT("Done\n");
return STATUS_SUCCESS;}
/* PUBLIC FUNCTIONS *********************************************************/
NTSTATUSNTAPIAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo){ DPRINT("AddDevice(%p %p)\n", DriverObject, Pdo);
/* Serial.sys is a legacy driver. AddDevice is called once * with a NULL Pdo just after the driver initialization. * Detect this case and return success. */ if (Pdo == NULL) return STATUS_SUCCESS;
/* We have here a PDO not null. It represents a real serial * port. So call the internal AddDevice function. */ return AddDeviceInternal(DriverObject, Pdo, NULL, NULL);}
NTSTATUSNTAPIFdoCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PFDO_DEVICE_EXTENSION DeviceExtension; PIO_STACK_LOCATION Stack; NTSTATUS Status = STATUS_SUCCESS;
DPRINT("FdoCreate()\n");
Stack = IoGetCurrentIrpStackLocation(Irp); DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE) { DPRINT1("Not a directory\n"); Status = STATUS_NOT_A_DIRECTORY; goto done; }
DPRINT("Open parallel port %lu: successful\n", DeviceExtension->PortNumber); DeviceExtension->OpenCount++;
done: Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;}
NTSTATUSNTAPIFdoClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PFDO_DEVICE_EXTENSION pDeviceExtension;
DPRINT("FdoClose()\n");
pDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; pDeviceExtension->OpenCount--;
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;}
NTSTATUSNTAPIFdoCleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ DPRINT("FdoCleanup()\n");
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;}
NTSTATUSNTAPIFdoRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ DPRINT("FdoRead()\n");
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_SUPPORTED;}
NTSTATUSNTAPIFdoWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ DPRINT("FdoWrite()\n");
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NOT_SUPPORTED;}
NTSTATUSNTAPIFdoPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PFDO_DEVICE_EXTENSION FdoExtension; ULONG MinorFunction; PIO_STACK_LOCATION Stack; ULONG_PTR Information = 0; NTSTATUS Status;
DPRINT("FdoPnp()\n");
Stack = IoGetCurrentIrpStackLocation(Irp); MinorFunction = Stack->MinorFunction;
switch (MinorFunction) { /* FIXME: do all these minor functions IRP_MN_QUERY_REMOVE_DEVICE 0x1 IRP_MN_REMOVE_DEVICE 0x2 { TRACE_(SERIAL, "IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n"); IoAcquireRemoveLock IoReleaseRemoveLockAndWait pass request to DeviceExtension-LowerDriver disable interface IoDeleteDevice(Fdo) and/or IoDetachDevice break; } IRP_MN_CANCEL_REMOVE_DEVICE 0x3 IRP_MN_STOP_DEVICE 0x4 IRP_MN_QUERY_STOP_DEVICE 0x5 IRP_MN_CANCEL_STOP_DEVICE 0x6 IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) 0x7 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7 IRP_MN_QUERY_INTERFACE (optional) 0x8 IRP_MN_QUERY_CAPABILITIES (optional) 0x9 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional) 0xd IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16 IRP_MN_SURPRISE_REMOVAL 0x17 */ case IRP_MN_START_DEVICE: /* 0x0 */ DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
/* Call lower driver */ FdoExtension = DeviceObject->DeviceExtension; Status = STATUS_UNSUCCESSFUL;
ASSERT(FdoExtension->Common.PnpState == dsStopped);
if (IoForwardIrpSynchronously(FdoExtension->LowerDevice, Irp)) { Status = Irp->IoStatus.Status; if (NT_SUCCESS(Status)) { Status = FdoStartDevice(DeviceObject, Stack->Parameters.StartDevice.AllocatedResources, Stack->Parameters.StartDevice.AllocatedResourcesTranslated); } } break;
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ switch (Stack->Parameters.QueryDeviceRelations.Type) { case BusRelations: DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); Status = FdoQueryBusRelations(DeviceObject, Irp, Stack); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status;
case RemovalRelations: DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); return ForwardIrpAndForget(DeviceObject, Irp);
default: DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", Stack->Parameters.QueryDeviceRelations.Type); return ForwardIrpAndForget(DeviceObject, Irp); } break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0xd */ DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); return ForwardIrpAndForget(DeviceObject, Irp);
default: DPRINT("Unknown minor function 0x%x\n", MinorFunction); return ForwardIrpAndForget(DeviceObject, Irp); }
Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;}
NTSTATUSNTAPIFdoPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PDEVICE_OBJECT LowerDevice;
DPRINT("FdoPower()\n");
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(LowerDevice, Irp);}
/* EOF */