Commit 313aa567104a63fbe84d6ec2eeff5b5c81cb3524

Authored by bellard
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
... ... @@ -74,6 +74,9 @@
74 74 /* debug PC keyboard */
75 75 //#define DEBUG_KBD
76 76  
  77 +/* debug PC keyboard : only mouse */
  78 +//#define DEBUG_MOUSE
  79 +
77 80 #define PHYS_RAM_BASE 0xac000000
78 81 #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
79 82  
... ... @@ -81,6 +84,8 @@
81 84 #define INITRD_LOAD_ADDR 0x00400000
82 85 #define KERNEL_PARAMS_ADDR 0x00090000
83 86  
  87 +#define GUI_REFRESH_INTERVAL 30
  88 +
84 89 #define MAX_DISKS 2
85 90  
86 91 /* from plex86 (BSD license) */
... ... @@ -198,9 +203,6 @@ struct __attribute__ ((packed)) linux_params {
198 203 #define KERNEL_CS 0x10
199 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 206 #define MAX_IOPORTS 4096
205 207  
206 208 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
... ... @@ -212,6 +214,11 @@ int loglevel;
212 214 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
213 215 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
214 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 224 /* x86 io ports */
... ... @@ -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 441 /* cmos emulation */
478 442  
479 443 #define RTC_SECONDS 0
... ... @@ -555,6 +519,7 @@ void cmos_init(void)
555 519 /* various important CMOS locations needed by PC/Bochs bios */
556 520  
557 521 cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */
  522 + cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */
558 523  
559 524 /* memory size */
560 525 val = (phys_ram_size / 1024) - 1024;
... ... @@ -674,13 +639,13 @@ static void pic_update_irq(void)
674 639 int64_t irq_time[16];
675 640 int64_t cpu_get_ticks(void);
676 641 #endif
677   -#ifdef DEBUG_PIC
  642 +#if defined(DEBUG_PIC)
678 643 int irq_level[16];
679 644 #endif
680 645  
681 646 void pic_set_irq(int irq, int level)
682 647 {
683   -#ifdef DEBUG_PIC
  648 +#if defined(DEBUG_PIC)
684 649 if (level != irq_level[irq]) {
685 650 printf("pic_set_irq: irq=%d level=%d\n", irq, level);
686 651 irq_level[irq] = level;
... ... @@ -702,7 +667,9 @@ int cpu_x86_get_pic_interrupt(CPUX86State *env)
702 667 /* signal the pic that the irq was acked by the CPU */
703 668 irq = pic_irq_requested;
704 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 673 #endif
707 674 #ifdef DEBUG_PIC
708 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 728 }
762 729 if (val == 0xa0)
763 730 s->priority_add = (s->priority_add + 1) & 7;
  731 + pic_update_irq();
764 732 break;
765 733 case 0x60 ... 0x67:
766 734 priority = val & 7;
767 735 s->isr &= ~(1 << priority);
  736 + pic_update_irq();
768 737 break;
769 738 case 0xc0 ... 0xc7:
770 739 s->priority_add = (val + 1) & 7;
  740 + pic_update_irq();
771 741 break;
772 742 case 0xe0 ... 0xe7:
773 743 priority = val & 7;
774 744 s->isr &= ~(1 << priority);
775 745 s->priority_add = (priority + 1) & 7;
  746 + pic_update_irq();
776 747 break;
777 748 }
778 749 }
... ... @@ -861,8 +832,6 @@ int speaker_data_on;
861 832 int dummy_refresh_clock;
862 833 int pit_min_timer_count = 0;
863 834  
864   -int64_t ticks_per_sec;
865   -
866 835 int64_t get_clock(void)
867 836 {
868 837 struct timeval tv;
... ... @@ -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 1326 void serial_init(void)
1389 1327 {
1390 1328 SerialState *s = &serial_ports[0];
... ... @@ -1393,8 +1331,6 @@ void serial_init(void)
1393 1331  
1394 1332 register_ioport_write(0x3f8, 8, serial_ioport_write, 1);
1395 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 2533 #define KBD_MODE_RFU 0x80
2598 2534  
2599 2535 /* Mouse Commands */
2600   -#define AUX_SET_RES 0xE8 /* Set resolution */
2601 2536 #define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
2602 2537 #define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
  2538 +#define AUX_SET_RES 0xE8 /* Set resolution */
2603 2539 #define AUX_GET_SCALE 0xE9 /* Get scaling factor */
2604 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 2546 #define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
2606 2547 #define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
2607 2548 #define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
  2549 +#define AUX_SET_DEFAULT 0xF6
2608 2550 #define AUX_RESET 0xFF /* Reset aux device */
2609 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 2559 typedef struct {
2614 2560 uint8_t data[KBD_QUEUE_SIZE];
2615 2561 int rptr, wptr, count;
2616 2562 } KBDQueue;
2617 2563  
2618   -enum KBDWriteState {
2619   - KBD_STATE_CMD = 0,
2620   - KBD_STATE_LED,
2621   -};
2622   -
2623 2564 typedef struct KBDState {
2624 2565 KBDQueue queues[2];
2625 2566 uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
2626 2567 uint8_t status;
2627 2568 uint8_t mode;
  2569 + /* keyboard state */
2628 2570 int kbd_write_cmd;
2629 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 2584 } KBDState;
2631 2585  
2632 2586 KBDState kbd_state;
2633 2587 int reset_requested;
2634 2588 int a20_enabled;
2635 2589  
  2590 +/* update irq and KBD_STAT_[MOUSE_]OBF */
2636 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 2614 static void kbd_queue(KBDState *s, int b, int aux)
2648 2615 {
2649 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 2626 if (q->count >= KBD_QUEUE_SIZE)
2652 2627 return;
2653 2628 q->data[q->wptr] = b;
2654 2629 if (++q->wptr == KBD_QUEUE_SIZE)
2655 2630 q->wptr = 0;
2656 2631 q->count++;
2657   - s->status |= KBD_STAT_OBF;
2658   - if (aux)
2659   - s->status |= KBD_STAT_MOUSE_OBF;
2660 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 2641 uint32_t kbd_read_status(CPUX86State *env, uint32_t addr)
2664 2642 {
2665 2643 KBDState *s = &kbd_state;
... ... @@ -2745,9 +2723,9 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr)
2745 2723 KBDQueue *q;
2746 2724 int val;
2747 2725  
2748   - q = &s->queues[1]; /* first check AUX data */
  2726 + q = &s->queues[0]; /* first check KBD data */
2749 2727 if (q->count == 0)
2750   - q = &s->queues[0]; /* then check KBD data */
  2728 + q = &s->queues[1]; /* then check AUX data */
2751 2729 if (q->count == 0) {
2752 2730 /* XXX: return something else ? */
2753 2731 val = 0;
... ... @@ -2756,14 +2734,14 @@ uint32_t kbd_read_data(CPUX86State *env, uint32_t addr)
2756 2734 if (++q->rptr == KBD_QUEUE_SIZE)
2757 2735 q->rptr = 0;
2758 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 2745 #ifdef DEBUG_KBD
2768 2746 printf("kbd: read data=0x%02x\n", val);
2769 2747 #endif
... ... @@ -2820,12 +2798,212 @@ static void kbd_write_keyboard(KBDState *s, int val)
2820 2798 break;
2821 2799 case KBD_CMD_SET_LEDS:
2822 2800 kbd_queue(s, KBD_REPLY_ACK, 0);
  2801 + s->kbd_write_cmd = -1;
2823 2802 break;
2824 2803 case KBD_CMD_SET_RATE:
2825 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 3005 break;
2827 3006 }
2828   - s->kbd_write_cmd = -1;
2829 3007 }
2830 3008  
2831 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 3035 cpu_x86_interrupt(global_env, CPU_INTERRUPT_EXIT);
2858 3036 }
2859 3037 break;
  3038 + case KBD_CCMD_WRITE_MOUSE:
  3039 + kbd_write_mouse(s, val);
  3040 + break;
2860 3041 default:
2861 3042 break;
2862 3043 }
... ... @@ -2869,8 +3050,9 @@ void kbd_reset(KBDState *s)
2869 3050 int i;
2870 3051  
2871 3052 s->kbd_write_cmd = -1;
  3053 + s->mouse_write_cmd = -1;
