x86interface.c
来自「适合KS8695X」· C语言 代码 · 共 815 行 · 第 1/2 页
C
815 行
#include "x86emu.h"
#include "glue.h"
/*
* This isn't nice, but there are a lot of incompatibilities in the U-Boot and scitech include
* files that this is the only really workable solution.
* Might be cleaned out later.
*/
#ifdef DEBUG
#undef DEBUG
#endif
#undef IO_LOGGING
#undef MEM_LOGGING
#ifdef IO_LOGGING
#define LOGIO(port, format, args...) if (dolog(port)) _printf(format , ## args)
#else
#define LOGIO(port, format, args...)
#endif
#ifdef MEM_LOGGIN
#define LOGMEM(format, args...) _printf(format , ## args)
#else
#define LOGMEM(format, args...)
#endif
#ifdef DEBUG
#define PRINTF(format, args...) _printf(format , ## args)
#else
#define PRINTF(format, argc...)
#endif
typedef unsigned char UBYTE;
typedef unsigned short UWORD;
typedef unsigned long ULONG;
typedef char BYTE;
typedef short WORT;
typedef long LONG;
#define EMULATOR_MEM_SIZE (1024*1024)
#define EMULATOR_BIOS_OFFSET 0xC0000
#define EMULATOR_STRAP_OFFSET 0x30000
#define EMULATOR_STACK_OFFSET 0x20000
#define EMULATOR_LOGO_OFFSET 0x40000 /* If you change this, change the strap code, too */
#define VIDEO_BASE (void *)0xFD0B8000
extern char *getenv(char *);
extern int tstc(void);
extern int getc(void);
extern unsigned char video_get_attr(void);
int atoi(char *string)
{
int res = 0;
while (*string>='0' && *string <='9')
{
res *= 10;
res += *string-'0';
string++;
}
return res;
}
void cons_gets(char *buffer)
{
int i = 0;
char c = 0;
buffer[0] = 0;
if (getenv("x86_runthru")) return; /*FIXME: */
while (c != 0x0D && c != 0x0A)
{
while (!tstc());
c = getc();
if (c>=32 && c < 127)
{
buffer[i] = c;
i++;
buffer[i] = 0;
putc(c);
}
else
{
if (c == 0x08)
{
if (i>0) i--;
buffer[i] = 0;
}
}
}
buffer[i] = '\n';
buffer[i+1] = 0;
}
char *bios_date = "08/14/02";
UBYTE model = 0xFC;
UBYTE submodel = 0x00;
static inline UBYTE read_byte(volatile UBYTE* from)
{
int x;
asm volatile ("lbz %0,%1\n eieio" : "=r" (x) : "m" (*from));
return (UBYTE)x;
}
static inline void write_byte(volatile UBYTE *to, int x)
{
asm volatile ("stb %1,%0\n eieio" : "=m" (*to) : "r" (x));
}
static inline UWORD read_word_little(volatile UWORD *from)
{
int x;
asm volatile ("lhbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m" (*from));
return (UWORD)x;
}
static inline UWORD read_word_big(volatile UWORD *from)
{
int x;
asm volatile ("lhz %0,%1\n eieio" : "=r" (x) : "m" (*from));
return (UWORD)x;
}
static inline void write_word_little(volatile UWORD *to, int x)
{
asm volatile ("sthbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to));
}
static inline void write_word_big(volatile UWORD *to, int x)
{
asm volatile ("sth %1,%0\n eieio" : "=m" (*to) : "r" (x));
}
static inline ULONG read_long_little(volatile ULONG *from)
{
unsigned long x;
asm volatile ("lwbrx %0,0,%1\n eieio" : "=r" (x) : "r" (from), "m"(*from));
return (ULONG)x;
}
static inline ULONG read_long_big(volatile ULONG *from)
{
unsigned long x;
asm volatile ("lwz %0,%1\n eieio" : "=r" (x) : "m" (*from));
return (ULONG)x;
}
static inline void write_long_little(volatile ULONG *to, ULONG x)
{
asm volatile ("stwbrx %1,0,%2\n eieio" : "=m" (*to) : "r" (x), "r" (to));
}
static inline void write_long_big(volatile ULONG *to, ULONG x)
{
asm volatile ("stw %1,%0\n eieio" : "=m" (*to) : "r" (x));
}
static int log_init = 0;
static int log_do = 0;
static int log_low = 0;
int dolog(int port)
{
if (log_init && log_do)
{
if (log_low && port > 0x400) return 0;
return 1;
}
if (!log_init)
{
log_init = 1;
log_do = (getenv("x86_logio") != (char *)0);
log_low = (getenv("x86_loglow") != (char *)0);
if (log_do)
{
if (log_low && port > 0x400) return 0;
return 1;
}
}
return 0;
}
/* Converts an emulator address to a physical address. */
/* Handles all special cases (bios date, model etc), and might need work */
u32 memaddr(u32 addr)
{
/* if (addr >= 0xF0000 && addr < 0xFFFFF) printf("WARNING: Segment F access (0x%x)\n", addr); */
/* printf("MemAddr=%p\n", addr); */
if (addr >= 0xA0000 && addr < 0xC0000)
return 0xFD000000 + addr;
else if (addr >= 0xFFFF5 && addr < 0xFFFFE)
{
return (u32)bios_date+addr-0xFFFF5;
}
else if (addr == 0xFFFFE)
return (u32)&model;
else if (addr == 0xFFFFF)
return (u32)&submodel;
else if (addr >= 0x80000000)
{
/*printf("Warning: High memory access at 0x%x\n", addr); */
return addr;
}
else
return (u32)M.mem_base+addr;
}
u8 A1_rdb(u32 addr)
{
u8 a = read_byte((UBYTE *)memaddr(addr));
LOGMEM("rdb: %x -> %x\n", addr, a);
return a;
}
u16 A1_rdw(u32 addr)
{
u16 a = read_word_little((UWORD *)memaddr(addr));
LOGMEM("rdw: %x -> %x\n", addr, a);
return a;
}
u32 A1_rdl(u32 addr)
{
u32 a = read_long_little((ULONG *)memaddr(addr));
LOGMEM("rdl: %x -> %x\n", addr, a);
return a;
}
void A1_wrb(u32 addr, u8 val)
{
LOGMEM("wrb: %x <- %x\n", addr, val);
write_byte((UBYTE *)memaddr(addr), val);
}
void A1_wrw(u32 addr, u16 val)
{
LOGMEM("wrw: %x <- %x\n", addr, val);
write_word_little((UWORD *)memaddr(addr), val);
}
void A1_wrl(u32 addr, u32 val)
{
LOGMEM("wrl: %x <- %x\n", addr, val);
write_long_little((ULONG *)memaddr(addr), val);
}
X86EMU_memFuncs _A1_mem =
{
A1_rdb,
A1_rdw,
A1_rdl,
A1_wrb,
A1_wrw,
A1_wrl,
};
#define ARTICIAS_PCI_CFGADDR 0xfec00cf8
#define ARTICIAS_PCI_CFGDATA 0xfee00cfc
#define IOBASE 0xFE000000
#define in_byte(from) read_byte( (UBYTE *)port_to_mem(from))
#define in_word(from) read_word_little((UWORD *)port_to_mem(from))
#define in_long(from) read_long_little((ULONG *)port_to_mem(from))
#define out_byte(to, val) write_byte((UBYTE *)port_to_mem(to), val)
#define out_word(to, val) write_word_little((UWORD *)port_to_mem(to), val)
#define out_long(to, val) write_long_little((ULONG *)port_to_mem(to), val)
u32 port_to_mem(int port)
{
if (port >= 0xCFC && port <= 0xCFF) return 0xFEE00000+port;
else if (port >= 0xCF8 && port <= 0xCFB) return 0xFEC00000+port;
else return IOBASE + port;
}
u8 A1_inb(int port)
{
u8 a;
/*if (port == 0x3BA) return 0; */
a = in_byte(port);
LOGIO(port, "inb: %Xh -> %d (%Xh)\n", port, a, a);
return a;
}
u16 A1_inw(int port)
{
u16 a = in_word(port);
LOGIO(port, "inw: %Xh -> %d (%Xh)\n", port, a, a);
return a;
}
u32 A1_inl(int port)
{
u32 a = in_long(port);
LOGIO(port, "inl: %Xh -> %d (%Xh)\n", port, a, a);
return a;
}
void A1_outb(int port, u8 val)
{
LOGIO(port, "outb: %Xh <- %d (%Xh)\n", port, val, val);
/* if (port == 0xCF8) port = 0xCFB;
else if (port == 0xCF9) port = 0xCFA;
else if (port == 0xCFA) port = 0xCF9;
else if (port == 0xCFB) port = 0xCF8;*/
out_byte(port, val);
}
void A1_outw(int port, u16 val)
{
LOGIO(port, "outw: %Xh <- %d (%Xh)\n", port, val, val);
out_word(port, val);
}
void A1_outl(int port, u32 val)
{
LOGIO(port, "outl: %Xh <- %d (%Xh)\n", port, val, val);
out_long(port, val);
}
X86EMU_pioFuncs _A1_pio =
{
A1_inb,
A1_inw,
A1_inl,
A1_outb,
A1_outw,
A1_outl,
};
static int reloced_ops = 0;
void reloc_ops(void *reloc_addr)
{
extern void (*x86emu_optab[256])(u8);
extern void (*x86emu_optab2[256])(u8);
extern void tables_relocate(unsigned int offset);
int i;
unsigned long delta;
if (reloced_ops == 1) return;
reloced_ops = 1;
delta = TEXT_BASE - (unsigned long)reloc_addr;
for (i=0; i<256; i++)
{
x86emu_optab[i] -= delta;
x86emu_optab2[i] -= delta;
}
_A1_mem.rdb = A1_rdb;
_A1_mem.rdw = A1_rdw;
_A1_mem.rdl = A1_rdl;
_A1_mem.wrb = A1_wrb;
_A1_mem.wrw = A1_wrw;
_A1_mem.wrl = A1_wrl;
_A1_pio.inb = A1_inb;
_A1_pio.inw = A1_inw;
_A1_pio.inl = A1_inl;
_A1_pio.outb = A1_outb;
_A1_pio.outw = A1_outw;
_A1_pio.outl = A1_outl;
tables_relocate(delta);
}
#define ANY_KEY(text) \
printf(text); \
while (!tstc());
unsigned char more_strap[] = {
0xb4, 0x0, 0xb0, 0x2, 0xcd, 0x10,
};
#define MORE_STRAP_BYTES 6 /* Additional bytes of strap code */
unsigned char *done_msg="VGA Initialized\0";
int execute_bios(pci_dev_t gr_dev, void *reloc_addr)
{
extern void bios_init(void);
extern void remove_init_data(void);
extern int video_rows(void);
extern int video_cols(void);
extern int video_size(int, int);
u8 *strap;
unsigned char *logo;
u8 cfg;
int i;
char c;
char *s;
#ifdef EASTEREGG
int easteregg_active = 0;
#endif
char *pal_reset;
u8 *fb;
unsigned char *msg;
unsigned char current_attr;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?