Skip to content

Commit

Permalink
Misc changes
Browse files Browse the repository at this point in the history
- remove redundant addr >> 2 from PLIC MMIO access
- set the uart in_fd and out_fd using the registered fds in attribute of
  RISCV instance
- streamline the uart.c
- replace UART register magic number with enum.
  • Loading branch information
ChinYikMing committed Dec 10, 2024
1 parent 7b578a7 commit b4329fb
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 49 deletions.
8 changes: 4 additions & 4 deletions src/devices/plic.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
#include <stdint.h>

enum PLIC_REG {
PLIC_INTR_PENDING = 0x400,
PLIC_INTR_ENABLE = 0x800,
PLIC_INTR_PRIORITY_THRESHOLD = 0x80000,
PLIC_INTR_CLAIM_OR_COMPLETE = 0x80001,
PLIC_INTR_PENDING = 0x1000,
PLIC_INTR_ENABLE = 0x2000,
PLIC_INTR_PRIORITY_THRESHOLD = 0x200000,
PLIC_INTR_CLAIM_OR_COMPLETE = 0x200004,
};

/* PLIC */
Expand Down
49 changes: 20 additions & 29 deletions src/devices/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

/* Emulate 8250 (plain, without loopback mode support) */

#define U8250_INT_THRE 1
#define U8250_INTR_THRE 1

void u8250_update_interrupts(u8250_state_t *uart)
{
Expand Down Expand Up @@ -73,79 +73,70 @@ static uint8_t u8250_handle_in(u8250_state_t *uart)
return value;
}

static uint8_t u8250_reg_read(u8250_state_t *uart, uint32_t addr)
uint32_t u8250_read(u8250_state_t *uart, uint32_t addr)
{
uint8_t ret;
uint8_t ret = 0;

switch (addr) {
case 0:
case U8250_THR_RBR_DLL:
if (uart->lcr & (1 << 7)) /* DLAB */
return uart->dll;
return u8250_handle_in(uart);
case 1:
case U8250_IER_DLH:
if (uart->lcr & (1 << 7)) /* DLAB */
return uart->dlh;
return uart->ier;
case 2:
case U8250_IIR_FCR:
ret = (uart->current_intr << 1) | (uart->pending_intrs ? 0 : 1);
if (uart->current_intr == U8250_INT_THRE)
if (uart->current_intr == U8250_INTR_THRE)
uart->pending_intrs &= ~(1 << uart->current_intr);
return ret;
case 3:
case U8250_LCR:
return uart->lcr;
case 4:
case U8250_MCR:
return uart->mcr;
break;
case 5:
case U8250_LSR:
/* LSR = no error, TX done & ready */
return (0x60 | (uint8_t) uart->in_ready);
case 6:
case U8250_MSR:
/* MSR = carrier detect, no ring, data ready, clear to send. */
return 0xb0;
/* no scratch register, so we should be detected as a plain 8250. */
default:
return 0;
break;
}

return 0;
return (uint32_t) (int8_t) ret;
}

static void u8250_reg_write(u8250_state_t *uart, uint32_t addr, uint8_t value)
void u8250_write(u8250_state_t *uart, uint32_t addr, uint32_t value)
{
switch (addr) {
case 0:
case U8250_THR_RBR_DLL:
if (uart->lcr & (1 << 7)) { /* DLAB */
uart->dll = value;
break;
}
u8250_handle_out(uart, value);
uart->pending_intrs |= 1 << U8250_INT_THRE;
uart->pending_intrs |= 1 << U8250_INTR_THRE;
break;
case 1:
case U8250_IER_DLH:
if (uart->lcr & (1 << 7)) { /* DLAB */
uart->dlh = value;
break;
}
uart->ier = value;
break;
case 3:
case U8250_LCR:
uart->lcr = value;
break;
case 4:
case U8250_MCR:
uart->mcr = value;
break;
}
}

uint32_t u8250_read(u8250_state_t *uart, uint32_t addr)
{
return (uint32_t) (int8_t) u8250_reg_read(uart, addr);
}

void u8250_write(u8250_state_t *uart, uint32_t addr, uint32_t value)
{
u8250_reg_write(uart, addr, value);
}

u8250_state_t *u8250_new()
{
u8250_state_t *uart = calloc(1, sizeof(u8250_state_t));
Expand Down
11 changes: 11 additions & 0 deletions src/devices/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
#define IRQ_UART_SHIFT 1
#define IRQ_UART_BIT (1 << IRQ_UART_SHIFT)

enum UART_REG {
U8250_THR_RBR_DLL = 0,
U8250_IER_DLH,
U8250_IIR_FCR,
U8250_LCR,
U8250_MCR,
U8250_LSR,
U8250_MSR,
U8250_SR,
};

typedef struct {
uint8_t dll, dlh; /* divisor (ignored) */
uint8_t lcr; /* UART config */
Expand Down
30 changes: 16 additions & 14 deletions src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,20 @@ riscv_t *rv_create(riscv_user_t rv_attr)
/* reset */
rv_reset(rv, 0U);

/*
* default standard stream.
* rv_remap_stdstream() can be called to overwrite them
*
*/
attr->fd_map = map_init(int, FILE *, map_cmp_int);
rv_remap_stdstream(rv,
(fd_stream_pair_t[]){
{STDIN_FILENO, stdin},
{STDOUT_FILENO, stdout},
{STDERR_FILENO, stderr},
},
3);

#if !RV32_HAS(SYSTEM) || (RV32_HAS(SYSTEM) && RV32_HAS(ELF_LOADER))
elf_t *elf = elf_new();
assert(elf && elf_open(elf, attr->data.user.elf_program));
Expand Down Expand Up @@ -407,24 +421,12 @@ riscv_t *rv_create(riscv_user_t rv_attr)
/* setup UART */
attr->uart = u8250_new();
assert(attr->uart);
attr->uart->in_fd = 0;
attr->uart->out_fd = 1;
attr->uart->in_fd = attr->fd_stdin;
attr->uart->out_fd = attr->fd_stdout;

capture_keyboard_input();
#endif /* !RV32_HAS(SYSTEM) || (RV32_HAS(SYSTEM) && RV32_HAS(ELF_LOADER)) */

/* default standard stream.
* rv_remap_stdstream can be called to overwrite them
*/
attr->fd_map = map_init(int, FILE *, map_cmp_int);
rv_remap_stdstream(rv,
(fd_stream_pair_t[]){
{STDIN_FILENO, stdin},
{STDOUT_FILENO, stdout},
{STDERR_FILENO, stderr},
},
3);

/* create block and IRs memory pool */
rv->block_mp = mpool_create(sizeof(block_t) << BLOCK_MAP_CAPACITY_BITS,
sizeof(block_t));
Expand Down
4 changes: 2 additions & 2 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ enum SUPPORTED_MMIO {
switch(io){ \
case MMIO_PLIC: \
IIF(rw)( /* read */ \
mmio_read_val = plic_read(PRIV(rv)->plic, (addr & 0x3FFFFFF) >> 2); \
mmio_read_val = plic_read(PRIV(rv)->plic, addr & 0x3FFFFFF); \
plic_update_interrupts(PRIV(rv)->plic); \
return mmio_read_val; \
, /* write */ \
plic_write(PRIV(rv)->plic, (addr & 0x3FFFFFF) >> 2, val); \
plic_write(PRIV(rv)->plic, addr & 0x3FFFFFF, val); \
plic_update_interrupts(PRIV(rv)->plic); \
return; \
) \
Expand Down

0 comments on commit b4329fb

Please sign in to comment.