mirror of
https://github.com/reactos/reactos.git
synced 2025-07-04 14:01:23 +00:00
[PARPORT]
- Add FdoQueryBusRelations to enumerate the 'attached' raw port. - Create the PDO for the raw port (\Device\ParallelX) and let the symbolic link (\DosDevices\LPTX) point to it. - Move the open, close and write code from the FDO to the PDO. svn path=/trunk/; revision=67936
This commit is contained in:
parent
556d08c8f1
commit
f4494b1b46
5 changed files with 290 additions and 124 deletions
|
@ -7,37 +7,6 @@
|
||||||
|
|
||||||
#include "parport.h"
|
#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 ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -86,11 +55,7 @@ AddDeviceInternal(IN PDRIVER_OBJECT DriverObject,
|
||||||
DeviceExtension->Common.IsFDO = TRUE;
|
DeviceExtension->Common.IsFDO = TRUE;
|
||||||
DeviceExtension->Common.PnpState = dsStopped;
|
DeviceExtension->Common.PnpState = dsStopped;
|
||||||
|
|
||||||
DeviceExtension->ParallelPortNumber = IoGetConfigurationInformation()->ParallelCount++;
|
DeviceExtension->PortNumber = IoGetConfigurationInformation()->ParallelCount++;
|
||||||
if (pLptPortNumber == NULL)
|
|
||||||
DeviceExtension->LptPort = DeviceExtension->ParallelPortNumber + 1;
|
|
||||||
else
|
|
||||||
DeviceExtension->LptPort = *pLptPortNumber;
|
|
||||||
DeviceExtension->Pdo = Pdo;
|
DeviceExtension->Pdo = Pdo;
|
||||||
|
|
||||||
Status = IoAttachDeviceToDeviceStackSafe(Fdo,
|
Status = IoAttachDeviceToDeviceStackSafe(Fdo,
|
||||||
|
@ -141,22 +106,12 @@ FdoStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PCM_RESOURCE_LIST ResourceListTranslated)
|
IN PCM_RESOURCE_LIST ResourceListTranslated)
|
||||||
{
|
{
|
||||||
PFDO_DEVICE_EXTENSION DeviceExtension;
|
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 i;
|
||||||
// ULONG Vector = 0;
|
// ULONG Vector = 0;
|
||||||
// KIRQL Dirql = 0;
|
// KIRQL Dirql = 0;
|
||||||
// KAFFINITY Affinity = 0;
|
// KAFFINITY Affinity = 0;
|
||||||
// KINTERRUPT_MODE InterruptMode = Latched;
|
// KINTERRUPT_MODE InterruptMode = Latched;
|
||||||
// BOOLEAN ShareInterrupt = TRUE;
|
// BOOLEAN ShareInterrupt = TRUE;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
UNICODE_STRING KeyName;
|
|
||||||
HANDLE KeyHandle;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("FdoStartDevice ()\n");
|
DPRINT("FdoStartDevice ()\n");
|
||||||
|
|
||||||
|
@ -247,21 +202,89 @@ FdoStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create link \DosDevices\LPTX -> \Device\ParallelPortX */
|
DeviceExtension->Common.PnpState = dsStarted;
|
||||||
swprintf(DeviceNameBuffer, L"\\Device\\ParallelPort%lu", DeviceExtension->ParallelPortNumber);
|
|
||||||
swprintf(LinkNameBuffer, L"\\DosDevices\\LPT%lu", DeviceExtension->LptPort);
|
|
||||||
swprintf(LptPortBuffer, L"LPT%lu", DeviceExtension->LptPort);
|
/* We don't really care if the call succeeded or not... */
|
||||||
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
|
|
||||||
|
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(&LinkName, LinkNameBuffer);
|
||||||
RtlInitUnicodeString(&LptPort, LptPortBuffer);
|
|
||||||
Status = IoCreateSymbolicLink(&LinkName,
|
Status = IoCreateSymbolicLink(&LinkName,
|
||||||
&DeviceName);
|
&DeviceName);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("IoCreateSymbolicLink() failed with status 0x%08x\n", 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. */
|
/* Write an entry value under HKLM\HARDWARE\DeviceMap\PARALLEL PORTS. */
|
||||||
/* This step is not mandatory, so do not exit in case of error. */
|
/* This step is not mandatory, so do not exit in case of error. */
|
||||||
|
@ -292,10 +315,66 @@ FdoStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||||
ZwClose(KeyHandle);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* We don't really care if the call succeeded or not... */
|
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;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -345,7 +424,7 @@ FdoCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Open LPT%lu: successful\n", DeviceExtension->LptPort);
|
DPRINT("Open parallel port %lu: successful\n", DeviceExtension->PortNumber);
|
||||||
DeviceExtension->OpenCount++;
|
DeviceExtension->OpenCount++;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -397,68 +476,11 @@ NTAPI
|
||||||
FdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
FdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
PFDO_DEVICE_EXTENSION DeviceExtension;
|
|
||||||
PIO_STACK_LOCATION IoStack;
|
|
||||||
PUCHAR Buffer;
|
|
||||||
ULONG i;
|
|
||||||
UCHAR PortStatus;
|
|
||||||
ULONG ulCount;
|
|
||||||
|
|
||||||
DPRINT("FdoWrite()\n");
|
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);
|
|
||||||
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR)(DeviceExtension->BaseAddress + 2), (LP_PSELECP | LP_PINITP | LP_PSTROBE));
|
|
||||||
|
|
||||||
KeStallExecutionProcessor(10);
|
|
||||||
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR)(DeviceExtension->BaseAddress + 2), (LP_PSELECP | LP_PINITP));
|
|
||||||
}
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,26 +546,29 @@ FdoPnp(IN PDEVICE_OBJECT DeviceObject,
|
||||||
switch (Stack->Parameters.QueryDeviceRelations.Type)
|
switch (Stack->Parameters.QueryDeviceRelations.Type)
|
||||||
{
|
{
|
||||||
case BusRelations:
|
case BusRelations:
|
||||||
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
|
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
|
||||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
Status = FdoQueryBusRelations(DeviceObject, Irp, Stack);
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
|
||||||
case RemovalRelations:
|
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);
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
|
||||||
default:
|
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);
|
Stack->Parameters.QueryDeviceRelations.Type);
|
||||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0xd */
|
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);
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT1("Unknown minor function 0x%x\n", MinorFunction);
|
DPRINT("Unknown minor function 0x%x\n", MinorFunction);
|
||||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
41
reactos/drivers/parallel/parport/hardware.h
Normal file
41
reactos/drivers/parallel/parport/hardware.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: Parallel Port Function Driver
|
||||||
|
* FILE: drivers/parallel/parport/hardware.h
|
||||||
|
* PURPOSE: Hardware definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HARDWARE_H_
|
||||||
|
#define _HARDWARE_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 */
|
||||||
|
|
||||||
|
#endif /* _HARDWARE_H_ */
|
|
@ -61,7 +61,10 @@ ForwardIrpAndForget(IN PDEVICE_OBJECT DeviceObject,
|
||||||
{
|
{
|
||||||
PDEVICE_OBJECT LowerDevice;
|
PDEVICE_OBJECT LowerDevice;
|
||||||
|
|
||||||
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||||
|
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||||
|
else
|
||||||
|
LowerDevice = ((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedFdo;
|
||||||
ASSERT(LowerDevice);
|
ASSERT(LowerDevice);
|
||||||
|
|
||||||
IoSkipCurrentIrpStackLocation(Irp);
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: Parallel Port Function Driver
|
* PROJECT: Parallel Port Function Driver
|
||||||
|
* FILE: drivers/parallel/parport/parport.h
|
||||||
* PURPOSE: Parport driver header
|
* PURPOSE: Parport driver header
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -12,6 +13,8 @@
|
||||||
#include <ntddpar.h>
|
#include <ntddpar.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "hardware.h"
|
||||||
|
|
||||||
//#define NDEBUG
|
//#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
@ -37,9 +40,11 @@ typedef struct _FDO_DEVICE_EXTENSION
|
||||||
PDEVICE_OBJECT Pdo;
|
PDEVICE_OBJECT Pdo;
|
||||||
PDEVICE_OBJECT LowerDevice;
|
PDEVICE_OBJECT LowerDevice;
|
||||||
|
|
||||||
ULONG ParallelPortNumber;
|
PDEVICE_OBJECT AttachedRawPdo;
|
||||||
|
PDEVICE_OBJECT AttachedPdo[2];
|
||||||
|
|
||||||
|
ULONG PortNumber;
|
||||||
|
|
||||||
ULONG LptPort;
|
|
||||||
ULONG OpenCount;
|
ULONG OpenCount;
|
||||||
|
|
||||||
ULONG BaseAddress;
|
ULONG BaseAddress;
|
||||||
|
@ -51,8 +56,16 @@ typedef struct _PDO_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
COMMON_DEVICE_EXTENSION Common;
|
COMMON_DEVICE_EXTENSION Common;
|
||||||
|
|
||||||
|
PDEVICE_OBJECT AttachedFdo;
|
||||||
|
|
||||||
|
ULONG PortNumber;
|
||||||
|
ULONG LptPort;
|
||||||
|
|
||||||
|
ULONG OpenCount;
|
||||||
|
|
||||||
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
#define PARPORT_TAG 'trpP'
|
||||||
|
|
||||||
/* fdo.c */
|
/* fdo.c */
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,31 @@ NTAPI
|
||||||
PdoCreate(IN PDEVICE_OBJECT DeviceObject,
|
PdoCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
|
PPDO_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
DPRINT("PdoCreate()\n");
|
DPRINT("PdoCreate()\n");
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
DeviceExtension = (PPDO_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 LPT%lu: successful\n", DeviceExtension->LptPort);
|
||||||
|
DeviceExtension->OpenCount++;
|
||||||
|
|
||||||
|
done:
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,11 +47,17 @@ NTAPI
|
||||||
PdoClose(IN PDEVICE_OBJECT DeviceObject,
|
PdoClose(IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
|
PPDO_DEVICE_EXTENSION pDeviceExtension;
|
||||||
|
|
||||||
DPRINT("PdoClose()\n");
|
DPRINT("PdoClose()\n");
|
||||||
|
|
||||||
|
pDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
pDeviceExtension->OpenCount--;
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +81,67 @@ NTAPI
|
||||||
PdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
PdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp)
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
|
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
|
||||||
|
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
ULONG i;
|
||||||
|
UCHAR PortStatus;
|
||||||
|
ULONG ulCount;
|
||||||
|
|
||||||
DPRINT("PdoWrite()\n");
|
DPRINT("PdoWrite()\n");
|
||||||
|
|
||||||
|
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->AttachedFdo->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)(FdoDeviceExtension->BaseAddress + 1));
|
||||||
|
ulCount++;
|
||||||
|
}
|
||||||
|
while (ulCount < 500000 && !(PortStatus & LP_PBUSY));
|
||||||
|
|
||||||
|
if (ulCount == 500000)
|
||||||
|
{
|
||||||
|
DPRINT("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)FdoDeviceExtension->BaseAddress, Buffer[i]);
|
||||||
|
|
||||||
|
KeStallExecutionProcessor(10);
|
||||||
|
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)(FdoDeviceExtension->BaseAddress + 2), (LP_PSELECP | LP_PINITP | LP_PSTROBE));
|
||||||
|
|
||||||
|
KeStallExecutionProcessor(10);
|
||||||
|
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)(FdoDeviceExtension->BaseAddress + 2), (LP_PSELECP | LP_PINITP));
|
||||||
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue