Loading hw/grlib_apbuart.c +89 −17 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ #include "sysbus.h" #include "qemu-char.h" #include "ptimer.h" #include "trace.h" Loading Loading @@ -66,6 +65,8 @@ #define SCALER_OFFSET 0x0C /* not supported */ #define FIFO_DEBUG_OFFSET 0x10 /* not supported */ #define FIFO_LENGTH 1024 typedef struct UART { SysBusDevice busdev; MemoryRegion iomem; Loading @@ -77,20 +78,66 @@ typedef struct UART { uint32_t receive; uint32_t status; uint32_t control; /* FIFO */ char buffer[FIFO_LENGTH]; int len; int current; } UART; static int uart_data_to_read(UART *uart) { return uart->current < uart->len; } static char uart_pop(UART *uart) { char ret; if (uart->len == 0) { uart->status &= ~UART_DATA_READY; return 0; } ret = uart->buffer[uart->current++]; if (uart->current >= uart->len) { /* Flush */ uart->len = 0; uart->current = 0; } if (!uart_data_to_read(uart)) { uart->status &= ~UART_DATA_READY; } return ret; } static void uart_add_to_fifo(UART *uart, const uint8_t *buffer, int length) { if (uart->len + length > FIFO_LENGTH) { abort(); } memcpy(uart->buffer + uart->len, buffer, length); uart->len += length; } static int grlib_apbuart_can_receive(void *opaque) { UART *uart = opaque; return !!(uart->status & UART_DATA_READY); return FIFO_LENGTH - uart->len; } static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) { UART *uart = opaque; uart->receive = *buf; uart_add_to_fifo(uart, buf, size); uart->status |= UART_DATA_READY; if (uart->control & UART_RECEIVE_INTERRUPT) { Loading @@ -103,8 +150,38 @@ static void grlib_apbuart_event(void *opaque, int event) trace_grlib_apbuart_event(event); } static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr, static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr, unsigned size) { UART *uart = opaque; addr &= 0xff; /* Unit registers */ switch (addr) { case DATA_OFFSET: case DATA_OFFSET + 3: /* when only one byte read */ return uart_pop(uart); case STATUS_OFFSET: /* Read Only */ return uart->status; case CONTROL_OFFSET: return uart->control; case SCALER_OFFSET: /* Not supported */ return 0; default: trace_grlib_apbuart_readl_unknown(addr); return 0; } } static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { UART *uart = opaque; Loading @@ -115,6 +192,7 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr, /* Unit registers */ switch (addr) { case DATA_OFFSET: case DATA_OFFSET + 3: /* When only one byte write */ c = value & 0xFF; qemu_chr_fe_write(uart->chr, &c, 1); return; Loading @@ -124,7 +202,7 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr, return; case CONTROL_OFFSET: /* Not supported */ uart->control = value; return; case SCALER_OFFSET: Loading @@ -138,15 +216,9 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr, trace_grlib_apbuart_writel_unknown(addr, value); } static bool grlib_apbuart_accepts(void *opaque, target_phys_addr_t addr, unsigned size, bool is_write) { return is_write && size == 4; } static const MemoryRegionOps grlib_apbuart_ops = { .write = grlib_apbuart_write, .valid.accepts = grlib_apbuart_accepts, .read = grlib_apbuart_read, .endianness = DEVICE_NATIVE_ENDIAN, }; Loading trace-events +1 −0 Original line number Diff line number Diff line Loading @@ -351,6 +351,7 @@ grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" valu # hw/grlib_apbuart.c grlib_apbuart_event(int event) "event:%d" grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64"" # hw/leon3.c leon3_set_irq(int intno) "Set CPU IRQ %d" Loading Loading
hw/grlib_apbuart.c +89 −17 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ #include "sysbus.h" #include "qemu-char.h" #include "ptimer.h" #include "trace.h" Loading Loading @@ -66,6 +65,8 @@ #define SCALER_OFFSET 0x0C /* not supported */ #define FIFO_DEBUG_OFFSET 0x10 /* not supported */ #define FIFO_LENGTH 1024 typedef struct UART { SysBusDevice busdev; MemoryRegion iomem; Loading @@ -77,20 +78,66 @@ typedef struct UART { uint32_t receive; uint32_t status; uint32_t control; /* FIFO */ char buffer[FIFO_LENGTH]; int len; int current; } UART; static int uart_data_to_read(UART *uart) { return uart->current < uart->len; } static char uart_pop(UART *uart) { char ret; if (uart->len == 0) { uart->status &= ~UART_DATA_READY; return 0; } ret = uart->buffer[uart->current++]; if (uart->current >= uart->len) { /* Flush */ uart->len = 0; uart->current = 0; } if (!uart_data_to_read(uart)) { uart->status &= ~UART_DATA_READY; } return ret; } static void uart_add_to_fifo(UART *uart, const uint8_t *buffer, int length) { if (uart->len + length > FIFO_LENGTH) { abort(); } memcpy(uart->buffer + uart->len, buffer, length); uart->len += length; } static int grlib_apbuart_can_receive(void *opaque) { UART *uart = opaque; return !!(uart->status & UART_DATA_READY); return FIFO_LENGTH - uart->len; } static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) { UART *uart = opaque; uart->receive = *buf; uart_add_to_fifo(uart, buf, size); uart->status |= UART_DATA_READY; if (uart->control & UART_RECEIVE_INTERRUPT) { Loading @@ -103,8 +150,38 @@ static void grlib_apbuart_event(void *opaque, int event) trace_grlib_apbuart_event(event); } static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr, static uint64_t grlib_apbuart_read(void *opaque, target_phys_addr_t addr, unsigned size) { UART *uart = opaque; addr &= 0xff; /* Unit registers */ switch (addr) { case DATA_OFFSET: case DATA_OFFSET + 3: /* when only one byte read */ return uart_pop(uart); case STATUS_OFFSET: /* Read Only */ return uart->status; case CONTROL_OFFSET: return uart->control; case SCALER_OFFSET: /* Not supported */ return 0; default: trace_grlib_apbuart_readl_unknown(addr); return 0; } } static void grlib_apbuart_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { UART *uart = opaque; Loading @@ -115,6 +192,7 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr, /* Unit registers */ switch (addr) { case DATA_OFFSET: case DATA_OFFSET + 3: /* When only one byte write */ c = value & 0xFF; qemu_chr_fe_write(uart->chr, &c, 1); return; Loading @@ -124,7 +202,7 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr, return; case CONTROL_OFFSET: /* Not supported */ uart->control = value; return; case SCALER_OFFSET: Loading @@ -138,15 +216,9 @@ grlib_apbuart_write(void *opaque, target_phys_addr_t addr, trace_grlib_apbuart_writel_unknown(addr, value); } static bool grlib_apbuart_accepts(void *opaque, target_phys_addr_t addr, unsigned size, bool is_write) { return is_write && size == 4; } static const MemoryRegionOps grlib_apbuart_ops = { .write = grlib_apbuart_write, .valid.accepts = grlib_apbuart_accepts, .read = grlib_apbuart_read, .endianness = DEVICE_NATIVE_ENDIAN, }; Loading
trace-events +1 −0 Original line number Diff line number Diff line Loading @@ -351,6 +351,7 @@ grlib_irqmp_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" valu # hw/grlib_apbuart.c grlib_apbuart_event(int event) "event:%d" grlib_apbuart_writel_unknown(uint64_t addr, uint32_t value) "addr 0x%"PRIx64" value 0x%x" grlib_apbuart_readl_unknown(uint64_t addr) "addr 0x%"PRIx64"" # hw/leon3.c leon3_set_irq(int intno) "Set CPU IRQ %d" Loading