// RS-232 Serial Port Library for DJGPP // Ported from DOS Serial Library 1.4 by Karl Stenerud (MIT License) // // ISR-driven UART communication with ring buffers and flow control. // Supports up to 4 simultaneous COM ports with auto-detected IRQ. // // Architecture: // A single ISR (comGeneralIsr) handles all open COM ports. When any // UART interrupts, the ISR loops over all open ports draining their // FIFOs into per-port ring buffers. The application reads from these // buffers at its leisure. This decouples the UART's byte-at-a-time // pace from application-level processing. // // Ring buffers are power-of-2 sized (2048 bytes) so head/tail index // wrapping is a single AND, not a modulo — critical for ISR speed. // // Flow control (XON/XOFF, RTS/CTS, DTR/DSR) operates entirely within // the ISR using watermark thresholds. When the RX buffer is 80% full, // we signal the remote to stop; at 20%, we allow it to resume. This // prevents buffer overflow without application involvement. // // The ISR and its data structures are locked in memory via DPMI to // prevent page faults during interrupt handling — a requirement for // any ISR running under a DPMI host (DOS extender, Windows, etc.). #ifndef RS232_H #define RS232_H #include #include // COM Ports #define RS232_COM1 0 #define RS232_COM2 1 #define RS232_COM3 2 #define RS232_COM4 3 // Handshaking Modes #define RS232_HANDSHAKE_NONE 0 #define RS232_HANDSHAKE_XONXOFF 1 #define RS232_HANDSHAKE_RTSCTS 2 #define RS232_HANDSHAKE_DTRDSR 3 // UART Types (detected by probing scratch register and FIFO capability) // 8250: No scratch register, no FIFO (original IBM PC) // 16450: Has scratch register, no FIFO // 16550: Has FIFO but it's buggy (rare) // 16550A: Has working 16-byte FIFO (most common in 486+ era hardware) #define RS232_UART_UNKNOWN 0 #define RS232_UART_8250 1 #define RS232_UART_16450 2 #define RS232_UART_16550 3 #define RS232_UART_16550A 4 // Error Codes #define RS232_SUCCESS 0 #define RS232_ERR_UNKNOWN -1 #define RS232_ERR_NOT_OPEN -2 #define RS232_ERR_ALREADY_OPEN -3 #define RS232_ERR_NO_UART -4 #define RS232_ERR_INVALID_PORT -5 #define RS232_ERR_INVALID_BASE -6 #define RS232_ERR_INVALID_IRQ -7 #define RS232_ERR_INVALID_BPS -8 #define RS232_ERR_INVALID_DATA -9 #define RS232_ERR_INVALID_PARITY -10 #define RS232_ERR_INVALID_STOP -11 #define RS232_ERR_INVALID_HANDSHAKE -12 #define RS232_ERR_INVALID_FIFO -13 #define RS232_ERR_NULL_PTR -14 #define RS232_ERR_IRQ_NOT_FOUND -15 #define RS232_ERR_LOCK_MEM -16 // Buffer management int rs232ClearRxBuffer(int com); int rs232ClearTxBuffer(int com); // Open/close int rs232Close(int com); int rs232Open(int com, int32_t bps, int dataBits, char parity, int stopBits, int handshake); // Getters int rs232GetBase(int com); int32_t rs232GetBps(int com); int rs232GetCts(int com); int rs232GetData(int com); int rs232GetDsr(int com); int rs232GetDtr(int com); int rs232GetHandshake(int com); int rs232GetIrq(int com); int rs232GetLsr(int com); int rs232GetMcr(int com); int rs232GetMsr(int com); char rs232GetParity(int com); int rs232GetRts(int com); int rs232GetRxBuffered(int com); int rs232GetStop(int com); int rs232GetTxBuffered(int com); int rs232GetUartType(int com); // Read/write // rs232Read: non-blocking drain from RX ring buffer, returns bytes read // rs232Write: blocking polled write directly to UART THR (bypasses TX buffer) // rs232WriteBuf: non-blocking write to TX ring buffer, ISR drains to UART int rs232Read(int com, char *data, int len); int rs232Write(int com, const char *data, int len); int rs232WriteBuf(int com, const char *data, int len); // Setters int rs232Set(int com, int32_t bps, int dataBits, char parity, int stopBits, int handshake); int rs232SetBase(int com, int base); int rs232SetBps(int com, int32_t bps); int rs232SetData(int com, int dataBits); int rs232SetDtr(int com, bool dtr); int rs232SetFifoThreshold(int com, int threshold); int rs232SetHandshake(int com, int handshake); int rs232SetIrq(int com, int irq); int rs232SetMcr(int com, int mcr); int rs232SetParity(int com, char parity); int rs232SetRts(int com, bool rts); int rs232SetStop(int com, int stopBits); #endif