uart: Support EARLY_PRINTF on x86 for port-mapped COM ports

Support early printf for the ns8250 uart driver. Adding
	options UART_NS8250_EARLY_PORT=0xYYY
	options EARLY_PRINTF
to your kernel config will enable it. The code is rather simple minded,
so caveat emptor. This will enable printf before cninit. cninit
automatically disables this and switches to the real routine. It only
works for port-mapped COM ports, and only if you know the port's address
at compile time. It's intended for be a debugging aide, not a general
purpose thing.

Sponsored by:		Netflix
Reviewed by:		emaste
Differential Revision:	https://reviews.freebsd.org/D42306
This commit is contained in:
Warner Losh 2023-10-20 16:07:03 -06:00
parent f6c2774fe4
commit a113f9dd98
3 changed files with 27 additions and 0 deletions

View file

@ -65,3 +65,6 @@ NO_LEGACY_PCIB opt_cpu.h
# Compatibility with Linux MP table bugs.
MPTABLE_LINUX_BUG_COMPAT
# x86 specific uart options
UART_NS8250_EARLY_PORT opt_uart.h

View file

@ -109,3 +109,6 @@ NO_LEGACY_PCIB opt_cpu.h
# Compatibility with Linux MP table bugs.
MPTABLE_LINUX_BUG_COMPAT
# x86 specific uart options
UART_NS8250_EARLY_PORT opt_uart.h

View file

@ -78,6 +78,27 @@ static int broken_txfifo = 0;
SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RWTUN,
&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
/*
* To use early printf on x86, add the following to your kernel config:
*
* options UART_NS8250_EARLY_PORT=0x3f8
* options EARLY_PRINTF
*/
#if defined(EARLY_PRINTF) && (defined(__amd64__) || defined(__i386__))
static void
uart_ns8250_early_putc(int c)
{
u_int stat = UART_NS8250_EARLY_PORT + REG_LSR;
u_int tx = UART_NS8250_EARLY_PORT + REG_DATA;
int limit = 10000; /* 10ms is plenty of time */
while ((inb(stat) & LSR_THRE) == 0 && --limit > 0)
continue;
outb(tx, c);
}
early_putc_t *early_putc = uart_ns8250_early_putc;
#endif /* EARLY_PRINTF */
/*
* Clear pending interrupts. THRE is cleared by reading IIR. Data
* that may have been received gets lost here.