diff --git a/hypervisor/debug/uart16550.c b/hypervisor/debug/uart16550.c index dfab19bd0..11bd859ae 100644 --- a/hypervisor/debug/uart16550.c +++ b/hypervisor/debug/uart16550.c @@ -14,27 +14,35 @@ #define MAX_BDF_LEN 8 +struct console_uart { + bool enabled; + bool serial_port_mapped; + union { + uint16_t port_address; + void *mmio_base_vaddr; + }; + spinlock_t rx_lock; + spinlock_t tx_lock; +}; + #if defined(CONFIG_SERIAL_PIO_BASE) -static bool serial_port_mapped = true; -static bool uart_enabled = true; -static uint64_t uart_base_address = CONFIG_SERIAL_PIO_BASE; +static struct console_uart uart = { + .enabled = true, + .serial_port_mapped = true, + .port_address = CONFIG_SERIAL_PIO_BASE, +}; static char pci_bdf_info[MAX_BDF_LEN + 1U]; #elif defined(CONFIG_SERIAL_PCI_BDF) -static bool serial_port_mapped; -static bool uart_enabled = true; -static uint64_t uart_base_address; +static struct console_uart uart = { + .enabled = true, +}; static char pci_bdf_info[MAX_BDF_LEN + 1U] = CONFIG_SERIAL_PCI_BDF; #else -static bool serial_port_mapped; -static bool uart_enabled; -static uint64_t uart_base_address; +static struct console_uart uart; static char pci_bdf_info[MAX_BDF_LEN + 1U]; #endif typedef uint32_t uart_reg_t; - -static spinlock_t uart_rx_lock; -static spinlock_t uart_tx_lock; static union pci_bdf serial_pci_bdf; /* PCI BDF must follow format: bus:dev.func, for example 0:18.2 */ @@ -64,26 +72,26 @@ static uint16_t get_pci_bdf_value(char *bdf) } /** - * @pre uart_enabled == true + * @pre uart->enabled == true */ -static inline uint32_t uart16550_read_reg(uint64_t base, uint16_t reg_idx) +static inline uint32_t uart16550_read_reg(struct console_uart uart, uint16_t reg_idx) { - if (serial_port_mapped) { - return pio_read8((uint16_t)base + reg_idx); + if (uart.serial_port_mapped) { + return pio_read8(uart.port_address + reg_idx); } else { - return mmio_read32((void *)((uint32_t *)hpa2hva(base) + reg_idx)); + return mmio_read32((uint32_t *)uart.mmio_base_vaddr + reg_idx); } } /** - * @pre uart_enabled == true + * @pre uart->enabled == true */ -static inline void uart16550_write_reg(uint64_t base, uint32_t val, uint16_t reg_idx) +static inline void uart16550_write_reg(struct console_uart uart, uint32_t val, uint16_t reg_idx) { - if (serial_port_mapped) { - pio_write8((uint8_t)val, (uint16_t)base + reg_idx); + if (uart.serial_port_mapped) { + pio_write8(val, uart.port_address + reg_idx); } else { - mmio_write32(val, (void *)((uint32_t *)hpa2hva(base) + reg_idx)); + mmio_write32(val, (uint32_t *)uart.mmio_base_vaddr + reg_idx); } } @@ -99,7 +107,7 @@ static void uart16550_calc_baud_div(uint32_t ref_freq, uint32_t *baud_div_ptr, u } /** - * @pre uart_enabled == true + * @pre uart->enabled == true */ static void uart16550_set_baud_rate(uint32_t baud_rate) { @@ -110,75 +118,76 @@ static void uart16550_set_baud_rate(uint32_t baud_rate) uart16550_calc_baud_div(duart_clock, &baud_div, baud_rate); /* Enable DLL and DLM registers for setting the Divisor */ - temp_reg = uart16550_read_reg(uart_base_address, UART16550_LCR); + temp_reg = uart16550_read_reg(uart, UART16550_LCR); temp_reg |= LCR_DLAB; - uart16550_write_reg(uart_base_address, temp_reg, UART16550_LCR); + uart16550_write_reg(uart, temp_reg, UART16550_LCR); /* Write the appropriate divisor value */ - uart16550_write_reg(uart_base_address, ((baud_div >> 8U) & 0xFFU), UART16550_DLM); - uart16550_write_reg(uart_base_address, (baud_div & 0xFFU), UART16550_DLL); + uart16550_write_reg(uart, ((baud_div >> 8U) & 0xFFU), UART16550_DLM); + uart16550_write_reg(uart, (baud_div & 0xFFU), UART16550_DLL); /* Disable DLL and DLM registers */ temp_reg &= ~LCR_DLAB; - uart16550_write_reg(uart_base_address, temp_reg, UART16550_LCR); + uart16550_write_reg(uart, temp_reg, UART16550_LCR); } void uart16550_init(void) { - if (!uart_enabled) { + if (!uart.enabled) { return; } /* if configure serial PCI BDF, get its base MMIO address */ - if (!serial_port_mapped) { + if (!uart.serial_port_mapped) { serial_pci_bdf.value = get_pci_bdf_value(pci_bdf_info); - uart_base_address = pci_pdev_read_cfg(serial_pci_bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE; + uart.mmio_base_vaddr = + hpa2hva(pci_pdev_read_cfg(serial_pci_bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE); } - if (!serial_port_mapped) { - hv_access_memory_region_update(uart_base_address, PDE_SIZE); + if (!uart.serial_port_mapped) { + hv_access_memory_region_update((uint64_t)uart.mmio_base_vaddr, PDE_SIZE); } - spinlock_init(&uart_rx_lock); - spinlock_init(&uart_tx_lock); + spinlock_init(&uart.rx_lock); + spinlock_init(&uart.tx_lock); /* Enable TX and RX FIFOs */ - uart16550_write_reg(uart_base_address, FCR_FIFOE | FCR_RFR | FCR_TFR, UART16550_FCR); + uart16550_write_reg(uart, FCR_FIFOE | FCR_RFR | FCR_TFR, UART16550_FCR); /* Set-up data bits / parity / stop bits. */ - uart16550_write_reg(uart_base_address, (LCR_WL8 | LCR_NB_STOP_BITS_1 | LCR_PARITY_NONE), UART16550_LCR); + uart16550_write_reg(uart, (LCR_WL8 | LCR_NB_STOP_BITS_1 | LCR_PARITY_NONE), UART16550_LCR); /* Disable interrupts (we use polling) */ - uart16550_write_reg(uart_base_address, UART_IER_DISABLE_ALL, UART16550_IER); + uart16550_write_reg(uart, UART_IER_DISABLE_ALL, UART16550_IER); /* Set baud rate */ uart16550_set_baud_rate(BAUD_115200); /* Data terminal ready + Request to send */ - uart16550_write_reg(uart_base_address, MCR_RTS | MCR_DTR, UART16550_MCR); + uart16550_write_reg(uart, MCR_RTS | MCR_DTR, UART16550_MCR); } char uart16550_getc(void) { char ret = -1; - if (!uart_enabled) { + if (!uart.enabled) { return ret; } - spinlock_obtain(&uart_rx_lock); + spinlock_obtain(&uart.rx_lock); /* If a character has been received, read it */ - if ((uart16550_read_reg(uart_base_address, UART16550_LSR) & LSR_DR) == LSR_DR) { + if ((uart16550_read_reg(uart, UART16550_LSR) & LSR_DR) == LSR_DR) { /* Read a character */ - ret = uart16550_read_reg(uart_base_address, UART16550_RBR); + ret = uart16550_read_reg(uart, UART16550_RBR); } - spinlock_release(&uart_rx_lock); + spinlock_release(&uart.rx_lock); return ret; } /** - * @pre uart_enabled == true + * @pre uart->enabled == true */ static void uart16550_putc(char c) { @@ -187,21 +196,21 @@ static void uart16550_putc(char c) /* Ensure there are no further Transmit buffer write requests */ do { - reg = uart16550_read_reg(uart_base_address, UART16550_LSR); + reg = uart16550_read_reg(uart, UART16550_LSR); } while ((reg & LSR_THRE) == 0U || (reg & LSR_TEMT) == 0U); temp = (uint8_t)c; /* Transmit the character. */ - uart16550_write_reg(uart_base_address, (uint32_t)temp, UART16550_THR); + uart16550_write_reg(uart, (uint32_t)temp, UART16550_THR); } size_t uart16550_puts(const char *buf, uint32_t len) { uint32_t i; - if (!uart_enabled) { + if (!uart.enabled) { return len; } - spinlock_obtain(&uart_tx_lock); + spinlock_obtain(&uart.tx_lock); for (i = 0U; i < len; i++) { /* Transmit character */ uart16550_putc(*buf); @@ -211,17 +220,17 @@ size_t uart16550_puts(const char *buf, uint32_t len) } buf++; } - spinlock_release(&uart_tx_lock); + spinlock_release(&uart.tx_lock); return len; } void uart16550_set_property(bool enabled, bool port_mapped, uint64_t base_addr) { - uart_enabled = enabled; - serial_port_mapped = port_mapped; + uart.enabled = enabled; + uart.serial_port_mapped = port_mapped; if (port_mapped) { - uart_base_address = base_addr; + uart.port_address = base_addr; } else { const char *bdf = (const char *)base_addr; strncpy_s(pci_bdf_info, MAX_BDF_LEN + 1U, bdf, MAX_BDF_LEN); @@ -232,7 +241,7 @@ bool is_pci_dbg_uart(union pci_bdf bdf_value) { bool ret = false; - if (uart_enabled && !serial_port_mapped) { + if (uart.enabled && !uart.serial_port_mapped) { if (bdf_value.value == serial_pci_bdf.value) { ret = true; }