Last active
May 16, 2021 14:03
-
-
Save X547/4d345a9ebe65ebc954baf13807cf61be to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 2baa0abbbb8a97b0c1eb70b1aeafcf7fdba25ad4 Mon Sep 17 00:00:00 2001 | |
From: X512 <danger_mail@list.ru> | |
Date: Wed, 12 May 2021 18:03:24 +0900 | |
Subject: WIP: Haiku patches, share UART with RISC-V machine | |
--- | |
Makefile | 9 +- | |
cutils.h | 2 +- | |
fs_disk.c | 15 +++ | |
riscv_cpu.c | 7 +- | |
riscv_machine.c | 26 ++++- | |
sdl.c | 2 +- | |
temu.c | 18 ++-- | |
uart.c | 228 +++++++++++++++++++++++++++++++++++++++ | |
uart.h | 58 ++++++++++ | |
x86_machine.c | 275 +----------------------------------------------- | |
10 files changed, 349 insertions(+), 291 deletions(-) | |
create mode 100644 uart.c | |
create mode 100644 uart.h | |
diff --git a/Makefile b/Makefile | |
index 390ae37..dc059cd 100644 | |
--- a/Makefile | |
+++ b/Makefile | |
@@ -24,12 +24,12 @@ | |
# if set, network filesystem is enabled. libcurl and libcrypto | |
# (openssl) must be installed. | |
-CONFIG_FS_NET=y | |
+#CONFIG_FS_NET=y | |
# SDL support (optional) | |
CONFIG_SDL=y | |
# if set, compile the 128 bit emulator. Note: the 128 bit target does | |
# not compile if gcc does not support the int128 type (32 bit hosts). | |
-CONFIG_INT128=y | |
+#CONFIG_INT128=y | |
# build x86 emulator | |
CONFIG_X86EMU=y | |
# win32 build (not usable yet) | |
@@ -62,7 +62,7 @@ endif | |
all: $(PROGS) | |
-EMU_OBJS:=virtio.o pci.o fs.o cutils.o iomem.o simplefb.o \ | |
+EMU_OBJS:=virtio.o uart.o pci.o fs.o cutils.o iomem.o simplefb.o \ | |
json.o machine.o temu.o | |
ifdef CONFIG_SLIRP | |
@@ -72,7 +72,8 @@ endif | |
ifndef CONFIG_WIN32 | |
EMU_OBJS+=fs_disk.o | |
-EMU_LIBS=-lrt | |
+#EMU_LIBS=-lrt | |
+EMU_LIBS=-lnetwork | |
endif | |
ifdef CONFIG_FS_NET | |
CFLAGS+=-DCONFIG_FS_NET | |
diff --git a/cutils.h b/cutils.h | |
index 689542e..19283e2 100644 | |
--- a/cutils.h | |
+++ b/cutils.h | |
@@ -84,7 +84,7 @@ static inline int min_int(int a, int b) | |
void *mallocz(size_t size); | |
-#if defined(_WIN32) | |
+#if defined(_WIN32) || defined(__HAIKU__) | |
static inline uint32_t bswap_32(uint32_t v) | |
{ | |
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) | | |
diff --git a/fs_disk.c b/fs_disk.c | |
index bf96c89..11708d9 100644 | |
--- a/fs_disk.c | |
+++ b/fs_disk.c | |
@@ -27,9 +27,13 @@ | |
#include <inttypes.h> | |
#include <assert.h> | |
#include <stdarg.h> | |
+#if !defined(__HAIKU__) | |
#include <sys/statfs.h> | |
+#endif | |
#include <sys/stat.h> | |
+#if !defined(__HAIKU__) | |
#include <sys/sysmacros.h> | |
+#endif | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <dirent.h> | |
@@ -144,6 +148,7 @@ static void stat_to_qid(FSQID *qid, const struct stat *st) | |
static void fs_statfs(FSDevice *fs1, FSStatFS *st) | |
{ | |
+#if !defined(__HAIKU__) | |
FSDeviceDisk *fs = (FSDeviceDisk *)fs1; | |
struct statfs st1; | |
statfs(fs->root_path, &st1); | |
@@ -153,6 +158,7 @@ static void fs_statfs(FSDevice *fs1, FSStatFS *st) | |
st->f_bavail = st1.f_bavail; | |
st->f_files = st1.f_files; | |
st->f_ffree = st1.f_ffree; | |
+#endif | |
} | |
static char *compose_path(const char *path, const char *name) | |
@@ -312,6 +318,10 @@ static int fs_readdir(FSDevice *fs, FSFile *f, uint64_t offset, | |
if ((pos + len) > count) | |
break; | |
offset = telldir(f->u.dirp); | |
+#if defined(__HAIKU__) | |
+ d_type = 0; | |
+ type = P9_QTFILE; | |
+#else | |
d_type = de->d_type; | |
if (d_type == DT_UNKNOWN) { | |
char *path; | |
@@ -330,6 +340,7 @@ static int fs_readdir(FSDevice *fs, FSFile *f, uint64_t offset, | |
type = P9_QTSYMLINK; | |
else | |
type = P9_QTFILE; | |
+#endif | |
buf[pos++] = type; | |
put_le32(buf + pos, 0); /* version */ | |
pos += 4; | |
@@ -507,6 +518,9 @@ static int fs_mknod(FSDevice *fs, FSQID *qid, | |
FSFile *f, const char *name, uint32_t mode, uint32_t major, | |
uint32_t minor, uint32_t gid) | |
{ | |
+#if defined(__HAIKU__) | |
+ return -errno_to_p9(ENOTSUP); | |
+#else | |
char *path; | |
struct stat st; | |
@@ -522,6 +536,7 @@ static int fs_mknod(FSDevice *fs, FSQID *qid, | |
free(path); | |
stat_to_qid(qid, &st); | |
return 0; | |
+#endif | |
} | |
static int fs_readlink(FSDevice *fs, char *buf, int buf_size, FSFile *f) | |
diff --git a/riscv_cpu.c b/riscv_cpu.c | |
index ba4fa4c..cfb910a 100644 | |
--- a/riscv_cpu.c | |
+++ b/riscv_cpu.c | |
@@ -40,7 +40,7 @@ | |
#error CONFIG_RISCV_MAX_XLEN must be defined | |
#endif | |
-//#define DUMP_INVALID_MEM_ACCESS | |
+#define DUMP_INVALID_MEM_ACCESS | |
//#define DUMP_MMU_EXCEPTIONS | |
//#define DUMP_INTERRUPTS | |
//#define DUMP_INVALID_CSR | |
@@ -377,6 +377,8 @@ int target_read_slow(RISCVCPUState *s, mem_uint_t *pval, | |
#ifdef DUMP_INVALID_MEM_ACCESS | |
printf("target_read_slow: invalid physical address 0x"); | |
print_target_ulong(paddr); | |
+ printf(", PC: "); | |
+ print_target_ulong(s->pc); | |
printf("\n"); | |
#endif | |
return 0; | |
@@ -464,7 +466,10 @@ int target_write_slow(RISCVCPUState *s, target_ulong addr, | |
#ifdef DUMP_INVALID_MEM_ACCESS | |
printf("target_write_slow: invalid physical address 0x"); | |
print_target_ulong(paddr); | |
+ printf(", PC: "); | |
+ print_target_ulong(s->pc); | |
printf("\n"); | |
+ exit(1); | |
#endif | |
} else if (pr->is_ram) { | |
phys_mem_set_dirty_bit(pr, paddr - pr->addr); | |
diff --git a/riscv_machine.c b/riscv_machine.c | |
index a7149fd..0e27da4 100644 | |
--- a/riscv_machine.c | |
+++ b/riscv_machine.c | |
@@ -35,6 +35,7 @@ | |
#include "cutils.h" | |
#include "iomem.h" | |
#include "riscv_cpu.h" | |
+#include "uart.h" | |
#include "virtio.h" | |
#include "machine.h" | |
@@ -56,6 +57,7 @@ typedef struct RISCVMachine { | |
/* HTIF */ | |
uint64_t htif_tohost, htif_fromhost; | |
+ SerialState *serial_state; | |
VIRTIODevice *keyboard_dev; | |
VIRTIODevice *mouse_dev; | |
@@ -74,6 +76,9 @@ typedef struct RISCVMachine { | |
#define PLIC_BASE_ADDR 0x40100000 | |
#define PLIC_SIZE 0x00400000 | |
#define FRAMEBUFFER_BASE_ADDR 0x41000000 | |
+#define UART_BASE_ADDR 0x10000000 | |
+#define UART_SIZE 0x100 | |
+#define UART_IRQ 10 | |
#define RTC_FREQ 10000000 | |
#define RTC_FREQ_DIV 16 /* arbitrary, relative to CPU freq to have a | |
@@ -192,6 +197,14 @@ static void htif_poll(RISCVMachine *s) | |
} | |
#endif | |
+static void serial_write_cb(void *opaque, const uint8_t *buf, int buf_len) | |
+{ | |
+ RISCVMachine *s = opaque; | |
+ if (s->common.console) { | |
+ s->common.console->write_data(s->common.console->opaque, buf, buf_len); | |
+ } | |
+} | |
+ | |
static uint32_t clint_read(void *opaque, uint32_t offset, int size_log2) | |
{ | |
RISCVMachine *m = opaque; | |
@@ -696,6 +709,14 @@ static int riscv_build_fdt(RISCVMachine *m, uint8_t *dst, | |
fdt_prop_u32(s, "phandle", plic_phandle); | |
fdt_end_node(s); /* plic */ | |
+ | |
+ fdt_begin_node_num(s, "serial", UART_BASE_ADDR); | |
+ fdt_prop_str(s, "compatible", "ns16550a"); | |
+ fdt_prop_tab_u64_2(s, "reg", UART_BASE_ADDR, UART_SIZE); | |
+ tab[0] = plic_phandle; | |
+ tab[1] = UART_IRQ; | |
+ fdt_prop_tab_u32(s, "interrupts-extended", tab, 2); | |
+ fdt_end_node(s); /* serial */ | |
for(i = 0; i < m->virtio_count; i++) { | |
fdt_begin_node_num(s, "virtio", VIRTIO_BASE_ADDR + i * VIRTIO_SIZE); | |
@@ -739,7 +760,7 @@ static int riscv_build_fdt(RISCVMachine *m, uint8_t *dst, | |
fdt_end_node(s); /* / */ | |
size = fdt_output(s, dst); | |
-#if 0 | |
+#if 1 | |
{ | |
FILE *f; | |
f = fopen("/tmp/riscvemu.dtb", "wb"); | |
@@ -881,6 +902,9 @@ static VirtMachine *riscv_machine_init(const VirtMachineParams *p) | |
s, htif_read, htif_write, DEVIO_SIZE32); | |
s->common.console = p->console; | |
+ s->serial_state = serial_init(s->mem_map, UART_BASE_ADDR, &s->plic_irq[UART_IRQ], | |
+ serial_write_cb, s); | |
+ | |
memset(vbus, 0, sizeof(*vbus)); | |
vbus->mem_map = s->mem_map; | |
vbus->addr = VIRTIO_BASE_ADDR; | |
diff --git a/sdl.c b/sdl.c | |
index c2afeba..fba33aa 100644 | |
--- a/sdl.c | |
+++ b/sdl.c | |
@@ -84,7 +84,7 @@ static void sdl_update(FBDevice *fb_dev, void *opaque, | |
SDL_UpdateRect(screen, r.x, r.y, r.w, r.h); | |
} | |
-#if defined(_WIN32) | |
+#if defined(_WIN32) || defined(__HAIKU__) | |
static int sdl_get_keycode(const SDL_KeyboardEvent *ev) | |
{ | |
diff --git a/temu.c b/temu.c | |
index 7c07f3b..f5372d8 100644 | |
--- a/temu.c | |
+++ b/temu.c | |
@@ -36,8 +36,10 @@ | |
#include <termios.h> | |
#include <sys/ioctl.h> | |
#include <net/if.h> | |
+#ifndef __HAIKU__ | |
#include <linux/if_tun.h> | |
#endif | |
+#endif | |
#include <sys/stat.h> | |
#include <signal.h> | |
@@ -346,7 +348,7 @@ static BlockDevice *block_device_init(const char *filename, | |
return bs; | |
} | |
-#ifndef _WIN32 | |
+#if !defined(_WIN32) && !defined(__HAIKU__) | |
typedef struct { | |
int fd; | |
@@ -763,7 +765,7 @@ int main(int argc, char **argv) | |
} else | |
#endif | |
{ | |
-#ifdef _WIN32 | |
+#if defined(_WIN32) | |
fprintf(stderr, "Filesystem access not supported yet\n"); | |
exit(1); | |
#else | |
@@ -788,7 +790,7 @@ int main(int argc, char **argv) | |
exit(1); | |
} else | |
#endif | |
-#ifndef _WIN32 | |
+#if !defined(_WIN32) && !defined(__HAIKU__) | |
if (!strcmp(p->tab_eth[i].driver, "tap")) { | |
p->tab_eth[i].net = tun_open(p->tab_eth[i].ifname); | |
if (!p->tab_eth[i].net) | |
@@ -805,16 +807,14 @@ int main(int argc, char **argv) | |
#ifdef CONFIG_SDL | |
if (p->display_device) { | |
sdl_init(p->width, p->height); | |
- } else | |
+ } | |
#endif | |
- { | |
#ifdef _WIN32 | |
- fprintf(stderr, "Console not supported yet\n"); | |
- exit(1); | |
+ fprintf(stderr, "Console not supported yet\n"); | |
+ exit(1); | |
#else | |
- p->console = console_init(allow_ctrlc); | |
+ p->console = console_init(allow_ctrlc); | |
#endif | |
- } | |
p->rtc_real_time = TRUE; | |
s = virt_machine_init(p); | |
diff --git a/uart.c b/uart.c | |
new file mode 100644 | |
index 0000000..147160d | |
--- /dev/null | |
+++ b/uart.c | |
@@ -0,0 +1,228 @@ | |
+#include "uart.h" | |
+#include <stdint.h> | |
+ | |
+static void serial_write(void *opaque, uint32_t offset, | |
+ uint32_t val, int size_log2); | |
+static uint32_t serial_read(void *opaque, uint32_t offset, int size_log2); | |
+ | |
+SerialState *serial_init(PhysMemoryMap *port_map, int addr, | |
+ IRQSignal *irq, | |
+ void (*write_func)(void *opaque, const uint8_t *buf, int buf_len), void *opaque) | |
+{ | |
+ SerialState *s; | |
+ s = mallocz(sizeof(*s)); | |
+ | |
+ /* all 8 bit registers */ | |
+ s->divider = 0; | |
+ s->rbr = 0; /* receive register */ | |
+ s->ier = 0; | |
+ s->iir = UART_IIR_NO_INT; /* read only */ | |
+ s->lcr = 0; | |
+ s->mcr = 0; | |
+ s->lsr = UART_LSR_TEMT | UART_LSR_THRE; /* read only */ | |
+ s->msr = 0; | |
+ s->scr = 0; | |
+ s->fcr = 0; | |
+ | |
+ s->irq = irq; | |
+ s->write_func = write_func; | |
+ s->opaque = opaque; | |
+ | |
+ cpu_register_device(port_map, addr, 8, s, serial_read, serial_write, | |
+ DEVIO_SIZE8); | |
+ return s; | |
+} | |
+ | |
+static void serial_update_irq(SerialState *s) | |
+{ | |
+ if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { | |
+ s->iir = UART_IIR_RDI; | |
+ } else if ((s->lsr & UART_LSR_THRE) && (s->ier & UART_IER_THRI)) { | |
+ s->iir = UART_IIR_THRI; | |
+ } else { | |
+ s->iir = UART_IIR_NO_INT; | |
+ } | |
+ if (s->iir != UART_IIR_NO_INT) { | |
+ set_irq(s->irq, 1); | |
+ } else { | |
+ set_irq(s->irq, 0); | |
+ } | |
+} | |
+ | |
+#if 0 | |
+/* send remainining chars in fifo */ | |
+Serial.prototype.write_tx_fifo = function() | |
+{ | |
+ if (s->tx_fifo != "") { | |
+ s->write_func(s->tx_fifo); | |
+ s->tx_fifo = ""; | |
+ | |
+ s->lsr |= UART_LSR_THRE; | |
+ s->lsr |= UART_LSR_TEMT; | |
+ s->update_irq(); | |
+ } | |
+} | |
+#endif | |
+ | |
+static void serial_write(void *opaque, uint32_t offset, | |
+ uint32_t val, int size_log2) | |
+{ | |
+ SerialState *s = opaque; | |
+ int addr; | |
+ | |
+ addr = offset & 7; | |
+ switch(addr) { | |
+ default: | |
+ case 0: | |
+ if (s->lcr & UART_LCR_DLAB) { | |
+ s->divider = (s->divider & 0xff00) | val; | |
+ } else { | |
+#if 0 | |
+ if (s->fcr & UART_FCR_FE) { | |
+ s->tx_fifo += String.fromCharCode(val); | |
+ s->lsr &= ~UART_LSR_THRE; | |
+ serial_update_irq(s); | |
+ if (s->tx_fifo.length >= UART_FIFO_LENGTH) { | |
+ /* write to the terminal */ | |
+ s->write_tx_fifo(); | |
+ } | |
+ } else | |
+#endif | |
+ { | |
+ uint8_t ch; | |
+ s->lsr &= ~UART_LSR_THRE; | |
+ serial_update_irq(s); | |
+ | |
+ /* write to the terminal */ | |
+ ch = val; | |
+ s->write_func(s->opaque, &ch, 1); | |
+ s->lsr |= UART_LSR_THRE; | |
+ s->lsr |= UART_LSR_TEMT; | |
+ serial_update_irq(s); | |
+ } | |
+ } | |
+ break; | |
+ case 1: | |
+ if (s->lcr & UART_LCR_DLAB) { | |
+ s->divider = (s->divider & 0x00ff) | (val << 8); | |
+ } else { | |
+ s->ier = val; | |
+ serial_update_irq(s); | |
+ } | |
+ break; | |
+ case 2: | |
+#if 0 | |
+ if ((s->fcr ^ val) & UART_FCR_FE) { | |
+ /* clear fifos */ | |
+ val |= UART_FCR_XFR | UART_FCR_RFR; | |
+ } | |
+ if (val & UART_FCR_XFR) | |
+ s->tx_fifo = ""; | |
+ if (val & UART_FCR_RFR) | |
+ s->rx_fifo = ""; | |
+ s->fcr = val & UART_FCR_FE; | |
+#endif | |
+ break; | |
+ case 3: | |
+ s->lcr = val; | |
+ break; | |
+ case 4: | |
+ s->mcr = val; | |
+ break; | |
+ case 5: | |
+ break; | |
+ case 6: | |
+ s->msr = val; | |
+ break; | |
+ case 7: | |
+ s->scr = val; | |
+ break; | |
+ } | |
+} | |
+ | |
+static uint32_t serial_read(void *opaque, uint32_t offset, int size_log2) | |
+{ | |
+ SerialState *s = opaque; | |
+ int ret, addr; | |
+ | |
+ addr = offset & 7; | |
+ switch(addr) { | |
+ default: | |
+ case 0: | |
+ if (s->lcr & UART_LCR_DLAB) { | |
+ ret = s->divider & 0xff; | |
+ } else { | |
+ ret = s->rbr; | |
+ s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); | |
+ serial_update_irq(s); | |
+#if 0 | |
+ /* try to receive next chars */ | |
+ s->send_char_from_fifo(); | |
+#endif | |
+ } | |
+ break; | |
+ case 1: | |
+ if (s->lcr & UART_LCR_DLAB) { | |
+ ret = (s->divider >> 8) & 0xff; | |
+ } else { | |
+ ret = s->ier; | |
+ } | |
+ break; | |
+ case 2: | |
+ ret = s->iir; | |
+ if (s->fcr & UART_FCR_FE) | |
+ ret |= UART_IIR_FE; | |
+ break; | |
+ case 3: | |
+ ret = s->lcr; | |
+ break; | |
+ case 4: | |
+ ret = s->mcr; | |
+ break; | |
+ case 5: | |
+ ret = s->lsr; | |
+ break; | |
+ case 6: | |
+ ret = s->msr; | |
+ break; | |
+ case 7: | |
+ ret = s->scr; | |
+ break; | |
+ } | |
+ return ret; | |
+} | |
+ | |
+void serial_send_break(SerialState *s) | |
+{ | |
+ s->rbr = 0; | |
+ s->lsr |= UART_LSR_BI | UART_LSR_DR; | |
+ serial_update_irq(s); | |
+} | |
+ | |
+#if 0 | |
+static void serial_send_char(SerialState *s, int ch) | |
+{ | |
+ s->rbr = ch; | |
+ s->lsr |= UART_LSR_DR; | |
+ serial_update_irq(s); | |
+} | |
+ | |
+Serial.prototype.send_char_from_fifo = function() | |
+{ | |
+ var fifo; | |
+ | |
+ fifo = s->rx_fifo; | |
+ if (fifo != "" && !(s->lsr & UART_LSR_DR)) { | |
+ s->send_char(fifo.charCodeAt(0)); | |
+ s->rx_fifo = fifo.substr(1, fifo.length - 1); | |
+ } | |
+} | |
+ | |
+/* queue the string in the UART receive fifo and send it ASAP */ | |
+Serial.prototype.send_chars = function(str) | |
+{ | |
+ s->rx_fifo += str; | |
+ s->send_char_from_fifo(); | |
+} | |
+ | |
+#endif | |
diff --git a/uart.h b/uart.h | |
new file mode 100644 | |
index 0000000..12b92ec | |
--- /dev/null | |
+++ b/uart.h | |
@@ -0,0 +1,58 @@ | |
+#ifndef _UART_H_ | |
+#define _UART_H_ | |
+ | |
+#include <stddef.h> | |
+#include "cutils.h" | |
+#include "iomem.h" | |
+ | |
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ | |
+ | |
+#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ | |
+#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ | |
+#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ | |
+#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ | |
+ | |
+#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ | |
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ | |
+ | |
+#define UART_IIR_MSI 0x00 /* Modem status interrupt */ | |
+#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ | |
+#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ | |
+#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ | |
+#define UART_IIR_FE 0xC0 /* Fifo enabled */ | |
+ | |
+#define UART_LSR_TEMT 0x40 /* Transmitter empty */ | |
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ | |
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */ | |
+#define UART_LSR_FE 0x08 /* Frame error indicator */ | |
+#define UART_LSR_PE 0x04 /* Parity error indicator */ | |
+#define UART_LSR_OE 0x02 /* Overrun error indicator */ | |
+#define UART_LSR_DR 0x01 /* Receiver data ready */ | |
+ | |
+#define UART_FCR_XFR 0x04 /* XMIT Fifo Reset */ | |
+#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */ | |
+#define UART_FCR_FE 0x01 /* FIFO Enable */ | |
+ | |
+#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ | |
+ | |
+typedef struct { | |
+ uint8_t divider; | |
+ uint8_t rbr; /* receive register */ | |
+ uint8_t ier; | |
+ uint8_t iir; /* read only */ | |
+ uint8_t lcr; | |
+ uint8_t mcr; | |
+ uint8_t lsr; /* read only */ | |
+ uint8_t msr; | |
+ uint8_t scr; | |
+ uint8_t fcr; | |
+ IRQSignal *irq; | |
+ void (*write_func)(void *opaque, const uint8_t *buf, int buf_len); | |
+ void *opaque; | |
+} SerialState; | |
+ | |
+SerialState *serial_init(PhysMemoryMap *port_map, int addr, | |
+ IRQSignal *irq, | |
+ void (*write_func)(void *opaque, const uint8_t *buf, int buf_len), void *opaque); | |
+ | |
+#endif // _UART_H_ | |
diff --git a/x86_machine.c b/x86_machine.c | |
index db8f6bb..8497a45 100644 | |
--- a/x86_machine.c | |
+++ b/x86_machine.c | |
@@ -36,6 +36,7 @@ | |
#include "cutils.h" | |
#include "iomem.h" | |
#include "virtio.h" | |
+#include "uart.h" | |
#include "x86_cpu.h" | |
#include "machine.h" | |
#include "pci.h" | |
@@ -980,280 +981,6 @@ static int pit_update_irq(PITState *pit) | |
return delay / (PIT_FREQ / 1000); | |
} | |
-/***********************************************************/ | |
-/* serial port emulation */ | |
- | |
-#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ | |
- | |
-#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ | |
-#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ | |
-#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ | |
-#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ | |
- | |
-#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ | |
-#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ | |
- | |
-#define UART_IIR_MSI 0x00 /* Modem status interrupt */ | |
-#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ | |
-#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ | |
-#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ | |
-#define UART_IIR_FE 0xC0 /* Fifo enabled */ | |
- | |
-#define UART_LSR_TEMT 0x40 /* Transmitter empty */ | |
-#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ | |
-#define UART_LSR_BI 0x10 /* Break interrupt indicator */ | |
-#define UART_LSR_FE 0x08 /* Frame error indicator */ | |
-#define UART_LSR_PE 0x04 /* Parity error indicator */ | |
-#define UART_LSR_OE 0x02 /* Overrun error indicator */ | |
-#define UART_LSR_DR 0x01 /* Receiver data ready */ | |
- | |
-#define UART_FCR_XFR 0x04 /* XMIT Fifo Reset */ | |
-#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */ | |
-#define UART_FCR_FE 0x01 /* FIFO Enable */ | |
- | |
-#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ | |
- | |
-typedef struct { | |
- uint8_t divider; | |
- uint8_t rbr; /* receive register */ | |
- uint8_t ier; | |
- uint8_t iir; /* read only */ | |
- uint8_t lcr; | |
- uint8_t mcr; | |
- uint8_t lsr; /* read only */ | |
- uint8_t msr; | |
- uint8_t scr; | |
- uint8_t fcr; | |
- IRQSignal *irq; | |
- void (*write_func)(void *opaque, const uint8_t *buf, int buf_len); | |
- void *opaque; | |
-} SerialState; | |
- | |
-static void serial_write(void *opaque, uint32_t offset, | |
- uint32_t val, int size_log2); | |
-static uint32_t serial_read(void *opaque, uint32_t offset, int size_log2); | |
- | |
-SerialState *serial_init(PhysMemoryMap *port_map, int addr, | |
- IRQSignal *irq, | |
- void (*write_func)(void *opaque, const uint8_t *buf, int buf_len), void *opaque) | |
-{ | |
- SerialState *s; | |
- s = mallocz(sizeof(*s)); | |
- | |
- /* all 8 bit registers */ | |
- s->divider = 0; | |
- s->rbr = 0; /* receive register */ | |
- s->ier = 0; | |
- s->iir = UART_IIR_NO_INT; /* read only */ | |
- s->lcr = 0; | |
- s->mcr = 0; | |
- s->lsr = UART_LSR_TEMT | UART_LSR_THRE; /* read only */ | |
- s->msr = 0; | |
- s->scr = 0; | |
- s->fcr = 0; | |
- | |
- s->irq = irq; | |
- s->write_func = write_func; | |
- s->opaque = opaque; | |
- | |
- cpu_register_device(port_map, addr, 8, s, serial_read, serial_write, | |
- DEVIO_SIZE8); | |
- return s; | |
-} | |
- | |
-static void serial_update_irq(SerialState *s) | |
-{ | |
- if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { | |
- s->iir = UART_IIR_RDI; | |
- } else if ((s->lsr & UART_LSR_THRE) && (s->ier & UART_IER_THRI)) { | |
- s->iir = UART_IIR_THRI; | |
- } else { | |
- s->iir = UART_IIR_NO_INT; | |
- } | |
- if (s->iir != UART_IIR_NO_INT) { | |
- set_irq(s->irq, 1); | |
- } else { | |
- set_irq(s->irq, 0); | |
- } | |
-} | |
- | |
-#if 0 | |
-/* send remainining chars in fifo */ | |
-Serial.prototype.write_tx_fifo = function() | |
-{ | |
- if (s->tx_fifo != "") { | |
- s->write_func(s->tx_fifo); | |
- s->tx_fifo = ""; | |
- | |
- s->lsr |= UART_LSR_THRE; | |
- s->lsr |= UART_LSR_TEMT; | |
- s->update_irq(); | |
- } | |
-} | |
-#endif | |
- | |
-static void serial_write(void *opaque, uint32_t offset, | |
- uint32_t val, int size_log2) | |
-{ | |
- SerialState *s = opaque; | |
- int addr; | |
- | |
- addr = offset & 7; | |
- switch(addr) { | |
- default: | |
- case 0: | |
- if (s->lcr & UART_LCR_DLAB) { | |
- s->divider = (s->divider & 0xff00) | val; | |
- } else { | |
-#if 0 | |
- if (s->fcr & UART_FCR_FE) { | |
- s->tx_fifo += String.fromCharCode(val); | |
- s->lsr &= ~UART_LSR_THRE; | |
- serial_update_irq(s); | |
- if (s->tx_fifo.length >= UART_FIFO_LENGTH) { | |
- /* write to the terminal */ | |
- s->write_tx_fifo(); | |
- } | |
- } else | |
-#endif | |
- { | |
- uint8_t ch; | |
- s->lsr &= ~UART_LSR_THRE; | |
- serial_update_irq(s); | |
- | |
- /* write to the terminal */ | |
- ch = val; | |
- s->write_func(s->opaque, &ch, 1); | |
- s->lsr |= UART_LSR_THRE; | |
- s->lsr |= UART_LSR_TEMT; | |
- serial_update_irq(s); | |
- } | |
- } | |
- break; | |
- case 1: | |
- if (s->lcr & UART_LCR_DLAB) { | |
- s->divider = (s->divider & 0x00ff) | (val << 8); | |
- } else { | |
- s->ier = val; | |
- serial_update_irq(s); | |
- } | |
- break; | |
- case 2: | |
-#if 0 | |
- if ((s->fcr ^ val) & UART_FCR_FE) { | |
- /* clear fifos */ | |
- val |= UART_FCR_XFR | UART_FCR_RFR; | |
- } | |
- if (val & UART_FCR_XFR) | |
- s->tx_fifo = ""; | |
- if (val & UART_FCR_RFR) | |
- s->rx_fifo = ""; | |
- s->fcr = val & UART_FCR_FE; | |
-#endif | |
- break; | |
- case 3: | |
- s->lcr = val; | |
- break; | |
- case 4: | |
- s->mcr = val; | |
- break; | |
- case 5: | |
- break; | |
- case 6: | |
- s->msr = val; | |
- break; | |
- case 7: | |
- s->scr = val; | |
- break; | |
- } | |
-} | |
- | |
-static uint32_t serial_read(void *opaque, uint32_t offset, int size_log2) | |
-{ | |
- SerialState *s = opaque; | |
- int ret, addr; | |
- | |
- addr = offset & 7; | |
- switch(addr) { | |
- default: | |
- case 0: | |
- if (s->lcr & UART_LCR_DLAB) { | |
- ret = s->divider & 0xff; | |
- } else { | |
- ret = s->rbr; | |
- s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); | |
- serial_update_irq(s); | |
-#if 0 | |
- /* try to receive next chars */ | |
- s->send_char_from_fifo(); | |
-#endif | |
- } | |
- break; | |
- case 1: | |
- if (s->lcr & UART_LCR_DLAB) { | |
- ret = (s->divider >> 8) & 0xff; | |
- } else { | |
- ret = s->ier; | |
- } | |
- break; | |
- case 2: | |
- ret = s->iir; | |
- if (s->fcr & UART_FCR_FE) | |
- ret |= UART_IIR_FE; | |
- break; | |
- case 3: | |
- ret = s->lcr; | |
- break; | |
- case 4: | |
- ret = s->mcr; | |
- break; | |
- case 5: | |
- ret = s->lsr; | |
- break; | |
- case 6: | |
- ret = s->msr; | |
- break; | |
- case 7: | |
- ret = s->scr; | |
- break; | |
- } | |
- return ret; | |
-} | |
- | |
-void serial_send_break(SerialState *s) | |
-{ | |
- s->rbr = 0; | |
- s->lsr |= UART_LSR_BI | UART_LSR_DR; | |
- serial_update_irq(s); | |
-} | |
- | |
-#if 0 | |
-static void serial_send_char(SerialState *s, int ch) | |
-{ | |
- s->rbr = ch; | |
- s->lsr |= UART_LSR_DR; | |
- serial_update_irq(s); | |
-} | |
- | |
-Serial.prototype.send_char_from_fifo = function() | |
-{ | |
- var fifo; | |
- | |
- fifo = s->rx_fifo; | |
- if (fifo != "" && !(s->lsr & UART_LSR_DR)) { | |
- s->send_char(fifo.charCodeAt(0)); | |
- s->rx_fifo = fifo.substr(1, fifo.length - 1); | |
- } | |
-} | |
- | |
-/* queue the string in the UART receive fifo and send it ASAP */ | |
-Serial.prototype.send_chars = function(str) | |
-{ | |
- s->rx_fifo += str; | |
- s->send_char_from_fifo(); | |
-} | |
- | |
-#endif | |
#ifdef DEBUG_BIOS | |
static void bios_debug_write(void *opaque, uint32_t offset, | |
-- | |
2.30.2 | |
From da1e4672ff3f6fa53ee0c7ea72e6e116b8903999 Mon Sep 17 00:00:00 2001 | |
From: X512 <danger_mail@list.ru> | |
Date: Sun, 16 May 2021 22:58:16 +0900 | |
Subject: implement `utime` register | |
--- | |
riscv_cpu.c | 5 +++++ | |
1 file changed, 5 insertions(+) | |
diff --git a/riscv_cpu.c b/riscv_cpu.c | |
index cfb910a..b765be6 100644 | |
--- a/riscv_cpu.c | |
+++ b/riscv_cpu.c | |
@@ -29,6 +29,8 @@ | |
#include <assert.h> | |
#include <fcntl.h> | |
+#include <OS.h> // system_time() | |
+ | |
#include "cutils.h" | |
#include "iomem.h" | |
#include "riscv_cpu.h" | |
@@ -748,6 +750,9 @@ static int csr_read(RISCVCPUState *s, target_ulong *pval, uint32_t csr, | |
} | |
val = (int64_t)s->insn_counter; | |
break; | |
+ case 0xc01: /* utime */ | |
+ val = system_time(); | |
+ break; | |
case 0xc80: /* mcycleh */ | |
case 0xc82: /* minstreth */ | |
if (s->cur_xlen != 32) | |
-- | |
2.30.2 | |
From beafad98395ef74fc64c9b3461ee46879d9ae647 Mon Sep 17 00:00:00 2001 | |
From: X512 <danger_mail@list.ru> | |
Date: Sun, 16 May 2021 22:58:38 +0900 | |
Subject: virtio: increase queue size, style changes for Pe editor | |
--- | |
virtio.c | 22 +++++++++++----------- | |
1 file changed, 11 insertions(+), 11 deletions(-) | |
diff --git a/virtio.c b/virtio.c | |
index 8d07f44..56746db 100644 | |
--- a/virtio.c | |
+++ b/virtio.c | |
@@ -93,7 +93,7 @@ | |
#define MAX_QUEUE 8 | |
#define MAX_CONFIG_SPACE_SIZE 256 | |
-#define MAX_QUEUE_NUM 16 | |
+#define MAX_QUEUE_NUM 32 | |
typedef struct { | |
uint32_t ready; /* 0 or 1 */ | |
@@ -977,8 +977,8 @@ static void virtio_config_change_notify(VIRTIODevice *s) | |
set_irq(s->irq, 1); | |
} | |
-/*********************************************************************/ | |
-/* block device */ | |
+ | |
+//#pragma mark block device | |
typedef struct { | |
uint32_t type; | |
@@ -1131,8 +1131,8 @@ VIRTIODevice *virtio_block_init(VIRTIOBusDef *bus, BlockDevice *bs) | |
return (VIRTIODevice *)s; | |
} | |
-/*********************************************************************/ | |
-/* network device */ | |
+ | |
+//#pragma mark network device | |
typedef struct VIRTIONetDevice { | |
VIRTIODevice common; | |
@@ -1257,8 +1257,8 @@ VIRTIODevice *virtio_net_init(VIRTIOBusDef *bus, EthernetDevice *es) | |
return (VIRTIODevice *)s; | |
} | |
-/*********************************************************************/ | |
-/* console device */ | |
+ | |
+//#pragma mark console device | |
typedef struct VIRTIOConsoleDevice { | |
VIRTIODevice common; | |
@@ -1359,8 +1359,8 @@ VIRTIODevice *virtio_console_init(VIRTIOBusDef *bus, CharacterDevice *cs) | |
return (VIRTIODevice *)s; | |
} | |
-/*********************************************************************/ | |
-/* input device */ | |
+ | |
+//#pragma mark input device | |
enum { | |
VIRTIO_INPUT_CFG_UNSET = 0x00, | |
@@ -1643,8 +1643,8 @@ VIRTIODevice *virtio_input_init(VIRTIOBusDef *bus, VirtioInputTypeEnum type) | |
return (VIRTIODevice *)s; | |
} | |
-/*********************************************************************/ | |
-/* 9p filesystem device */ | |
+ | |
+//#pragma mark 9p filesystem device | |
typedef struct { | |
struct list_head link; | |
-- | |
2.30.2 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment