74 |
/* debug PC keyboard */ |
/* debug PC keyboard */ |
75 |
//#define DEBUG_KBD |
//#define DEBUG_KBD |
76 |
|
|
77 |
|
/* debug PC keyboard : only mouse */ |
78 |
|
//#define DEBUG_MOUSE |
79 |
|
|
80 |
#define PHYS_RAM_BASE 0xac000000 |
#define PHYS_RAM_BASE 0xac000000 |
81 |
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
82 |
|
|
84 |
#define INITRD_LOAD_ADDR 0x00400000 |
#define INITRD_LOAD_ADDR 0x00400000 |
85 |
#define KERNEL_PARAMS_ADDR 0x00090000 |
#define KERNEL_PARAMS_ADDR 0x00090000 |
86 |
|
|
87 |
|
#define GUI_REFRESH_INTERVAL 30 |
88 |
|
|
89 |
#define MAX_DISKS 2 |
#define MAX_DISKS 2 |
90 |
|
|
91 |
/* from plex86 (BSD license) */ |
/* from plex86 (BSD license) */ |
203 |
#define KERNEL_CS 0x10 |
#define KERNEL_CS 0x10 |
204 |
#define KERNEL_DS 0x18 |
#define KERNEL_DS 0x18 |
205 |
|
|
|
typedef void (IOPortWriteFunc)(CPUX86State *env, uint32_t address, uint32_t data); |
|
|
typedef uint32_t (IOPortReadFunc)(CPUX86State *env, uint32_t address); |
|
|
|
|
206 |
#define MAX_IOPORTS 4096 |
#define MAX_IOPORTS 4096 |
207 |
|
|
208 |
static const char *interp_prefix = CONFIG_QEMU_PREFIX; |
static const char *interp_prefix = CONFIG_QEMU_PREFIX; |
214 |
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; |
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; |
215 |
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
216 |
BlockDriverState *bs_table[MAX_DISKS]; |
BlockDriverState *bs_table[MAX_DISKS]; |
217 |
|
int vga_ram_size; |
218 |
|
static DisplayState display_state; |
219 |
|
int nodisp; |
220 |
|
int term_inited; |
221 |
|
int64_t ticks_per_sec; |
222 |
|
|
223 |
/***********************************************************/ |
/***********************************************************/ |
224 |
/* x86 io ports */ |
/* x86 io ports */ |
438 |
} |
} |
439 |
|
|
440 |
/***********************************************************/ |
/***********************************************************/ |
|
/* 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; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
/***********************************************************/ |
|
441 |
/* cmos emulation */ |
/* cmos emulation */ |
442 |
|
|
443 |
#define RTC_SECONDS 0 |
#define RTC_SECONDS 0 |
519 |
/* various important CMOS locations needed by PC/Bochs bios */ |
/* various important CMOS locations needed by PC/Bochs bios */ |
520 |
|
|
521 |
cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
522 |
|
cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */ |
523 |
|
|
524 |
/* memory size */ |
/* memory size */ |
525 |
val = (phys_ram_size / 1024) - 1024; |
val = (phys_ram_size / 1024) - 1024; |
639 |
int64_t irq_time[16]; |
int64_t irq_time[16]; |
640 |
int64_t cpu_get_ticks(void); |
int64_t cpu_get_ticks(void); |
641 |
#endif |
#endif |
642 |
#ifdef DEBUG_PIC |
#if defined(DEBUG_PIC) |
643 |
int irq_level[16]; |
int irq_level[16]; |
644 |
#endif |
#endif |
645 |
|
|
646 |
void pic_set_irq(int irq, int level) |
void pic_set_irq(int irq, int level) |
647 |
{ |
{ |
648 |
#ifdef DEBUG_PIC |
#if defined(DEBUG_PIC) |
649 |
if (level != irq_level[irq]) { |
if (level != irq_level[irq]) { |
650 |
printf("pic_set_irq: irq=%d level=%d\n", irq, level); |
printf("pic_set_irq: irq=%d level=%d\n", irq, level); |
651 |
irq_level[irq] = level; |
irq_level[irq] = level; |
667 |
/* signal the pic that the irq was acked by the CPU */ |
/* signal the pic that the irq was acked by the CPU */ |
668 |
irq = pic_irq_requested; |
irq = pic_irq_requested; |
669 |
#ifdef DEBUG_IRQ_LATENCY |
#ifdef DEBUG_IRQ_LATENCY |
670 |
printf("IRQ%d latency=%Ld\n", irq, cpu_get_ticks() - irq_time[irq]); |
printf("IRQ%d latency=%0.3fus\n", |
671 |
|
irq, |
672 |
|
(double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec); |
673 |
#endif |
#endif |
674 |
#ifdef DEBUG_PIC |
#ifdef DEBUG_PIC |
675 |
printf("pic_interrupt: irq=%d\n", irq); |
printf("pic_interrupt: irq=%d\n", irq); |
728 |
} |
} |
729 |
if (val == 0xa0) |
if (val == 0xa0) |
730 |
s->priority_add = (s->priority_add + 1) & 7; |
s->priority_add = (s->priority_add + 1) & 7; |
731 |
|
pic_update_irq(); |
732 |
break; |
break; |
733 |
case 0x60 ... 0x67: |
case 0x60 ... 0x67: |
734 |
priority = val & 7; |
priority = val & 7; |
735 |
s->isr &= ~(1 << priority); |
s->isr &= ~(1 << priority); |
736 |
|
pic_update_irq(); |
737 |
break; |
break; |
738 |
case 0xc0 ... 0xc7: |
case 0xc0 ... 0xc7: |
739 |
s->priority_add = (val + 1) & 7; |
s->priority_add = (val + 1) & 7; |
740 |
|
pic_update_irq(); |
741 |
break; |
break; |
742 |
case 0xe0 ... 0xe7: |
case 0xe0 ... 0xe7: |
743 |
priority = val & 7; |
priority = val & 7; |
744 |
s->isr &= ~(1 << priority); |
s->isr &= ~(1 << priority); |
745 |
s->priority_add = (priority + 1) & 7; |
s->priority_add = (priority + 1) & 7; |
746 |
|
pic_update_irq(); |
747 |
break; |
break; |
748 |
} |
} |
749 |
} |
} |
832 |
int dummy_refresh_clock; |
int dummy_refresh_clock; |
833 |
int pit_min_timer_count = 0; |
int pit_min_timer_count = 0; |
834 |
|
|
|
int64_t ticks_per_sec; |
|
|
|
|
835 |
int64_t get_clock(void) |
int64_t get_clock(void) |
836 |
{ |
{ |
837 |
struct timeval tv; |
struct timeval tv; |
1323 |
} |
} |
1324 |
} |
} |
1325 |
|
|
|
/* 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); |
|
|
} |
|
|
|
|
1326 |
void serial_init(void) |
void serial_init(void) |
1327 |
{ |
{ |
1328 |
SerialState *s = &serial_ports[0]; |
SerialState *s = &serial_ports[0]; |
1331 |
|
|
1332 |
register_ioport_write(0x3f8, 8, serial_ioport_write, 1); |
register_ioport_write(0x3f8, 8, serial_ioport_write, 1); |
1333 |
register_ioport_read(0x3f8, 8, serial_ioport_read, 1); |
register_ioport_read(0x3f8, 8, serial_ioport_read, 1); |
|
|
|
|
term_init(); |
|
1334 |
} |
} |
1335 |
|
|
1336 |
/***********************************************************/ |
/***********************************************************/ |
2533 |
#define KBD_MODE_RFU 0x80 |
#define KBD_MODE_RFU 0x80 |
2534 |
|
|
2535 |
/* Mouse Commands */ |
/* Mouse Commands */ |
|
#define AUX_SET_RES 0xE8 /* Set resolution */ |
|
2536 |
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ |
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ |
2537 |
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ |
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ |
2538 |
|
#define AUX_SET_RES 0xE8 /* Set resolution */ |
2539 |
#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ |
#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ |
2540 |
#define AUX_SET_STREAM 0xEA /* Set stream mode */ |
#define AUX_SET_STREAM 0xEA /* Set stream mode */ |
2541 |
|
#define AUX_POLL 0xEB /* Poll */ |
2542 |
|
#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ |
2543 |
|
#define AUX_SET_WRAP 0xEE /* Set wrap mode */ |
2544 |
|
#define AUX_SET_REMOTE 0xF0 /* Set remote mode */ |
2545 |
|
#define AUX_GET_TYPE 0xF2 /* Get type */ |
2546 |
#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ |
#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ |
2547 |
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ |
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ |
2548 |
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ |
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ |
2549 |
|
#define AUX_SET_DEFAULT 0xF6 |
2550 |
#define AUX_RESET 0xFF /* Reset aux device */ |
#define AUX_RESET 0xFF /* Reset aux device */ |
2551 |
#define AUX_ACK 0xFA /* Command byte ACK. */ |
#define AUX_ACK 0xFA /* Command byte ACK. */ |
2552 |
|
|
2553 |
#define KBD_QUEUE_SIZE 64 |
#define MOUSE_STATUS_REMOTE 0x40 |
2554 |
|
#define MOUSE_STATUS_ENABLED 0x20 |
2555 |
|
#define MOUSE_STATUS_SCALE21 0x10 |
2556 |
|
|
2557 |
|
#define KBD_QUEUE_SIZE 256 |
2558 |
|
|
2559 |
typedef struct { |
typedef struct { |
2560 |
uint8_t data[KBD_QUEUE_SIZE]; |
uint8_t data[KBD_QUEUE_SIZE]; |
2561 |
int rptr, wptr, count; |
int rptr, wptr, count; |
2562 |
} KBDQueue; |
} KBDQueue; |
2563 |
|
|
|
enum KBDWriteState { |
|
|
KBD_STATE_CMD = 0, |
|
|
KBD_STATE_LED, |
|
|
}; |
|
|
|
|
2564 |
typedef struct KBDState { |
typedef struct KBDState { |
2565 |
KBDQueue queues[2]; |
KBDQueue queues[2]; |
2566 |
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ |
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ |
2567 |
uint8_t status; |
uint8_t status; |
2568 |
uint8_t mode; |
uint8_t mode; |
2569 |
|
/* keyboard state */ |
2570 |
int kbd_write_cmd; |
int kbd_write_cmd; |
2571 |
int scan_enabled; |
int scan_enabled; |
2572 |
|
/* mouse state */ |
2573 |
|
int mouse_write_cmd; |
2574 |
|
uint8_t mouse_status; |
2575 |
|
uint8_t mouse_resolution; |
2576 |
|
uint8_t mouse_sample_rate; |
2577 |
|
uint8_t mouse_wrap; |
2578 |
|
uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ |
2579 |
|
uint8_t mouse_detect_state; |
2580 |
|
int mouse_dx; /* current values, needed for 'poll' mode */ |
2581 |
|
int mouse_dy; |
2582 |
|
int mouse_dz; |
2583 |
|
uint8_t mouse_buttons; |
2584 |
} KBDState; |
} KBDState; |
2585 |
|
|
2586 |
KBDState kbd_state; |
KBDState kbd_state; |
2587 |
int reset_requested; |
int reset_requested; |
2588 |
int a20_enabled; |
int a20_enabled; |
2589 |
|
|
2590 |
|
/* update irq and KBD_STAT_[MOUSE_]OBF */ |
2591 |
static void kbd_update_irq(KBDState *s) |
static void kbd_update_irq(KBDState *s) |
2592 |
{ |
{ |
2593 |
int level; |
int irq12_level, irq1_level; |
2594 |
|
|
2595 |
level = ((s->status & KBD_STAT_OBF) && (s->mode & KBD_MODE_KBD_INT)); |
irq1_level = 0; |
2596 |
pic_set_irq(1, level); |
irq12_level = 0; |
2597 |
|
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); |
2598 |
level = ((s->status & KBD_STAT_MOUSE_OBF) && (s->mode & KBD_MODE_MOUSE_INT)); |
if (s->queues[0].count != 0 || |
2599 |
pic_set_irq(12, level); |
s->queues[1].count != 0) { |
2600 |
|
s->status |= KBD_STAT_OBF; |
2601 |
|
if (s->queues[1].count != 0) { |
2602 |
|
s->status |= KBD_STAT_MOUSE_OBF; |
2603 |
|
if (s->mode & KBD_MODE_MOUSE_INT) |
2604 |
|
irq12_level = 1; |
2605 |
|
} else { |
2606 |
|
if (s->mode & KBD_MODE_KBD_INT) |
2607 |
|
irq1_level = 1; |
2608 |
|
} |
2609 |
|
} |
2610 |
|
pic_set_irq(1, irq1_level); |
2611 |
|
pic_set_irq(12, irq12_level); |
2612 |
} |
} |
2613 |
|
|
2614 |
static void kbd_queue(KBDState *s, int b, int aux) |
static void kbd_queue(KBDState *s, int b, int aux) |
2615 |
{ |
{ |
2616 |
KBDQueue *q = &kbd_state.queues[aux]; |
KBDQueue *q = &kbd_state.queues[aux]; |
2617 |
|
|
2618 |
|
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD) |
2619 |
|
if (aux) |
2620 |
|
printf("mouse event: 0x%02x\n", b); |
2621 |
|
#ifdef DEBUG_KBD |
2622 |
|
else |
2623 |
|
printf("kbd event: 0x%02x\n", b); |
2624 |
|
#endif |
2625 |
|
#endif |
2626 |
if (q->count >= KBD_QUEUE_SIZE) |
if (q->count >= KBD_QUEUE_SIZE) |
2627 |
return; |
return; |
2628 |
q->data[q->wptr] = b; |
q->data[q->wptr] = b; |
2629 |
if (++q->wptr == KBD_QUEUE_SIZE) |
if (++q->wptr == KBD_QUEUE_SIZE) |
2630 |
q->wptr = 0; |
q->wptr = 0; |
2631 |
q->count++; |
q->count++; |
|
s->status |= KBD_STAT_OBF; |
|
|
if (aux) |
|
|
s->status |= KBD_STAT_MOUSE_OBF; |
|
2632 |
kbd_update_irq(s); |
kbd_update_irq(s); |
2633 |
} |
} |
2634 |
|
|
2635 |
|
void kbd_put_keycode(int keycode) |
2636 |
|
{ |
2637 |
|
KBDState *s = &kbd_state; |
2638 |
|
kbd_queue(s, keycode, 0); |
2639 |
|
} |
2640 |
|
|
2641 |
uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
2642 |
{ |
{ |
2643 |
KBDState *s = &kbd_state; |
KBDState *s = &kbd_state; |
2723 |
KBDQueue *q; |
KBDQueue *q; |
2724 |
int val; |
int val; |
2725 |
|
|
2726 |
q = &s->queues[1]; /* first check AUX data */ |
q = &s->queues[0]; /* first check KBD data */ |
2727 |
if (q->count == 0) |
if (q->count == 0) |
2728 |
q = &s->queues[0]; /* then check KBD data */ |
q = &s->queues[1]; /* then check AUX data */ |
2729 |
if (q->count == 0) { |
if (q->count == 0) { |
2730 |
/* XXX: return something else ? */ |
/* XXX: return something else ? */ |
2731 |
val = 0; |
val = 0; |
2734 |
if (++q->rptr == KBD_QUEUE_SIZE) |
if (++q->rptr == KBD_QUEUE_SIZE) |
2735 |
q->rptr = 0; |
q->rptr = 0; |
2736 |
q->count--; |
q->count--; |
2737 |
|
/* reading deasserts IRQ */ |
2738 |
|
if (q == &s->queues[0]) |
2739 |
|
pic_set_irq(1, 0); |
2740 |
|
else |
2741 |
|
pic_set_irq(12, 0); |
2742 |
} |
} |
2743 |
if (s->queues[1].count == 0) { |
/* reassert IRQs if data left */ |
2744 |
s->status &= ~KBD_STAT_MOUSE_OBF; |
kbd_update_irq(s); |
|
if (s->queues[0].count == 0) |
|
|
s->status &= ~KBD_STAT_OBF; |
|
|
kbd_update_irq(s); |
|
|
} |
|
|
|
|
2745 |
#ifdef DEBUG_KBD |
#ifdef DEBUG_KBD |
2746 |
printf("kbd: read data=0x%02x\n", val); |
printf("kbd: read data=0x%02x\n", val); |
2747 |
#endif |
#endif |
2798 |
break; |
break; |
2799 |
case KBD_CMD_SET_LEDS: |
case KBD_CMD_SET_LEDS: |
2800 |
kbd_queue(s, KBD_REPLY_ACK, 0); |
kbd_queue(s, KBD_REPLY_ACK, 0); |
2801 |
|
s->kbd_write_cmd = -1; |
2802 |
break; |
break; |
2803 |
case KBD_CMD_SET_RATE: |
case KBD_CMD_SET_RATE: |
2804 |
kbd_queue(s, KBD_REPLY_ACK, 0); |
kbd_queue(s, KBD_REPLY_ACK, 0); |
2805 |
|
s->kbd_write_cmd = -1; |
2806 |
|
break; |
2807 |
|
} |
2808 |
|
} |
2809 |
|
|
2810 |
|
static void kbd_mouse_send_packet(KBDState *s) |
2811 |
|
{ |
2812 |
|
unsigned int b; |
2813 |
|
int dx1, dy1, dz1; |
2814 |
|
|
2815 |
|
dx1 = s->mouse_dx; |
2816 |
|
dy1 = s->mouse_dy; |
2817 |
|
dz1 = s->mouse_dz; |
2818 |
|
/* XXX: increase range to 8 bits ? */ |
2819 |
|
if (dx1 > 127) |
2820 |
|
dx1 = 127; |
2821 |
|
else if (dx1 < -127) |
2822 |
|
dx1 = -127; |
2823 |
|
if (dy1 > 127) |
2824 |
|
dy1 = 127; |
2825 |
|
else if (dy1 < -127) |
2826 |
|
dy1 = -127; |
2827 |
|
b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); |
2828 |
|
kbd_queue(s, b, 1); |
2829 |
|
kbd_queue(s, dx1 & 0xff, 1); |
2830 |
|
kbd_queue(s, dy1 & 0xff, 1); |
2831 |
|
/* extra byte for IMPS/2 or IMEX */ |
2832 |
|
switch(s->mouse_type) { |
2833 |
|
default: |
2834 |
|
break; |
2835 |
|
case 3: |
2836 |
|
if (dz1 > 127) |
2837 |
|
dz1 = 127; |
2838 |
|
else if (dz1 < -127) |
2839 |
|
dz1 = -127; |
2840 |
|
kbd_queue(s, dz1 & 0xff, 1); |
2841 |
|
break; |
2842 |
|
case 4: |
2843 |
|
if (dz1 > 7) |
2844 |
|
dz1 = 7; |
2845 |
|
else if (dz1 < -7) |
2846 |
|
dz1 = -7; |
2847 |
|
b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); |
2848 |
|
kbd_queue(s, b, 1); |
2849 |
|
break; |
2850 |
|
} |
2851 |
|
|
2852 |
|
/* update deltas */ |
2853 |
|
s->mouse_dx -= dx1; |
2854 |
|
s->mouse_dy -= dy1; |
2855 |
|
s->mouse_dz -= dz1; |
2856 |
|
} |
2857 |
|
|
2858 |
|
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) |
2859 |
|
{ |
2860 |
|
KBDState *s = &kbd_state; |
2861 |
|
|
2862 |
|
/* check if deltas are recorded when disabled */ |
2863 |
|
if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) |
2864 |
|
return; |
2865 |
|
|
2866 |
|
s->mouse_dx += dx; |
2867 |
|
s->mouse_dy -= dy; |
2868 |
|
s->mouse_dz += dz; |
2869 |
|
s->mouse_buttons = buttons_state; |
2870 |
|
|
2871 |
|
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && |
2872 |
|
(s->queues[1].count < (KBD_QUEUE_SIZE - 16))) { |
2873 |
|
for(;;) { |
2874 |
|
/* if not remote, send event. Multiple events are sent if |
2875 |
|
too big deltas */ |
2876 |
|
kbd_mouse_send_packet(s); |
2877 |
|
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) |
2878 |
|
break; |
2879 |
|
} |
2880 |
|
} |
2881 |
|
} |
2882 |
|
|
2883 |
|
static void kbd_write_mouse(KBDState *s, int val) |
2884 |
|
{ |
2885 |
|
#ifdef DEBUG_MOUSE |
2886 |
|
printf("kbd: write mouse 0x%02x\n", val); |
2887 |
|
#endif |
2888 |
|
switch(s->mouse_write_cmd) { |
2889 |
|
default: |
2890 |
|
case -1: |
2891 |
|
/* mouse command */ |
2892 |
|
if (s->mouse_wrap) { |
2893 |
|
if (val == AUX_RESET_WRAP) { |
2894 |
|
s->mouse_wrap = 0; |
2895 |
|
kbd_queue(s, AUX_ACK, 1); |
2896 |
|
return; |
2897 |
|
} else if (val != AUX_RESET) { |
2898 |
|
kbd_queue(s, val, 1); |
2899 |
|
return; |
2900 |
|
} |
2901 |
|
} |
2902 |
|
switch(val) { |
2903 |
|
case AUX_SET_SCALE11: |
2904 |
|
s->mouse_status &= ~MOUSE_STATUS_SCALE21; |
2905 |
|
kbd_queue(s, AUX_ACK, 1); |
2906 |
|
break; |
2907 |
|
case AUX_SET_SCALE21: |
2908 |
|
s->mouse_status |= MOUSE_STATUS_SCALE21; |
2909 |
|
kbd_queue(s, AUX_ACK, 1); |
2910 |
|
break; |
2911 |
|
case AUX_SET_STREAM: |
2912 |
|
s->mouse_status &= ~MOUSE_STATUS_REMOTE; |
2913 |
|
kbd_queue(s, AUX_ACK, 1); |
2914 |
|
break; |
2915 |
|
case AUX_SET_WRAP: |
2916 |
|
s->mouse_wrap = 1; |
2917 |
|
kbd_queue(s, AUX_ACK, 1); |
2918 |
|
break; |
2919 |
|
case AUX_SET_REMOTE: |
2920 |
|
s->mouse_status |= MOUSE_STATUS_REMOTE; |
2921 |
|
kbd_queue(s, AUX_ACK, 1); |
2922 |
|
break; |
2923 |
|
case AUX_GET_TYPE: |
2924 |
|
kbd_queue(s, AUX_ACK, 1); |
2925 |
|
kbd_queue(s, s->mouse_type, 1); |
2926 |
|
break; |
2927 |
|
case AUX_SET_RES: |
2928 |
|
case AUX_SET_SAMPLE: |
2929 |
|
s->mouse_write_cmd = val; |
2930 |
|
kbd_queue(s, AUX_ACK, 1); |
2931 |
|
break; |
2932 |
|
case AUX_GET_SCALE: |
2933 |
|
kbd_queue(s, AUX_ACK, 1); |
2934 |
|
kbd_queue(s, s->mouse_status, 1); |
2935 |
|
kbd_queue(s, s->mouse_resolution, 1); |
2936 |
|
kbd_queue(s, s->mouse_sample_rate, 1); |
2937 |
|
break; |
2938 |
|
case AUX_POLL: |
2939 |
|
kbd_queue(s, AUX_ACK, 1); |
2940 |
|
kbd_mouse_send_packet(s); |
2941 |
|
break; |
2942 |
|
case AUX_ENABLE_DEV: |
2943 |
|
s->mouse_status |= MOUSE_STATUS_ENABLED; |
2944 |
|
kbd_queue(s, AUX_ACK, 1); |
2945 |
|
break; |
2946 |
|
case AUX_DISABLE_DEV: |
2947 |
|
s->mouse_status &= ~MOUSE_STATUS_ENABLED; |
2948 |
|
kbd_queue(s, AUX_ACK, 1); |
2949 |
|
break; |
2950 |
|
case AUX_SET_DEFAULT: |
2951 |
|
s->mouse_sample_rate = 100; |
2952 |
|
s->mouse_resolution = 2; |
2953 |
|
s->mouse_status = 0; |
2954 |
|
kbd_queue(s, AUX_ACK, 1); |
2955 |
|
break; |
2956 |
|
case AUX_RESET: |
2957 |
|
s->mouse_sample_rate = 100; |
2958 |
|
s->mouse_resolution = 2; |
2959 |
|
s->mouse_status = 0; |
2960 |
|
kbd_queue(s, AUX_ACK, 1); |
2961 |
|
kbd_queue(s, 0xaa, 1); |
2962 |
|
kbd_queue(s, s->mouse_type, 1); |
2963 |
|
break; |
2964 |
|
default: |
2965 |
|
break; |
2966 |
|
} |
2967 |
|
break; |
2968 |
|
case AUX_SET_SAMPLE: |
2969 |
|
s->mouse_sample_rate = val; |
2970 |
|
#if 0 |
2971 |
|
/* detect IMPS/2 or IMEX */ |
2972 |
|
switch(s->mouse_detect_state) { |
2973 |
|
default: |
2974 |
|
case 0: |
2975 |
|
if (val == 200) |
2976 |
|
s->mouse_detect_state = 1; |
2977 |
|
break; |
2978 |
|
case 1: |
2979 |
|
if (val == 100) |
2980 |
|
s->mouse_detect_state = 2; |
2981 |
|
else if (val == 200) |
2982 |
|
s->mouse_detect_state = 3; |
2983 |
|
else |
2984 |
|
s->mouse_detect_state = 0; |
2985 |
|
break; |
2986 |
|
case 2: |
2987 |
|
if (val == 80) |
2988 |
|
s->mouse_type = 3; /* IMPS/2 */ |
2989 |
|
s->mouse_detect_state = 0; |
2990 |
|
break; |
2991 |
|
case 3: |
2992 |
|
if (val == 80) |
2993 |
|
s->mouse_type = 4; /* IMEX */ |
2994 |
|
s->mouse_detect_state = 0; |
2995 |
|
break; |
2996 |
|
} |
2997 |
|
#endif |
2998 |
|
kbd_queue(s, AUX_ACK, 1); |
2999 |
|
s->mouse_write_cmd = -1; |
3000 |
|
break; |
3001 |
|
case AUX_SET_RES: |
3002 |
|
s->mouse_resolution = val; |
3003 |
|
kbd_queue(s, AUX_ACK, 1); |
3004 |
|
s->mouse_write_cmd = -1; |
3005 |
break; |
break; |
3006 |
} |
} |
|
s->kbd_write_cmd = -1; |
|
3007 |
} |
} |
3008 |
|
|
3009 |
void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) |
void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) |
3035 |
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
3036 |
} |
} |
3037 |
break; |
break; |
3038 |
|
case KBD_CCMD_WRITE_MOUSE: |
3039 |
|
kbd_write_mouse(s, val); |
3040 |
|
break; |
3041 |
default: |
default: |
3042 |
break; |
break; |
3043 |
} |
} |
3050 |
int i; |
int i; |
3051 |
|
|
3052 |
s->kbd_write_cmd = -1; |
s->kbd_write_cmd = -1; |
3053 |
|
s->mouse_write_cmd = -1; |
3054 |
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; |
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; |
3055 |
s->status = KBD_MODE_SYS | KBD_MODE_NO_KEYLOCK; |
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED; |
3056 |
for(i = 0; i < 2; i++) { |
for(i = 0; i < 2; i++) { |
3057 |
q = &s->queues[i]; |
q = &s->queues[i]; |
3058 |
q->rptr = 0; |
q->rptr = 0; |
3116 |
} |
} |
3117 |
|
|
3118 |
/***********************************************************/ |
/***********************************************************/ |
3119 |
|
/* dumb display */ |
3120 |
|
|
3121 |
|
/* init terminal so that we can grab keys */ |
3122 |
|
static struct termios oldtty; |
3123 |
|
|
3124 |
|
static void term_exit(void) |
3125 |
|
{ |
3126 |
|
tcsetattr (0, TCSANOW, &oldtty); |
3127 |
|
} |
3128 |
|
|
3129 |
|
static void term_init(void) |
3130 |
|
{ |
3131 |
|
struct termios tty; |
3132 |
|
|
3133 |
|
tcgetattr (0, &tty); |
3134 |
|
oldtty = tty; |
3135 |
|
|
3136 |
|
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |
3137 |
|
|INLCR|IGNCR|ICRNL|IXON); |
3138 |
|
tty.c_oflag |= OPOST; |
3139 |
|
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); |
3140 |
|
tty.c_cflag &= ~(CSIZE|PARENB); |
3141 |
|
tty.c_cflag |= CS8; |
3142 |
|
tty.c_cc[VMIN] = 1; |
3143 |
|
tty.c_cc[VTIME] = 0; |
3144 |
|
|
3145 |
|
tcsetattr (0, TCSANOW, &tty); |
3146 |
|
|
3147 |
|
atexit(term_exit); |
3148 |
|
|
3149 |
|
fcntl(0, F_SETFL, O_NONBLOCK); |
3150 |
|
} |
3151 |
|
|
3152 |
|
static void dumb_update(DisplayState *ds, int x, int y, int w, int h) |
3153 |
|
{ |
3154 |
|
} |
3155 |
|
|
3156 |
|
static void dumb_resize(DisplayState *ds, int w, int h) |
3157 |
|
{ |
3158 |
|
} |
3159 |
|
|
3160 |
|
static void dumb_refresh(DisplayState *ds) |
3161 |
|
{ |
3162 |
|
vga_update_display(); |
3163 |
|
} |
3164 |
|
|
3165 |
|
void dumb_display_init(DisplayState *ds) |
3166 |
|
{ |
3167 |
|
ds->data = NULL; |
3168 |
|
ds->linesize = 0; |
3169 |
|
ds->depth = 0; |
3170 |
|
ds->dpy_update = dumb_update; |
3171 |
|
ds->dpy_resize = dumb_resize; |
3172 |
|
ds->dpy_refresh = dumb_refresh; |
3173 |
|
} |
3174 |
|
|
3175 |
|
/***********************************************************/ |
3176 |
/* cpu signal handler */ |
/* cpu signal handler */ |
3177 |
static void host_segv_handler(int host_signum, siginfo_t *info, |
static void host_segv_handler(int host_signum, siginfo_t *info, |
3178 |
void *puc) |
void *puc) |
3186 |
static int timer_irq_pending; |
static int timer_irq_pending; |
3187 |
static int timer_irq_count; |
static int timer_irq_count; |
3188 |
|
|
3189 |
|
static int timer_ms; |
3190 |
|
static int gui_refresh_pending, gui_refresh_count; |
3191 |
|
|
3192 |
static void host_alarm_handler(int host_signum, siginfo_t *info, |
static void host_alarm_handler(int host_signum, siginfo_t *info, |
3193 |
void *puc) |
void *puc) |
3194 |
{ |
{ |
3200 |
if (timer_irq_count > 2) |
if (timer_irq_count > 2) |
3201 |
timer_irq_count = 2; |
timer_irq_count = 2; |
3202 |
timer_irq_count--; |
timer_irq_count--; |
3203 |
|
timer_irq_pending = 1; |
3204 |
|
} |
3205 |
|
gui_refresh_count += timer_ms; |
3206 |
|
if (gui_refresh_count >= GUI_REFRESH_INTERVAL) { |
3207 |
|
gui_refresh_count = 0; |
3208 |
|
gui_refresh_pending = 1; |
3209 |
|
} |
3210 |
|
|
3211 |
|
if (gui_refresh_pending || timer_irq_pending) { |
3212 |
/* just exit from the cpu to have a chance to handle timers */ |
/* just exit from the cpu to have a chance to handle timers */ |
3213 |
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
|
timer_irq_pending = 1; |
|
3214 |
} |
} |
3215 |
} |
} |
3216 |
|
|
3238 |
uint8_t ch; |
uint8_t ch; |
3239 |
CPUState *env = global_env; |
CPUState *env = global_env; |
3240 |
|
|
3241 |
|
if (nodisp && !term_inited) { |
3242 |
|
/* initialize terminal only there so that the user has a |
3243 |
|
chance to stop QEMU with Ctrl-C before the gdb connection |
3244 |
|
is launched */ |
3245 |
|
term_inited = 1; |
3246 |
|
term_init(); |
3247 |
|
} |
3248 |
|
|
3249 |
for(;;) { |
for(;;) { |
3250 |
|
|
3251 |
ret = cpu_x86_exec(env); |
ret = cpu_x86_exec(env); |
3317 |
pic_set_irq(0, 0); |
pic_set_irq(0, 0); |
3318 |
timer_irq_pending = 0; |
timer_irq_pending = 0; |
3319 |
} |
} |
3320 |
|
|
3321 |
|
/* VGA */ |
3322 |
|
if (gui_refresh_pending) { |
3323 |
|
display_state.dpy_refresh(&display_state); |
3324 |
|
gui_refresh_pending = 0; |
3325 |
|
} |
3326 |
} |
} |
3327 |
return EXCP_INTERRUPT; |
return EXCP_INTERRUPT; |
3328 |
} |
} |
3362 |
{ "hdb", 1, NULL, 0, }, |
{ "hdb", 1, NULL, 0, }, |
3363 |
{ "snapshot", 0, NULL, 0, }, |
{ "snapshot", 0, NULL, 0, }, |
3364 |
{ "hdachs", 1, NULL, 0, }, |
{ "hdachs", 1, NULL, 0, }, |
3365 |
|
{ "nodisp", 0, NULL, 0, }, |
3366 |
{ NULL, 0, NULL, 0 }, |
{ NULL, 0, NULL, 0 }, |
3367 |
}; |
}; |
3368 |
|
|
3369 |
int main(int argc, char **argv) |
int main(int argc, char **argv) |
3370 |
{ |
{ |
3371 |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
3372 |
int snapshot, linux_boot; |
int snapshot, linux_boot, total_ram_size; |
3373 |
struct linux_params *params; |
struct linux_params *params; |
3374 |
struct sigaction act; |
struct sigaction act; |
3375 |
struct itimerval itv; |
struct itimerval itv; |
3376 |
CPUX86State *env; |
CPUX86State *env; |
3377 |
const char *tmpdir, *initrd_filename; |
const char *tmpdir, *initrd_filename; |
3378 |
const char *hd_filename[MAX_DISKS]; |
const char *hd_filename[MAX_DISKS]; |
3379 |
|
DisplayState *ds = &display_state; |
3380 |
|
|
3381 |
/* we never want that malloc() uses mmap() */ |
/* we never want that malloc() uses mmap() */ |
3382 |
mallopt(M_MMAP_THRESHOLD, 4096 * 1024); |
mallopt(M_MMAP_THRESHOLD, 4096 * 1024); |
3383 |
initrd_filename = NULL; |
initrd_filename = NULL; |
3384 |
for(i = 0; i < MAX_DISKS; i++) |
for(i = 0; i < MAX_DISKS; i++) |
3385 |
hd_filename[i] = NULL; |
hd_filename[i] = NULL; |
3386 |
phys_ram_size = 32 * 1024 * 1024; |
phys_ram_size = 32 * 1024 * 1024; |
3387 |
|
vga_ram_size = VGA_RAM_SIZE; |
3388 |
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
3389 |
use_gdbstub = 0; |
use_gdbstub = 0; |
3390 |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
3391 |
snapshot = 0; |
snapshot = 0; |
3392 |
linux_boot = 0; |
linux_boot = 0; |
3393 |
|
nodisp = 0; |
3394 |
for(;;) { |
for(;;) { |
3395 |
c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
3396 |
if (c == -1) |
if (c == -1) |
3432 |
chs_fail: ; |
chs_fail: ; |
3433 |
} |
} |
3434 |
break; |
break; |
3435 |
|
case 5: |
3436 |
|
nodisp = 1; |
3437 |
|
break; |
3438 |
} |
} |
3439 |
break; |
break; |
3440 |
case 'h': |
case 'h': |
3503 |
phys_ram_file); |
phys_ram_file); |
3504 |
exit(1); |
exit(1); |
3505 |
} |
} |
3506 |
ftruncate(phys_ram_fd, phys_ram_size); |
total_ram_size = phys_ram_size + vga_ram_size; |
3507 |
|
ftruncate(phys_ram_fd, total_ram_size); |
3508 |
unlink(phys_ram_file); |
unlink(phys_ram_file); |
3509 |
phys_ram_base = mmap(get_mmap_addr(phys_ram_size), phys_ram_size, |
phys_ram_base = mmap(get_mmap_addr(total_ram_size), |
3510 |
|
total_ram_size, |
3511 |
PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, |
PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, |
3512 |
phys_ram_fd, 0); |
phys_ram_fd, 0); |
3513 |
if (phys_ram_base == MAP_FAILED) { |
if (phys_ram_base == MAP_FAILED) { |
3534 |
|
|
3535 |
init_ioports(); |
init_ioports(); |
3536 |
|
|
3537 |
|
/* allocate RAM */ |
3538 |
|
cpu_register_physical_memory(0, phys_ram_size, 0); |
3539 |
|
|
3540 |
if (linux_boot) { |
if (linux_boot) { |
3541 |
/* now we can load the kernel */ |
/* now we can load the kernel */ |
3542 |
ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); |
ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); |
3642 |
bochs_bios_init(); |
bochs_bios_init(); |
3643 |
} |
} |
3644 |
|
|
3645 |
|
/* terminal init */ |
3646 |
|
if (nodisp) { |
3647 |
|
dumb_display_init(ds); |
3648 |
|
} else { |
3649 |
|
#ifdef CONFIG_SDL |
3650 |
|
sdl_display_init(ds); |
3651 |
|
/* the pthreads modify sigaction. We don't want that. */ |
3652 |
|
#define sigaction __sigaction |
3653 |
|
#else |
3654 |
|
dumb_display_init(ds); |
3655 |
|
#endif |
3656 |
|
} |
3657 |
/* init basic PC hardware */ |
/* init basic PC hardware */ |
3658 |
register_ioport_write(0x80, 1, ioport80_write, 1); |
register_ioport_write(0x80, 1, ioport80_write, 1); |
3659 |
|
|
3660 |
register_ioport_write(0x3d4, 2, vga_ioport_write, 1); |
vga_init(ds, phys_ram_base + phys_ram_size, phys_ram_size, |
3661 |
|
vga_ram_size); |
3662 |
cmos_init(); |
cmos_init(); |
3663 |
pic_init(); |
pic_init(); |
3664 |
pit_init(); |
pit_init(); |
3666 |
ne2000_init(); |
ne2000_init(); |
3667 |
ide_init(); |
ide_init(); |
3668 |
kbd_init(); |
kbd_init(); |
3669 |
|
|
3670 |
/* setup cpu signal handlers for MMU / self modifying code handling */ |
/* setup cpu signal handlers for MMU / self modifying code handling */ |
3671 |
sigfillset(&act.sa_mask); |
sigfillset(&act.sa_mask); |
3672 |
act.sa_flags = SA_SIGINFO; |
act.sa_flags = SA_SIGINFO; |
3685 |
/* we probe the tick duration of the kernel to inform the user if |
/* we probe the tick duration of the kernel to inform the user if |
3686 |
the emulated kernel requested a too high timer frequency */ |
the emulated kernel requested a too high timer frequency */ |
3687 |
getitimer(ITIMER_REAL, &itv); |
getitimer(ITIMER_REAL, &itv); |
3688 |
|
timer_ms = itv.it_interval.tv_usec / 1000; |
3689 |
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
3690 |
1000000; |
1000000; |
3691 |
|
|