|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1990, 1991 Microsoft Corporation
4:
5: Module Name :
6:
7: par.h
8:
9: Abstract:
10:
11: Type definitions and data for the parallel port driver
12:
13: Author:
14:
15:
16: Revision History:
17: --*/
18:
19:
20: #if DBG
21: #define PARCONFIG ((ULONG)0x00000001)
22: #define PARUNLOAD ((ULONG)0x00000002)
23: #define PARINITDEV ((ULONG)0x00000004)
24: #define PARIRPPATH ((ULONG)0x00000008)
25: #define PARSTARTER ((ULONG)0x00000010)
26: #define PARPUSHER ((ULONG)0x00000020)
27: #define PARERRORS ((ULONG)0x00000040)
28: #define PARTHREAD ((ULONG)0x00000080)
29:
30: extern ULONG ParDebugLevel;
31: #define ParDump(LEVEL,STRING) \
32: do { \
33: ULONG _level = (LEVEL); \
34: if (ParDebugLevel & _level) { \
35: DbgPrint STRING; \
36: } \
37: } while (0)
38: #else
39: #define ParDump(LEVEL,STRING) do {NOTHING;} while (0)
40: #endif
41:
42: //
43: // This define gives the default Object directory
44: // that we should use to insert the symbolic links
45: // between the NT device name and namespace used by
46: // that object directory.
47: #define DEFAULT_DIRECTORY L"DosDevices"
48:
49: //
50: // For the above directory, the serial port will
51: // use the following name as the suffix of the serial
52: // ports for that directory. It will also append
53: // a number onto the end of the name. That number
54: // will start at 1.
55: #define DEFAULT_PARALLEL_NAME L"LPT"
56: //
57: //
58: // This define gives the default NT name for
59: // for serial ports detected by the firmware.
60: // This name will be appended to Device prefix
61: // with a number following it. The number is
62: // incremented each time encounter a serial
63: // port detected by the firmware. Note that
64: // on a system with multiple busses, this means
65: // that the first port on a bus is not necessarily
66: // \Device\Parallel0.
67: //
68: #define DEFAULT_NT_SUFFIX L"Parallel"
69:
70:
71: //
72: // Defines the number of interrupts it takes for us to decide that
73: // we have an interrupt storm on machine
74: //
75: #define PARALLEL_STORM_WATCH 500
76:
77: #define PARALLEL_DATA_OFFSET 0
78: #define PARALLEL_STATUS_OFFSET 1
79: #define PARALLEL_CONTROL_OFFSET 2
80: #define PARALLEL_REGISTER_SPAN 3
81:
82: typedef struct _CONFIG_DATA {
83: //
84: // This list entry is used to link all of the "valid"
85: // configuration entries together.
86: //
87: LIST_ENTRY ConfigList;
88:
89: //
90: // The nt object directory into which to place the symbolic
91: // link to this port.
92: //
93: UNICODE_STRING ObjectDirectory;
94:
95: //
96: // The suffix to be used in the nt device name space for this
97: // port.
98: //
99: UNICODE_STRING NtNameForPort;
100:
101: //
102: // The name to be symbolic linked to the nt name.
103: //
104: UNICODE_STRING SymbolicLinkName;
105:
106: //
107: // The base address of the registry set for this device.
108: //
109: PHYSICAL_ADDRESS Controller;
110:
111: //
112: // The number of contiguous bytes take up by the register
113: // set for the device.
114: //
115: ULONG SpanOfController;
116:
117: //
118: // The bus number (with respect to the bus type) of the bus
119: // that this device occupies.
120: //
121: ULONG BusNumber;
122:
123: //
124: // Denotes whether this devices physical addresses live in io space
125: // or memory space.
126: //
127: ULONG AddressSpace;
128:
129: //
130: // Denotes whether this device is latched or level sensitive.
131: //
132: KINTERRUPT_MODE InterruptMode;
133:
134: //
135: // The kind of bus that this device lives on (e.g. Isa, Eisa, MCA, etc)
136: //
137: INTERFACE_TYPE InterfaceType;
138:
139: //
140: // The originalirql is what is optained from the firmware data. The level
141: // is also obtained from the firmware data. When we get a configuration
142: // record based on the services portion of the registry we will always set
143: // the vector equal to the irql unless overridden by user input.
144: //
145: ULONG OriginalVector;
146: ULONG OriginalIrql;
147:
148: //
149: // Denotes whether the device should be disabled after it has been
150: // initialized.
151: //
152: ULONG DisablePort;
153:
154: } CONFIG_DATA,*PCONFIG_DATA;
155:
156: typedef struct _PAR_DEVICE_EXTENSION {
157:
158: //
159: // Queue of irps waiting to be processes.
160: //
161: LIST_ENTRY WorkQueue;
162:
163: //
164: // For reporting resource usage, we keep around the physical
165: // address we got from the registry.
166: //
167: PHYSICAL_ADDRESS OriginalController;
168:
169: //
170: // Pointer to the current irp that the thread is working on.
171: //
172: PIRP CurrentOpIrp;
173:
174: //
175: // We keep a pointer around to our device name for dumps
176: // and for creating "external" symbolic links to this
177: // device.
178: //
179: UNICODE_STRING DeviceName;
180:
181: //
182: // This points to the object directory that we will place
183: // a symbolic link to our device name.
184: //
185: UNICODE_STRING ObjectDirectory;
186:
187: //
188: // This points to the device name for this device
189: // sans device prefix.
190: //
191: UNICODE_STRING NtNameForPort;
192:
193: //
194: // This points to the symbolic link name that will be
195: // linked to the actual nt device name.
196: //
197: UNICODE_STRING SymbolicLinkName;
198:
199: //
200: // Points to the device object that contains
201: // this device extension.
202: //
203: PDEVICE_OBJECT DeviceObject;
204:
205: //
206: // This holds the current value to initialie a countdown
207: // to when an operation starts.
208: //
209: ULONG TimerStart;
210:
211: //
212: // The base address for the set of device registers
213: // of the port.
214: //
215: PUCHAR Controller;
216:
217: //
218: // This value holds the span (in units of bytes) of the register
219: // set controlling this port. This is constant over the life
220: // of the port.
221: //
222: ULONG SpanOfController;
223:
224: //
225: // Set at intialization to indicate that on the current
226: // architecture we need to unmap the base register address
227: // when we unload the driver.
228: //
229: BOOLEAN UnMapRegisters;
230:
231: //
232: // Set to false whenever we think that the device needs to be
233: // initilized.
234: //
235: BOOLEAN Initialized;
236:
237: BOOLEAN AutoFeed;
238:
239: BOOLEAN TimeToTerminateThread;
240:
241: //
242: // Records whether we actually created the symbolic link name
243: // at driver load time. If we didn't create it, we won't try
244: // to distroy it when we unload.
245: //
246: BOOLEAN CreatedSymbolicLink;
247:
248: //
249: // Says whether this device can share interrupts with devices
250: // other than parallel devices.
251: //
252: BOOLEAN InterruptShareable;
253:
254: //
255: // We keep the following values around so that we can connect
256: // to the interrupt and report resources after the configuration
257: // record is gone.
258: //
259: //
260: // The following two values are obtained from HalGetInterruptVector
261: //
262: ULONG Vector;
263: KIRQL Irql;
264:
265: //
266: // The following two values are what is obtained (or deduced) from either
267: // the firmware created portion of the registry, or the user data.
268: //
269: ULONG OriginalVector;
270: ULONG OriginalIrql;
271:
272: //
273: // This is either what is deduced from the particular bus this port is
274: // on, or overridden by what the user placed in the registry.
275: //
276: KINTERRUPT_MODE InterruptMode;
277:
278: //
279: // Give back by HalGetInterruptVector. This says what processors this
280: // device can interrupt to.
281: //
282: KAFFINITY ProcessorAffinity;
283:
284: //
285: // The next three are supplied by the firmware or overridden by the user.
286: //
287: ULONG AddressSpace;
288: ULONG BusNumber;
289: INTERFACE_TYPE InterfaceType;
290:
291: //
292: // Handle of the thread doing all the real work.
293: //
294: PVOID ThreadObjectPointer;
295:
296: KSEMAPHORE RequestSemaphore;
297:
298: //
299: // One second expressed in system time units.
300: //
301: LARGE_INTEGER AbsoluteOneSecond;
302:
303: //
304: // One delta second expressed in system time units.
305: //
306: LARGE_INTEGER OneSecond;
307: } PAR_DEVICE_EXTENSION, *PPAR_DEVICE_EXTENSION;
308:
309: //
310: // Bit Definitions in the status register.
311: //
312:
313: #define PAR_STATUS_NOT_ERROR 0x08 //not error on device
314: #define PAR_STATUS_SLCT 0x10 //device is selected (on-line)
315: #define PAR_STATUS_PE 0x20 //paper empty
316: #define PAR_STATUS_NOT_ACK 0x40 //not acknowledge (data transfer was not ok)
317: #define PAR_STATUS_NOT_BUSY 0x80 //operation in progress
318:
319: //
320: // Bit Definitions in the control register.
321: //
322:
323: #define PAR_CONTROL_STROBE 0x01 //to read or write data
324: #define PAR_CONTROL_AUTOFD 0x02 //to autofeed continuous form paper
325: #define PAR_CONTROL_NOT_INIT 0x04 //begin an initialization routine
326: #define PAR_CONTROL_SLIN 0x08 //to select the device
327: #define PAR_CONTROL_IRQ_ENB 0x10 //to enable interrupts
328: #define PAR_CONTROL_DIR 0x20 //direction = read
329: #define PAR_CONTROL_WR_CONTROL 0xc0 //the 2 highest bits of the control
330: // register must be 1
331:
332: //VOID StoreData(
333: // IN PUCHAR RegisterBase,
334: // IN UCHAR DataByte
335: // )
336: //Data must be on line before Strobe = 1;
337: // Strobe = 1, DIR = 0
338: //Strobe = 0
339: //
340: // We change the port direction to output (and make sure stobe is low).
341: //
342: // Note that the data must be available at the port for at least
343: // .5 microseconds before and after you strobe, and that the strobe
344: // must be active for at least 500 nano seconds. We are going
345: // to end up stalling for twice as much time as we need to, but, there
346: // isn't much we can do about that.
347: //
348: // We put the data into the port and wait for 1 micro.
349: // We strobe the line for at least 1 micro
350: // We lower the strobe and again delay for 1 micro
351: // We then revert to the original port direction.
352: //
353: // Thanks to Olivetti for advice.
354: //
355:
356: #define StoreData(RegisterBase,DataByte) \
357: { \
358: PUCHAR _Address = RegisterBase; \
359: UCHAR _Control; \
360: _Control = GetControl(_Address); \
361: ASSERT(!(_Control & PAR_CONTROL_STROBE)); \
362: StoreControl( \
363: _Address, \
364: (UCHAR)(_Control & ~(PAR_CONTROL_STROBE | PAR_CONTROL_DIR)) \
365: ); \
366: WRITE_PORT_UCHAR( \
367: _Address+PARALLEL_DATA_OFFSET, \
368: (UCHAR)DataByte \
369: ); \
370: KeStallExecutionProcessor((ULONG)1); \
371: StoreControl( \
372: _Address, \
373: (UCHAR)((_Control | PAR_CONTROL_STROBE) & ~PAR_CONTROL_DIR) \
374: ); \
375: KeStallExecutionProcessor((ULONG)1); \
376: StoreControl( \
377: _Address, \
378: (UCHAR)(_Control & ~(PAR_CONTROL_STROBE | PAR_CONTROL_DIR)) \
379: ); \
380: KeStallExecutionProcessor((ULONG)1); \
381: StoreControl( \
382: _Address, \
383: (UCHAR)_Control \
384: ); \
385: }
386:
387: //UCHAR
388: //GetControl(
389: // IN PUCHAR RegisterBase
390: // )
391: #define GetControl(RegisterBase) \
392: (READ_PORT_UCHAR((RegisterBase)+PARALLEL_CONTROL_OFFSET))
393:
394:
395: //VOID
396: //StoreControl(
397: // IN PUCHAR RegisterBase,
398: // IN UCHAR ControlByte
399: // )
400: #define StoreControl(RegisterBase,ControlByte) \
401: { \
402: WRITE_PORT_UCHAR( \
403: (RegisterBase)+PARALLEL_CONTROL_OFFSET, \
404: (UCHAR)ControlByte \
405: ); \
406: }
407:
408:
409: //UCHAR
410: //GetStatus(
411: // IN PUCHAR RegisterBase
412: // )
413:
414: #define GetStatus(RegisterBase) \
415: (READ_PORT_UCHAR((RegisterBase)+PARALLEL_STATUS_OFFSET))
416:
417: UCHAR
418: ParInitializeDevice(
419: IN PPAR_DEVICE_EXTENSION Extension
420: );
421:
422: NTSTATUS
423: ParCreateOpen(
424: IN PDEVICE_OBJECT DeviceObject,
425: IN PIRP Irp
426: );
427:
428: NTSTATUS
429: ParClose(
430: IN PDEVICE_OBJECT DeviceObject,
431: IN PIRP Irp
432: );
433:
434: NTSTATUS
435: ParCleanup(
436: IN PDEVICE_OBJECT DeviceObject,
437: IN PIRP Irp
438: );
439:
440: NTSTATUS
441: ParDispatch(
442: IN PDEVICE_OBJECT DeviceObject,
443: IN PIRP Irp
444: );
445:
446: NTSTATUS
447: ParSetInformationFile(
448: IN PDEVICE_OBJECT DeviceObject,
449: IN PIRP Irp
450: );
451:
452: NTSTATUS
453: ParQueryInformationFile(
454: IN PDEVICE_OBJECT DeviceObject,
455: IN PIRP Irp
456: );
457:
458: VOID
459: ParStartIo(
460: IN PPAR_DEVICE_EXTENSION DeviceObject
461: );
462:
463: VOID
464: ParUnload(
465: IN PDRIVER_OBJECT DriverObject
466: );
467:
468: VOID
469: ParCancelRequest(
470: IN PDEVICE_OBJECT DeviceObject,
471: IN PIRP Irp
472: );
473:
474: VOID
475: ParLogError(
476: IN PDRIVER_OBJECT DriverObject,
477: IN PDEVICE_OBJECT DeviceObject OPTIONAL,
478: IN PHYSICAL_ADDRESS P1,
479: IN PHYSICAL_ADDRESS P2,
480: IN ULONG SequenceNumber,
481: IN UCHAR MajorFunctionCode,
482: IN UCHAR RetryCount,
483: IN ULONG UniqueErrorValue,
484: IN NTSTATUS FinalStatus,
485: IN NTSTATUS SpecificIOStatus
486: );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.