Commit 313aa567104a63fbe84d6ec2eeff5b5c81cb3524
1 parent
4cbf74b6
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
Showing
2 changed files
with
454 additions
and
120 deletions
vl.c
| @@ -74,6 +74,9 @@ | @@ -74,6 +74,9 @@ | ||
| 74 | /* debug PC keyboard */ | 74 | /* debug PC keyboard */ |
| 75 | //#define DEBUG_KBD | 75 | //#define DEBUG_KBD |
| 76 | 76 | ||
| 77 | +/* debug PC keyboard : only mouse */ | ||
| 78 | +//#define DEBUG_MOUSE | ||
| 79 | + | ||
| 77 | #define PHYS_RAM_BASE 0xac000000 | 80 | #define PHYS_RAM_BASE 0xac000000 |
| 78 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) | 81 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
| 79 | 82 | ||
| @@ -81,6 +84,8 @@ | @@ -81,6 +84,8 @@ | ||
| 81 | #define INITRD_LOAD_ADDR 0x00400000 | 84 | #define INITRD_LOAD_ADDR 0x00400000 |
| 82 | #define KERNEL_PARAMS_ADDR 0x00090000 | 85 | #define KERNEL_PARAMS_ADDR 0x00090000 |
| 83 | 86 | ||
| 87 | +#define GUI_REFRESH_INTERVAL 30 | ||
| 88 | + | ||
| 84 | #define MAX_DISKS 2 | 89 | #define MAX_DISKS 2 |
| 85 | 90 | ||
| 86 | /* from plex86 (BSD license) */ | 91 | /* from plex86 (BSD license) */ |
| @@ -198,9 +203,6 @@ struct __attribute__ ((packed)) linux_params { | @@ -198,9 +203,6 @@ struct __attribute__ ((packed)) linux_params { | ||
| 198 | #define KERNEL_CS 0x10 | 203 | #define KERNEL_CS 0x10 |
| 199 | #define KERNEL_DS 0x18 | 204 | #define KERNEL_DS 0x18 |
| 200 | 205 | ||
| 201 | -typedef void (IOPortWriteFunc)(CPUX86State *env, uint32_t address, uint32_t data); | ||
| 202 | -typedef uint32_t (IOPortReadFunc)(CPUX86State *env, uint32_t address); | ||
| 203 | - | ||
| 204 | #define MAX_IOPORTS 4096 | 206 | #define MAX_IOPORTS 4096 |
| 205 | 207 | ||
| 206 | static const char *interp_prefix = CONFIG_QEMU_PREFIX; | 208 | static const char *interp_prefix = CONFIG_QEMU_PREFIX; |
| @@ -212,6 +214,11 @@ int loglevel; | @@ -212,6 +214,11 @@ int loglevel; | ||
| 212 | IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; | 214 | IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; |
| 213 | IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; | 215 | IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
| 214 | BlockDriverState *bs_table[MAX_DISKS]; | 216 | 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; | ||
| 215 | 222 | ||
| 216 | /***********************************************************/ | 223 | /***********************************************************/ |
| 217 | /* x86 io ports */ | 224 | /* x86 io ports */ |
| @@ -431,49 +438,6 @@ void hw_error(const char *fmt, ...) | @@ -431,49 +438,6 @@ void hw_error(const char *fmt, ...) | ||
| 431 | } | 438 | } |
| 432 | 439 | ||
| 433 | /***********************************************************/ | 440 | /***********************************************************/ |
| 434 | -/* vga emulation */ | ||
| 435 | -static uint8_t vga_index; | ||
| 436 | -static uint8_t vga_regs[256]; | ||
| 437 | -static int last_cursor_pos; | ||
| 438 | - | ||
| 439 | -void update_console_messages(void) | ||
| 440 | -{ | ||
| 441 | - int c, i, cursor_pos, eol; | ||
| 442 | - | ||
| 443 | - cursor_pos = vga_regs[0x0f] | (vga_regs[0x0e] << 8); | ||
| 444 | - eol = 0; | ||
| 445 | - for(i = last_cursor_pos; i < cursor_pos; i++) { | ||
| 446 | - c = phys_ram_base[0xb8000 + (i) * 2]; | ||
| 447 | - if (c >= ' ') { | ||
| 448 | - putchar(c); | ||
| 449 | - eol = 0; | ||
| 450 | - } else { | ||
| 451 | - if (!eol) | ||
| 452 | - putchar('\n'); | ||
| 453 | - eol = 1; | ||
| 454 | - } | ||
| 455 | - } | ||
| 456 | - fflush(stdout); | ||
| 457 | - last_cursor_pos = cursor_pos; | ||
| 458 | -} | ||
| 459 | - | ||
| 460 | -/* just to see first Linux console messages, we intercept cursor position */ | ||
| 461 | -void vga_ioport_write(CPUX86State *env, uint32_t addr, uint32_t data) | ||
| 462 | -{ | ||
| 463 | - switch(addr) { | ||
| 464 | - case 0x3d4: | ||
| 465 | - vga_index = data; | ||
| 466 | - break; | ||
| 467 | - case 0x3d5: | ||
| 468 | - vga_regs[vga_index] = data; | ||
| 469 | - if (vga_index == 0x0f) | ||
| 470 | - update_console_messages(); | ||
| 471 | - break; | ||
| 472 | - } | ||
| 473 | - | ||
| 474 | -} | ||
| 475 | - | ||
| 476 | -/***********************************************************/ | ||
| 477 | /* cmos emulation */ | 441 | /* cmos emulation */ |
| 478 | 442 | ||
| 479 | #define RTC_SECONDS 0 | 443 | #define RTC_SECONDS 0 |
| @@ -555,6 +519,7 @@ void cmos_init(void) | @@ -555,6 +519,7 @@ void cmos_init(void) | ||
| 555 | /* various important CMOS locations needed by PC/Bochs bios */ | 519 | /* various important CMOS locations needed by PC/Bochs bios */ |
| 556 | 520 | ||
| 557 | cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ | 521 | cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */ |
| 522 | + cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */ | ||
| 558 | 523 | ||
| 559 | /* memory size */ | 524 | /* memory size */ |
| 560 | val = (phys_ram_size / 1024) - 1024; | 525 | val = (phys_ram_size / 1024) - 1024; |
| @@ -674,13 +639,13 @@ static void pic_update_irq(void) | @@ -674,13 +639,13 @@ static void pic_update_irq(void) | ||
| 674 | int64_t irq_time[16]; | 639 | int64_t irq_time[16]; |
| 675 | int64_t cpu_get_ticks(void); | 640 | int64_t cpu_get_ticks(void); |
| 676 | #endif | 641 | #endif |
| 677 | -#ifdef DEBUG_PIC | 642 | +#if defined(DEBUG_PIC) |
| 678 | int irq_level[16]; | 643 | int irq_level[16]; |
| 679 | #endif | 644 | #endif |
| 680 | 645 | ||
| 681 | void pic_set_irq(int irq, int level) | 646 | void pic_set_irq(int irq, int level) |
| 682 | { | 647 | { |
| 683 | -#ifdef DEBUG_PIC | 648 | +#if defined(DEBUG_PIC) |
| 684 | if (level != irq_level[irq]) { | 649 | if (level != irq_level[irq]) { |
| 685 | printf("pic_set_irq: irq=%d level=%d\n", irq, level); | 650 | printf("pic_set_irq: irq=%d level=%d\n", irq, level); |
| 686 | irq_level[irq] = level; | 651 | irq_level[irq] = level; |
| @@ -702,7 +667,9 @@ int cpu_x86_get_pic_interrupt(CPUX86State *env) | @@ -702,7 +667,9 @@ int cpu_x86_get_pic_interrupt(CPUX86State *env) | ||
| 702 | /* signal the pic that the irq was acked by the CPU */ | 667 | /* signal the pic that the irq was acked by the CPU */ |
| 703 | irq = pic_irq_requested; | 668 | irq = pic_irq_requested; |
| 704 | #ifdef DEBUG_IRQ_LATENCY | 669 | #ifdef DEBUG_IRQ_LATENCY |
| 705 | - printf("IRQ%d latency=%Ld\n", irq, cpu_get_ticks() - irq_time[irq]); | 670 | + printf("IRQ%d latency=%0.3fus\n", |
| 671 | + irq, | ||
| 672 | + (double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec); | ||
| 706 | #endif | 673 | #endif |
| 707 | #ifdef DEBUG_PIC | 674 | #ifdef DEBUG_PIC |
| 708 | printf("pic_interrupt: irq=%d\n", irq); | 675 | printf("pic_interrupt: irq=%d\n", irq); |
| @@ -761,18 +728,22 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | @@ -761,18 +728,22 @@ void pic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) | ||
| 761 | } | 728 | } |
| 762 | if (val == 0xa0) | 729 | if (val == 0xa0) |
| 763 | s->priority_add = (s->priority_add + 1) & 7; | 730 | s->priority_add = (s->priority_add + 1) & 7; |
| 731 | + pic_update_irq(); | ||
| 764 | break; | 732 | break; |
| 765 | case 0x60 ... 0x67: | 733 | case 0x60 ... 0x67: |
| 766 | priority = val & 7; | 734 | priority = val & 7; |
| 767 | s->isr &= ~(1 << priority); | 735 | s->isr &= ~(1 << priority); |
| 736 | + pic_update_irq(); | ||
| 768 | break; | 737 | break; |
| 769 | case 0xc0 ... 0xc7: | 738 | case 0xc0 ... 0xc7: |
| 770 | s->priority_add = (val + 1) & 7; | 739 | s->priority_add = (val + 1) & 7; |
| 740 | + pic_update_irq(); | ||
| 771 | break; | 741 | break; |
| 772 | case 0xe0 ... 0xe7: | 742 | case 0xe0 ... 0xe7: |
| 773 | priority = val & 7; | 743 | priority = val & 7; |
| 774 | s->isr &= ~(1 << priority); | 744 | s->isr &= ~(1 << priority); |
| 775 | s->priority_add = (priority + 1) & 7; | 745 | s->priority_add = (priority + 1) & 7; |
| 746 | + pic_update_irq(); | ||
| 776 | break; | 747 | break; |
| 777 | } | 748 | } |
| 778 | } | 749 | } |
| @@ -861,8 +832,6 @@ int speaker_data_on; | @@ -861,8 +832,6 @@ int speaker_data_on; | ||
| 861 | int dummy_refresh_clock; | 832 | int dummy_refresh_clock; |
| 862 | int pit_min_timer_count = 0; | 833 | int pit_min_timer_count = 0; |
| 863 | 834 | ||
| 864 | -int64_t ticks_per_sec; | ||
| 865 | - | ||
| 866 | int64_t get_clock(void) | 835 | int64_t get_clock(void) |
| 867 | { | 836 | { |
| 868 | struct timeval tv; | 837 | struct timeval tv; |
| @@ -1354,37 +1323,6 @@ void serial_received_byte(SerialState *s, int ch) | @@ -1354,37 +1323,6 @@ void serial_received_byte(SerialState *s, int ch) | ||
| 1354 | } | 1323 | } |
| 1355 | } | 1324 | } |
| 1356 | 1325 | ||
| 1357 | -/* init terminal so that we can grab keys */ | ||
| 1358 | -static struct termios oldtty; | ||
| 1359 | - | ||
| 1360 | -static void term_exit(void) | ||
| 1361 | -{ | ||
| 1362 | - tcsetattr (0, TCSANOW, &oldtty); | ||
| 1363 | -} | ||
| 1364 | - | ||
| 1365 | -static void term_init(void) | ||
| 1366 | -{ | ||
| 1367 | - struct termios tty; | ||
| 1368 | - | ||
| 1369 | - tcgetattr (0, &tty); | ||
| 1370 | - oldtty = tty; | ||
| 1371 | - | ||
| 1372 | - tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP | ||
| 1373 | - |INLCR|IGNCR|ICRNL|IXON); | ||
| 1374 | - tty.c_oflag |= OPOST; | ||
| 1375 | - tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); | ||
| 1376 | - tty.c_cflag &= ~(CSIZE|PARENB); | ||
| 1377 | - tty.c_cflag |= CS8; | ||
| 1378 | - tty.c_cc[VMIN] = 1; | ||
| 1379 | - tty.c_cc[VTIME] = 0; | ||
| 1380 | - | ||
| 1381 | - tcsetattr (0, TCSANOW, &tty); | ||
| 1382 | - | ||
| 1383 | - atexit(term_exit); | ||
| 1384 | - | ||
| 1385 | - fcntl(0, F_SETFL, O_NONBLOCK); | ||
| 1386 | -} | ||
| 1387 | - | ||
| 1388 | void serial_init(void) | 1326 | void serial_init(void) |
| 1389 | { | 1327 | { |
| 1390 | SerialState *s = &serial_ports[0]; | 1328 | SerialState *s = &serial_ports[0]; |
| @@ -1393,8 +1331,6 @@ void serial_init(void) | @@ -1393,8 +1331,6 @@ void serial_init(void) | ||
| 1393 | 1331 | ||
| 1394 | register_ioport_write(0x3f8, 8, serial_ioport_write, 1); | 1332 | register_ioport_write(0x3f8, 8, serial_ioport_write, 1); |
| 1395 | register_ioport_read(0x3f8, 8, serial_ioport_read, 1); | 1333 | register_ioport_read(0x3f8, 8, serial_ioport_read, 1); |
| 1396 | - | ||
| 1397 | - term_init(); | ||
| 1398 | } | 1334 | } |
| 1399 | 1335 | ||
| 1400 | /***********************************************************/ | 1336 | /***********************************************************/ |
| @@ -2597,69 +2533,111 @@ void ide_init(void) | @@ -2597,69 +2533,111 @@ void ide_init(void) | ||
| 2597 | #define KBD_MODE_RFU 0x80 | 2533 | #define KBD_MODE_RFU 0x80 |
| 2598 | 2534 | ||
| 2599 | /* Mouse Commands */ | 2535 | /* Mouse Commands */ |
| 2600 | -#define AUX_SET_RES 0xE8 /* Set resolution */ | ||
| 2601 | #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ | 2536 | #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ |
| 2602 | #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ | 2537 | #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ |
| 2538 | +#define AUX_SET_RES 0xE8 /* Set resolution */ | ||
| 2603 | #define AUX_GET_SCALE 0xE9 /* Get scaling factor */ | 2539 | #define AUX_GET_SCALE 0xE9 /* Get scaling factor */ |
| 2604 | #define AUX_SET_STREAM 0xEA /* Set stream mode */ | 2540 | #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 */ | ||
| 2605 | #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ | 2546 | #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ |
| 2606 | #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ | 2547 | #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ |
| 2607 | #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ | 2548 | #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ |
| 2549 | +#define AUX_SET_DEFAULT 0xF6 | ||
| 2608 | #define AUX_RESET 0xFF /* Reset aux device */ | 2550 | #define AUX_RESET 0xFF /* Reset aux device */ |
| 2609 | #define AUX_ACK 0xFA /* Command byte ACK. */ | 2551 | #define AUX_ACK 0xFA /* Command byte ACK. */ |
| 2610 | 2552 | ||
| 2611 | -#define KBD_QUEUE_SIZE 64 | 2553 | +#define MOUSE_STATUS_REMOTE 0x40 |
| 2554 | +#define MOUSE_STATUS_ENABLED 0x20 | ||
| 2555 | +#define MOUSE_STATUS_SCALE21 0x10 | ||
| 2556 | + | ||
| 2557 | +#define KBD_QUEUE_SIZE 256 | ||
| 2612 | 2558 | ||
| 2613 | typedef struct { | 2559 | typedef struct { |
| 2614 | uint8_t data[KBD_QUEUE_SIZE]; | 2560 | uint8_t data[KBD_QUEUE_SIZE]; |
| 2615 | int rptr, wptr, count; | 2561 | int rptr, wptr, count; |
| 2616 | } KBDQueue; | 2562 | } KBDQueue; |
| 2617 | 2563 | ||
| 2618 | -enum KBDWriteState { | ||
| 2619 | - KBD_STATE_CMD = 0, | ||
| 2620 | - KBD_STATE_LED, | ||
| 2621 | -}; | ||
| 2622 | - | ||
| 2623 | typedef struct KBDState { | 2564 | typedef struct KBDState { |
| 2624 | KBDQueue queues[2]; | 2565 | KBDQueue queues[2]; |
| 2625 | uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ | 2566 | uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ |
| 2626 | uint8_t status; | 2567 | uint8_t status; |
| 2627 | uint8_t mode; | 2568 | uint8_t mode; |
| 2569 | + /* keyboard state */ | ||
| 2628 | int kbd_write_cmd; | 2570 | int kbd_write_cmd; |
| 2629 | int scan_enabled; | 2571 | 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; | ||
| 2630 | } KBDState; | 2584 | } KBDState; |
| 2631 | 2585 | ||
| 2632 | KBDState kbd_state; | 2586 | KBDState kbd_state; |
| 2633 | int reset_requested; | 2587 | int reset_requested; |
| 2634 | int a20_enabled; | 2588 | int a20_enabled; |
| 2635 | 2589 | ||
| 2590 | +/* update irq and KBD_STAT_[MOUSE_]OBF */ | ||
| 2636 | static void kbd_update_irq(KBDState *s) | 2591 | static void kbd_update_irq(KBDState *s) |
| 2637 | { | 2592 | { |
| 2638 | - int level; | ||
| 2639 | - | ||
| 2640 | - level = ((s->status & KBD_STAT_OBF) && (s->mode & KBD_MODE_KBD_INT)); | ||
| 2641 | - pic_set_irq(1, level); | ||
| 2642 | - | ||
| 2643 | - level = ((s->status & KBD_STAT_MOUSE_OBF) && (s->mode & KBD_MODE_MOUSE_INT)); | ||
| 2644 | - pic_set_irq(12, level); | 2593 | + int irq12_level, irq1_level; |
| 2594 | + | ||
| 2595 | + irq1_level = 0; | ||
| 2596 | + irq12_level = 0; | ||
| 2597 | + s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); | ||
| 2598 | + if (s->queues[0].count != 0 || | ||
| 2599 | + 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); | ||
| 2645 | } | 2612 | } |
| 2646 | 2613 | ||
| 2647 | static void kbd_queue(KBDState *s, int b, int aux) | 2614 | static void kbd_queue(KBDState *s, int b, int aux) |
| 2648 | { | 2615 | { |
| 2649 | KBDQueue *q = &kbd_state.queues[aux]; | 2616 | KBDQueue *q = &kbd_state.queues[aux]; |
| 2650 | 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 | ||
| 2651 | if (q->count >= KBD_QUEUE_SIZE) | 2626 | if (q->count >= KBD_QUEUE_SIZE) |
| 2652 | return; | 2627 | return; |
| 2653 | q->data[q->wptr] = b; | 2628 | q->data[q->wptr] = b; |
| 2654 | if (++q->wptr == KBD_QUEUE_SIZE) | 2629 | if (++q->wptr == KBD_QUEUE_SIZE) |
| 2655 | q->wptr = 0; | 2630 | q->wptr = 0; |
| 2656 | q->count++; | 2631 | q->count++; |
| 2657 | - s->status |= KBD_STAT_OBF; | ||
| 2658 | - if (aux) | ||
| 2659 | - s->status |= KBD_STAT_MOUSE_OBF; | ||
| 2660 | kbd_update_irq(s); | 2632 | kbd_update_irq(s); |
| 2661 | } | 2633 | } |
| 2662 | 2634 | ||
| 2635 | +void kbd_put_keycode(int keycode) | ||
| 2636 | +{ | ||
| 2637 | + KBDState *s = &kbd_state; | ||
| 2638 | + kbd_queue(s, keycode, 0); | ||
| 2639 | +} | ||
| 2640 | + | ||
| 2663 | uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) | 2641 | uint32_t kbd_read_status(CPUX86State *env, uint32_t addr) |
| 2664 | { | 2642 | { |
| 2665 | KBDState *s = &kbd_state; | 2643 | KBDState *s = &kbd_state; |
| @@ -2745,9 +2723,9 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | @@ -2745,9 +2723,9 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | ||
| 2745 | KBDQueue *q; | 2723 | KBDQueue *q; |
| 2746 | int val; | 2724 | int val; |
| 2747 | 2725 | ||
| 2748 | - q = &s->queues[1]; /* first check AUX data */ | 2726 | + q = &s->queues[0]; /* first check KBD data */ |
| 2749 | if (q->count == 0) | 2727 | if (q->count == 0) |
| 2750 | - q = &s->queues[0]; /* then check KBD data */ | 2728 | + q = &s->queues[1]; /* then check AUX data */ |
| 2751 | if (q->count == 0) { | 2729 | if (q->count == 0) { |
| 2752 | /* XXX: return something else ? */ | 2730 | /* XXX: return something else ? */ |
| 2753 | val = 0; | 2731 | val = 0; |
| @@ -2756,14 +2734,14 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | @@ -2756,14 +2734,14 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr) | ||
| 2756 | if (++q->rptr == KBD_QUEUE_SIZE) | 2734 | if (++q->rptr == KBD_QUEUE_SIZE) |
| 2757 | q->rptr = 0; | 2735 | q->rptr = 0; |
| 2758 | q->count--; | 2736 | 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); | ||
| 2759 | } | 2742 | } |
| 2760 | - if (s->queues[1].count == 0) { | ||
| 2761 | - s->status &= ~KBD_STAT_MOUSE_OBF; | ||
| 2762 | - if (s->queues[0].count == 0) | ||
| 2763 | - s->status &= ~KBD_STAT_OBF; | ||
| 2764 | - kbd_update_irq(s); | ||
| 2765 | - } | ||
| 2766 | - | 2743 | + /* reassert IRQs if data left */ |
| 2744 | + kbd_update_irq(s); | ||
| 2767 | #ifdef DEBUG_KBD | 2745 | #ifdef DEBUG_KBD |
| 2768 | printf("kbd: read data=0x%02x\n", val); | 2746 | printf("kbd: read data=0x%02x\n", val); |
| 2769 | #endif | 2747 | #endif |
| @@ -2820,12 +2798,212 @@ static void kbd_write_keyboard(KBDState *s, int val) | @@ -2820,12 +2798,212 @@ static void kbd_write_keyboard(KBDState *s, int val) | ||
| 2820 | break; | 2798 | break; |
| 2821 | case KBD_CMD_SET_LEDS: | 2799 | case KBD_CMD_SET_LEDS: |
| 2822 | kbd_queue(s, KBD_REPLY_ACK, 0); | 2800 | kbd_queue(s, KBD_REPLY_ACK, 0); |
| 2801 | + s->kbd_write_cmd = -1; | ||
| 2823 | break; | 2802 | break; |
| 2824 | case KBD_CMD_SET_RATE: | 2803 | case KBD_CMD_SET_RATE: |
| 2825 | kbd_queue(s, KBD_REPLY_ACK, 0); | 2804 | 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; | ||
| 2826 | break; | 3005 | break; |
| 2827 | } | 3006 | } |
| 2828 | - s->kbd_write_cmd = -1; | ||
| 2829 | } | 3007 | } |
| 2830 | 3008 | ||
| 2831 | void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) | 3009 | 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) | @@ -2857,6 +3035,9 @@ void kbd_write_data(CPUX86State *env, uint32_t addr, uint32_t val) | ||
| 2857 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | 3035 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
| 2858 | } | 3036 | } |
| 2859 | break; | 3037 | break; |
| 3038 | + case KBD_CCMD_WRITE_MOUSE: | ||
| 3039 | + kbd_write_mouse(s, val); | ||
| 3040 | + break; | ||
| 2860 | default: | 3041 | default: |
| 2861 | break; | 3042 | break; |
| 2862 | } | 3043 | } |
| @@ -2869,8 +3050,9 @@ void kbd_reset(KBDState *s) | @@ -2869,8 +3050,9 @@ void kbd_reset(KBDState *s) | ||
| 2869 | int i; | 3050 | int i; |
| 2870 | 3051 | ||
| 2871 | s->kbd_write_cmd = -1; | 3052 | s->kbd_write_cmd = -1; |
| 3053 | + s->mouse_write_cmd = -1; | ||
| 2872 | s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; | 3054 | s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; |
| 2873 | - s->status = KBD_MODE_SYS | KBD_MODE_NO_KEYLOCK; | 3055 | + s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED; |
| 2874 | for(i = 0; i < 2; i++) { | 3056 | for(i = 0; i < 2; i++) { |
| 2875 | q = &s->queues[i]; | 3057 | q = &s->queues[i]; |
| 2876 | q->rptr = 0; | 3058 | q->rptr = 0; |
| @@ -2934,6 +3116,63 @@ void bochs_bios_init(void) | @@ -2934,6 +3116,63 @@ void bochs_bios_init(void) | ||
| 2934 | } | 3116 | } |
| 2935 | 3117 | ||
| 2936 | /***********************************************************/ | 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 | +/***********************************************************/ | ||
| 2937 | /* cpu signal handler */ | 3176 | /* cpu signal handler */ |
| 2938 | static void host_segv_handler(int host_signum, siginfo_t *info, | 3177 | static void host_segv_handler(int host_signum, siginfo_t *info, |
| 2939 | void *puc) | 3178 | void *puc) |
| @@ -2947,6 +3186,9 @@ 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, | ||
| 2947 | static int timer_irq_pending; | 3186 | static int timer_irq_pending; |
| 2948 | static int timer_irq_count; | 3187 | static int timer_irq_count; |
| 2949 | 3188 | ||
| 3189 | +static int timer_ms; | ||
| 3190 | +static int gui_refresh_pending, gui_refresh_count; | ||
| 3191 | + | ||
| 2950 | static void host_alarm_handler(int host_signum, siginfo_t *info, | 3192 | static void host_alarm_handler(int host_signum, siginfo_t *info, |
| 2951 | void *puc) | 3193 | void *puc) |
| 2952 | { | 3194 | { |
| @@ -2958,9 +3200,17 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, | @@ -2958,9 +3200,17 @@ static void host_alarm_handler(int host_signum, siginfo_t *info, | ||
| 2958 | if (timer_irq_count > 2) | 3200 | if (timer_irq_count > 2) |
| 2959 | timer_irq_count = 2; | 3201 | timer_irq_count = 2; |
| 2960 | timer_irq_count--; | 3202 | 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) { | ||
| 2961 | /* just exit from the cpu to have a chance to handle timers */ | 3212 | /* just exit from the cpu to have a chance to handle timers */ |
| 2962 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); | 3213 | cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT); |
| 2963 | - timer_irq_pending = 1; | ||
| 2964 | } | 3214 | } |
| 2965 | } | 3215 | } |
| 2966 | 3216 | ||
| @@ -2988,6 +3238,14 @@ int main_loop(void *opaque) | @@ -2988,6 +3238,14 @@ int main_loop(void *opaque) | ||
| 2988 | uint8_t ch; | 3238 | uint8_t ch; |
| 2989 | CPUState *env = global_env; | 3239 | CPUState *env = global_env; |
| 2990 | 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 | + | ||
| 2991 | for(;;) { | 3249 | for(;;) { |
| 2992 | 3250 | ||
| 2993 | ret = cpu_x86_exec(env); | 3251 | ret = cpu_x86_exec(env); |
| @@ -3059,6 +3317,12 @@ int main_loop(void *opaque) | @@ -3059,6 +3317,12 @@ int main_loop(void *opaque) | ||
| 3059 | pic_set_irq(0, 0); | 3317 | pic_set_irq(0, 0); |
| 3060 | timer_irq_pending = 0; | 3318 | timer_irq_pending = 0; |
| 3061 | } | 3319 | } |
| 3320 | + | ||
| 3321 | + /* VGA */ | ||
| 3322 | + if (gui_refresh_pending) { | ||
| 3323 | + display_state.dpy_refresh(&display_state); | ||
| 3324 | + gui_refresh_pending = 0; | ||
| 3325 | + } | ||
| 3062 | } | 3326 | } |
| 3063 | return EXCP_INTERRUPT; | 3327 | return EXCP_INTERRUPT; |
| 3064 | } | 3328 | } |
| @@ -3098,31 +3362,35 @@ struct option long_options[] = { | @@ -3098,31 +3362,35 @@ struct option long_options[] = { | ||
| 3098 | { "hdb", 1, NULL, 0, }, | 3362 | { "hdb", 1, NULL, 0, }, |
| 3099 | { "snapshot", 0, NULL, 0, }, | 3363 | { "snapshot", 0, NULL, 0, }, |
| 3100 | { "hdachs", 1, NULL, 0, }, | 3364 | { "hdachs", 1, NULL, 0, }, |
| 3365 | + { "nodisp", 0, NULL, 0, }, | ||
| 3101 | { NULL, 0, NULL, 0 }, | 3366 | { NULL, 0, NULL, 0 }, |
| 3102 | }; | 3367 | }; |
| 3103 | 3368 | ||
| 3104 | int main(int argc, char **argv) | 3369 | int main(int argc, char **argv) |
| 3105 | { | 3370 | { |
| 3106 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; | 3371 | int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index; |
| 3107 | - int snapshot, linux_boot; | 3372 | + int snapshot, linux_boot, total_ram_size; |
| 3108 | struct linux_params *params; | 3373 | struct linux_params *params; |
| 3109 | struct sigaction act; | 3374 | struct sigaction act; |
| 3110 | struct itimerval itv; | 3375 | struct itimerval itv; |
| 3111 | CPUX86State *env; | 3376 | CPUX86State *env; |
| 3112 | const char *tmpdir, *initrd_filename; | 3377 | const char *tmpdir, *initrd_filename; |
| 3113 | const char *hd_filename[MAX_DISKS]; | 3378 | const char *hd_filename[MAX_DISKS]; |
| 3114 | - | 3379 | + DisplayState *ds = &display_state; |
| 3380 | + | ||
| 3115 | /* we never want that malloc() uses mmap() */ | 3381 | /* we never want that malloc() uses mmap() */ |
| 3116 | mallopt(M_MMAP_THRESHOLD, 4096 * 1024); | 3382 | mallopt(M_MMAP_THRESHOLD, 4096 * 1024); |
| 3117 | initrd_filename = NULL; | 3383 | initrd_filename = NULL; |
| 3118 | for(i = 0; i < MAX_DISKS; i++) | 3384 | for(i = 0; i < MAX_DISKS; i++) |
| 3119 | hd_filename[i] = NULL; | 3385 | hd_filename[i] = NULL; |
| 3120 | phys_ram_size = 32 * 1024 * 1024; | 3386 | phys_ram_size = 32 * 1024 * 1024; |
| 3387 | + vga_ram_size = VGA_RAM_SIZE; | ||
| 3121 | pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); | 3388 | pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
| 3122 | use_gdbstub = 0; | 3389 | use_gdbstub = 0; |
| 3123 | gdbstub_port = DEFAULT_GDBSTUB_PORT; | 3390 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
| 3124 | snapshot = 0; | 3391 | snapshot = 0; |
| 3125 | linux_boot = 0; | 3392 | linux_boot = 0; |
| 3393 | + nodisp = 0; | ||
| 3126 | for(;;) { | 3394 | for(;;) { |
| 3127 | c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); | 3395 | c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index); |
| 3128 | if (c == -1) | 3396 | if (c == -1) |
| @@ -3164,6 +3432,9 @@ int main(int argc, char **argv) | @@ -3164,6 +3432,9 @@ int main(int argc, char **argv) | ||
| 3164 | chs_fail: ; | 3432 | chs_fail: ; |
| 3165 | } | 3433 | } |
| 3166 | break; | 3434 | break; |
| 3435 | + case 5: | ||
| 3436 | + nodisp = 1; | ||
| 3437 | + break; | ||
| 3167 | } | 3438 | } |
| 3168 | break; | 3439 | break; |
| 3169 | case 'h': | 3440 | case 'h': |
| @@ -3232,9 +3503,11 @@ int main(int argc, char **argv) | @@ -3232,9 +3503,11 @@ int main(int argc, char **argv) | ||
| 3232 | phys_ram_file); | 3503 | phys_ram_file); |
| 3233 | exit(1); | 3504 | exit(1); |
| 3234 | } | 3505 | } |
| 3235 | - ftruncate(phys_ram_fd, phys_ram_size); | 3506 | + total_ram_size = phys_ram_size + vga_ram_size; |
| 3507 | + ftruncate(phys_ram_fd, total_ram_size); | ||
| 3236 | unlink(phys_ram_file); | 3508 | unlink(phys_ram_file); |
| 3237 | - phys_ram_base = mmap(get_mmap_addr(phys_ram_size), phys_ram_size, | 3509 | + phys_ram_base = mmap(get_mmap_addr(total_ram_size), |
| 3510 | + total_ram_size, | ||
| 3238 | PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, | 3511 | PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, |
| 3239 | phys_ram_fd, 0); | 3512 | phys_ram_fd, 0); |
| 3240 | if (phys_ram_base == MAP_FAILED) { | 3513 | if (phys_ram_base == MAP_FAILED) { |
| @@ -3261,6 +3534,9 @@ int main(int argc, char **argv) | @@ -3261,6 +3534,9 @@ int main(int argc, char **argv) | ||
| 3261 | 3534 | ||
| 3262 | init_ioports(); | 3535 | init_ioports(); |
| 3263 | 3536 | ||
| 3537 | + /* allocate RAM */ | ||
| 3538 | + cpu_register_physical_memory(0, phys_ram_size, 0); | ||
| 3539 | + | ||
| 3264 | if (linux_boot) { | 3540 | if (linux_boot) { |
| 3265 | /* now we can load the kernel */ | 3541 | /* now we can load the kernel */ |
| 3266 | ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); | 3542 | ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR); |
| @@ -3366,11 +3642,23 @@ int main(int argc, char **argv) | @@ -3366,11 +3642,23 @@ int main(int argc, char **argv) | ||
| 3366 | bochs_bios_init(); | 3642 | bochs_bios_init(); |
| 3367 | } | 3643 | } |
| 3368 | 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 | + } | ||
| 3369 | /* init basic PC hardware */ | 3657 | /* init basic PC hardware */ |
| 3370 | register_ioport_write(0x80, 1, ioport80_write, 1); | 3658 | register_ioport_write(0x80, 1, ioport80_write, 1); |
| 3371 | 3659 | ||
| 3372 | - register_ioport_write(0x3d4, 2, vga_ioport_write, 1); | ||
| 3373 | - | 3660 | + vga_init(ds, phys_ram_base + phys_ram_size, phys_ram_size, |
| 3661 | + vga_ram_size); | ||
| 3374 | cmos_init(); | 3662 | cmos_init(); |
| 3375 | pic_init(); | 3663 | pic_init(); |
| 3376 | pit_init(); | 3664 | pit_init(); |
| @@ -3378,7 +3666,7 @@ int main(int argc, char **argv) | @@ -3378,7 +3666,7 @@ int main(int argc, char **argv) | ||
| 3378 | ne2000_init(); | 3666 | ne2000_init(); |
| 3379 | ide_init(); | 3667 | ide_init(); |
| 3380 | kbd_init(); | 3668 | kbd_init(); |
| 3381 | - | 3669 | + |
| 3382 | /* setup cpu signal handlers for MMU / self modifying code handling */ | 3670 | /* setup cpu signal handlers for MMU / self modifying code handling */ |
| 3383 | sigfillset(&act.sa_mask); | 3671 | sigfillset(&act.sa_mask); |
| 3384 | act.sa_flags = SA_SIGINFO; | 3672 | act.sa_flags = SA_SIGINFO; |
| @@ -3397,6 +3685,7 @@ int main(int argc, char **argv) | @@ -3397,6 +3685,7 @@ int main(int argc, char **argv) | ||
| 3397 | /* we probe the tick duration of the kernel to inform the user if | 3685 | /* we probe the tick duration of the kernel to inform the user if |
| 3398 | the emulated kernel requested a too high timer frequency */ | 3686 | the emulated kernel requested a too high timer frequency */ |
| 3399 | getitimer(ITIMER_REAL, &itv); | 3687 | getitimer(ITIMER_REAL, &itv); |
| 3688 | + timer_ms = itv.it_interval.tv_usec / 1000; | ||
| 3400 | pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / | 3689 | pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
| 3401 | 1000000; | 3690 | 1000000; |
| 3402 | 3691 |
vl.h
| @@ -25,7 +25,22 @@ | @@ -25,7 +25,22 @@ | ||
| 25 | #define VL_H | 25 | #define VL_H |
| 26 | 26 | ||
| 27 | /* vl.c */ | 27 | /* vl.c */ |
| 28 | +struct CPUX86State; | ||
| 29 | +extern int reset_requested; | ||
| 30 | + | ||
| 31 | +typedef void (IOPortWriteFunc)(struct CPUX86State *env, uint32_t address, uint32_t data); | ||
| 32 | +typedef uint32_t (IOPortReadFunc)(struct CPUX86State *env, uint32_t address); | ||
| 33 | + | ||
| 28 | void *get_mmap_addr(unsigned long size); | 34 | void *get_mmap_addr(unsigned long size); |
| 35 | +int register_ioport_read(int start, int length, IOPortReadFunc *func, int size); | ||
| 36 | +int register_ioport_write(int start, int length, IOPortWriteFunc *func, int size); | ||
| 37 | + | ||
| 38 | +void kbd_put_keycode(int keycode); | ||
| 39 | + | ||
| 40 | +#define MOUSE_EVENT_LBUTTON 0x01 | ||
| 41 | +#define MOUSE_EVENT_RBUTTON 0x02 | ||
| 42 | +#define MOUSE_EVENT_MBUTTON 0x04 | ||
| 43 | +void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); | ||
| 29 | 44 | ||
| 30 | /* block.c */ | 45 | /* block.c */ |
| 31 | typedef struct BlockDriverState BlockDriverState; | 46 | typedef struct BlockDriverState BlockDriverState; |
| @@ -52,4 +67,34 @@ struct cow_header_v2 { | @@ -52,4 +67,34 @@ struct cow_header_v2 { | ||
| 52 | uint32_t sectorsize; | 67 | uint32_t sectorsize; |
| 53 | }; | 68 | }; |
| 54 | 69 | ||
| 70 | +/* vga.c */ | ||
| 71 | + | ||
| 72 | +#define VGA_RAM_SIZE (8192 * 1024) | ||
| 73 | + | ||
| 74 | +typedef struct DisplayState { | ||
| 75 | + uint8_t *data; | ||
| 76 | + int linesize; | ||
| 77 | + int depth; | ||
| 78 | + void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); | ||
| 79 | + void (*dpy_resize)(struct DisplayState *s, int w, int h); | ||
| 80 | + void (*dpy_refresh)(struct DisplayState *s); | ||
| 81 | +} DisplayState; | ||
| 82 | + | ||
| 83 | +static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) | ||
| 84 | +{ | ||
| 85 | + s->dpy_update(s, x, y, w, h); | ||
| 86 | +} | ||
| 87 | + | ||
| 88 | +static inline void dpy_resize(DisplayState *s, int w, int h) | ||
| 89 | +{ | ||
| 90 | + s->dpy_resize(s, w, h); | ||
| 91 | +} | ||
| 92 | + | ||
| 93 | +int vga_init(DisplayState *ds, uint8_t *vga_ram_base, | ||
| 94 | + unsigned long vga_ram_offset, int vga_ram_size); | ||
| 95 | +void vga_update_display(void); | ||
| 96 | + | ||
| 97 | +/* sdl.c */ | ||
| 98 | +void sdl_display_init(DisplayState *ds); | ||
| 99 | + | ||
| 55 | #endif /* VL_H */ | 100 | #endif /* VL_H */ |