[PARPORT]
authorEric Kohl <eric.kohl@reactos.org>
Thu, 14 May 2015 14:42:05 +0000 (14:42 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Thu, 14 May 2015 14:42:05 +0000 (14:42 +0000)
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

reactos/drivers/parallel/parport/CMakeLists.txt
reactos/drivers/parallel/parport/fdo.c [new file with mode: 0644]
reactos/drivers/parallel/parport/misc.c [new file with mode: 0644]
reactos/drivers/parallel/parport/parport.c
reactos/drivers/parallel/parport/parport.h
reactos/drivers/parallel/parport/pdo.c [new file with mode: 0644]

index e675c31..1b7b926 100644 (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)
diff --git a/reactos/drivers/parallel/parport/fdo.c b/reactos/drivers/parallel/parport/fdo.c
new file mode 100644 (file)
index 0000000..c8192a8
--- /dev/null
@@ -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 */
diff --git a/reactos/drivers/parallel/parport/misc.c b/reactos/drivers/parallel/parport/misc.c
new file mode 100644 (file)
index 0000000..dab517f
--- /dev/null
@@ -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 */
index 6223ae0..6508ec8 100644 (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;
 }
index 54581ca..74b0876 100644 (file)
@@ -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_ */
diff --git a/reactos/drivers/parallel/parport/pdo.c b/reactos/drivers/parallel/parport/pdo.c
new file mode 100644 (file)
index 0000000..495032b
--- /dev/null
@@ -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 */