|
|
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)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.