mips32-nemu: add ioe
This commit is contained in:
parent
d0e185cf9e
commit
16f8226f12
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue