Annotation of ntddk/src/comm/oldpar/par.h, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.