added VGA emulation - added PS/2 mouse and keyboard emulation - use SDL for VGA display

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@356 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-08-10 21:52:11 +00:00
parent 4cbf74b6b8
commit 313aa56710
2 changed files with 454 additions and 120 deletions

529
vl.c
View File

@ -74,6 +74,9 @@
/* debug PC keyboard */
//#define DEBUG_KBD
/* debug PC keyboard : only mouse */
//#define DEBUG_MOUSE
#define PHYS_RAM_BASE 0xac000000
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
@ -81,6 +84,8 @@
#define INITRD_LOAD_ADDR 0x00400000
#define KERNEL_PARAMS_ADDR 0x00090000
#define GUI_REFRESH_INTERVAL 30
#define MAX_DISKS 2
/* from plex86 (BSD license) */
@ -198,9 +203,6 @@ struct __attribute__ ((packed)) linux_params {
#define KERNEL_CS 0x10
#define KERNEL_DS 0x18
typedef void (IOPortWriteFunc)(CPUX86State *env, uint32_t address, uint32_t data);
typedef uint32_t (IOPortReadFunc)(CPUX86State *env, uint32_t address);
#define MAX_IOPORTS 4096
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
@ -212,6 +214,11 @@ int loglevel;
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
BlockDriverState *bs_table[MAX_DISKS];
int vga_ram_size;
static DisplayState display_state;
int nodisp;
int term_inited;
int64_t ticks_per_sec;
/***********************************************************/
/* x86 io ports */
@ -430,49 +437,6 @@ void hw_error(const char *fmt, ...)
abort();
}
/***********************************************************/
/* vga emulation */
static uint8_t vga_index;
static uint8_t vga_regs[256];
static int last_cursor_pos;
void update_console_messages(void)
{
int c, i, cursor_pos, eol;
cursor_pos = vga_regs[0x0f] | (vga_regs[0x0e] << 8);
eol = 0;
for(i = last_cursor_pos; i < cursor_pos; i++) {
c = phys_ram_base[0xb8000 + (i) * 2];
if (c >= ' ') {
putchar(c);
eol = 0;
} else {
if (!eol)
putchar('\n');
eol = 1;
}
}
fflush(stdout);
last_cursor_pos = cursor_pos;
}
/* just to see first Linux console messages, we intercept cursor position */
void vga_ioport_write(CPUX86State *env, uint32_t addr, uint32_t data)
{
switch(addr) {
case 0x3d4:
vga_index = data;
break;
case 0x3d5:
vga_regs[vga_index] = data;
if (vga_index == 0x0f)
update_console_messages();
break;
}
}
/***********************************************************/
/* cmos emulation */
@ -555,6 +519,7 @@ void cmos_init(void)
/* various important CMOS locations needed by PC/Bochs bios */
cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */
cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */
/* memory size */
val = (phys_ram_size / 1024) - 1024;
@ -674,13 +639,13 @@ static void pic_update_irq(void)
int64_t irq_time[16];
int64_t cpu_get_ticks(void);
#endif
#ifdef DEBUG_PIC
#if defined(DEBUG_PIC)
int irq_level[16];
#endif
void pic_set_irq(int irq, int level)
{
#ifdef DEBUG_PIC
#if defined(DEBUG_PIC)
if (level != irq_level[irq]) {
printf("pic_set_irq: irq=%d level=%d\n", irq, level);
irq_level[irq] = level;
@ -702,7 +667,9 @@ int cpu_x86_get_pic_interrupt(CPUX86State *env)
/* signal the pic that the irq was acked by the CPU */
irq = pic_irq_requested;
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%Ld\n", irq, cpu_get_ticks() - irq_time[irq]);
printf("IRQ%d latency=%0.3fus\n",
irq,
(double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec);
#endif
#ifdef DEBUG_PIC
printf("pic_interrupt: irq=%d\n", irq);
@ -761,18 +728,22 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
}
if (val == 0xa0)
s->priority_add = (s->priority_add + 1) & 7;
pic_update_irq();
break;
case 0x60 ... 0x67:
priority = val & 7;
s->isr &= ~(1 << priority);
pic_update_irq();
break;
case 0xc0 ... 0xc7:
s->priority_add = (val + 1) & 7;
pic_update_irq();
break;
case 0xe0 ... 0xe7:
priority = val & 7;
s->isr &= ~(1 << priority);
s->priority_add = (priority + 1) & 7;
pic_update_irq();
break;
}
}
@ -861,8 +832,6 @@ int speaker_data_on;
int dummy_refresh_clock;
int pit_min_timer_count = 0;
int64_t ticks_per_sec;
int64_t get_clock(void)
{
struct timeval tv;
@ -1354,37 +1323,6 @@ void serial_received_byte(SerialState *s, int ch)
}
}
/* init terminal so that we can grab keys */
static struct termios oldtty;
static void term_exit(void)
{
tcsetattr (0, TCSANOW, &oldtty);
}
static void term_init(void)
{
struct termios tty;
tcgetattr (0, &tty);
oldtty = tty;
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
tty.c_oflag |= OPOST;
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
tty.c_cflag &= ~(CSIZE|PARENB);
tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr (0, TCSANOW, &tty);
atexit(term_exit);
fcntl(0, F_SETFL, O_NONBLOCK);
}
void serial_init(void)
{
SerialState *s = &serial_ports[0];
@ -1393,8 +1331,6 @@ void serial_init(void)
register_ioport_write(0x3f8, 8, serial_ioport_write, 1);
register_ioport_read(0x3f8, 8, serial_ioport_read, 1);
term_init();
}
/***********************************************************/
@ -2597,69 +2533,111 @@ void ide_init(void)
#define KBD_MODE_RFU 0x80
/* Mouse Commands */
#define AUX_SET_RES 0xE8 /* Set resolution */
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
#define AUX_SET_RES 0xE8 /* Set resolution */
#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
#define AUX_SET_STREAM 0xEA /* Set stream mode */
#define AUX_POLL 0xEB /* Poll */
#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
#define AUX_SET_WRAP 0xEE /* Set wrap mode */
#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
#define AUX_GET_TYPE 0xF2 /* Get type */
#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
#define AUX_SET_DEFAULT 0xF6
#define AUX_RESET 0xFF /* Reset aux device */
#define AUX_ACK 0xFA /* Command byte ACK. */
#define KBD_QUEUE_SIZE 64
#define MOUSE_STATUS_REMOTE 0x40
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10
#define KBD_QUEUE_SIZE 256
typedef struct {
uint8_t data[KBD_QUEUE_SIZE];
int rptr, wptr, count;
} KBDQueue;
enum KBDWriteState {
KBD_STATE_CMD = 0,
KBD_STATE_LED,
};
typedef struct KBDState {
KBDQueue queues[2];
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
uint8_t status;
uint8_t mode;
/* keyboard state */
int kbd_write_cmd;
int scan_enabled;
/* mouse state */
int mouse_write_cmd;
uint8_t mouse_status;
uint8_t mouse_resolution;
uint8_t mouse_sample_rate;
uint8_t mouse_wrap;
uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
uint8_t mouse_detect_state;
int mouse_dx; /* current values, needed for 'poll' mode */
int mouse_dy;
int mouse_dz;
uint8_t mouse_buttons;
} KBDState;
KBDState kbd_state;
int reset_requested;
int a20_enabled;
/* update irq and KBD_STAT_[MOUSE_]OBF */
static void kbd_update_irq(KBDState *s)
{
int level;
level = ((s->status & KBD_STAT_OBF) && (s->mode & KBD_MODE_KBD_INT));
pic_set_irq(1, level);
level = ((s->status & KBD_STAT_MOUSE_OBF) && (s->mode & KBD_MODE_MOUSE_INT));
pic_set_irq(12, level);
int irq12_level, irq1_level;
irq1_level = 0;
irq12_level = 0;
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
if (s->queues[0].count != 0 ||
s->queues[1].count != 0) {
s->status |= KBD_STAT_OBF;
if (s->queues[1].count != 0) {
s->status |= KBD_STAT_MOUSE_OBF;
if (s->mode & KBD_MODE_MOUSE_INT)
irq12_level = 1;
} else {
if (s->mode & KBD_MODE_KBD_INT)
irq1_level = 1;
}
}
pic_set_irq(1, irq1_level);
pic_set_irq(12, irq12_level);
}
static void kbd_queue(KBDState *s, int b, int aux)
{
KBDQueue *q = &kbd_state.queues[aux];
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
if (aux)
printf("mouse event: 0x%02x\n", b);
#ifdef DEBUG_KBD
else
printf("kbd event: 0x%02x\n", b);
#endif
#endif
if (q->count >= KBD_QUEUE_SIZE)
return;
q->data[q->wptr] = b;
if (++q->wptr == KBD_QUEUE_SIZE)
q->wptr = 0;
q->count++;
s->status |= KBD_STAT_OBF;
if (aux)
s->status |= KBD_STAT_MOUSE_OBF;
kbd_update_irq(s);
}
void kbd_put_keycode(int keycode)
{
KBDState *s = &kbd_state;
kbd_queue(s, keycode, 0);
}
uint32_t kbd_read_status(CPUX86State *env, uint32_t addr)
{
KBDState *s = &kbd_state;
@ -2745,9 +2723,9 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr)
KBDQueue *q;
int val;
q = &s->queues[1]; /* first check AUX data */
q = &s->queues[0]; /* first check KBD data */
if (q->count == 0)
q = &s->queues[0]; /* then check KBD data */
q = &s->queues[1]; /* then check AUX data */
if (q->count == 0) {
/* XXX: return something else ? */
val = 0;
@ -2756,14 +2734,14 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr)
if (++q->rptr == KBD_QUEUE_SIZE)
q->rptr = 0;
q->count--;
/* reading deasserts IRQ */
if (q == &s->queues[0])
pic_set_irq(1, 0);
else
pic_set_irq(12, 0);
}
if (s->queues[1].count == 0) {
s->status &= ~KBD_STAT_MOUSE_OBF;
if (s->queues[0].count == 0)
s->status &= ~KBD_STAT_OBF;
kbd_update_irq(s);
}
/* reassert IRQs if data left */
kbd_update_irq(s);
#ifdef DEBUG_KBD
printf("kbd: read data=0x%02x\n", val);
#endif
@ -2820,12 +2798,212 @@ static void kbd_write_keyboard(KBDState *s, int val)
break;
case KBD_CMD_SET_LEDS:
kbd_queue(s, KBD_REPLY_ACK, 0);
s->kbd_write_cmd = -1;
break;
case KBD_CMD_SET_RATE:
kbd_queue(s, KBD_REPLY_ACK, 0);
s->kbd_write_cmd = -1;
break;
}
}
static void kbd_mouse_send_packet(KBDState *s)
{
unsigned int b;
int dx1, dy1, dz1;
dx1 = s->mouse_dx;
dy1 = s->mouse_dy;
dz1 = s->mouse_dz;
/* XXX: increase range to 8 bits ? */
if (dx1 > 127)
dx1 = 127;
else if (dx1 < -127)
dx1 = -127;
if (dy1 > 127)
dy1 = 127;
else if (dy1 < -127)
dy1 = -127;
b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
kbd_queue(s, b, 1);
kbd_queue(s, dx1 & 0xff, 1);
kbd_queue(s, dy1 & 0xff, 1);
/* extra byte for IMPS/2 or IMEX */
switch(s->mouse_type) {
default:
break;
case 3:
if (dz1 > 127)
dz1 = 127;
else if (dz1 < -127)
dz1 = -127;
kbd_queue(s, dz1 & 0xff, 1);
break;
case 4:
if (dz1 > 7)
dz1 = 7;
else if (dz1 < -7)
dz1 = -7;
b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
kbd_queue(s, b, 1);
break;
}
/* update deltas */
s->mouse_dx -= dx1;
s->mouse_dy -= dy1;
s->mouse_dz -= dz1;
}
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
{
KBDState *s = &kbd_state;
/* check if deltas are recorded when disabled */
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
return;
s->mouse_dx += dx;
s->mouse_dy -= dy;
s->mouse_dz += dz;
s->mouse_buttons = buttons_state;
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
(s->queues[1].count < (KBD_QUEUE_SIZE - 16))) {
for(;;) {
/* if not remote, send event. Multiple events are sent if
too big deltas */
kbd_mouse_send_packet(s);
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
break;
}
}
}
static void kbd_write_mouse(KBDState *s, int val)
{
#ifdef DEBUG_MOUSE
printf("kbd: write mouse 0x%02x\n", val);
#endif
switch(s->mouse_write_cmd) {
default:
case -1:
/* mouse command */
if (s->mouse_wrap) {
if (val == AUX_RESET_WRAP) {
s->mouse_wrap = 0;
kbd_queue(s, AUX_ACK, 1);
return;
} else if (val != AUX_RESET) {
kbd_queue(s, val, 1);
return;
}
}
switch(val) {
case AUX_SET_SCALE11:
s->mouse_status &= ~MOUSE_STATUS_SCALE21;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_SCALE21:
s->mouse_status |= MOUSE_STATUS_SCALE21;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_STREAM:
s->mouse_status &= ~MOUSE_STATUS_REMOTE;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_WRAP:
s->mouse_wrap = 1;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_REMOTE:
s->mouse_status |= MOUSE_STATUS_REMOTE;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_GET_TYPE:
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, s->mouse_type, 1);
break;
case AUX_SET_RES:
case AUX_SET_SAMPLE:
s->mouse_write_cmd = val;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_GET_SCALE:
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, s->mouse_status, 1);
kbd_queue(s, s->mouse_resolution, 1);
kbd_queue(s, s->mouse_sample_rate, 1);
break;
case AUX_POLL:
kbd_queue(s, AUX_ACK, 1);
kbd_mouse_send_packet(s);
break;
case AUX_ENABLE_DEV:
s->mouse_status |= MOUSE_STATUS_ENABLED;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_DISABLE_DEV:
s->mouse_status &= ~MOUSE_STATUS_ENABLED;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_DEFAULT:
s->mouse_sample_rate = 100;
s->mouse_resolution = 2;
s->mouse_status = 0;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_RESET:
s->mouse_sample_rate = 100;
s->mouse_resolution = 2;
s->mouse_status = 0;
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, 0xaa, 1);
kbd_queue(s, s->mouse_type, 1);
break;
default:
break;
}
break;
case AUX_SET_SAMPLE:
s->mouse_sample_rate = val;
#if 0
/* detect IMPS/2 or IMEX */
switch(s->mouse_detect_state) {
default:
case 0:
if (val == 200)
s->mouse_detect_state = 1;
break;
case 1:
if (val == 100)
s->mouse_detect_state = 2;
else if (val == 200)
s->mouse_detect_state = 3;
else
s->mouse_detect_state = 0;
break;
case 2:
if (val == 80)
s->mouse_type = 3; /* IMPS/2 */
s->mouse_detect_state = 0;
break;
case 3:
if (val == 80)
s->mouse_type = 4; /* IMEX */
s->mouse_detect_state = 0;
break;
}
#endif
kbd_queue(s, AUX_ACK, 1);
s->mouse_write_cmd = -1;
break;
case AUX_SET_RES:
s->mouse_resolution = val;
kbd_queue(s, AUX_ACK, 1);
s->mouse_write_cmd = -1;
break;
}
s->kbd_write_cmd = -1;
}
void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val)
@ -2857,6 +3035,9 @@ void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val)
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT);
}
break;
case KBD_CCMD_WRITE_MOUSE:
kbd_write_mouse(s, val);
break;
default:
break;
}
@ -2869,8 +3050,9 @@ void kbd_reset(KBDState *s)
int i;
s->kbd_write_cmd = -1;
s->mouse_write_cmd = -1;
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
s->status = KBD_MODE_SYS | KBD_MODE_NO_KEYLOCK;
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
for(i = 0; i < 2; i++) {
q = &s->queues[i];
q->rptr = 0;
@ -2933,6 +3115,63 @@ void bochs_bios_init(void)
register_ioport_write(0x503, 1, bochs_bios_write, 1);
}
/***********************************************************/
/* dumb display */
/* init terminal so that we can grab keys */
static struct termios oldtty;
static void term_exit(void)
{
tcsetattr (0, TCSANOW, &oldtty);
}
static void term_init(void)
{
struct termios tty;
tcgetattr (0, &tty);
oldtty = tty;
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
tty.c_oflag |= OPOST;
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
tty.c_cflag &= ~(CSIZE|PARENB);
tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr (0, TCSANOW, &tty);
atexit(term_exit);
fcntl(0, F_SETFL, O_NONBLOCK);
}
static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
{
}
static void dumb_resize(DisplayState *ds, int w, int h)
{
}
static void dumb_refresh(DisplayState *ds)
{
vga_update_display();
}
void dumb_display_init(DisplayState *ds)
{
ds->data = NULL;
ds->linesize = 0;
ds->depth = 0;
ds->dpy_update = dumb_update;
ds->dpy_resize = dumb_resize;
ds->dpy_refresh = dumb_refresh;
}
/***********************************************************/
/* cpu signal handler */
static void host_segv_handler(int host_signum, siginfo_t *info,
@ -2947,6 +3186,9 @@ static void host_segv_handler(int host_signum, siginfo_t *info,
static int timer_irq_pending;
static int timer_irq_count;
static int timer_ms;
static int gui_refresh_pending, gui_refresh_count;
static void host_alarm_handler(int host_signum, siginfo_t *info,
void *puc)
{
@ -2958,9 +3200,17 @@ static void host_alarm_handler(int host_signum, siginfo_t *info,
if (timer_irq_count > 2)
timer_irq_count = 2;
timer_irq_count--;
timer_irq_pending = 1;
}
gui_refresh_count += timer_ms;
if (gui_refresh_count >= GUI_REFRESH_INTERVAL) {
gui_refresh_count = 0;
gui_refresh_pending = 1;
}
if (gui_refresh_pending || timer_irq_pending) {
/* just exit from the cpu to have a chance to handle timers */
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT);
timer_irq_pending = 1;
}
}
@ -2988,6 +3238,14 @@ int main_loop(void *opaque)
uint8_t ch;
CPUState *env = global_env;
if (nodisp && !term_inited) {
/* initialize terminal only there so that the user has a
chance to stop QEMU with Ctrl-C before the gdb connection
is launched */
term_inited = 1;
term_init();
}
for(;;) {
ret = cpu_x86_exec(env);
@ -3059,6 +3317,12 @@ int main_loop(void *opaque)
pic_set_irq(0, 0);
timer_irq_pending = 0;
}
/* VGA */
if (gui_refresh_pending) {
display_state.dpy_refresh(&display_state);
gui_refresh_pending = 0;
}
}
return EXCP_INTERRUPT;
}
@ -3098,31 +3362,35 @@ struct option long_options[] = {
{ "hdb", 1, NULL, 0, },
{ "snapshot", 0, NULL, 0, },
{ "hdachs", 1, NULL, 0, },
{ "nodisp", 0, NULL, 0, },
{ NULL, 0, NULL, 0 },
};
int main(int argc, char **argv)
{
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index;
int snapshot, linux_boot;
int snapshot, linux_boot, total_ram_size;
struct linux_params *params;
struct sigaction act;
struct itimerval itv;
CPUX86State *env;
const char *tmpdir, *initrd_filename;
const char *hd_filename[MAX_DISKS];
DisplayState *ds = &display_state;
/* we never want that malloc() uses mmap() */
mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
initrd_filename = NULL;
for(i = 0; i < MAX_DISKS; i++)
hd_filename[i] = NULL;
phys_ram_size = 32 * 1024 * 1024;
vga_ram_size = VGA_RAM_SIZE;
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
use_gdbstub = 0;
gdbstub_port = DEFAULT_GDBSTUB_PORT;
snapshot = 0;
linux_boot = 0;
nodisp = 0;
for(;;) {
c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index);
if (c == -1)
@ -3164,6 +3432,9 @@ int main(int argc, char **argv)
chs_fail: ;
}
break;
case 5:
nodisp = 1;
break;
}
break;
case 'h':
@ -3232,9 +3503,11 @@ int main(int argc, char **argv)
phys_ram_file);
exit(1);
}
ftruncate(phys_ram_fd, phys_ram_size);
total_ram_size = phys_ram_size + vga_ram_size;
ftruncate(phys_ram_fd, total_ram_size);
unlink(phys_ram_file);
phys_ram_base = mmap(get_mmap_addr(phys_ram_size), phys_ram_size,
phys_ram_base = mmap(get_mmap_addr(total_ram_size),
total_ram_size,
PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED,
phys_ram_fd, 0);
if (phys_ram_base == MAP_FAILED) {
@ -3261,6 +3534,9 @@ int main(int argc, char **argv)
init_ioports();
/* allocate RAM */
cpu_register_physical_memory(0, phys_ram_size, 0);
if (linux_boot) {
/* now we can load the kernel */
ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR);
@ -3366,11 +3642,23 @@ int main(int argc, char **argv)
bochs_bios_init();
}
/* terminal init */
if (nodisp) {
dumb_display_init(ds);
} else {
#ifdef CONFIG_SDL
sdl_display_init(ds);
/* the pthreads modify sigaction. We don't want that. */
#define sigaction __sigaction
#else
dumb_display_init(ds);
#endif
}
/* init basic PC hardware */
register_ioport_write(0x80, 1, ioport80_write, 1);
register_ioport_write(0x3d4, 2, vga_ioport_write, 1);
vga_init(ds, phys_ram_base + phys_ram_size, phys_ram_size,
vga_ram_size);
cmos_init();
pic_init();
pit_init();
@ -3378,7 +3666,7 @@ int main(int argc, char **argv)
ne2000_init();
ide_init();
kbd_init();
/* setup cpu signal handlers for MMU / self modifying code handling */
sigfillset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
@ -3397,6 +3685,7 @@ int main(int argc, char **argv)
/* we probe the tick duration of the kernel to inform the user if
the emulated kernel requested a too high timer frequency */
getitimer(ITIMER_REAL, &itv);
timer_ms = itv.it_interval.tv_usec / 1000;
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) /
1000000;

