Added UART detection and reporting.

This commit is contained in:
Scott Duensing 2026-03-10 21:11:27 -05:00
parent 0fcaae54c3
commit bc102b7215
3 changed files with 77 additions and 0 deletions

View file

@ -10,6 +10,7 @@ stripped to DJGPP-only codepaths and restyled.
- ISR-driven receive and transmit with 2048-byte ring buffers - ISR-driven receive and transmit with 2048-byte ring buffers
- Auto-detected IRQ from BIOS data area - Auto-detected IRQ from BIOS data area
- UART type detection (8250, 16450, 16550, 16550A)
- 16550 FIFO detection and configurable trigger threshold - 16550 FIFO detection and configurable trigger threshold
- XON/XOFF, RTS/CTS, and DTR/DSR flow control - XON/XOFF, RTS/CTS, and DTR/DSR flow control
- DPMI memory locking for ISR safety - 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_COM3` | 2 | COM3 |
| `RS232_COM4` | 3 | COM4 | | `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 ### Handshaking Modes
| Constant | Value | Description | | 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 rs232GetRxBuffered(int com); // Bytes in receive buffer
int rs232GetStop(int com); // Stop bits setting int rs232GetStop(int com); // Stop bits setting
int rs232GetTxBuffered(int com); // Bytes in transmit buffer 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 #### Setters
```c ```c
@ -175,6 +196,10 @@ int main(void) {
return 1; return 1;
} }
// Identify UART chip
int uartType = rs232GetUartType(RS232_COM1);
// uartType == RS232_UART_16550A on most systems
// Blocking send // Blocking send
rs232Write(RS232_COM1, "Hello\r\n", 7); rs232Write(RS232_COM1, "Hello\r\n", 7);

View file

@ -107,6 +107,7 @@
#define UART_MCR 4 #define UART_MCR 4
#define UART_LSR 5 #define UART_LSR 5
#define UART_MSR 6 #define UART_MSR 6
#define UART_SCR 7 // scratch register (not present on 8250)
// UART read macros // UART read macros
#define UART_READ_DATA(C) inportb((C)->base + UART_RX) #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) { int rs232Open(int com, int32_t bps, int dataBits, char parity, int stopBits, int handshake) {
Rs232StateT *port = &sComPorts[com]; Rs232StateT *port = &sComPorts[com];
int rc = RS232_SUCCESS; int rc = RS232_SUCCESS;

View file

@ -22,6 +22,13 @@
#define RS232_HANDSHAKE_RTSCTS 2 #define RS232_HANDSHAKE_RTSCTS 2
#define RS232_HANDSHAKE_DTRDSR 3 #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 // Error Codes
#define RS232_SUCCESS 0 #define RS232_SUCCESS 0
#define RS232_ERR_UNKNOWN -1 #define RS232_ERR_UNKNOWN -1
@ -67,6 +74,7 @@ int rs232GetRts(int com);
int rs232GetRxBuffered(int com); int rs232GetRxBuffered(int com);
int rs232GetStop(int com); int rs232GetStop(int com);
int rs232GetTxBuffered(int com); int rs232GetTxBuffered(int com);
int rs232GetUartType(int com);
// Read/write // Read/write
int rs232Read(int com, char *data, int len); int rs232Read(int com, char *data, int len);