2872 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 3056 for(i = 0; i < 2; i++) {
2875 3057 q = &s->queues[i];
2876 3058 q->rptr = 0;
... ... @@ -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 3176 /* cpu signal handler */
2938 3177 static void host_segv_handler(int host_signum, siginfo_t *info,
2939 3178 void *puc)
... ... @@ -2947,6 +3186,9 @@ static void host_segv_handler(int host_signum, siginfo_t *info,
2947 3186 static int timer_irq_pending;
2948 3187 static int timer_irq_count;
2949 3188  
  3189 +static int timer_ms;
  3190 +static int gui_refresh_pending, gui_refresh_count;
  3191 +
2950 3192 static void host_alarm_handler(int host_signum, siginfo_t *info,
2951 3193 void *puc)
2952 3194 {
... ... @@ -2958,9 +3200,17 @@ static void host_alarm_handler(int host_signum, siginfo_t *info,
2958 3200 if (timer_irq_count > 2)
2959 3201 timer_irq_count = 2;
2960 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 3212 /* just exit from the cpu to have a chance to handle timers */
2962 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 3238 uint8_t ch;
2989 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 3249 for(;;) {
2992 3250  
2993 3251 ret = cpu_x86_exec(env);
... ... @@ -3059,6 +3317,12 @@ int main_loop(void *opaque)
3059 3317 pic_set_irq(0, 0);
3060 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 3327 return EXCP_INTERRUPT;
3064 3328 }
... ... @@ -3098,31 +3362,35 @@ struct option long_options[] = {
3098 3362 { "hdb", 1, NULL, 0, },
3099 3363 { "snapshot", 0, NULL, 0, },
3100 3364 { "hdachs", 1, NULL, 0, },
  3365 + { "nodisp", 0, NULL, 0, },
3101 3366 { NULL, 0, NULL, 0 },
3102 3367 };
3103 3368  
3104 3369 int main(int argc, char **argv)
3105 3370 {
3106 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 3373 struct linux_params *params;
3109 3374 struct sigaction act;
3110 3375 struct itimerval itv;
3111 3376 CPUX86State *env;
3112 3377 const char *tmpdir, *initrd_filename;
3113 3378 const char *hd_filename[MAX_DISKS];
3114   -
  3379 + DisplayState *ds = &display_state;
  3380 +
3115 3381 /* we never want that malloc() uses mmap() */
3116 3382 mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
3117 3383 initrd_filename = NULL;
3118 3384 for(i = 0; i < MAX_DISKS; i++)
3119 3385 hd_filename[i] = NULL;
3120 3386 phys_ram_size = 32 * 1024 * 1024;
  3387 + vga_ram_size = VGA_RAM_SIZE;
3121 3388 pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
3122 3389 use_gdbstub = 0;
3123 3390 gdbstub_port = DEFAULT_GDBSTUB_PORT;
3124 3391 snapshot = 0;
3125 3392 linux_boot = 0;
  3393 + nodisp = 0;
3126 3394 for(;;) {
3127 3395 c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index);
3128 3396 if (c == -1)
... ... @@ -3164,6 +3432,9 @@ int main(int argc, char **argv)
3164 3432 chs_fail: ;
3165 3433 }
3166 3434 break;
  3435 + case 5:
  3436 + nodisp = 1;
  3437 + break;
3167 3438 }
3168 3439 break;
3169 3440 case 'h':
... ... @@ -3232,9 +3503,11 @@ int main(int argc, char **argv)
3232 3503 phys_ram_file);
3233 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 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 3511 PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED,
3239 3512 phys_ram_fd, 0);
3240 3513 if (phys_ram_base == MAP_FAILED) {
... ... @@ -3261,6 +3534,9 @@ int main(int argc, char **argv)
3261 3534  
3262 3535 init_ioports();
3263 3536  
  3537 + /* allocate RAM */
  3538 + cpu_register_physical_memory(0, phys_ram_size, 0);
  3539 +
3264 3540 if (linux_boot) {
3265 3541 /* now we can load the kernel */
3266 3542 ret = load_kernel(argv[optind], phys_ram_base + KERNEL_LOAD_ADDR);
... ... @@ -3366,11 +3642,23 @@ int main(int argc, char **argv)
3366 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 3657 /* init basic PC hardware */
3370 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 3662 cmos_init();
3375 3663 pic_init();
3376 3664 pit_init();
... ... @@ -3378,7 +3666,7 @@ int main(int argc, char **argv)
3378 3666 ne2000_init();
3379 3667 ide_init();
3380 3668 kbd_init();
3381   -
  3669 +
3382 3670 /* setup cpu signal handlers for MMU / self modifying code handling */
3383 3671 sigfillset(&act.sa_mask);
3384 3672 act.sa_flags = SA_SIGINFO;
... ... @@ -3397,6 +3685,7 @@ int main(int argc, char **argv)
3397 3685 /* we probe the tick duration of the kernel to inform the user if
3398 3686 the emulated kernel requested a too high timer frequency */
3399 3687 getitimer(ITIMER_REAL, &itv);
  3688 + timer_ms = itv.it_interval.tv_usec / 1000;
3400 3689 pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) /
3401 3690 1000000;
3402 3691  
... ...
... ... @@ -25,7 +25,22 @@
25 25 #define VL_H
26 26  
27 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 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 45 /* block.c */
31 46 typedef struct BlockDriverState BlockDriverState;
... ... @@ -52,4 +67,34 @@ struct cow_header_v2 {
52 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 100 #endif /* VL_H */
... ...