45
vl.h
View File

@ -25,7 +25,22 @@
#define VL_H
/* vl.c */
struct CPUX86State;
extern int reset_requested;
typedef void (IOPortWriteFunc)(struct CPUX86State *env, uint32_t address, uint32_t data);
typedef uint32_t (IOPortReadFunc)(struct CPUX86State *env, uint32_t address);
void *get_mmap_addr(unsigned long size);
int register_ioport_read(int start, int length, IOPortReadFunc *func, int size);
int register_ioport_write(int start, int length, IOPortWriteFunc *func, int size);
void kbd_put_keycode(int keycode);
#define MOUSE_EVENT_LBUTTON 0x01
#define MOUSE_EVENT_RBUTTON 0x02
#define MOUSE_EVENT_MBUTTON 0x04
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
/* block.c */
typedef struct BlockDriverState BlockDriverState;
@ -52,4 +67,34 @@ struct cow_header_v2 {
uint32_t sectorsize;
};
/* vga.c */
#define VGA_RAM_SIZE (8192 * 1024)
typedef struct DisplayState {
uint8_t *data;
int linesize;
int depth;
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s, int w, int h);
void (*dpy_refresh)(struct DisplayState *s);
} DisplayState;
static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
{
s->dpy_update(s, x, y, w, h);
}
static inline void dpy_resize(DisplayState *s, int w, int h)
{
s->dpy_resize(s, w, h);
}
int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size);
void vga_update_display(void);
/* sdl.c */
void sdl_display_init(DisplayState *ds);
#endif /* VL_H */