NT4/private/ntos/dd/parclass/parclass.h
2020-09-30 17:12:29 +02:00

438 lines
12 KiB
C

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name :
parclass.h
Abstract:
Type definitions and data for the parallel port driver.
Author:
Revision History:
--*/
#include "parallel.h"
#if DBG
#define PARALWAYS ((ULONG)0x00000000)
#define PARCONFIG ((ULONG)0x00000001)
#define PARUNLOAD ((ULONG)0x00000002)
#define PARINITDEV ((ULONG)0x00000004)
#define PARIRPPATH ((ULONG)0x00000008)
#define PARSTARTER ((ULONG)0x00000010)
#define PARPUSHER ((ULONG)0x00000020)
#define PARERRORS ((ULONG)0x00000040)
#define PARTHREAD ((ULONG)0x00000080)
#define PARDEFERED ((ULONG)0x00000100)
extern ULONG ParDebugLevel;
#define ParDump(LEVEL,STRING) \
do { \
ULONG _level = (LEVEL); \
if ((_level == PARALWAYS)||(ParDebugLevel & _level)) { \
DbgPrint STRING; \
} \
} while (0)
#else
#define ParDump(LEVEL,STRING) do {NOTHING;} while (0)
#endif
//
// For the above directory, the serial port will
// use the following name as the suffix of the serial
// ports for that directory. It will also append
// a number onto the end of the name. That number
// will start at 1.
//
#define DEFAULT_PARALLEL_NAME L"LPT"
//
// This is the parallel class name.
//
#define DEFAULT_NT_SUFFIX L"Parallel"
#define PARALLEL_DATA_OFFSET 0
#define PARALLEL_STATUS_OFFSET 1
#define PARALLEL_CONTROL_OFFSET 2
#define PARALLEL_REGISTER_SPAN 3
typedef struct _DEVICE_EXTENSION {
//
// Points to the device object that contains
// this device extension.
//
PDEVICE_OBJECT DeviceObject;
//
// Points to the port device object that this class device is
// connected to.
//
PDEVICE_OBJECT PortDeviceObject;
//
// Keep a reference to the port device.
//
PFILE_OBJECT PortDeviceFileObject;
//
// Queue of irps waiting to be processed.
//
LIST_ENTRY WorkQueue;
//
// Handle of the thread doing all the real work.
//
PVOID ThreadObjectPointer;
KSEMAPHORE RequestSemaphore;
//
// Pointer to the current irp that the thread is working on.
//
PIRP CurrentOpIrp;
//
// This holds the current value to initialize a countdown
// to when an operation starts.
//
ULONG TimerStart;
//
// This holds the result of the get parallel port info
// request to the port driver.
//
PHYSICAL_ADDRESS OriginalController;
PUCHAR Controller;
ULONG SpanOfController;
PPARALLEL_FREE_ROUTINE FreePort;
PPARALLEL_QUERY_WAITERS_ROUTINE QueryNumWaiters;
PVOID PortContext;
//
// This parameter specifies the number of microseconds to
// wait after strobing a byte before checking the BUSY line.
//
ULONG BusyDelay;
//
// Indicates if the BusyDelay parameter has been computed yet.
//
BOOLEAN BusyDelayDetermined;
//
// This specifies whether or not to use processor independant
// write loop.
//
BOOLEAN UsePIWriteLoop;
//
// Set to false whenever we think that the device needs to be
// initilized.
//
BOOLEAN Initialized;
//
// Set to true before the deferred initialization routine is run
// and false once it has completed. Used to synchronize the deferred
// initialization worker thread and the parallel port thread
//
BOOLEAN Initializing;
//
// Holds the work item used to defer printer initialization
//
PWORK_QUEUE_ITEM DeferredWorkItem;
BOOLEAN TimeToTerminateThread;
//
// Records whether we actually created the symbolic link name
// at driver load time. If we didn't create it, we won't try
// to distroy it when we unload.
//
BOOLEAN CreatedSymbolicLink;
//
// This points to the symbolic link name that was
// linked to the actual nt device name.
//
UNICODE_STRING SymbolicLinkName;
//
// If the registry entry by the same name is set, run the parallel
// thread at the priority we used for NT 3.5 - this solves some
// cases where a dos app spinning for input in the foreground is
// starving the parallel thread
//
BOOLEAN UseNT35Priority;
//
// Seconds to wait for the device to respond to an initialization request.
// Note that if no printer is attached, we will spin for the maximum amount
// of time.
// Default is 15 seconds - value is overridden by registry entry of the
// same name.
//
ULONG InitializationTimeout;
//
// Miscelaneous contstants that are cheaper to put here than
// to put them in bss.
//
LARGE_INTEGER AbsoluteOneSecond;
LARGE_INTEGER OneSecond;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//
// Bit Definitions in the status register.
//
#define PAR_STATUS_NOT_ERROR 0x08 //not error on device
#define PAR_STATUS_SLCT 0x10 //device is selected (on-line)
#define PAR_STATUS_PE 0x20 //paper empty
#define PAR_STATUS_NOT_ACK 0x40 //not acknowledge (data transfer was not ok)
#define PAR_STATUS_NOT_BUSY 0x80 //operation in progress
//
// Bit Definitions in the control register.
//
#define PAR_CONTROL_STROBE 0x01 //to read or write data
#define PAR_CONTROL_AUTOFD 0x02 //to autofeed continuous form paper
#define PAR_CONTROL_NOT_INIT 0x04 //begin an initialization routine
#define PAR_CONTROL_SLIN 0x08 //to select the device
#define PAR_CONTROL_IRQ_ENB 0x10 //to enable interrupts
#define PAR_CONTROL_DIR 0x20 //direction = read
#define PAR_CONTROL_WR_CONTROL 0xc0 //the 2 highest bits of the control
// register must be 1
//
// More bit definitions.
//
#define DATA_OFFSET 0
#define DSR_OFFSET 1
#define DCR_OFFSET 2
//
// Bit definitions for the DSR.
//
#define DSR_NOT_BUSY 0x80
#define DSR_NOT_ACK 0x40
#define DSR_PERROR 0x20
#define DSR_SELECT 0x10
#define DSR_NOT_FAULT 0x08
//
// More bit definitions for the DSR.
//
#define DSR_NOT_PTR_BUSY 0x80
#define DSR_NOT_PERIPH_ACK 0x80
#define DSR_WAIT 0x80
#define DSR_PTR_CLK 0x40
#define DSR_PERIPH_CLK 0x40
#define DSR_INTR 0x40
#define DSR_ACK_DATA_REQ 0x20
#define DSR_NOT_ACK_REVERSE 0x20
#define DSR_XFLAG 0x10
#define DSR_NOT_DATA_AVAIL 0x08
#define DSR_NOT_PERIPH_REQUEST 0x08
//
// Bit definitions for the DCR.
//
#define DCR_RESERVED 0xC0
#define DCR_DIRECTION 0x20
#define DCR_ACKINT_ENABLED 0x10
#define DCR_SELECT_IN 0x08
#define DCR_NOT_INIT 0x04
#define DCR_AUTOFEED 0x02
#define DCR_STROBE 0x01
//
// More bit definitions for the DCR.
//
#define DCR_NOT_1284_ACTIVE 0x08
#define DCR_ASTRB 0x08
#define DCR_NOT_REVERSE_REQUEST 0x04
#define DCR_NOT_HOST_BUSY 0x02
#define DCR_NOT_HOST_ACK 0x02
#define DCR_DSTRB 0x02
#define DCR_NOT_HOST_CLK 0x01
#define DCR_WRITE 0x01
#define DCR_NEUTRAL (DCR_RESERVED | DCR_SELECT_IN | DCR_NOT_INIT)
//
// not error, not busy, selected.
//
#define PAR_ONLINE(Status) ( \
(Status & PAR_STATUS_NOT_ERROR) && \
(Status & PAR_STATUS_NOT_BUSY) && \
((Status & PAR_STATUS_PE) ^ PAR_STATUS_PE) && \
(Status & PAR_STATUS_SLCT) )
//VOID StoreData(
// IN PUCHAR RegisterBase,
// IN UCHAR DataByte
// )
//Data must be on line before Strobe = 1;
// Strobe = 1, DIR = 0
//Strobe = 0
//
// We change the port direction to output (and make sure stobe is low).
//
// Note that the data must be available at the port for at least
// .5 microseconds before and after you strobe, and that the strobe
// must be active for at least 500 nano seconds. We are going
// to end up stalling for twice as much time as we need to, but, there
// isn't much we can do about that.
//
// We put the data into the port and wait for 1 micro.
// We strobe the line for at least 1 micro
// We lower the strobe and again delay for 1 micro
// We then revert to the original port direction.
//
// Thanks to Olivetti for advice.
//
#define StoreData(RegisterBase,DataByte) \
{ \
PUCHAR _Address = RegisterBase; \
UCHAR _Control; \
_Control = GetControl(_Address); \
ASSERT(!(_Control & PAR_CONTROL_STROBE)); \
StoreControl( \
_Address, \
(UCHAR)(_Control & ~(PAR_CONTROL_STROBE | PAR_CONTROL_DIR)) \
); \
WRITE_PORT_UCHAR( \
_Address+PARALLEL_DATA_OFFSET, \
(UCHAR)DataByte \
); \
KeStallExecutionProcessor((ULONG)1); \
StoreControl( \
_Address, \
(UCHAR)((_Control | PAR_CONTROL_STROBE) & ~PAR_CONTROL_DIR) \
); \
KeStallExecutionProcessor((ULONG)1); \
StoreControl( \
_Address, \
(UCHAR)(_Control & ~(PAR_CONTROL_STROBE | PAR_CONTROL_DIR)) \
); \
KeStallExecutionProcessor((ULONG)1); \
StoreControl( \
_Address, \
(UCHAR)_Control \
); \
}
//UCHAR
//GetControl(
// IN PUCHAR RegisterBase
// )
#define GetControl(RegisterBase) \
(READ_PORT_UCHAR((RegisterBase)+PARALLEL_CONTROL_OFFSET))
//VOID
//StoreControl(
// IN PUCHAR RegisterBase,
// IN UCHAR ControlByte
// )
#define StoreControl(RegisterBase,ControlByte) \
{ \
WRITE_PORT_UCHAR( \
(RegisterBase)+PARALLEL_CONTROL_OFFSET, \
(UCHAR)ControlByte \
); \
}
//UCHAR
//GetStatus(
// IN PUCHAR RegisterBase
// )
#define GetStatus(RegisterBase) \
(READ_PORT_UCHAR((RegisterBase)+PARALLEL_STATUS_OFFSET))
ULONG
ParWriteLoop(
IN PUCHAR Controller,
IN PUCHAR WriteBuffer,
IN ULONG NumBytesToWrite
);
ULONG
ParWriteLoopPI(
IN PUCHAR Controller,
IN PUCHAR WriteBuffer,
IN ULONG NumBytesToWrite,
IN ULONG BusyDelay
);
NTSTATUS
ParCreateOpen(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ParClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ParCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ParReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ParDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ParQueryInformationFile(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
ParSetInformationFile(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
ParUnload(
IN PDRIVER_OBJECT DriverObject
);