mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[PARPORT]
Implement basic funtions of the parallel port driver. It supports Centronics-Mode only. You can print files using: copy <filename> lpt1: svn path=/trunk/; revision=67713
This commit is contained in:
parent
f1291bfaea
commit
a84978c658
6 changed files with 988 additions and 2 deletions
|
@ -1,5 +1,16 @@
|
|||
|
||||
add_library(parport SHARED parport.c parport.rc)
|
||||
list(APPEND SOURCE
|
||||
fdo.c
|
||||
misc.c
|
||||
pdo.c
|
||||
parport.c
|
||||
parport.h)
|
||||
|
||||
add_library(parport SHARED
|
||||
${SOURCE}
|
||||
parport.rc)
|
||||
|
||||
set_module_type(parport kernelmodedriver)
|
||||
add_pch(parport parport.h SOURCE)
|
||||
add_importlibs(parport ntoskrnl hal)
|
||||
add_cd_file(TARGET parport DESTINATION reactos/system32/drivers FOR all)
|
||||
|
|
572
reactos/drivers/parallel/parport/fdo.c
Normal file
572
reactos/drivers/parallel/parport/fdo.c
Normal file
|
@ -0,0 +1,572 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
/*
|
||||
* 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
|
||||
NTAPI
|
||||
AddDeviceInternal(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->ParallelPortNumber = IoGetConfigurationInformation()->ParallelCount++;
|
||||
if (pLptPortNumber == NULL)
|
||||
DeviceExtension->LptPort = DeviceExtension->ParallelPortNumber + 1;
|
||||
else
|
||||
DeviceExtension->LptPort = *pLptPortNumber;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PCM_RESOURCE_LIST ResourceList,
|
||||
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");
|
||||
|
||||
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 < 8)
|
||||
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);
|
||||
|
||||
// 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 ressource: \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
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* 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,
|
||||
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);
|
||||
}
|
||||
|
||||
DeviceExtension->Common.PnpState = dsStarted;
|
||||
|
||||
|
||||
/* We don't really care if the call succeeded or not... */
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS *********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
AddDevice(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);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoCreate(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 LPT%lu: successful\n", DeviceExtension->LptPort);
|
||||
DeviceExtension->OpenCount++;
|
||||
|
||||
done:
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoClose(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;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoCleanup(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;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoWrite(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);
|
||||
|
||||
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.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoPnp(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
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");
|
||||
|
||||
ASSERT(((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.PnpState == dsStopped);
|
||||
|
||||
/* Call lower driver */
|
||||
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
||||
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:
|
||||
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
|
||||
case RemovalRelations:
|
||||
DPRINT1("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",
|
||||
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");
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
|
||||
default:
|
||||
DPRINT1("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;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoPower(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("FdoPower()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
83
reactos/drivers/parallel/parport/misc.c
Normal file
83
reactos/drivers/parallel/parport/misc.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: Parallel Port Function Driver
|
||||
* FILE: drivers/parallel/parport/misc.c
|
||||
* PURPOSE: Miscellaneous functions
|
||||
*/
|
||||
|
||||
#include "parport.h"
|
||||
|
||||
|
||||
static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
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;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||
ASSERT(LowerDevice);
|
||||
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
DPRINT("Calling lower device %p\n", LowerDevice);
|
||||
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
|
||||
NTAPI
|
||||
ForwardIrpAndForget(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
|
||||
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
|
||||
ASSERT(LowerDevice);
|
||||
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(LowerDevice, Irp);
|
||||
}
|
||||
|
||||
|
||||
PVOID
|
||||
GetUserBuffer(IN PIRP Irp)
|
||||
{
|
||||
ASSERT(Irp);
|
||||
|
||||
if (Irp->MdlAddress)
|
||||
return Irp->MdlAddress;
|
||||
else
|
||||
return Irp->AssociatedIrp.SystemBuffer;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -7,8 +7,16 @@
|
|||
#include "parport.h"
|
||||
|
||||
static DRIVER_UNLOAD DriverUnload;
|
||||
static DRIVER_DISPATCH DispatchCreate;
|
||||
static DRIVER_DISPATCH DispatchClose;
|
||||
static DRIVER_DISPATCH DispatchCleanup;
|
||||
static DRIVER_DISPATCH DispatchPnp;
|
||||
static DRIVER_DISPATCH DispatchPower;
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
NTAPI
|
||||
|
@ -17,14 +25,109 @@ DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
|||
DPRINT("Parport DriverUnload\n");
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||
return FdoCreate(DeviceObject, Irp);
|
||||
else
|
||||
return PdoCreate(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||
return FdoClose(DeviceObject, Irp);
|
||||
else
|
||||
return PdoClose(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchCleanup(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||
return FdoCleanup(DeviceObject, Irp);
|
||||
else
|
||||
return PdoCleanup(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||
return FdoWrite(DeviceObject, Irp);
|
||||
else
|
||||
return PdoWrite(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchPnp(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||
return FdoPnp(DeviceObject, Irp);
|
||||
else
|
||||
return PdoPnp(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DispatchPower(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
if (((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
|
||||
return FdoPower(DeviceObject, Irp);
|
||||
else
|
||||
return PdoPower(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
DPRINT("Parport DriverEntry\n");
|
||||
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
|
||||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
DriverObject->MajorFunction[i] = ForwardIrpAndForget;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
|
||||
// DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
|
||||
// DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
|
||||
// DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = DispatchQueryInformation;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,131 @@
|
|||
#define _PARPORT_PCH_
|
||||
|
||||
#include <ntddk.h>
|
||||
#include <ntddser.h>
|
||||
#include <ndk/haltypes.h>
|
||||
#include <ntddpar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
dsStopped,
|
||||
dsStarted,
|
||||
dsPaused,
|
||||
dsRemoved,
|
||||
dsSurpriseRemoved
|
||||
} DEVICE_STATE;
|
||||
|
||||
typedef struct _COMMON_DEVICE_EXTENSION
|
||||
{
|
||||
BOOLEAN IsFDO;
|
||||
DEVICE_STATE PnpState;
|
||||
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct _FDO_DEVICE_EXTENSION
|
||||
{
|
||||
COMMON_DEVICE_EXTENSION Common;
|
||||
|
||||
PDEVICE_OBJECT Pdo;
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
|
||||
ULONG ParallelPortNumber;
|
||||
|
||||
ULONG LptPort;
|
||||
ULONG OpenCount;
|
||||
|
||||
ULONG BaseAddress;
|
||||
PKINTERRUPT Interrupt;
|
||||
|
||||
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct _PDO_DEVICE_EXTENSION
|
||||
{
|
||||
COMMON_DEVICE_EXTENSION Common;
|
||||
|
||||
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
/* fdo.c */
|
||||
|
||||
DRIVER_ADD_DEVICE AddDevice;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoCleanup(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoPnp(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FdoPower(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
|
||||
/* misc.c */
|
||||
|
||||
NTSTATUS
|
||||
ForwardIrpAndWait(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
DRIVER_DISPATCH ForwardIrpAndForget;
|
||||
|
||||
PVOID
|
||||
GetUserBuffer(IN PIRP Irp);
|
||||
|
||||
//KSERVICE_ROUTINE ParportInterruptService;
|
||||
|
||||
|
||||
/* pdo.c */
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoCleanup(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoPnp(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoPower(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
#endif /* _PARPORT_PCH_ */
|
||||
|
|
95
reactos/drivers/parallel/parport/pdo.c
Normal file
95
reactos/drivers/parallel/parport/pdo.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: Parallel Port Function Driver
|
||||
* FILE: drivers/parallel/parport/pdo.c
|
||||
* PURPOSE: PDO functions
|
||||
*/
|
||||
|
||||
#include "parport.h"
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("PdoCreate()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("PdoClose()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoCleanup(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("PdoCleanup()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("PdoWrite()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoPnp(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("PdoPnp()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PdoPower(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("PdoPower()\n");
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue