mirror of
https://github.com/yann64/haikuports.git
synced 2026-04-18 01:30:07 +02:00
1040 lines
28 KiB
Plaintext
1040 lines
28 KiB
Plaintext
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
|
|
|