mips32-nemu: add ioe

This commit is contained in:
Zihao Yu 2019-01-14 01:18:13 +08:00
parent d0e185cf9e
commit 16f8226f12
10 changed files with 180 additions and 41 deletions

View File

@ -1,6 +1,16 @@
#ifndef __ARCH_H__
#define __ARCH_H__
struct _Context {
uint32_t at,
v0,v1,
a0,a1,a2,a3,
t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,
s0,s1,s2,s3,s4,s5,s6,s7,
k0,k1,
gp,sp,fp,ra;
};
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -1,24 +0,0 @@
#ifndef __MIPS32_QEMU_H__
#define __MIPS32_QEMU_H__
#define EX_ENTRY 0x180
#ifndef __ASSEMBLER__
#include <arch.h>
#define MMIO_BASE 0x1fd00000
struct _Context {
uint32_t at,
v0,v1,
a0,a1,a2,a3,
t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,
s0,s1,s2,s3,s4,s5,s6,s7,
k0,k1,
gp,sp,fp,ra;
};
#endif
#endif

View File

@ -0,0 +1,20 @@
#ifndef __MIPS32_H__
#define __MIPS32_H__
#define EX_ENTRY 0x180
#ifndef __ASSEMBLER__
#include <arch.h>
static inline uint8_t inb(uintptr_t addr) { return *(volatile uint8_t *)addr; }
static inline uint16_t inw(uintptr_t addr) { return *(volatile uint16_t *)addr; }
static inline uint32_t inl(uintptr_t addr) { return *(volatile uint32_t *)addr; }
static inline void outb(uintptr_t addr, uint8_t data) { *(volatile uint8_t *)addr = data; }
static inline void outw(uintptr_t addr, uint16_t data) { *(volatile uint16_t *)addr = data; }
static inline void outl(uintptr_t addr, uint32_t data) { *(volatile uint32_t *)addr = data; }
#endif
#endif

View File

@ -0,0 +1,19 @@
#include <am.h>
#include <mips32.h>
#include <amdev.h>
#define KBD_DATA_PORT 0x60
#define KEYDOWN_MASK 0x8000
size_t input_read(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_INPUT_KBD: {
_KbdReg *kbd = (_KbdReg *)buf;
int k = inl(KBD_DATA_PORT);
kbd->keydown = (k & KEYDOWN_MASK ? 1 : 0);
kbd->keycode = k & ~KEYDOWN_MASK;
return sizeof(_KbdReg);
}
}
return 0;
}

View File

@ -0,0 +1,32 @@
#include <am.h>
#include <mips32.h>
#include <amdev.h>
#define RTC_MMIO 0x4048 // Note that this is not standard
static unsigned long boot_time;
size_t timer_read(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_TIMER_UPTIME: {
_UptimeReg *uptime = (_UptimeReg *)buf;
uptime->hi = 0;
uptime->lo = inl(RTC_MMIO) - boot_time;
return sizeof(_UptimeReg);
}
case _DEVREG_TIMER_DATE: {
_RTCReg *rtc = (_RTCReg *)buf;
rtc->second = 0;
rtc->minute = 0;
rtc->hour = 0;
rtc->day = 0;
rtc->month = 0;
rtc->year = 2018;
return sizeof(_RTCReg);
}
}
return 0;
}
void timer_init() {
boot_time = inl(RTC_MMIO);
}

View File

