Annotation of ntddk/src/comm/serial/serial.h, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
        !             4: 
        !             5: Module Name :
        !             6:        
        !             7:     serial.h
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     Type definitions and data for the serial port driver
        !            12: 
        !            13: Author:
        !            14: 
        !            15:     Anthony V. Ercolano                 April 8, 1991
        !            16: 
        !            17: Revision History:
        !            18: --*/
        !            19: 
        !            20: 
        !            21: 
        !            22: 
        !            23: #if DBG
        !            24: #define SERDIAG1              ((ULONG)0x00000001)
        !            25: #define SERDIAG2              ((ULONG)0x00000002)
        !            26: #define SERDIAG3              ((ULONG)0x00000004)
        !            27: #define SERDIAG4              ((ULONG)0x00000008)
        !            28: #define SERDIAG5              ((ULONG)0x00000010)
        !            29: #define SERIRPPATH            ((ULONG)0x00000020)
        !            30: #define SERFLOW               ((ULONG)0x20000000)
        !            31: #define SERERRORS             ((ULONG)0x40000000)
        !            32: #define SERBUGCHECK           ((ULONG)0x80000000)
        !            33: extern ULONG SerialDebugLevel;
        !            34: #define SerialDump(LEVEL,STRING) \
        !            35:         do { \
        !            36:             ULONG _level = (LEVEL); \
        !            37:             if (SerialDebugLevel & _level) { \
        !            38:                 DbgPrint STRING; \
        !            39:             } \
        !            40:             if (_level == SERBUGCHECK) { \
        !            41:                 ASSERT(FALSE); \
        !            42:             } \
        !            43:         } while (0)
        !            44: #else
        !            45: #define SerialDump(LEVEL,STRING) do {NOTHING;} while (0)
        !            46: #endif
        !            47: 
        !            48: //
        !            49: // This define gives the default Object directory
        !            50: // that we should use to insert the symbolic links
        !            51: // between the NT device name and namespace used by
        !            52: // that object directory.
        !            53: #define DEFAULT_DIRECTORY L"DosDevices"
        !            54: 
        !            55: //
        !            56: // For the above directory, the serial port will
        !            57: // use the following name as the suffix of the serial
        !            58: // ports for that directory.  It will also append
        !            59: // a number onto the end of the name.  That number
        !            60: // will start at 1.
        !            61: #define DEFAULT_SERIAL_NAME L"COM"
        !            62: //
        !            63: //
        !            64: // This define gives the default NT name for
        !            65: // for serial ports detected by the firmware.
        !            66: // This name will be appended to Device prefix
        !            67: // with a number following it.  The number is
        !            68: // incremented each time encounter a serial
        !            69: // port detected by the firmware.  Note that
        !            70: // on a system with multiple busses, this means
        !            71: // that the first port on a bus is not necessarily
        !            72: // \Device\Serial0.
        !            73: //
        !            74: #define DEFAULT_NT_SUFFIX L"Serial"
        !            75: 
        !            76: //
        !            77: // This value - which could be redefined at compile
        !            78: // time, define the stride between registers
        !            79: //
        !            80: #if !defined(SERIAL_REGISTER_STRIDE)
        !            81: #define SERIAL_REGISTER_STRIDE 1
        !            82: #endif
        !            83: 
        !            84: //
        !            85: // Offsets from the base register address of the
        !            86: // various registers for the 8250 family of UARTS.
        !            87: //
        !            88: #define RECEIVE_BUFFER_REGISTER    ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
        !            89: #define TRANSMIT_HOLDING_REGISTER  ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
        !            90: #define INTERRUPT_ENABLE_REGISTER  ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
        !            91: #define INTERRUPT_IDENT_REGISTER   ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
        !            92: #define FIFO_CONTROL_REGISTER      ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
        !            93: #define LINE_CONTROL_REGISTER      ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE))
        !            94: #define MODEM_CONTROL_REGISTER     ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE))
        !            95: #define LINE_STATUS_REGISTER       ((ULONG)((0x05)*SERIAL_REGISTER_STRIDE))
        !            96: #define MODEM_STATUS_REGISTER      ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE))
        !            97: #define DIVISOR_LATCH_LSB          ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
        !            98: #define DIVISOR_LATCH_MSB          ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
        !            99: #define SERIAL_REGISTER_SPAN       ((ULONG)(7*SERIAL_REGISTER_STRIDE))
        !           100: 
        !           101: //
        !           102: // If we have an interrupt status register this is its assumed
        !           103: // length.
        !           104: //
        !           105: #define SERIAL_STATUS_LENGTH       ((ULONG)(1*SERIAL_REGISTER_STRIDE))
        !           106: 
        !           107: //
        !           108: // Bitmask definitions for accessing the 8250 device registers.
        !           109: //
        !           110: 
        !           111: //
        !           112: // These bits define the number of data bits trasmitted in
        !           113: // the Serial Data Unit (SDU - Start,data, parity, and stop bits)
        !           114: //
        !           115: #define SERIAL_DATA_LENGTH_5 0x00
        !           116: #define SERIAL_DATA_LENGTH_6 0x01
        !           117: #define SERIAL_DATA_LENGTH_7 0x02
        !           118: #define SERIAL_DATA_LENGTH_8 0x03
        !           119: 
        !           120: 
        !           121: //
        !           122: // These masks define the interrupts that can be enabled or disabled.
        !           123: //
        !           124: //
        !           125: // This interrupt is used to notify that there is new incomming
        !           126: // data available.  The SERIAL_RDA interrupt is enabled by this bit.
        !           127: //
        !           128: #define SERIAL_IER_RDA   0x01
        !           129: 
        !           130: //
        !           131: // This interrupt is used to notify that there is space available
        !           132: // in the transmitter for another character.  The SERIAL_THR
        !           133: // interrupt is enabled by this bit.
        !           134: //
        !           135: #define SERIAL_IER_THR   0x02
        !           136: 
        !           137: //
        !           138: // This interrupt is used to notify that some sort of error occured
        !           139: // with the incomming data.  The SERIAL_RLS interrupt is enabled by
        !           140: // this bit.
        !           141: #define SERIAL_IER_RLS   0x04
        !           142: 
        !           143: //
        !           144: // This interrupt is used to notify that some sort of change has
        !           145: // taken place in the modem control line.  The SERIAL_MS interrupt is
        !           146: // enabled by this bit.
        !           147: //
        !           148: #define SERIAL_IER_MS    0x08
        !           149: 
        !           150: 
        !           151: //
        !           152: // These masks define the values of the interrupt identification
        !           153: // register.  The low bit must be clear in the interrupt identification
        !           154: // register for any of these interrupts to be valid.  The interrupts
        !           155: // are defined in priority order, with the highest value being most
        !           156: // important.  See above for a description of what each interrupt
        !           157: // implies.
        !           158: //
        !           159: #define SERIAL_IIR_RLS      0x06
        !           160: #define SERIAL_IIR_RDA      0x04
        !           161: #define SERIAL_IIR_CTI      0x0c
        !           162: #define SERIAL_IIR_THR      0x02
        !           163: #define SERIAL_IIR_MS       0x00
        !           164: 
        !           165: //
        !           166: // This bit mask get the value of the high two bits of the
        !           167: // interrupt id register.  If this is a 16550 class chip
        !           168: // these bits will be a one if the fifo's are enbled, otherwise
        !           169: // they will always be zero.
        !           170: //
        !           171: #define SERIAL_IIR_FIFOS_ENABLED 0xc0
        !           172: 
        !           173: //
        !           174: // If the low bit is logic one in the interrupt identification register
        !           175: // this implies that *NO* interrupts are pending on the device.
        !           176: //
        !           177: #define SERIAL_IIR_NO_INTERRUPT_PENDING 0x01
        !           178: 
        !           179: 
        !           180: 
        !           181: //
        !           182: // These masks define access to the fifo control register.
        !           183: //
        !           184: 
        !           185: //
        !           186: // Enabling this bit in the fifo control register will turn
        !           187: // on the fifos.  If the fifos are enabled then the high two
        !           188: // bits of the interrupt id register will be set to one.  Note
        !           189: // that this only occurs on a 16550 class chip.  If the high
        !           190: // two bits in the interrupt id register are not one then
        !           191: // we know we have a lower model chip.
        !           192: //
        !           193: //
        !           194: #define SERIAL_FCR_ENABLE     ((UCHAR)0x01)
        !           195: #define SERIAL_FCR_RCVR_RESET ((UCHAR)0x02)
        !           196: #define SERIAL_FCR_TXMT_RESET ((UCHAR)0x04)
        !           197: 
        !           198: //
        !           199: // This set of values define the high water marks (when the
        !           200: // interrupts trip) for the receive fifo.
        !           201: //
        !           202: #define SERIAL_1_BYTE_HIGH_WATER   ((UCHAR)0x00)
        !           203: #define SERIAL_4_BYTE_HIGH_WATER   ((UCHAR)0x40)
        !           204: #define SERIAL_8_BYTE_HIGH_WATER   ((UCHAR)0x80)
        !           205: #define SERIAL_14_BYTE_HIGH_WATER  ((UCHAR)0xc0)
        !           206: 
        !           207: //
        !           208: // These masks define access to the line control register.
        !           209: //
        !           210: 
        !           211: //
        !           212: // This defines the bit used to control the definition of the "first"
        !           213: // two registers for the 8250.  These registers are the input/output
        !           214: // register and the interrupt enable register.  When the DLAB bit is
        !           215: // enabled these registers become the least significant and most
        !           216: // significant bytes of the divisor value.
        !           217: //
        !           218: #define SERIAL_LCR_DLAB     0x80
        !           219: 
        !           220: //
        !           221: // This defines the bit used to control whether the device is sending
        !           222: // a break.  When this bit is set the device is sending a space (logic 0).
        !           223: //
        !           224: // Most protocols will assume that this is a hangup.
        !           225: //
        !           226: #define SERIAL_LCR_BREAK    0x40
        !           227: 
        !           228: //
        !           229: // These defines are used to set the line control register.
        !           230: //
        !           231: #define SERIAL_5_DATA       ((UCHAR)0x00)
        !           232: #define SERIAL_6_DATA       ((UCHAR)0x01)
        !           233: #define SERIAL_7_DATA       ((UCHAR)0x02)
        !           234: #define SERIAL_8_DATA       ((UCHAR)0x03)
        !           235: #define SERIAL_DATA_MASK    ((UCHAR)0x03)
        !           236: 
        !           237: #define SERIAL_1_STOP       ((UCHAR)0x00)
        !           238: #define SERIAL_1_5_STOP     ((UCHAR)0x04) // Only valid for 5 data bits
        !           239: #define SERIAL_2_STOP       ((UCHAR)0x04) // Not valid for 5 data bits
        !           240: #define SERIAL_STOP_MASK    ((UCHAR)0x04)
        !           241: 
        !           242: #define SERIAL_NONE_PARITY  ((UCHAR)0x00)
        !           243: #define SERIAL_ODD_PARITY   ((UCHAR)0x08)
        !           244: #define SERIAL_EVEN_PARITY  ((UCHAR)0x18)
        !           245: #define SERIAL_MARK_PARITY  ((UCHAR)0x28)
        !           246: #define SERIAL_SPACE_PARITY ((UCHAR)0x38)
        !           247: #define SERIAL_PARITY_MASK  ((UCHAR)0x38)
        !           248: 
        !           249: //
        !           250: // These masks define access the modem control register.
        !           251: //
        !           252: 
        !           253: //
        !           254: // This bit controls the data terminal ready (DTR) line.  When
        !           255: // this bit is set the line goes to logic 0 (which is then inverted
        !           256: // by normal hardware).  This is normally used to indicate that
        !           257: // the device is available to be used.  Some odd hardware
        !           258: // protocols (like the kernel debugger) use this for handshaking
        !           259: // purposes.
        !           260: //
        !           261: #define SERIAL_MCR_DTR      0x01
        !           262: 
        !           263: //
        !           264: // This bit controls the ready to send (RTS) line.  When this bit
        !           265: // is set the line goes to logic 0 (which is then inverted by the normal
        !           266: // hardware).  This is used for hardware handshaking.  It indicates that
        !           267: // the hardware is ready to send data and it is waiting for the
        !           268: // receiving end to set clear to send (CTS).
        !           269: //
        !           270: #define SERIAL_MCR_RTS      0x02
        !           271: 
        !           272: //
        !           273: // This bit is used for general purpose output.
        !           274: //
        !           275: #define SERIAL_MCR_OUT1     0x04
        !           276: 
        !           277: //
        !           278: // This bit is used for general purpose output.
        !           279: //
        !           280: #define SERIAL_MCR_OUT2     0x08
        !           281: 
        !           282: //
        !           283: // This bit controls the loopback testing mode of the device.  Basically
        !           284: // the outputs are connected to the inputs (and vice versa).
        !           285: //
        !           286: #define SERIAL_MCR_LOOP     0x10
        !           287: 
        !           288: 
        !           289: //
        !           290: // These masks define access to the line status register.  The line
        !           291: // status register contains information about the status of data
        !           292: // transfer.  The first five bits deal with receive data and the
        !           293: // last two bits deal with transmission.  An interrupt is generated
        !           294: // whenever bits 1 through 4 in this register are set.
        !           295: //
        !           296: 
        !           297: //
        !           298: // This bit is the data ready indicator.  It is set to indicate that
        !           299: // a complete character has been received.  This bit is cleared whenever
        !           300: // the receive buffer register has been read.
        !           301: //
        !           302: #define SERIAL_LSR_DR       0x01
        !           303: 
        !           304: //
        !           305: // This is the overrun indicator.  It is set to indicate that the receive
        !           306: // buffer register was not read befor a new character was transferred
        !           307: // into the buffer.  This bit is cleared when this register is read.
        !           308: //
        !           309: #define SERIAL_LSR_OE       0x02
        !           310: 
        !           311: //
        !           312: // This is the parity error indicator.  It is set whenever the hardware
        !           313: // detects that the incoming serial data unit does not have the correct
        !           314: // parity as defined by the parity select in the line control register.
        !           315: // This bit is cleared by reading this register.
        !           316: //
        !           317: #define SERIAL_LSR_PE       0x04
        !           318: 
        !           319: //
        !           320: // This is the framing error indicator.  It is set whenever the hardware
        !           321: // detects that the incoming serial data unit does not have a valid
        !           322: // stop bit.  This bit is cleared by reading this register.
        !           323: //
        !           324: #define SERIAL_LSR_FE       0x08
        !           325: 
        !           326: //
        !           327: // This is the break interrupt indicator.  It is set whenever the data
        !           328: // line is held to logic 0 for more than the amount of time it takes
        !           329: // to send one serial data unit.  This bit is cleared whenever the
        !           330: // this register is read.
        !           331: //
        !           332: #define SERIAL_LSR_BI       0x10
        !           333: 
        !           334: //
        !           335: // This is the transmit holding register empty indicator.  It is set
        !           336: // to indicate that the hardware is ready to accept another character
        !           337: // for transmission.  This bit is cleared whenever a character is
        !           338: // written to the transmit holding register.
        !           339: //
        !           340: #define SERIAL_LSR_THRE     0x20
        !           341: 
        !           342: //
        !           343: // This bit is the transmitter empty indicator.  It is set whenever the
        !           344: // transmit holding buffer is empty and the transmit shift register
        !           345: // (a non-software accessable register that is used to actually put
        !           346: // the data out on the wire) is empty.  Basically this means that all
        !           347: // data has been sent.  It is cleared whenever the transmit holding or
        !           348: // the shift registers contain data.
        !           349: //
        !           350: #define SERIAL_LSR_TEMT     0x40
        !           351: 
        !           352: //
        !           353: // This bit indicates that there is at least one error in the fifo.
        !           354: // The bit will not be turned off until there are no more errors
        !           355: // in the fifo.
        !           356: //
        !           357: #define SERIAL_LSR_FIFOERR  0x80
        !           358: 
        !           359: 
        !           360: //
        !           361: // These masks are used to access the modem status register.
        !           362: // Whenever one of the first four bits in the modem status
        !           363: // register changes state a modem status interrupt is generated.
        !           364: //
        !           365: 
        !           366: //
        !           367: // This bit is the delta clear to send.  It is used to indicate
        !           368: // that the clear to send bit (in this register) has *changed*
        !           369: // since this register was last read by the CPU.
        !           370: //
        !           371: #define SERIAL_MSR_DCTS     0x01
        !           372: 
        !           373: //
        !           374: // This bit is the delta data set ready.  It is used to indicate
        !           375: // that the data set ready bit (in this register) has *changed*
        !           376: // since this register was last read by the CPU.
        !           377: //
        !           378: #define SERIAL_MSR_DDSR     0x02
        !           379: 
        !           380: //
        !           381: // This is the trailing edge ring indicator.  It is used to indicate
        !           382: // that the ring indicator input has changed from a low to high state.
        !           383: //
        !           384: #define SERIAL_MSR_TERI     0x04
        !           385: 
        !           386: //
        !           387: // This bit is the delta data carrier detect.  It is used to indicate
        !           388: // that the data carrier bit (in this register) has *changed*
        !           389: // since this register was last read by the CPU.
        !           390: //
        !           391: #define SERIAL_MSR_DDCD     0x08
        !           392: 
        !           393: //
        !           394: // This bit contains the (complemented) state of the clear to send
        !           395: // (CTS) line.
        !           396: //
        !           397: #define SERIAL_MSR_CTS      0x10
        !           398: 
        !           399: //
        !           400: // This bit contains the (complemented) state of the data set ready
        !           401: // (DSR) line.
        !           402: //
        !           403: #define SERIAL_MSR_DSR      0x20
        !           404: 
        !           405: //
        !           406: // This bit contains the (complemented) state of the ring indicator
        !           407: // (RI) line.
        !           408: //
        !           409: #define SERIAL_MSR_RI       0x40
        !           410: 
        !           411: //
        !           412: // This bit contains the (complemented) state of the data carrier detect
        !           413: // (DCD) line.
        !           414: //
        !           415: #define SERIAL_MSR_DCD      0x80
        !           416: 
        !           417: //
        !           418: // This should be more than enough space to hold then
        !           419: // numeric suffix of the device name.
        !           420: //
        !           421: #define DEVICE_NAME_DELTA 20
        !           422: 
        !           423: 
        !           424: //
        !           425: // Up to 16 Ports Per card.  However for sixteen
        !           426: // port cards the interrupt status register must me
        !           427: // the indexing kind rather then the bitmask kind.
        !           428: //
        !           429: //
        !           430: #define SERIAL_MAX_PORTS_INDEXED (16)
        !           431: #define SERIAL_MAX_PORTS_NONINDEXED (8)
        !           432: typedef struct _CONFIG_DATA {
        !           433:     LIST_ENTRY ConfigList;
        !           434:     LIST_ENTRY SameInterruptStatus;
        !           435:     LIST_ENTRY SameInterrupt;
        !           436:     UNICODE_STRING ObjectDirectory;
        !           437:     UNICODE_STRING NtNameForPort;
        !           438:     UNICODE_STRING SymbolicLinkName;
        !           439:     PHYSICAL_ADDRESS Controller;
        !           440:     PHYSICAL_ADDRESS InterruptStatus;
        !           441:     ULONG SpanOfController;
        !           442:     ULONG SpanOfInterruptStatus;
        !           443:     ULONG PortIndex;
        !           444:     ULONG ClockRate;
        !           445:     ULONG BusNumber;
        !           446:     ULONG AddressSpace;
        !           447:     ULONG DisablePort;
        !           448:     ULONG ForceFifoEnable;
        !           449:     ULONG RxFIFO;
        !           450:     KINTERRUPT_MODE InterruptMode;
        !           451:     INTERFACE_TYPE InterfaceType;
        !           452:     ULONG OriginalVector;
        !           453:     ULONG OriginalIrql;
        !           454:     ULONG Indexed;
        !           455:     BOOLEAN Jensen;
        !           456:     } CONFIG_DATA,*PCONFIG_DATA;
        !           457: 
        !           458: 
        !           459: //
        !           460: // Default xon/xoff characters.
        !           461: //
        !           462: #define SERIAL_DEF_XON 0x11
        !           463: #define SERIAL_DEF_XOFF 0x13
        !           464: 
        !           465: //
        !           466: // Reasons that recption may be held up.
        !           467: //
        !           468: #define SERIAL_RX_DTR       ((ULONG)0x01)
        !           469: #define SERIAL_RX_XOFF      ((ULONG)0x02)
        !           470: #define SERIAL_RX_RTS       ((ULONG)0x04)
        !           471: #define SERIAL_RX_DSR       ((ULONG)0x08)
        !           472: 
        !           473: //
        !           474: // Reasons that transmission may be held up.
        !           475: //
        !           476: #define SERIAL_TX_CTS       ((ULONG)0x01)
        !           477: #define SERIAL_TX_DSR       ((ULONG)0x02)
        !           478: #define SERIAL_TX_DCD       ((ULONG)0x04)
        !           479: #define SERIAL_TX_XOFF      ((ULONG)0x08)
        !           480: #define SERIAL_TX_BREAK     ((ULONG)0x10)
        !           481: 
        !           482: //
        !           483: // These values are used by the routines that can be used
        !           484: // to complete a read (other than interval timeout) to indicate
        !           485: // to the interval timeout that it should complete.
        !           486: //
        !           487: #define SERIAL_COMPLETE_READ_CANCEL ((LONG)-1)
        !           488: #define SERIAL_COMPLETE_READ_TOTAL ((LONG)-2)
        !           489: #define SERIAL_COMPLETE_READ_COMPLETE ((LONG)-3)
        !           490: 
        !           491: 
        !           492: 
        !           493: typedef struct _SERIAL_DEVICE_EXTENSION {
        !           494: 
        !           495:     //
        !           496:     // This holds the isr that should be called from our own
        !           497:     // dispatching isr for "cards" that are trying to share the
        !           498:     // same interrupt.
        !           499:     //
        !           500:     PKSERVICE_ROUTINE TopLevelOurIsr;
        !           501: 
        !           502:     //
        !           503:     // This holds the context that should be used when we
        !           504:     // call the above service routine.
        !           505:     //
        !           506:     PVOID TopLevelOurIsrContext;
        !           507: 
        !           508:     //
        !           509:     // This links together all of the different "cards" that are
        !           510:     // trying to share the same interrupt of a non-mca machine.
        !           511:     //
        !           512:     LIST_ENTRY TopLevelSharers;
        !           513: 
        !           514:     //
        !           515:     // This circular doubly linked list links together all
        !           516:     // devices that are using the same interrupt object.
        !           517:     // NOTE: This does not mean that they are using the
        !           518:     // same interrupt "dispatching" routine.
        !           519:     //
        !           520:     LIST_ENTRY CommonInterruptObject;
        !           521: 
        !           522:     //
        !           523:     // For reporting resource usage, we keep around the physical
        !           524:     // address we got from the registry.
        !           525:     //
        !           526:     PHYSICAL_ADDRESS OriginalController;
        !           527: 
        !           528:     //
        !           529:     // For reporting resource usage, we keep around the physical
        !           530:     // address we got from the registry.
        !           531:     //
        !           532:     PHYSICAL_ADDRESS OriginalInterruptStatus;
        !           533: 
        !           534:     //
        !           535:     // This value is set by the read code to hold the time value
        !           536:     // used for read interval timing.  We keep it in the extension
        !           537:     // so that the interval timer dpc routine determine if the
        !           538:     // interval time has passed for the IO.
        !           539:     //
        !           540:     LARGE_INTEGER IntervalTime;
        !           541: 
        !           542:     //
        !           543:     // These two values hold the "constant" time that we should use
        !           544:     // to delay for the read interval time.
        !           545:     //
        !           546:     LARGE_INTEGER ShortIntervalAmount;
        !           547:     LARGE_INTEGER LongIntervalAmount;
        !           548: 
        !           549:     //
        !           550:     // This holds the value that we use to determine if we should use
        !           551:     // the long interval delay or the short interval delay.
        !           552:     //
        !           553:     LARGE_INTEGER CutOverAmount;
        !           554: 
        !           555:     //
        !           556:     // This holds the system time when we last time we had
        !           557:     // checked that we had actually read characters.  Used
        !           558:     // for interval timing.
        !           559:     //
        !           560:     LARGE_INTEGER LastReadTime;
        !           561: 
        !           562:     //
        !           563:     // We keep a pointer around to our device name for dumps
        !           564:     // and for creating "external" symbolic links to this
        !           565:     // device.
        !           566:     //
        !           567:     UNICODE_STRING DeviceName;
        !           568: 
        !           569:     //
        !           570:     // This points to the object directory that we will place
        !           571:     // a symbolic link to our device name.
        !           572:     //
        !           573:     UNICODE_STRING ObjectDirectory;
        !           574: 
        !           575:     //
        !           576:     // This points to the device name for this device
        !           577:     // sans device prefix.
        !           578:     //
        !           579:     UNICODE_STRING NtNameForPort;
        !           580: 
        !           581:     //
        !           582:     // This points to the symbolic link name that will be
        !           583:     // linked to the actual nt device name.
        !           584:     //
        !           585:     UNICODE_STRING SymbolicLinkName;
        !           586: 
        !           587:     //
        !           588:     // This points the the delta time that we should use to
        !           589:     // delay for interval timing.
        !           590:     //
        !           591:     PLARGE_INTEGER IntervalTimeToUse;
        !           592: 
        !           593:     //
        !           594:     // Points to the device object that contains
        !           595:     // this device extension.
        !           596:     //
        !           597:     PDEVICE_OBJECT DeviceObject;
        !           598: 
        !           599:     //
        !           600:     // After initialization of the driver is complete, this
        !           601:     // will either be NULL or point to the routine that the
        !           602:     // kernel will call when an interrupt occurs.
        !           603:     //
        !           604:     // If the pointer is null then this is part of a list
        !           605:     // of ports that are sharing an interrupt and this isn't
        !           606:     // the first port that we configured for this interrupt.
        !           607:     //
        !           608:     // If the pointer is non-null then this routine has some
        !           609:     // kind of structure that will "eventually" get us into
        !           610:     // the real serial isr with a pointer to this device extension.
        !           611:     //
        !           612:     // NOTE: On an MCA bus (except for multiport cards) this
        !           613:     // is always a pointer to the "real" serial isr.
        !           614:     PKSERVICE_ROUTINE OurIsr;
        !           615: 
        !           616:     //
        !           617:     // This will generally point right to this device extension.
        !           618:     //
        !           619:     // However, when the port that this device extension is
        !           620:     // "managing" was the first port initialized on a chain
        !           621:     // of ports that were trying to share an interrupt, this
        !           622:     // will point to a structure that will enable dispatching
        !           623:     // to any port on the chain of sharers of this interrupt.
        !           624:     //
        !           625:     PVOID OurIsrContext;
        !           626: 
        !           627:     //
        !           628:     // The base address for the set of device registers
        !           629:     // of the serial port.
        !           630:     //
        !           631:     PUCHAR Controller;
        !           632: 
        !           633:     //
        !           634:     // The base address for interrupt status register.
        !           635:     // This is only defined in the root extension.
        !           636:     //
        !           637:     PUCHAR InterruptStatus;
        !           638: 
        !           639:     //
        !           640:     // Points to the interrupt object for used by this device.
        !           641:     //
        !           642:     PKINTERRUPT Interrupt;
        !           643: 
        !           644:     //
        !           645:     // This list head is used to contain the time ordered list
        !           646:     // of read requests.  Access to this list is protected by
        !           647:     // the global cancel spinlock.
        !           648:     //
        !           649:     LIST_ENTRY ReadQueue;
        !           650: 
        !           651:     //
        !           652:     // This list head is used to contain the time ordered list
        !           653:     // of write requests.  Access to this list is protected by
        !           654:     // the global cancel spinlock.
        !           655:     //
        !           656:     LIST_ENTRY WriteQueue;
        !           657: 
        !           658:     //
        !           659:     // This list head is used to contain the time ordered list
        !           660:     // of set and wait mask requests.  Access to this list is protected by
        !           661:     // the global cancel spinlock.
        !           662:     //
        !           663:     LIST_ENTRY MaskQueue;
        !           664: 
        !           665:     //
        !           666:     // Holds the serialized list of purge requests.
        !           667:     //
        !           668:     LIST_ENTRY PurgeQueue;
        !           669: 
        !           670:     //
        !           671:     // This points to the irp that is currently being processed
        !           672:     // for the read queue.  This field is initialized by the open to
        !           673:     // NULL.
        !           674:     //
        !           675:     // This value is only set at dispatch level.  It may be
        !           676:     // read at interrupt level.
        !           677:     //
        !           678:     PIRP CurrentReadIrp;
        !           679: 
        !           680:     //
        !           681:     // This points to the irp that is currently being processed
        !           682:     // for the write queue.
        !           683:     //
        !           684:     // This value is only set at dispatch level.  It may be
        !           685:     // read at interrupt level.
        !           686:     //
        !           687:     PIRP CurrentWriteIrp;
        !           688: 
        !           689:     //
        !           690:     // Points to the irp that is currently being processed to
        !           691:     // affect the wait mask operations.
        !           692:     //
        !           693:     PIRP CurrentMaskIrp;
        !           694: 
        !           695:     //
        !           696:     // Points to the irp that is currently being processed to
        !           697:     // purge the read/write queues and buffers.
        !           698:     //
        !           699:     PIRP CurrentPurgeIrp;
        !           700: 
        !           701:     //
        !           702:     // Points to the current irp that is waiting on a comm event.
        !           703:     //
        !           704:     PIRP CurrentWaitIrp;
        !           705: 
        !           706:     //
        !           707:     // Points to the irp that is being used to send an immediate
        !           708:     // character.
        !           709:     //
        !           710:     PIRP CurrentImmediateIrp;
        !           711: 
        !           712:     //
        !           713:     // Points to the irp that is being used to count the number
        !           714:     // of characters received after an xoff (as currently defined
        !           715:     // by the IOCTL_SERIAL_XOFF_COUNTER ioctl) is sent.
        !           716:     //
        !           717:     PIRP CurrentXoffIrp;
        !           718: 
        !           719:     //
        !           720:     // Holds the number of bytes remaining in the current write
        !           721:     // irp.
        !           722:     //
        !           723:     // This location is only accessed while at interrupt level.
        !           724:     //
        !           725:     ULONG WriteLength;
        !           726: 
        !           727:     //
        !           728:     // Holds a pointer to the current character to be sent in
        !           729:     // the current write.
        !           730:     //
        !           731:     // This location is only accessed while at interrupt level.
        !           732:     //
        !           733:     PUCHAR WriteCurrentChar;
        !           734: 
        !           735:     //
        !           736:     // This is a buffer for the read processing.
        !           737:     //
        !           738:     // The buffer works as a ring.  When the character is read from
        !           739:     // the device it will be place at the end of the ring.
        !           740:     //
        !           741:     // Characters are only placed in this buffer at interrupt level
        !           742:     // although character may be read at any level. The pointers
        !           743:     // that manage this buffer may not be updated except at interrupt
        !           744:     // level.
        !           745:     //
        !           746:     PUCHAR InterruptReadBuffer;
        !           747: 
        !           748:     //
        !           749:     // This is a pointer to the first character of the buffer into
        !           750:     // which the interrupt service routine is copying characters.
        !           751:     //
        !           752:     PUCHAR ReadBufferBase;
        !           753: 
        !           754:     //
        !           755:     // This is a count of the number of characters in the interrupt
        !           756:     // buffer.  This value is set and read at interrupt level.  Note
        !           757:     // that this value is only *incremented* at interrupt level so
        !           758:     // it is safe to read it at any level.  When characters are
        !           759:     // copied out of the read buffer, this count is decremented by
        !           760:     // a routine that synchronizes with the ISR.
        !           761:     //
        !           762:     ULONG CharsInInterruptBuffer;
        !           763: 
        !           764:     //
        !           765:     // Points to the first available position for a newly received
        !           766:     // character.  This variable is only accessed at interrupt level and
        !           767:     // buffer initialization code.
        !           768:     //
        !           769:     PUCHAR CurrentCharSlot;
        !           770: 
        !           771:     //
        !           772:     // This variable is used to contain the last available position
        !           773:     // in the read buffer.  It is updated at open and at interrupt
        !           774:     // level when switching between the users buffer and the interrupt
        !           775:     // buffer.
        !           776:     //
        !           777:     PUCHAR LastCharSlot;
        !           778: 
        !           779:     //
        !           780:     // This marks the first character that is available to satisfy
        !           781:     // a read request.  Note that while this always points to valid
        !           782:     // memory, it may not point to a character that can be sent to
        !           783:     // the user.  This can occur when the buffer is empty.
        !           784:     //
        !           785:     PUCHAR FirstReadableChar;
        !           786: 
        !           787:     //
        !           788:     // This variable holds the size of whatever buffer we are currently
        !           789:     // using.
        !           790:     //
        !           791:     ULONG BufferSize;
        !           792: 
        !           793:     //
        !           794:     // This variable holds .8 of BufferSize. We don't want to recalculate
        !           795:     // this real often - It's needed when so that an application can be
        !           796:     // "notified" that the buffer is getting full.
        !           797:     //
        !           798:     ULONG BufferSizePt8;
        !           799: 
        !           800:     //
        !           801:     // This value holds the number of characters desired for a
        !           802:     // particular read.  It is initially set by read length in the
        !           803:     // IRP.  It is decremented each time more characters are placed
        !           804:     // into the "users" buffer buy the code that reads characters
        !           805:     // out of the typeahead buffer into the users buffer.  If the
        !           806:     // typeahead buffer is exhausted by the read, and the reads buffer
        !           807:     // is given to the isr to fill, this value is becomes meaningless.
        !           808:     //
        !           809:     ULONG NumberNeededForRead;
        !           810: 
        !           811:     //
        !           812:     // This mask will hold the bitmask sent down via the set mask
        !           813:     // ioctl.  It is used by the interrupt service routine to determine
        !           814:     // if the occurence of "events" (in the serial drivers understanding
        !           815:     // of the concept of an event) should be noted.
        !           816:     //
        !           817:     ULONG IsrWaitMask;
        !           818: 
        !           819:     //
        !           820:     // This mask will always be a subset of the IsrWaitMask.  While
        !           821:     // at device level, if an event occurs that is "marked" as interesting
        !           822:     // in the IsrWaitMask, the driver will turn on that bit in this
        !           823:     // history mask.  The driver will then look to see if there is a
        !           824:     // request waiting for an event to occur.  If there is one, it
        !           825:     // will copy the value of the history mask into the wait irp, zero
        !           826:     // the history mask, and complete the wait irp.  If there is no
        !           827:     // waiting request, the driver will be satisfied with just recording
        !           828:     // that the event occured.  If a wait request should be queued,
        !           829:     // the driver will look to see if the history mask is non-zero.  If
        !           830:     // it is non-zero, the driver will copy the history mask into the
        !           831:     // irp, zero the history mask, and then complete the irp.
        !           832:     //
        !           833:     ULONG HistoryMask;
        !           834: 
        !           835:     //
        !           836:     // This is a pointer to the where the history mask should be
        !           837:     // placed when completing a wait.  It is only accessed at
        !           838:     // device level.
        !           839:     //
        !           840:     // We have a pointer here to assist us to synchronize completing a wait.
        !           841:     // If this is non-zero, then we have wait outstanding, and the isr still
        !           842:     // knows about it.  We make this pointer null so that the isr won't
        !           843:     // attempt to complete the wait.
        !           844:     //
        !           845:     // We still keep a pointer around to the wait irp, since the actual
        !           846:     // pointer to the wait irp will be used for the "common" irp completion
        !           847:     // path.
        !           848:     //
        !           849:     ULONG *IrpMaskLocation;
        !           850: 
        !           851:     //
        !           852:     // This mask holds all of the reason that transmission
        !           853:     // is not proceeding.  Normal transmission can not occur
        !           854:     // if this is non-zero.
        !           855:     //
        !           856:     // This is only written from interrupt level.
        !           857:     // This could be (but is not) read at any level.
        !           858:     //
        !           859:     ULONG TXHolding;
        !           860: 
        !           861:     //
        !           862:     // This mask holds all of the reason that reception
        !           863:     // is not proceeding.  Normal reception can not occur
        !           864:     // if this is non-zero.
        !           865:     //
        !           866:     // This is only written from interrupt level.
        !           867:     // This could be (but is not) read at any level.
        !           868:     //
        !           869:     ULONG RXHolding;
        !           870: 
        !           871:     //
        !           872:     // This holds the reasons that the driver thinks it is in
        !           873:     // an error state.
        !           874:     //
        !           875:     // This is only written from interrupt level.
        !           876:     // This could be (but is not) read at any level.
        !           877:     //
        !           878:     ULONG ErrorWord;
        !           879: 
        !           880:     //
        !           881:     // This keeps a total of the number of characters that
        !           882:     // are in all of the "write" irps that the driver knows
        !           883:     // about.  It is only accessed with the cancel spinlock
        !           884:     // held.
        !           885:     //
        !           886:     ULONG TotalCharsQueued;
        !           887: 
        !           888:     //
        !           889:     // This holds a count of the number of characters read
        !           890:     // the last time the interval timer dpc fired.  It
        !           891:     // is a long (rather than a ulong) since the other read
        !           892:     // completion routines use negative values to indicate
        !           893:     // to the interval timer that it should complete the read
        !           894:     // if the interval timer DPC was lurking in some DPC queue when
        !           895:     // some other way to complete occurs.
        !           896:     //
        !           897:     LONG CountOnLastRead;
        !           898: 
        !           899:     //
        !           900:     // This is a count of the number of characters read by the
        !           901:     // isr routine.  It is *ONLY* written at isr level.  We can
        !           902:     // read it at dispatch level.
        !           903:     //
        !           904:     ULONG ReadByIsr;
        !           905: 
        !           906:     //
        !           907:     // This holds the current baud rate for the device.
        !           908:     //
        !           909:     ULONG CurrentBaud;
        !           910: 
        !           911:     //
        !           912:     // This is the number of characters read since the XoffCounter
        !           913:     // was started.  This variable is only accessed at device level.
        !           914:     // If it is greater than zero, it implies that there is an
        !           915:     // XoffCounter ioctl in the queue.
        !           916:     //
        !           917:     LONG CountSinceXoff;
        !           918: 
        !           919:     //
        !           920:     // This ulong is incremented each time something trys to start
        !           921:     // the execution path that tries to lower the RTS line when
        !           922:     // doing transmit toggling.  If it "bumps" into another path
        !           923:     // (indicated by a false return value from queueing a dpc
        !           924:     // and a TRUE return value tring to start a timer) it will
        !           925:     // decrement the count.  These increments and decrements
        !           926:     // are all done at device level.  Note that in the case
        !           927:     // of a bump while trying to start the timer, we have to
        !           928:     // go up to device level to do the decrement.
        !           929:     //
        !           930:     ULONG CountOfTryingToLowerRTS;
        !           931: 
        !           932:     //
        !           933:     // This ULONG is used to keep track of the "named" (in ntddser.h)
        !           934:     // baud rates that this particular device supports.
        !           935:     //
        !           936:     ULONG SupportedBauds;
        !           937: 
        !           938:     //
        !           939:     // This value holds the span (in units of bytes) of the register
        !           940:     // set controlling this port.  This is constant over the life
        !           941:     // of the port.
        !           942:     //
        !           943:     ULONG SpanOfController;
        !           944: 
        !           945:     //
        !           946:     // This value holds the span (in units of bytes) of the interrupt
        !           947:     // status register associated with this port.  This is constant
        !           948:     // over the life of the port.
        !           949:     //
        !           950:     ULONG SpanOfInterruptStatus;
        !           951: 
        !           952:     //
        !           953:     // Hold the clock rate input to the serial part.
        !           954:     //
        !           955:     ULONG ClockRate;
        !           956: 
        !           957:     //
        !           958:     // Holds the timeout controls for the device.  This value
        !           959:     // is set by the Ioctl processing.
        !           960:     //
        !           961:     // It should only be accessed under protection of the control
        !           962:     // lock since more than one request can be in the control dispatch
        !           963:     // routine at one time.
        !           964:     //
        !           965:     SERIAL_TIMEOUTS Timeouts;
        !           966: 
        !           967:     //
        !           968:     // This holds the various characters that are used
        !           969:     // for replacement on errors and also for flow control.
        !           970:     //
        !           971:     // They are only set at interrupt level.
        !           972:     //
        !           973:     SERIAL_CHARS SpecialChars;
        !           974: 
        !           975:     //
        !           976:     // This structure holds the handshake and control flow
        !           977:     // settings for the serial driver.
        !           978:     //
        !           979:     // It is only set at interrupt level.  It can be
        !           980:     // be read at any level with the control lock held.
        !           981:     //
        !           982:     SERIAL_HANDFLOW HandFlow;
        !           983: 
        !           984:     //
        !           985:     // This holds what we beleive to be the current value of
        !           986:     // the line control register.
        !           987:     //
        !           988:     // It should only be accessed under protection of the control
        !           989:     // lock since more than one request can be in the control dispatch
        !           990:     // routine at one time.
        !           991:     //
        !           992:     UCHAR LineControl;
        !           993: 
        !           994:     //
        !           995:     // We keep track of whether the somebody has the device currently
        !           996:     // opened with a simple boolean.  We need to know this so that
        !           997:     // spurious interrupts from the device (especially during initialization)
        !           998:     // will be ignored.  This value is only accessed in the ISR and
        !           999:     // is only set via synchronization routines.  We may be able
        !          1000:     // to get rid of this boolean when the code is more fleshed out.
        !          1001:     //
        !          1002:     BOOLEAN DeviceIsOpened;
        !          1003: 
        !          1004:     //
        !          1005:     // Set at intialization to indicate that on the current
        !          1006:     // architecture we need to unmap the base register address
        !          1007:     // when we unload the driver.
        !          1008:     //
        !          1009:     BOOLEAN UnMapRegisters;
        !          1010: 
        !          1011:     //
        !          1012:     // Set at intialization to indicate that on the current
        !          1013:     // architecture we need to unmap the interrupt status address
        !          1014:     // when we unload the driver.
        !          1015:     //
        !          1016:     BOOLEAN UnMapStatus;
        !          1017: 
        !          1018:     //
        !          1019:     // This is only accessed at interrupt level.  It keeps track
        !          1020:     // of whether the holding register is empty.
        !          1021:     //
        !          1022:     BOOLEAN HoldingEmpty;
        !          1023: 
        !          1024:     //
        !          1025:     // This variable is only accessed at interrupt level.  It
        !          1026:     // indicates that we want to transmit a character immediately.
        !          1027:     // That is - in front of any characters that could be transmitting
        !          1028:     // from a normal write.
        !          1029:     //
        !          1030:     BOOLEAN TransmitImmediate;
        !          1031: 
        !          1032:     //
        !          1033:     // This variable is only accessed at interrupt level.  Whenever
        !          1034:     // a wait is initiated this variable is set to false.
        !          1035:     // Whenever any kind of character is written it is set to true.
        !          1036:     // Whenever the write queue is found to be empty the code that
        !          1037:     // is processing that completing irp will synchonize with the interrupt.
        !          1038:     // If this synchronization code finds that the variable is true and that
        !          1039:     // there is a wait on the transmit queue being empty then it is
        !          1040:     // certain that the queue was emptied and that it has happened since
        !          1041:     // the wait was initiated.
        !          1042:     //
        !          1043:     BOOLEAN EmptiedTransmit;
        !          1044: 
        !          1045:     //
        !          1046:     // This simply indicates that the port associated with this
        !          1047:     // extension is part of a multiport card.
        !          1048:     //
        !          1049:     BOOLEAN PortOnAMultiportCard;
        !          1050: 
        !          1051:     //
        !          1052:     // We keep the following values around so that we can connect
        !          1053:     // to the interrupt and report resources after the configuration
        !          1054:     // record is gone.
        !          1055:     //
        !          1056:     ULONG Vector;
        !          1057:     KIRQL Irql;
        !          1058:     ULONG OriginalVector;
        !          1059:     ULONG OriginalIrql;
        !          1060:     KINTERRUPT_MODE InterruptMode;
        !          1061:     KAFFINITY ProcessorAffinity;
        !          1062:     ULONG AddressSpace;
        !          1063:     ULONG BusNumber;
        !          1064:     INTERFACE_TYPE InterfaceType;
        !          1065: 
        !          1066:     //
        !          1067:     // We hold the character that should be transmitted immediately.
        !          1068:     //
        !          1069:     // Note that we can't use this to determine whether there is
        !          1070:     // a character to send because the character to send could be
        !          1071:     // zero.
        !          1072:     //
        !          1073:     UCHAR ImmediateChar;
        !          1074: 
        !          1075:     //
        !          1076:     // This holds the mask that will be used to mask off unwanted
        !          1077:     // data bits of the received data (valid data bits can be 5,6,7,8)
        !          1078:     // The mask will normally be 0xff.  This is set while the control
        !          1079:     // lock is held since it wouldn't have adverse effects on the
        !          1080:     // isr if it is changed in the middle of reading characters.
        !          1081:     // (What it would do to the app is another question - but then
        !          1082:     // the app asked the driver to do it.)
        !          1083:     //
        !          1084:     UCHAR ValidDataMask;
        !          1085: 
        !          1086:     //
        !          1087:     // The application can turn on a mode,via the
        !          1088:     // IOCTL_SERIAL_LSRMST_INSERT ioctl, that will cause the
        !          1089:     // serial driver to insert the line status or the modem
        !          1090:     // status into the RX stream.  The parameter with the ioctl
        !          1091:     // is a pointer to a UCHAR.  If the value of the UCHAR is
        !          1092:     // zero, then no insertion will ever take place.  If the
        !          1093:     // value of the UCHAR is non-zero (and not equal to the
        !          1094:     // xon/xoff characters), then the serial driver will insert.
        !          1095:     //
        !          1096:     UCHAR EscapeChar;
        !          1097: 
        !          1098:     //
        !          1099:     // These two booleans are used to indicate to the isr transmit
        !          1100:     // code that it should send the xon or xoff character.  They are
        !          1101:     // only accessed at open and at interrupt level.
        !          1102:     //
        !          1103:     BOOLEAN SendXonChar;
        !          1104:     BOOLEAN SendXoffChar;
        !          1105: 
        !          1106:     //
        !          1107:     // This boolean will be true if a 16550 is present *and* enabled.
        !          1108:     //
        !          1109:     BOOLEAN FifoPresent;
        !          1110: 
        !          1111:     //
        !          1112:     // This denotes that this particular port is an on the motherboard
        !          1113:     // port for the Jensen hardware.  On these ports the OUT2 bit
        !          1114:     // which is used to enable/disable interrupts is always hight.
        !          1115:     //
        !          1116:     BOOLEAN Jensen;
        !          1117: 
        !          1118:     //
        !          1119:     // This is the water mark that the rxfifo should be
        !          1120:     // set to when the fifo is turned on.  This is not the actual
        !          1121:     // value, but the encoded value that goes into the register.
        !          1122:     //
        !          1123:     UCHAR RxFifoTrigger;
        !          1124: 
        !          1125:     //
        !          1126:     // Says whether this device can share interrupts with devices
        !          1127:     // other than serial devices.
        !          1128:     //
        !          1129:     BOOLEAN InterruptShareable;
        !          1130: 
        !          1131:     //
        !          1132:     // Records whether we actually created the symbolic link name
        !          1133:     // at driver load time.  If we didn't create it, we won't try
        !          1134:     // to distry it when we unload.
        !          1135:     //
        !          1136:     BOOLEAN CreatedSymbolicLink;
        !          1137: 
        !          1138:     //
        !          1139:     // We place all of the kernel and Io subsystem "opaque" structures
        !          1140:     // at the end of the extension.  We don't care about their contents.
        !          1141:     //
        !          1142: 
        !          1143:     //
        !          1144:     // This lock will be used to protect various fields in
        !          1145:     // the extension that are set (& read) in the extension
        !          1146:     // by the io controls.
        !          1147:     //
        !          1148:     KSPIN_LOCK ControlLock;
        !          1149: 
        !          1150:     //
        !          1151:     // This points to a DPC used to complete read requests.
        !          1152:     //
        !          1153:     KDPC CompleteWriteDpc;
        !          1154: 
        !          1155:     //
        !          1156:     // This points to a DPC used to complete read requests.
        !          1157:     //
        !          1158:     KDPC CompleteReadDpc;
        !          1159: 
        !          1160:     //
        !          1161:     // This dpc is fired off if the timer for the total timeout
        !          1162:     // for the read expires.  It will execute a dpc routine that
        !          1163:     // will cause the current read to complete.
        !          1164:     //
        !          1165:     //
        !          1166:     KDPC TotalReadTimeoutDpc;
        !          1167: 
        !          1168:     //
        !          1169:     // This dpc is fired off if the timer for the interval timeout
        !          1170:     // expires.  If no more characters have been read then the
        !          1171:     // dpc routine will cause the read to complete.  However, if
        !          1172:     // more characters have been read then the dpc routine will
        !          1173:     // resubmit the timer.
        !          1174:     //
        !          1175:     KDPC IntervalReadTimeoutDpc;
        !          1176: 
        !          1177:     //
        !          1178:     // This dpc is fired off if the timer for the total timeout
        !          1179:     // for the write expires.  It will execute a dpc routine that
        !          1180:     // will cause the current write to complete.
        !          1181:     //
        !          1182:     //
        !          1183:     KDPC TotalWriteTimeoutDpc;
        !          1184: 
        !          1185:     //
        !          1186:     // This dpc is fired off if a comm error occurs.  It will
        !          1187:     // execute a dpc routine that will cancel all pending reads
        !          1188:     // and writes.
        !          1189:     //
        !          1190:     KDPC CommErrorDpc;
        !          1191: 
        !          1192:     //
        !          1193:     // This dpc is fired off if an event occurs and there was
        !          1194:     // a irp waiting on that event.  A dpc routine will execute
        !          1195:     // that completes the irp.
        !          1196:     //
        !          1197:     KDPC CommWaitDpc;
        !          1198: 
        !          1199:     //
        !          1200:     // This dpc is fired off when the transmit immediate char
        !          1201:     // character is given to the hardware.  It will simply complete
        !          1202:     // the irp.
        !          1203:     //
        !          1204:     KDPC CompleteImmediateDpc;
        !          1205: 
        !          1206:     //
        !          1207:     // This dpc is fired off if the transmit immediate char
        !          1208:     // character times out.  The dpc routine will "grab" the
        !          1209:     // irp from the isr and time it out.
        !          1210:     //
        !          1211:     KDPC TotalImmediateTimeoutDpc;
        !          1212: 
        !          1213:     //
        !          1214:     // This dpc is fired off if the timer used to "timeout" counting
        !          1215:     // the number of characters received after the Xoff ioctl is started
        !          1216:     // expired.
        !          1217:     //
        !          1218:     KDPC XoffCountTimeoutDpc;
        !          1219: 
        !          1220:     //
        !          1221:     // This dpc is fired off if the xoff counter actually runs down
        !          1222:     // to zero.
        !          1223:     //
        !          1224:     KDPC XoffCountCompleteDpc;
        !          1225: 
        !          1226:     //
        !          1227:     // This dpc is fired off only from device level to start off
        !          1228:     // a timer that will queue a dpc to check if the RTS line
        !          1229:     // should be lowered when we are doing transmit toggling.
        !          1230:     //
        !          1231:     KDPC StartTimerLowerRTSDpc;
        !          1232: 
        !          1233:     //
        !          1234:     // This dpc is fired off when a timer expires (after one
        !          1235:     // character time), so that code can be invoked that will
        !          1236:     // check to see if we should lower the RTS line when
        !          1237:     // doing transmit toggling.
        !          1238:     //
        !          1239:     KDPC PerhapsLowerRTSDpc;
        !          1240: 
        !          1241:     //
        !          1242:     // This is the kernal timer structure used to handle
        !          1243:     // total read request timing.
        !          1244:     //
        !          1245:     KTIMER ReadRequestTotalTimer;
        !          1246: 
        !          1247:     //
        !          1248:     // This is the kernal timer structure used to handle
        !          1249:     // interval read request timing.
        !          1250:     //
        !          1251:     KTIMER ReadRequestIntervalTimer;
        !          1252: 
        !          1253:     //
        !          1254:     // This is the kernal timer structure used to handle
        !          1255:     // total time request timing.
        !          1256:     //
        !          1257:     KTIMER WriteRequestTotalTimer;
        !          1258: 
        !          1259:     //
        !          1260:     // This is the kernal timer structure used to handle
        !          1261:     // total time request timing.
        !          1262:     //
        !          1263:     KTIMER ImmediateTotalTimer;
        !          1264: 
        !          1265:     //
        !          1266:     // This timer is used to timeout the xoff counter
        !          1267:     // io.
        !          1268:     //
        !          1269:     KTIMER XoffCountTimer;
        !          1270: 
        !          1271:     //
        !          1272:     // This timer is used to invoke a dpc one character time
        !          1273:     // after the timer is set.  That dpc will be used to check
        !          1274:     // whether we should lower the RTS line if we are doing
        !          1275:     // transmit toggling.
        !          1276:     //
        !          1277:     KTIMER LowerRTSTimer;
        !          1278:     } SERIAL_DEVICE_EXTENSION,*PSERIAL_DEVICE_EXTENSION;
        !          1279: 
        !          1280: 
        !          1281: 
        !          1282: //
        !          1283: // When dealing with a multi-port device (that is possibly
        !          1284: // daisy chained with other multi-port device), the interrupt
        !          1285: // service routine will actually be a routine that determines
        !          1286: // which port on which board is actually causing the interrupt.
        !          1287: //
        !          1288: // The following structure is used so that only one device
        !          1289: // extension will actually need to connect to the interrupt.
        !          1290: // The following structure which is passed to the interrupt
        !          1291: // service routine contains the addresses of all of the
        !          1292: // interrupt status registers (there will be multiple
        !          1293: // status registers when multi-port cards are chained).  It
        !          1294: // will contain the addresses of all the extensions whose
        !          1295: // devices are being serviced by this interrupt.
        !          1296: //
        !          1297: 
        !          1298: typedef struct _SERIAL_MULTIPORT_DISPATCH {
        !          1299:     PUCHAR InterruptStatus;
        !          1300:     PSERIAL_DEVICE_EXTENSION Extensions[SERIAL_MAX_PORTS_INDEXED];
        !          1301:     UCHAR UsablePortMask;
        !          1302:     } SERIAL_MULTIPORT_DISPATCH,*PSERIAL_MULTIPORT_DISPATCH;
        !          1303: 
        !          1304: 
        !          1305: //
        !          1306: // Sets the divisor latch register.  The divisor latch register
        !          1307: // is used to control the baud rate of the 8250.
        !          1308: //
        !          1309: // As with all of these routines it is assumed that it is called
        !          1310: // at a safe point to access the hardware registers.  In addition
        !          1311: // it also assumes that the data is correct.
        !          1312: //
        !          1313: // Arguments:
        !          1314: //
        !          1315: // BaseAddress - A pointer to the address from which the hardware
        !          1316: //               device registers are located.
        !          1317: //
        !          1318: // DesiredDivisor - The value to which the divisor latch register should
        !          1319: //                  be set.
        !          1320: //
        !          1321: #define WRITE_DIVISOR_LATCH(BaseAddress,DesiredDivisor)           \
        !          1322: do                                                                \
        !          1323: {                                                                 \
        !          1324:     PUCHAR Address = BaseAddress;                                 \
        !          1325:     SHORT Divisor = DesiredDivisor;                               \
        !          1326:     UCHAR LineControl;                                            \
        !          1327:     LineControl = READ_PORT_UCHAR(Address+LINE_CONTROL_REGISTER); \
        !          1328:     WRITE_PORT_UCHAR(                                             \
        !          1329:         Address+LINE_CONTROL_REGISTER,                            \
        !          1330:         (UCHAR)(LineControl | SERIAL_LCR_DLAB)                    \
        !          1331:         );                                                        \
        !          1332:     WRITE_PORT_UCHAR(                                             \
        !          1333:         Address+DIVISOR_LATCH_LSB,                                \
        !          1334:         (UCHAR)(Divisor & 0xff)                                   \
        !          1335:         );                                                        \
        !          1336:     WRITE_PORT_UCHAR(                                             \
        !          1337:         Address+DIVISOR_LATCH_MSB,                                \
        !          1338:         (UCHAR)((Divisor & 0xff00) >> 8)                          \
        !          1339:         );                                                        \
        !          1340:     WRITE_PORT_UCHAR(                                             \
        !          1341:         Address+LINE_CONTROL_REGISTER,                            \
        !          1342:         LineControl                                               \
        !          1343:         );                                                        \
        !          1344: } while (0)
        !          1345: 
        !          1346: //
        !          1347: // Reads the divisor latch register.  The divisor latch register
        !          1348: // is used to control the baud rate of the 8250.
        !          1349: //
        !          1350: // As with all of these routines it is assumed that it is called
        !          1351: // at a safe point to access the hardware registers.  In addition
        !          1352: // it also assumes that the data is correct.
        !          1353: //
        !          1354: // Arguments:
        !          1355: //
        !          1356: // BaseAddress - A pointer to the address from which the hardware
        !          1357: //               device registers are located.
        !          1358: //
        !          1359: // DesiredDivisor - A pointer to the 2 byte word which will contain
        !          1360: //                  the value of the divisor.
        !          1361: //
        !          1362: #define READ_DIVISOR_LATCH(BaseAddress,PDesiredDivisor)           \
        !          1363: do                                                                \
        !          1364: {                                                                 \
        !          1365:     PUCHAR Address = BaseAddress;                                 \
        !          1366:     PSHORT PDivisor = PDesiredDivisor;                            \
        !          1367:     UCHAR LineControl;                                            \
        !          1368:     UCHAR Lsb;                                                    \
        !          1369:     UCHAR Msb;                                                    \
        !          1370:     LineControl = READ_PORT_UCHAR(Address+LINE_CONTROL_REGISTER); \
        !          1371:     WRITE_PORT_UCHAR(                                             \
        !          1372:         Address+LINE_CONTROL_REGISTER,                            \
        !          1373:         (UCHAR)(LineControl | SERIAL_LCR_DLAB)                    \
        !          1374:         );                                                        \
        !          1375:     Lsb = READ_PORT_UCHAR(Address+DIVISOR_LATCH_LSB);             \
        !          1376:     Msb = READ_PORT_UCHAR(Address+DIVISOR_LATCH_MSB);             \
        !          1377:     *PDivisor = Lsb;                                              \
        !          1378:     *PDivisor = *PDivisor | (((USHORT)Msb) << 8);                 \
        !          1379:     WRITE_PORT_UCHAR(                                             \
        !          1380:         Address+LINE_CONTROL_REGISTER,                            \
        !          1381:         LineControl                                               \
        !          1382:         );                                                        \
        !          1383: } while (0)
        !          1384: 
        !          1385: //
        !          1386: // This macro reads the interrupt enable register.
        !          1387: //
        !          1388: // Arguments:
        !          1389: //
        !          1390: // BaseAddress - A pointer to the address from which the hardware
        !          1391: //               device registers are located.
        !          1392: //
        !          1393: #define READ_INTERRUPT_ENABLE(BaseAddress)                     \
        !          1394:     (READ_PORT_UCHAR((BaseAddress)+INTERRUPT_ENABLE_REGISTER))
        !          1395: 
        !          1396: //
        !          1397: // This macro writes the interrupt enable register.
        !          1398: //
        !          1399: // Arguments:
        !          1400: //
        !          1401: // BaseAddress - A pointer to the address from which the hardware
        !          1402: //               device registers are located.
        !          1403: //
        !          1404: // Values - The values to write to the interrupt enable register.
        !          1405: //
        !          1406: #define WRITE_INTERRUPT_ENABLE(BaseAddress,Values)                \
        !          1407: do                                                                \
        !          1408: {                                                                 \
        !          1409:     WRITE_PORT_UCHAR(                                             \
        !          1410:         BaseAddress+INTERRUPT_ENABLE_REGISTER,                    \
        !          1411:         Values                                                    \
        !          1412:         );                                                        \
        !          1413: } while (0)
        !          1414: 
        !          1415: //
        !          1416: // This macro disables all interrupts on the hardware.
        !          1417: //
        !          1418: // Arguments:
        !          1419: //
        !          1420: // BaseAddress - A pointer to the address from which the hardware
        !          1421: //               device registers are located.
        !          1422: //
        !          1423: //
        !          1424: #define DISABLE_ALL_INTERRUPTS(BaseAddress)       \
        !          1425: do                                                \
        !          1426: {                                                 \
        !          1427:     WRITE_INTERRUPT_ENABLE(BaseAddress,0);        \
        !          1428: } while (0)
        !          1429: 
        !          1430: //
        !          1431: // This macro enables all interrupts on the hardware.
        !          1432: //
        !          1433: // Arguments:
        !          1434: //
        !          1435: // BaseAddress - A pointer to the address from which the hardware
        !          1436: //               device registers are located.
        !          1437: //
        !          1438: //
        !          1439: #define ENABLE_ALL_INTERRUPTS(BaseAddress)        \
        !          1440: do                                                \
        !          1441: {                                                 \
        !          1442:                                                   \
        !          1443:     WRITE_INTERRUPT_ENABLE(                       \
        !          1444:         (BaseAddress),                            \
        !          1445:         (UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \
        !          1446:                 SERIAL_IER_RLS | SERIAL_IER_MS)   \
        !          1447:         );                                        \
        !          1448:                                                   \
        !          1449: } while (0)
        !          1450: 
        !          1451: //
        !          1452: // This macro reads the interrupt identification register
        !          1453: //
        !          1454: // Arguments:
        !          1455: //
        !          1456: // BaseAddress - A pointer to the address from which the hardware
        !          1457: //               device registers are located.
        !          1458: //
        !          1459: // Note that this routine potententially quites a transmitter
        !          1460: // empty interrupt.  This is because one way that the transmitter
        !          1461: // empty interrupt is cleared is to simply read the interrupt id
        !          1462: // register.
        !          1463: //
        !          1464: //
        !          1465: #define READ_INTERRUPT_ID_REG(BaseAddress)                          \
        !          1466:     (READ_PORT_UCHAR((BaseAddress)+INTERRUPT_IDENT_REGISTER))
        !          1467: 
        !          1468: //
        !          1469: // This macro reads the modem control register
        !          1470: //
        !          1471: // Arguments:
        !          1472: //
        !          1473: // BaseAddress - A pointer to the address from which the hardware
        !          1474: //               device registers are located.
        !          1475: //
        !          1476: //
        !          1477: #define READ_MODEM_CONTROL(BaseAddress)                          \
        !          1478:     (READ_PORT_UCHAR((BaseAddress)+MODEM_CONTROL_REGISTER))
        !          1479: 
        !          1480: //
        !          1481: // This macro reads the modem status register
        !          1482: //
        !          1483: // Arguments:
        !          1484: //
        !          1485: // BaseAddress - A pointer to the address from which the hardware
        !          1486: //               device registers are located.
        !          1487: //
        !          1488: //
        !          1489: #define READ_MODEM_STATUS(BaseAddress)                          \
        !          1490:     (READ_PORT_UCHAR((BaseAddress)+MODEM_STATUS_REGISTER))
        !          1491: 
        !          1492: //
        !          1493: // This macro reads a value out of the receive buffer
        !          1494: //
        !          1495: // Arguments:
        !          1496: //
        !          1497: // BaseAddress - A pointer to the address from which the hardware
        !          1498: //               device registers are located.
        !          1499: //
        !          1500: //
        !          1501: #define READ_RECEIVE_BUFFER(BaseAddress)                          \
        !          1502:     (READ_PORT_UCHAR((BaseAddress)+RECEIVE_BUFFER_REGISTER))
        !          1503: 
        !          1504: //
        !          1505: // This macro reads the line status register
        !          1506: //
        !          1507: // Arguments:
        !          1508: //
        !          1509: // BaseAddress - A pointer to the address from which the hardware
        !          1510: //               device registers are located.
        !          1511: //
        !          1512: //
        !          1513: #define READ_LINE_STATUS(BaseAddress)                          \
        !          1514:     (READ_PORT_UCHAR((BaseAddress)+LINE_STATUS_REGISTER))
        !          1515: 
        !          1516: //
        !          1517: // This macro writes the line control register
        !          1518: //
        !          1519: // Arguments:
        !          1520: //
        !          1521: // BaseAddress - A pointer to the address from which the hardware
        !          1522: //               device registers are located.
        !          1523: //
        !          1524: //
        !          1525: #define WRITE_LINE_CONTROL(BaseAddress,NewLineControl)           \
        !          1526: do                                                               \
        !          1527: {                                                                \
        !          1528:     WRITE_PORT_UCHAR(                                            \
        !          1529:         (BaseAddress)+LINE_CONTROL_REGISTER,                     \
        !          1530:         (NewLineControl)                                         \
        !          1531:         );                                                       \
        !          1532: } while (0)
        !          1533: 
        !          1534: //
        !          1535: // This macro reads the line control register
        !          1536: //
        !          1537: // Arguments:
        !          1538: //
        !          1539: // BaseAddress - A pointer to the address from which the hardware
        !          1540: //               device registers are located.
        !          1541: //
        !          1542: //
        !          1543: #define READ_LINE_CONTROL(BaseAddress)           \
        !          1544:     (READ_PORT_UCHAR((BaseAddress)+LINE_CONTROL_REGISTER))
        !          1545: 
        !          1546: 
        !          1547: //
        !          1548: // This macro writes to the transmit register
        !          1549: //
        !          1550: // Arguments:
        !          1551: //
        !          1552: // BaseAddress - A pointer to the address from which the hardware
        !          1553: //               device registers are located.
        !          1554: //
        !          1555: // TransmitChar - The character to send down the wire.
        !          1556: //
        !          1557: //
        !          1558: #define WRITE_TRANSMIT_HOLDING(BaseAddress,TransmitChar)       \
        !          1559: do                                                             \
        !          1560: {                                                              \
        !          1561:     WRITE_PORT_UCHAR(                                          \
        !          1562:         (BaseAddress)+TRANSMIT_HOLDING_REGISTER,               \
        !          1563:         (TransmitChar)                                         \
        !          1564:         );                                                     \
        !          1565: } while (0)
        !          1566: 
        !          1567: //
        !          1568: // This macro writes to the control register
        !          1569: //
        !          1570: // Arguments:
        !          1571: //
        !          1572: // BaseAddress - A pointer to the address from which the hardware
        !          1573: //               device registers are located.
        !          1574: //
        !          1575: // ControlValue - The value to set the fifo control register too.
        !          1576: //
        !          1577: //
        !          1578: #define WRITE_FIFO_CONTROL(BaseAddress,ControlValue)           \
        !          1579: do                                                             \
        !          1580: {                                                              \
        !          1581:     WRITE_PORT_UCHAR(                                          \
        !          1582:         (BaseAddress)+FIFO_CONTROL_REGISTER,                   \
        !          1583:         (ControlValue)                                         \
        !          1584:         );                                                     \
        !          1585: } while (0)
        !          1586: 
        !          1587: //
        !          1588: // This macro writes to the modem control register
        !          1589: //
        !          1590: // Arguments:
        !          1591: //
        !          1592: // BaseAddress - A pointer to the address from which the hardware
        !          1593: //               device registers are located.
        !          1594: //
        !          1595: // ModemControl - The control bits to send to the modem control.
        !          1596: //
        !          1597: //
        !          1598: #define WRITE_MODEM_CONTROL(BaseAddress,ModemControl)          \
        !          1599: do                                                             \
        !          1600: {                                                              \
        !          1601:     WRITE_PORT_UCHAR(                                          \
        !          1602:         (BaseAddress)+MODEM_CONTROL_REGISTER,                  \
        !          1603:         (ModemControl)                                         \
        !          1604:         );                                                     \
        !          1605: } while (0)

unix.superglobalmegacorp.com

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