|
|
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 PARTIMEOUT ((ULONG)0x00000008)
25: #define PARSTART ((ULONG)0x00000010)
26: #define PARISR ((ULONG)0x00000020)
27: #define PARDPC ((ULONG)0x00000040)
28: #define PARCRIT ((ULONG)0x00000080)
29: #define PARBUSYPATH ((ULONG)0x00000100)
30: #define PARIRPCOMPLETE ((ULONG)0x00000200)
31: #define PARDISPATCH ((ULONG)0x00000400)
32: #define PARISRACTION ((ULONG)0x00000800)
33: #define PARPOLLREPORT ((ULONG)0x00001000)
34: #define PARERRORS ((ULONG)0x40000000)
35: #define PARBUGCHECK ((ULONG)0x80000000)
36: extern ULONG ParDebugLevel;
37: #define ParDump(LEVEL,STRING) \
38: do { \
39: ULONG _level = (LEVEL); \
40: if (ParDebugLevel & _level) { \
41: DbgPrint STRING; \
42: } \
43: if (_level == PARBUGCHECK) { \
44: ASSERT(FALSE); \
45: } \
46: } while (0)
47: #else
48: #define ParDump(LEVEL,STRING) do {NOTHING;} while (0)
49: #endif
50:
51: //
52: // This define gives the default Object directory
53: // that we should use to insert the symbolic links
54: // between the NT device name and namespace used by
55: // that object directory.
56: #define DEFAULT_DIRECTORY L"DosDevices"
57:
58: //
59: // For the above directory, the serial port will
60: // use the following name as the suffix of the serial
61: // ports for that directory. It will also append
62: // a number onto the end of the name. That number
63: // will start at 1.
64: #define DEFAULT_PARALLEL_NAME L"LPT"
65: //
66: //
67: // This define gives the default NT name for
68: // for serial ports detected by the firmware.
69: // This name will be appended to Device prefix
70: // with a number following it. The number is
71: // incremented each time encounter a serial
72: // port detected by the firmware. Note that
73: // on a system with multiple busses, this means
74: // that the first port on a bus is not necessarily
75: // \Device\Parallel0.
76: //
77: #define DEFAULT_NT_SUFFIX L"Parallel"
78:
79:
80: //
81: // Defines the number of interrupts it takes for us to decide that
82: // we have an interrupt storm on machine
83: //
84: #define PARALLEL_STORM_WATCH 500
85:
86: #define PARALLEL_DATA_OFFSET 0
87: #define PARALLEL_STATUS_OFFSET 1
88: #define PARALLEL_CONTROL_OFFSET 2
89: #define PARALLEL_REGISTER_SPAN 3
90:
91: typedef struct _CONFIG_DATA {
92: //
93: // This list entry is used to link all of the "valid"
94: // configuration entries together.
95: //
96: LIST_ENTRY ConfigList;
97:
98: //
99: // The nt object directory into which to place the symbolic
100: // link to this port.
101: //
102: UNICODE_STRING ObjectDirectory;
103:
104: //
105: // The suffix to be used in the nt device name space for this
106: // port.
107: //
108: UNICODE_STRING NtNameForPort;
109:
110: //
111: // The name to be symbolic linked to the nt name.
112: //
113: UNICODE_STRING SymbolicLinkName;
114:
115: //
116: // The base address of the registry set for this device.
117: //
118: PHYSICAL_ADDRESS Controller;
119:
120: //
121: // The number of contiguous bytes take up by the register
122: // set for the device.
123: //
124: ULONG SpanOfController;
125:
126: //
127: // The bus number (with respect to the bus type) of the bus
128: // that this device occupies.
129: //
130: ULONG BusNumber;
131:
132: //
133: // Denotes whether this devices physical addresses live in io space
134: // or memory space.
135: //
136: ULONG AddressSpace;
137:
138: //
139: // Denotes whether this device is latched or level sensitive.
140: //
141: KINTERRUPT_MODE InterruptMode;
142:
143: //
144: // The kind of bus that this device lives on (e.g. Isa, Eisa, MCA, etc)
145: //
146: INTERFACE_TYPE InterfaceType;
147:
148: //
149: // The originalirql is what is optained from the firmware data. The level
150: // is also obtained from the firmware data. When we get a configuration
151: // record based on the services portion of the registry we will always set
152: // the vector equal to the irql unless overridden by user input.
153: //
154: ULONG OriginalVector;
155: ULONG OriginalIrql;
156:
157: //
158: // Denotes whether the device should be disabled after it has been
159: // initialized.
160: //
161: ULONG DisablePort;
162:
163: } CONFIG_DATA,*PCONFIG_DATA;
164:
165: typedef enum _PAR_COMMAND {
166: ParWrite,
167: ParSetInformation,
168: ParQueryInformation
169: } PAR_COMMAND, *PPAR_COMMAND;
170:
171: typedef struct _PAR_DEVICE_EXTENSION {
172:
173: //
174: // For reporting resource usage, we keep around the physical
175: // address we got from the registry.
176: //
177: PHYSICAL_ADDRESS OriginalController;
178:
179: //
180: // We keep a pointer around to our device name for dumps
181: // and for creating "external" symbolic links to this
182: // device.
183: //
184: UNICODE_STRING DeviceName;
185:
186: //
187: // This points to the object directory that we will place
188: // a symbolic link to our device name.
189: //
190: UNICODE_STRING ObjectDirectory;
191:
192: //
193: // This points to the device name for this device
194: // sans device prefix.
195: //
196: UNICODE_STRING NtNameForPort;
197:
198: //
199: // This points to the symbolic link name that will be
200: // linked to the actual nt device name.
201: //
202: UNICODE_STRING SymbolicLinkName;
203:
204: //
205: // Points to the device object that contains
206: // this device extension.
207: //
208: PDEVICE_OBJECT DeviceObject;
209:
210: //
211: // For value -1 when the interval timer maintained by the IO system
212: // fires, it implies that the timer routine is to do nothing.
213: //
214: // For value 0, then the timer routine should timeout the particular
215: // operation.
216: //
217: // For values > 0 then the timer should do nothing other then synchronize
218: // with the isr and decrement this value by 1.
219: //
220: LONG TimerCount;
221:
222: //
223: // This holds the current value to initialize TimerCount
224: // to when an operation starts.
225: //
226: ULONG TimerStart;
227:
228: //
229: // Unexpected interrupts are counted here. It is cleared
230: // every second by the timer management routine. On
231: // a device that is being interrupt driven, if the unexpected
232: // interrupt count exceeds a threshold, the interrupts will
233: // be disabled on the device and the device will go to polled
234: // mode.
235: //
236: ULONG UnexpectedCount;
237:
238: //
239: // The base address for the set of device registers
240: // of the port.
241: //
242: PUCHAR Controller;
243:
244: //
245: // Points to the interrupt object used by this device.
246: //
247: PKINTERRUPT Interrupt;
248:
249: //
250: // This value holds the span (in units of bytes) of the register
251: // set controlling this port. This is constant over the life
252: // of the port.
253: //
254: ULONG SpanOfController;
255:
256: //
257: // Set at intialization to indicate that on the current
258: // architecture we need to unmap the base register address
259: // when we unload the driver.
260: //
261: BOOLEAN UnMapRegisters;
262:
263: //
264: // These two variables denote the "staging" of initializing the
265: // device. Some devices won't respond with an interrupt when
266: // initializing. When we start initializing, we set the Initializing
267: // variable to TRUE and the Initialized flag to FALES.
268: //
269: // Whenever we go an access the hardware we check the initializing flag.
270: // If it is true, then we check the "status" of the device, and if the
271: // everything is ok, set initializing to FALSE and Initialized to TRUE.
272: // If the "status" of the device is not "good", then we process it as an
273: // error, and return the error indication to the caller.
274: //
275: BOOLEAN Initialized;
276: BOOLEAN Initializing;
277:
278: //
279: // This denotes the number of characters left in the current write.
280: //
281: ULONG CountBuffer;
282:
283: BOOLEAN AutoFeed;
284: BOOLEAN CompletingIoControl;
285:
286: //
287: // Records whether we actually created the symbolic link name
288: // at driver load time. If we didn't create it, we won't try
289: // to distroy it when we unload.
290: //
291: BOOLEAN CreatedSymbolicLink;
292:
293: //
294: // This field will denote that the driver is using a timer instead of
295: // interrupts to "schedule" work out to the device.
296: //
297: BOOLEAN UsingATimer;
298:
299: PAR_COMMAND Command;
300:
301: //
302: // Says whether this device can share interrupts with devices
303: // other than parallel devices.
304: //
305: BOOLEAN InterruptShareable;
306:
307: //
308: // Denotes to the timer routine whether it should log an error
309: // because we were blasted by to many interrupts.
310: //
311: BOOLEAN StormKnocksOutInterrupts;
312:
313: //
314: // We keep the following values around so that we can connect
315: // to the interrupt and report resources after the configuration
316: // record is gone.
317: //
318: //
319: // The following two values are obtained from HalGetInterruptVector
320: //
321: ULONG Vector;
322: KIRQL Irql;
323:
324: //
325: // The following two values are what is obtained (or deduced) from either
326: // the firmware created portion of the registry, or the user data.
327: //
328: ULONG OriginalVector;
329: ULONG OriginalIrql;
330:
331: //
332: // This is either what is deduced from the particular bus this port is
333: // on, or overridden by what the user placed in the registry.
334: //
335: KINTERRUPT_MODE InterruptMode;
336:
337: //
338: // Give back by HalGetInterruptVector. This says what processors this
339: // device can interrupt to.
340: //
341: KAFFINITY ProcessorAffinity;
342:
343: //
344: // The next three are supplied by the firmware or overridden by the user.
345: //
346: ULONG AddressSpace;
347: ULONG BusNumber;
348: INTERFACE_TYPE InterfaceType;
349:
350: //
351: // All irps go through the start io routine. Whenver
352: // we start out a new irp we increment this value. This
353: // is how we can have a unique irp value to give if we
354: // need to log an error during the processing of a particular
355: // irp.
356: //
357: ULONG IrpSequence;
358:
359: //
360: // This spinlock is used to synchronize access to the hardware
361: // when the port is being driver off of a timer, rather than
362: // when using interrupts.
363: //
364: KSPIN_LOCK PollingLock;
365:
366: //
367: // We use a timer so that we can try to do a bunch of
368: // operations, then give the rest of the system time
369: // to run
370: //
371: KTIMER PollingTimer;
372:
373: //
374: // This dpc is queued when the polling timer expires, and it is
375: // also queued after we start a write operations.
376: //
377: KDPC PollingDpc;
378:
379: //
380: // This is the length of time the timer will spend in the
381: // timer queue.
382: //
383: LARGE_INTEGER PollingDelayAmount;
384:
385: //
386: // This timer is used for polling the busy bit.
387: //
388: KTIMER BusyTimer;
389:
390: //
391: // This dpc is queued from the isr to start the above timer.
392: //
393: KDPC StartBusyTimerDpc;
394:
395: //
396: // This is the dpc queued when the above timer fires.
397: //
398: KDPC BusyTimerDpc;
399:
400: //
401: // This holds the delta time fed to above timer.
402: //
403: LARGE_INTEGER BusyDelayAmount;
404:
405: //
406: // We keep this boolean around to tell use that we've started off
407: // the busy "path of execution". If this variable is true when
408: // the isr would start off the busy path, it won't start it. If
409: // it is false, we set it to true and start the path. It is not
410: // set back to false until just before the path calls back the
411: // isr.
412: //
413: BOOLEAN BusyPath;
414: } PAR_DEVICE_EXTENSION, *PPAR_DEVICE_EXTENSION;
415:
416: //
417: // Bit Definitions in the status register.
418: //
419:
420: #define PAR_STATUS_NOT_ERROR 0x08 //not error on device
421: #define PAR_STATUS_SLCT 0x10 //device is selected (on-line)
422: #define PAR_STATUS_PE 0x20 //paper empty
423: #define PAR_STATUS_NOT_ACK 0x40 //not acknowledge (data transfer was not ok)
424: #define PAR_STATUS_NOT_BUSY 0x80 //operation in progress
425:
426: //
427: // Bit Definitions in the control register.
428: //
429:
430: #define PAR_CONTROL_STROBE 0x01 //to read or write data
431: #define PAR_CONTROL_AUTOFD 0x02 //to autofeed continuous form paper
432: #define PAR_CONTROL_NOT_INIT 0x04 //begin an initialization routine
433: #define PAR_CONTROL_SLIN 0x08 //to select the device
434: #define PAR_CONTROL_IRQ_ENB 0x10 //to enable interrupts
435: #define PAR_CONTROL_DIR 0x20 //direction = read
436: #define PAR_CONTROL_WR_CONTROL 0xc0 //the 2 highest bits of the control
437: // register must be 1
438:
439: //VOID StoreData(
440: // IN PUCHAR RegisterBase,
441: // IN UCHAR DataByte
442: // )
443: //Data must be on line before Strobe = 1;
444: // Strobe = 1, DIR = 0
445: //Strobe = 0
446: //
447: // We change the port direction to output (and make sure stobe is low).
448: //
449: // Note that the data must be available at the port for at least
450: // .5 microseconds before and after you strobe, and that the strobe
451: // must be active for at least 500 nano seconds. We are going
452: // to end up stalling for twice as much time as we need to, but, there
453: // isn't much we can do about that.
454: //
455: // We put the data into the port and wait for 1 micro.
456: // We strobe the line for at least 1 micro
457: // We lower the strobe and again delay for 1 micro
458: // We then revert to the original port direction.
459: //
460: // Thanks to Olivetti for advice.
461: //
462:
463: #define StoreData(RegisterBase,DataByte) \
464: { \
465: PUCHAR _Address = RegisterBase; \
466: UCHAR _Control; \
467: _Control = GetControl(_Address); \
468: ASSERT(!(_Control & PAR_CONTROL_STROBE)); \
469: StoreControl( \
470: _Address, \
471: (UCHAR)(_Control & ~(PAR_CONTROL_STROBE | PAR_CONTROL_DIR)) \
472: ); \
473: WRITE_PORT_UCHAR( \
474: _Address+PARALLEL_DATA_OFFSET, \
475: (UCHAR)DataByte \
476: ); \
477: KeStallExecutionProcessor((ULONG)1); \
478: StoreControl( \
479: _Address, \
480: (UCHAR)((_Control | PAR_CONTROL_STROBE) & ~PAR_CONTROL_DIR) \
481: ); \
482: KeStallExecutionProcessor((ULONG)1); \
483: StoreControl( \
484: _Address, \
485: (UCHAR)(_Control & ~(PAR_CONTROL_STROBE | PAR_CONTROL_DIR)) \
486: ); \
487: KeStallExecutionProcessor((ULONG)1); \
488: StoreControl( \
489: _Address, \
490: (UCHAR)_Control \
491: ); \
492: }
493:
494: //UCHAR
495: //GetControl(
496: // IN PUCHAR RegisterBase
497: // )
498: #define GetControl(RegisterBase) \
499: (READ_PORT_UCHAR((RegisterBase)+PARALLEL_CONTROL_OFFSET))
500:
501:
502: //VOID
503: //StoreControl(
504: // IN PUCHAR RegisterBase,
505: // IN UCHAR ControlByte
506: // )
507: #define StoreControl(RegisterBase,ControlByte) \
508: { \
509: WRITE_PORT_UCHAR( \
510: (RegisterBase)+PARALLEL_CONTROL_OFFSET, \
511: (UCHAR)ControlByte \
512: ); \
513: }
514:
515:
516: //UCHAR
517: //GetStatus(
518: // IN PUCHAR RegisterBase
519: // )
520:
521: #define GetStatus(RegisterBase) \
522: (READ_PORT_UCHAR((RegisterBase)+PARALLEL_STATUS_OFFSET))
523:
524: typedef enum _PAR_ERROR_TYPE {
525: PoweredOff,
526: NotConnected,
527: Offline,
528: PaperEmpty,
529: PowerFailure,
530: DataError,
531: Busy
532: } PAR_ERROR_TYPE, *PPAR_ERROR_TYPE;
533:
534: BOOLEAN
535: ParInitializeDevice(
536: IN PVOID Context
537: );
538:
539: NTSTATUS
540: ParDispatch(
541: IN PDEVICE_OBJECT DeviceObject,
542: IN PIRP Irp
543: );
544:
545: NTSTATUS
546: ParSetInformationFile(
547: IN PDEVICE_OBJECT DeviceObject,
548: IN PIRP Irp
549: );
550:
551: NTSTATUS
552: ParQueryInformationFile(
553: IN PDEVICE_OBJECT DeviceObject,
554: IN PIRP Irp
555: );
556:
557: VOID
558: ParDpcRoutine(
559: IN PKDPC Dpc,
560: IN PDEVICE_OBJECT DeviceObject,
561: IN PIRP Irp,
562: IN PVOID Context
563: );
564:
565: VOID
566: ParTimerRoutine(
567: PDEVICE_OBJECT DeviceObject,
568: IN PVOID Context
569: );
570:
571: BOOLEAN
572: ParManageTimeOut(
573: IN PVOID Context
574: );
575:
576: BOOLEAN
577: ParInterruptServiceRoutine(
578: IN PKINTERRUPT InterruptObject,
579: IN PVOID Context
580: );
581:
582: BOOLEAN
583: ParInitiateIo(
584: IN PDEVICE_OBJECT DeviceObject
585: );
586:
587: VOID
588: ParStartIo(
589: IN PDEVICE_OBJECT DeviceObject,
590: IN PIRP Irp
591: );
592:
593: VOID
594: ParUnload(
595: IN PDRIVER_OBJECT DriverObject
596: );
597:
598: VOID
599: ParCancelRequest(
600: IN PDEVICE_OBJECT DeviceObject,
601: IN PIRP Irp
602: );
603:
604: BOOLEAN
605: ParSynchronizeExecution(
606: IN PPAR_DEVICE_EXTENSION Extension,
607: IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
608: IN PVOID SynchronizeContext
609: );
610:
611: VOID
612: ParPollingDpcRoutine(
613: IN PKDPC Dpc,
614: IN PVOID DeferredContext,
615: IN PVOID SystemContext1,
616: IN PVOID SystemContext2
617: );
618:
619: BOOLEAN
620: ParPolling(
621: IN PVOID Context
622: );
623:
624: VOID
625: ParLogError(
626: IN PDRIVER_OBJECT DriverObject,
627: IN PDEVICE_OBJECT DeviceObject OPTIONAL,
628: IN PHYSICAL_ADDRESS P1,
629: IN PHYSICAL_ADDRESS P2,
630: IN ULONG SequenceNumber,
631: IN UCHAR MajorFunctionCode,
632: IN UCHAR RetryCount,
633: IN ULONG UniqueErrorValue,
634: IN NTSTATUS FinalStatus,
635: IN NTSTATUS SpecificIOStatus
636: );
637:
638: VOID
639: ParStartBusyTimer(
640: IN PKDPC Dpc,
641: IN PVOID DeferredContext,
642: IN PVOID SystemContext1,
643: IN PVOID SystemContext2
644: );
645:
646: VOID
647: ParBusyTimer(
648: IN PKDPC Dpc,
649: IN PVOID DeferredContext,
650: IN PVOID SystemContext1,
651: IN PVOID SystemContext2
652: );
653:
654: BOOLEAN
655: ParBusyCallIsr(
656: IN PVOID Context
657: );
658:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.