diff --git a/rs232/README.md b/rs232/README.md index 879bacc..5af39e5 100644 --- a/rs232/README.md +++ b/rs232/README.md @@ -10,6 +10,7 @@ stripped to DJGPP-only codepaths and restyled. - ISR-driven receive and transmit with 2048-byte ring buffers - Auto-detected IRQ from BIOS data area +- UART type detection (8250, 16450, 16550, 16550A) - 16550 FIFO detection and configurable trigger threshold - XON/XOFF, RTS/CTS, and DTR/DSR flow control - DPMI memory locking for ISR safety @@ -29,6 +30,16 @@ All functions take a COM port index (`int com`) as their first argument: | `RS232_COM3` | 2 | COM3 | | `RS232_COM4` | 3 | COM4 | +### UART Types + +| Constant | Value | Description | +|---------------------|-------|--------------------------------------| +| `RS232_UART_UNKNOWN`| 0 | Unknown or undetected | +| `RS232_UART_8250` | 1 | 8250 — no FIFO, no scratch register | +| `RS232_UART_16450` | 2 | 16450 — scratch register, no FIFO | +| `RS232_UART_16550` | 3 | 16550 — broken FIFO (unusable) | +| `RS232_UART_16550A` | 4 | 16550A — working 16-byte FIFO | + ### Handshaking Modes | Constant | Value | Description | @@ -138,8 +149,18 @@ int rs232GetRts(int com); // RTS line state (0 or 1) int rs232GetRxBuffered(int com); // Bytes in receive buffer int rs232GetStop(int com); // Stop bits setting int rs232GetTxBuffered(int com); // Bytes in transmit buffer +int rs232GetUartType(int com); // UART type (RS232_UART_* constant) ``` +`rs232GetUartType` probes the UART hardware to identify the chip: + +1. **Scratch register test** — writes two values to register 7 and + reads them back. The 8250 lacks this register, so readback fails. +2. **FIFO test** — enables the FIFO via the FCR, then reads IIR bits + 7:6. `0b11` = 16550A (working FIFO), `0b10` = 16550 (broken FIFO), + `0b00` = 16450 (no FIFO). The original FCR value is restored after + probing. + #### Setters ```c @@ -175,6 +196,10 @@ int main(void) { return 1; } + // Identify UART chip + int uartType = rs232GetUartType(RS232_COM1); + // uartType == RS232_UART_16550A on most systems + // Blocking send rs232Write(RS232_COM1, "Hello\r\n", 7); diff --git a/rs232/rs232.c b/rs232/rs232.c index 86c5615..ba31c00 100644 --- a/rs232/rs232.c +++ b/rs232/rs232.c @@ -107,6 +107,7 @@ #define UART_MCR 4 #define UART_LSR 5 #define UART_MSR 6 +#define UART_SCR 7 // scratch register (not present on 8250) // UART read macros #define UART_READ_DATA(C) inportb((C)->base + UART_RX) @@ -955,6 +956,49 @@ int rs232GetTxBuffered(int com) { } +int rs232GetUartType(int com) { + Rs232StateT *port = &sComPorts[com]; + uint8_t scratch; + uint8_t iir; + + if (com < COM_MIN || com > COM_MAX) { + return RS232_ERR_INVALID_PORT; + } + if (!port->isOpen) { + return RS232_ERR_NOT_OPEN; + } + + // Test scratch register — 8250 lacks it + outportb(port->base + UART_SCR, 0xA5); + scratch = inportb(port->base + UART_SCR); + if (scratch != 0xA5) { + return RS232_UART_8250; + } + outportb(port->base + UART_SCR, 0x5A); + scratch = inportb(port->base + UART_SCR); + if (scratch != 0x5A) { + return RS232_UART_8250; + } + + // Has scratch register — at least 16450. Try enabling FIFO. + outportb(port->base + UART_FCR, FCR_ENABLE); + iir = inportb(port->base + UART_IIR); + + // Restore original FCR + outportb(port->base + UART_FCR, port->fcr); + + // Check IIR bits 7:6 for FIFO status + switch (iir & 0xC0) { + case 0xC0: + return RS232_UART_16550A; + case 0x80: + return RS232_UART_16550; + default: + return RS232_UART_16450; + } +} + + int rs232Open(int com, int32_t bps, int dataBits, char parity, int stopBits, int handshake) { Rs232StateT *port = &sComPorts[com]; int rc = RS232_SUCCESS; diff --git a/rs232/rs232.h b/rs232/rs232.h index af1e7c0..0d7abe7 100644 --- a/rs232/rs232.h +++ b/rs232/rs232.h @@ -22,6 +22,13 @@ #define RS232_HANDSHAKE_RTSCTS 2 #define RS232_HANDSHAKE_DTRDSR 3 +// UART Types +#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 @@ -67,6 +74,7 @@ int rs232GetRts(int com); int rs232GetRxBuffered(int com); int rs232GetStop(int com); int rs232GetTxBuffered(int com); +int rs232GetUartType(int com); // Read/write int rs232Read(int com, char *data, int len);