I'm confused about how the baud rate 38.4K
is calculated in xv6.
Here is the UART documentation.
void
uartinit(void)
{
// disable interrupts.
WriteReg(IER, 0x00);
// special mode to set baud rate.
WriteReg(LCR, LCR_BAUD_LATCH);
// LSB for baud rate of 38.4K.
WriteReg(0, 0x03);
// MSB for baud rate of 38.4K.
WriteReg(1, 0x00);
// leave set-baud mode,
// and set word length to 8 bits, no parity.
WriteReg(LCR, LCR_EIGHT_BITS);
// reset and enable FIFOs.
WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR);
// enable transmit and receive interrupts.
WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE);
initlock(&uart_tx_lock, "uart");
}
I think these lines in the above documentation may illustrate baud rate settings:
PROGRAMMABLE BAUD RATE GENERATOR: The 16550 contains a programmable Baud Rate Generator that is capable of tracking any clock input from DC-8 MHz and dividing it by any divisor from 1 to 2^16-1. The output frequency of the Baudout is equal to the 16X of transmission baud rate (Baudout=16 X Baud Rate). Customize Baud Rates can be achieved by selecting proper divisor values for MSB and LSB of baud rate generator.
xv6 targets standard x86 PC hardware, and on a PC, the 16550 UART is connected to a clock source with frequency 1.8432 MHz. This has been true ever since the original IBM PC released in 1981 (with an 8250 UART); see page 2-135 of its Technical Reference Manual.
The divisor in that code is set to 3, so the output frequency is 1.8432 / 3 = 0.6144 MHz, or 614.4 KHz. The baud rate is 1/16 of that, which is indeed 38.4K.