MS-DOS 6.22 COM Port Interrupt Buffer Overflows
In MS-DOS 6.22, native serial communications rely primarily on polled I/O through BIOS INT 14h or DOS character-device calls rather than an OS-managed interrupt-driven buffering architecture. Consequently, MS-DOS 6.22 does not manage an internal ring buffer or process serial hardware interrupts natively; instead, serial buffer overflows are detected strictly at the hardware UART (Universal Asynchronous Receiver/Transmitter) level via line status registers, requiring user-level software, TSR drivers, or custom interrupt service routines to detect, handle, or prevent data loss.
Native DOS Handling and the Polled I/O Architecture
MS-DOS 6.22 accesses serial ports through the standard
AUX, COM1, COM2,
COM3, and COM4 character device drivers via
INT 21h functions, which route down to BIOS INT 14h. Under this native
stack:
- No Background Interrupt Processing: MS-DOS does not hook IRQ 4 (assigned to COM1 and COM3 via INT 0Ch) or IRQ 3 (assigned to COM2 and COM4 via INT 0Bh).
- Synchronous Polling: When an application requests a byte from a COM port using DOS API calls, the system reads the UART registers synchronously. If no character is present, it either waits or returns a status flag indicating the receiver is not ready.
- Absence of an OS-Level Circular Buffer: Because DOS does not maintain a circular software buffer in RAM for incoming serial data, it cannot absorb bursts of data received when the processor is executing other tasks.
Hardware Overrun Detection at the UART
When data arrives over the serial line, the physical UART chip (typically an 8250, 16450, or 16550 in DOS-era PCs) deserializes the signal into the Receiver Buffer Register (RBR). Handling depends on the hardware state:
- Hardware Overrun (OE Flag): If a new character is completely assembled in the Shift Register while the RBR already holds an unread byte, the UART sets Bit 1 (Overrun Error, or OE) of the Line Status Register (LSR, located at I/O base address + 5).
- Data Destruction: The previous unread byte in the RBR is overwritten by the incoming character.
- Interrupt Generation (Hardware): If Bit 2 of the Interrupt Enable Register (IER, I/O base address + 1) is enabled, the UART triggers a Receiver Line Status interrupt (Priority 1). Under default MS-DOS 6.22 execution, this hardware interrupt remains unhandled by the OS kernel, meaning the OE flag remains latched until an external read operation explicitly accesses the LSR.
16550 FIFO Buffering
On PCs equipped with a 16550A UART, a 16-byte hardware FIFO exists for both transmission and reception. However:
- MS-DOS 6.22 and standard BIOS routines do not enable the FIFO buffer automatically, running the chip in backward-compatible 8250 mode.
- If enabled by external software (via the FIFO Control Register at base address + 2), the UART triggers a Receiver Data Available interrupt at a programmable trigger level (1, 4, 8, or 14 bytes). If the FIFO fills completely (16 bytes) and another character arrives, an overrun interrupt triggers, and the incoming character is discarded.
How Applications Manage Buffer Overflows in DOS 6.22
Because MS-DOS 6.22 provides no native mitigation for overruns, communication software (such as terminal emulators, SLIP/PPP packet drivers, or BBS hosts) bypasses DOS altogether:
- Vector Interception: The application hooks INT 0Ch (IRQ 4) or INT 0Bh (IRQ 3) to point to a custom Interrupt Service Routine (ISR).
- Software Ring Buffering: The custom ISR reads bytes directly from the UART RBR (base address + 0) as soon as data arrives and places them into an allocated circular RAM buffer (typically 1 KB to 64 KB).
- Software-Level Overflow Management: If the software
ring buffer reaches capacity:
- Hardware Flow Control (RTS/CTS): The ISR drops the Request to Send (RTS) line via the Modem Control Register (MCR, base address + 4) to force the transmitting device to halt transmission.
- Software Flow Control (XON/XOFF): The routine
queues an ASCII
0x13(DC3/XOFF) byte into the Transmitter Holding Register (THR) to pause the sender. - Packet Dropping: If flow control fails or is disabled, the ISR deliberately discards the oldest or newest bytes and increments a software overrun counter to preserve program integrity.