Merge r67713 and r67936 (Eric's parport driver) from trunk

svn path=/branches/colins-printing-for-freedom/; revision=68406
This commit is contained in:
Colin Finck 2015-07-16 15:12:50 +00:00
commit 30af627761
7 changed files with 1154 additions and 2 deletions

View file

@ -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)

View file

@ -0,0 +1,597 @@
/*
* 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"
/* 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->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;
}
NTSTATUS
NTAPI
FdoStartDevice(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 < 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
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);
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,
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;
}
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;
}
/* 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 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;
}
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)
{
DPRINT("FdoWrite()\n");
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:
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;
}
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 */

View 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_ */

View file

@ -0,0 +1,86 @@
/*
* 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;
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);
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 */

View file

@ -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;
}

View file

@ -1,6 +1,7 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: Parallel Port Function Driver
* FILE: drivers/parallel/parport/parport.h
* PURPOSE: Parport driver header
*/
@ -8,9 +9,143 @@
#define _PARPORT_PCH_
#include <ntddk.h>
#include <ntddser.h>
#include <ndk/haltypes.h>
#include <ntddpar.h>
#include <stdio.h>
#include "hardware.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;
PDEVICE_OBJECT AttachedRawPdo;
PDEVICE_OBJECT AttachedPdo[2];
ULONG PortNumber;
ULONG OpenCount;
ULONG BaseAddress;
PKINTERRUPT Interrupt;
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct _PDO_DEVICE_EXTENSION
{
COMMON_DEVICE_EXTENSION Common;
PDEVICE_OBJECT AttachedFdo;
ULONG PortNumber;
ULONG LptPort;
ULONG OpenCount;
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
#define PARPORT_TAG 'trpP'
/* 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_ */

View file

@ -0,0 +1,179 @@
/*
* 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)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_SUCCESS;
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;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
NTAPI
PdoClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PPDO_DEVICE_EXTENSION pDeviceExtension;
DPRINT("PdoClose()\n");
pDeviceExtension = (PPDO_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
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)
{
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PIO_STACK_LOCATION IoStack;
PUCHAR Buffer;
ULONG i;
UCHAR PortStatus;
ULONG ulCount;
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.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 */