16c95x Serial Port Driver Direct
The driver calculates divisor values using the enhanced baud rate generator. For non-standard rates, the driver can switch to a fractional divisor mode.
# Unbind the generic driver
echo -n "0000:01:00.0" > /sys/bus/pci/drivers/serial/unbind
# Bind to the 16C95x-capable driver
echo -n "0000:01:00.0" > /sys/bus/pci/drivers/8250-pci/bind
Due to the high potential data rates (up to 15 Mbps), the CPU must service interrupts very quickly. If the operating system has high interrupt latency, the 128-byte RX FIFO may overflow before the ISR runs. The driver must often utilize a "Low Latency" mode or increase the service thread priority.
setserial /dev/ttyS0 uart 16C95x fifo 112 16c95x serial port driver
For kernel driver modification, ensure UART_CAP_FIFO_SIZE and UART_CAP_RPM are set correctly in 8250_port.c.
For half-duplex RS-485 networks, the 16C95x can automatically assert RTS (as a direction control signal) before transmitting and deassert it after the last stop bit. The driver calculates divisor values using the enhanced
Set the following in EFCR (Extended Features Control Register):
The driver then simply writes to THR; the hardware handles the turnaround delay. Implement struct uart_port for each port, mapping to
To understand the driver requirements, one must first understand the hardware capabilities it manages.
The Tx interrupt (THRE – Transmitter Holding Register Empty) asserts when the Tx FIFO falls below the programmed trigger level (default empty). The driver’s Tx ISR should fill the FIFO up to its capacity or until the Tx buffer is empty.
void uart_isr_tx(uart_t *dev)
while (!(read_reg(dev->base + UART_LSR) & LSR_TXFIFO_FULL))
if (ringbuf_empty(&dev->tx_ring))
// No more data: disable Tx interrupt
uint8_t ier = read_reg(dev->base + UART_IER);
write_reg(dev->base + UART_IER, ier & ~IER_THRE);
break;
uint8_t data = ringbuf_pop(&dev->tx_ring);
write_reg(dev->base + UART_THR, data);
A common pitfall: After initial Tx, you must enable THRE interrupt only when there is data to send. Many drivers enable it unconditionally, causing an immediate interrupt storm.