#include "parport.h"
-/*
- * The following constants describe the various signals of the printer port
- * hardware. Note that the hardware inverts some signals and that some
- * signals are active low. An example is LP_STROBE, which must be programmed
- * with 1 for being active and 0 for being inactive, because the strobe signal
- * gets inverted, but it is also active low.
- */
-
-/*
- * bit defines for 8255 status port
- * base + 1
- * accessed with LP_S(minor), which gets the byte...
- */
-#define LP_PBUSY 0x80 /* inverted input, active high */
-#define LP_PACK 0x40 /* unchanged input, active low */
-#define LP_POUTPA 0x20 /* unchanged input, active high */
-#define LP_PSELECD 0x10 /* unchanged input, active high */
-#define LP_PERRORP 0x08 /* unchanged input, active low */
-
-/*
- * defines for 8255 control port
- * base + 2
- * accessed with LP_C(minor)
- */
-#define LP_PINTEN 0x10
-#define LP_PSELECP 0x08 /* inverted output, active low */
-#define LP_PINITP 0x04 /* unchanged output, active low */
-#define LP_PAUTOLF 0x02 /* inverted output, active low */
-#define LP_PSTROBE 0x01 /* inverted output, active low */
-
-
/* FUNCTIONS ****************************************************************/
NTSTATUS
DeviceExtension->Common.IsFDO = TRUE;
DeviceExtension->Common.PnpState = dsStopped;
- DeviceExtension->ParallelPortNumber = IoGetConfigurationInformation()->ParallelCount++;
- if (pLptPortNumber == NULL)
- DeviceExtension->LptPort = DeviceExtension->ParallelPortNumber + 1;
- else
- DeviceExtension->LptPort = *pLptPortNumber;
+ DeviceExtension->PortNumber = IoGetConfigurationInformation()->ParallelCount++;
DeviceExtension->Pdo = Pdo;
Status = IoAttachDeviceToDeviceStackSafe(Fdo,
IN PCM_RESOURCE_LIST ResourceListTranslated)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
- WCHAR DeviceNameBuffer[32];
- WCHAR LinkNameBuffer[32];
- WCHAR LptPortBuffer[32];
- UNICODE_STRING DeviceName;
- UNICODE_STRING LinkName;
- UNICODE_STRING LptPort;
ULONG i;
// ULONG Vector = 0;
// KIRQL Dirql = 0;
// KAFFINITY Affinity = 0;
// KINTERRUPT_MODE InterruptMode = Latched;
// BOOLEAN ShareInterrupt = TRUE;
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING KeyName;
- HANDLE KeyHandle;
- NTSTATUS Status;
DPRINT("FdoStartDevice ()\n");
if (DeviceExtension->BaseAddress == 0)
{
- if (PartialDescriptor->u.Port.Length < 8)
+ if (PartialDescriptor->u.Port.Length < 4)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart;
return STATUS_INSUFFICIENT_RESOURCES;
#endif
- /* Create link \DosDevices\LPTX -> \Device\ParallelPortX */
- swprintf(DeviceNameBuffer, L"\\Device\\ParallelPort%lu", DeviceExtension->ParallelPortNumber);
- swprintf(LinkNameBuffer, L"\\DosDevices\\LPT%lu", DeviceExtension->LptPort);
- swprintf(LptPortBuffer, L"LPT%lu", DeviceExtension->LptPort);
- RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
+ DeviceExtension->Common.PnpState = dsStarted;
+
+
+ /* We don't really care if the call succeeded or not... */
+
+ return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+FdoCreateRawParallelPdo(
+ 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);
- RtlInitUnicodeString(&LptPort, LptPortBuffer);
Status = IoCreateSymbolicLink(&LinkName,
&DeviceName);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateSymbolicLink() failed with status 0x%08x\n", Status);
- return 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. */
L"\\Registry\\Machine\\HARDWARE\\DeviceMap\\PARALLEL PORTS");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
- OBJ_CASE_INSENSITIVE,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
ZwClose(KeyHandle);
}
- DeviceExtension->Common.PnpState = dsStarted;
+ Pdo->Flags |= DO_BUFFERED_IO;
+ Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+done:
+ if (!NT_SUCCESS(Status))
+ {
+ if (Pdo)
+ {
+ ASSERT(PdoDeviceExtension);
+ IoDeleteDevice(Pdo);
+ }
+ }
- /* We don't really care if the call succeeded or not... */
+ return Status;
+}
+
+
+static
+NTSTATUS
+FdoQueryBusRelations(
+ 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;
+
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+ DPRINT("Done\n");
return STATUS_SUCCESS;
}
goto done;
}
- DPRINT("Open LPT%lu: successful\n", DeviceExtension->LptPort);
+ DPRINT("Open parallel port %lu: successful\n", DeviceExtension->PortNumber);
DeviceExtension->OpenCount++;
done:
NTSTATUS
NTAPI
-FdoWrite(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+FdoRead(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- PFDO_DEVICE_EXTENSION DeviceExtension;
- PIO_STACK_LOCATION IoStack;
- PUCHAR Buffer;
- ULONG i;
- UCHAR PortStatus;
- ULONG ulCount;
-
- DPRINT("FdoWrite()\n");
-
- DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- IoStack = IoGetCurrentIrpStackLocation(Irp);
-
- Buffer = GetUserBuffer(Irp);
- DPRINT("Length: %lu\n", IoStack->Parameters.Write.Length);
- DPRINT("Buffer: %p\n", Buffer);
-
- if (Buffer != NULL)
- {
- DPRINT("%s\n", Buffer);
- }
-
- for (i = 0; i < IoStack->Parameters.Write.Length; i++)
- {
- DPRINT("%lu: %c\n", i, Buffer[i]);
-
- ulCount = 0;
-
- do
- {
- KeStallExecutionProcessor(10);
- PortStatus = READ_PORT_UCHAR((PUCHAR)(DeviceExtension->BaseAddress + 1));
- ulCount++;
- }
- while (ulCount < 500000 && !(PortStatus & LP_PBUSY));
-
- if (ulCount == 500000)
- {
- DPRINT1("Timed out\n");
-
- Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_TIMEOUT;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return STATUS_TIMEOUT;
- }
-
- /* Write character */
- WRITE_PORT_UCHAR((PUCHAR)DeviceExtension->BaseAddress, Buffer[i]);
-
- KeStallExecutionProcessor(10);
+ DPRINT("FdoRead()\n");
- WRITE_PORT_UCHAR((PUCHAR)(DeviceExtension->BaseAddress + 2), (LP_PSELECP | LP_PINITP | LP_PSTROBE));
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NOT_SUPPORTED;
+}
- KeStallExecutionProcessor(10);
- WRITE_PORT_UCHAR((PUCHAR)(DeviceExtension->BaseAddress + 2), (LP_PSELECP | LP_PINITP));
- }
+NTSTATUS
+NTAPI
+FdoWrite(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("FdoWrite()\n");
Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return STATUS_SUCCESS;
+ return STATUS_NOT_SUPPORTED;
}
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
- DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
- return ForwardIrpAndForget(DeviceObject, Irp);
+ 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:
- DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
+ DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
default:
- DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
+ 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 */
- DPRINT1("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
+ DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
return ForwardIrpAndForget(DeviceObject, Irp);
default:
- DPRINT1("Unknown minor function 0x%x\n", MinorFunction);
+ DPRINT("Unknown minor function 0x%x\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}