@ -0,0 +1,52 @@
#include <am.h>
#include <mips32.h>
#include <amdev.h>
#include <klib.h>
#define SCREEN_PORT 0x100
static int W, H;
static uint32_t* const fb = (uint32_t *)0x40000;
size_t video_read(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_VIDEO_INFO: {
_VideoInfoReg *info = (_VideoInfoReg *)buf;
info->width = W;
info->height = H;
return sizeof(_VideoInfoReg);
}
}
return 0;
}
size_t video_write(uintptr_t reg, void *buf, size_t size) {
switch (reg) {
case _DEVREG_VIDEO_FBCTL: {
_FBCtlReg *ctl = (_FBCtlReg *)buf;
int x = ctl->x, y = ctl->y, w = ctl->w, h = ctl->h;
uint32_t *pixels = ctl->pixels;
int len = sizeof(uint32_t) * ( (x + w >= W) ? W - x : w );
uint32_t *p_fb = &fb[y * W + x];
int j;
for (j = 0; j < h; j ++) {
if (y + j < H) { memcpy(p_fb, pixels, len); }
else { break; }
p_fb += W;
pixels += w;
}
if (ctl->sync) {
// do nothing, hardware syncs.
}
return size;
}
}
return 0;
}
void vga_init() {
uint32_t data = inl(SCREEN_PORT);
W = data >> 16;
H = data & 0xffff;
}

View File

@ -0,0 +1,41 @@
#include <am.h>
#include <amdev.h>
#include <klib.h>
static inline size_t no_read(uintptr_t reg, void *buf, size_t size) {
assert(0);
return 0;
}
static inline size_t no_write(uintptr_t reg, void *buf, size_t size) {
assert(0);
return 0;
}
void vga_init();
void timer_init();
int _ioe_init() {
vga_init();
timer_init();
return 0;
}
size_t timer_read(uintptr_t reg, void *buf, size_t size);
size_t video_read(uintptr_t reg, void *buf, size_t size);
size_t video_write(uintptr_t reg, void *buf, size_t size);
size_t input_read(uintptr_t reg, void *buf, size_t size);
static _Device nemu_dev[] = {
{_DEV_TIMER, "NEMU Timer", timer_read, no_write},
{_DEV_INPUT, "NEMU Keyboard Controller", input_read, no_write},
{_DEV_VIDEO, "NEMU VGA Controller", video_read, video_write},
};
#define NR_DEV (sizeof(nemu_dev) / sizeof(nemu_dev[0]))
_Device *_device(int n) {
n --;
return (n >= 0 && (unsigned int)n < NR_DEV) ? &nemu_dev[n] : NULL;
}

View File

@ -1,10 +1,10 @@
#include <am.h>
#include <mips32-nemu.h>
#include <mips32.h>
// Define this macro after serial has been implemented
#define HAS_SERIAL
#define SERIAL_PORT ((volatile char *)((MMIO_BASE) + 0x3f8))
#define SERIAL_PORT 0x43f8
extern char _heap_start;
extern char _heap_end;
@ -17,7 +17,7 @@ _Area _heap = {
void _putc(char ch) {
#ifdef HAS_SERIAL
SERIAL_PORT[0] = ch;
outb(SERIAL_PORT, ch);
#endif
}

View File

@ -1,11 +0,0 @@
#ifndef __X86_NEMU_H__
#define __X86_NEMU_H__
#ifndef __ASSEMBLER__
/* The following code will be included if the source file is a "*.c" file. */
#include <arch.h>
#endif
#endif

View File

@ -27,15 +27,15 @@ size_t video_write(uintptr_t reg, void *buf, size_t size);
size_t input_read(uintptr_t reg, void *buf, size_t size);
static _Device n86_dev[] = {
static _Device nemu_dev[] = {
{_DEV_TIMER, "NEMU Timer", timer_read, no_write},
{_DEV_INPUT, "NEMU Keyboard Controller", input_read, no_write},
{_DEV_VIDEO, "NEMU VGA Controller", video_read, video_write},
};
#define NR_DEV (sizeof(n86_dev) / sizeof(n86_dev[0]))
#define NR_DEV (sizeof(nemu_dev) / sizeof(nemu_dev[0]))
_Device *_device(int n) {
n --;
return (n >= 0 && (unsigned int)n < NR_DEV) ? &n86_dev[n] : NULL;
return (n >= 0 && (unsigned int)n < NR_DEV) ? &nemu_dev[n] : NULL;
}