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,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
@@ -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 */