Commit cb5a7aa8c32141bb19a8f6571f630c779faebc25

Authored by malc
1 parent 3893c124

Optional "precise" VGA retrace support

Selected via: -vga <name>,retrace=precise

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5336 c046a42c-6fe2-441c-8c8c-71466251a162
hw/cirrus_vga.c
... ... @@ -2744,8 +2744,7 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2744 2744 case 0x3ba:
2745 2745 case 0x3da:
2746 2746 /* just toggle to fool polling */
2747   - s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
2748   - val = s->st01;
  2747 + val = s->st01 = s->retrace((VGAState *) s);
2749 2748 s->ar_flip_flop = 0;
2750 2749 break;
2751 2750 default:
... ... @@ -2808,6 +2807,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2808 2807 break;
2809 2808 case 0x3c2:
2810 2809 s->msr = val & ~0x10;
  2810 + s->update_retrace_info((VGAState *) s);
2811 2811 break;
2812 2812 case 0x3c4:
2813 2813 s->sr_index = val;
... ... @@ -2819,6 +2819,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2819 2819 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2820 2820 #endif
2821 2821 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
  2822 + if (s->sr_index == 1) s->update_retrace_info((VGAState *) s);
2822 2823 break;
2823 2824 case 0x3c6:
2824 2825 cirrus_write_hidden_dac(s, val);
... ... @@ -2886,6 +2887,18 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2886 2887 s->cr[s->cr_index] = val;
2887 2888 break;
2888 2889 }
  2890 +
  2891 + switch(s->cr_index) {
  2892 + case 0x00:
  2893 + case 0x04:
  2894 + case 0x05:
  2895 + case 0x06:
  2896 + case 0x07:
  2897 + case 0x11:
  2898 + case 0x17:
  2899 + s->update_retrace_info((VGAState *) s);
  2900 + break;
  2901 + }
2889 2902 break;
2890 2903 case 0x3ba:
2891 2904 case 0x3da:
... ...
... ... @@ -108,6 +108,12 @@ void i440fx_init_memory_mappings(PCIDevice *d);
108 108 int piix4_init(PCIBus *bus, int devfn);
109 109  
110 110 /* vga.c */
  111 +enum vga_retrace_method {
  112 + VGA_RETRACE_DUMB,
  113 + VGA_RETRACE_PRECISE
  114 +};
  115 +
  116 +extern enum vga_retrace_method vga_retrace_method;
111 117  
112 118 #ifndef TARGET_SPARC
113 119 #define VGA_RAM_SIZE (8192 * 1024)
... ...
hw/vga.c
... ... @@ -27,6 +27,7 @@
27 27 #include "pci.h"
28 28 #include "vga_int.h"
29 29 #include "pixel_ops.h"
  30 +#include "qemu-timer.h"
30 31  
31 32 //#define DEBUG_VGA
32 33 //#define DEBUG_VGA_MEM
... ... @@ -149,6 +150,139 @@ static uint8_t expand4to8[16];
149 150  
150 151 static void vga_screen_dump(void *opaque, const char *filename);
151 152  
  153 +static void vga_dumb_update_retrace_info(VGAState *s)
  154 +{
  155 + (void) s;
  156 +}
  157 +
  158 +static void vga_precise_update_retrace_info(VGAState *s)
  159 +{
  160 + int htotal_chars;
  161 + int hretr_start_char;
  162 + int hretr_skew_chars;
  163 + int hretr_end_char;
  164 +
  165 + int vtotal_lines;
  166 + int vretr_start_line;
  167 + int vretr_end_line;
  168 +
  169 + int div2, sldiv2, dots;
  170 + int clocking_mode;
  171 + int clock_sel;
  172 + const int hz[] = {25175000, 28322000, 25175000, 25175000};
  173 + int64_t chars_per_sec;
  174 + struct vga_precise_retrace *r = &s->retrace_info.precise;
  175 +
  176 + htotal_chars = s->cr[0x00] + 5;
  177 + hretr_start_char = s->cr[0x04];
  178 + hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
  179 + hretr_end_char = s->cr[0x05] & 0x1f;
  180 +
  181 + vtotal_lines = (s->cr[0x06]
  182 + | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
  183 + ;
  184 + vretr_start_line = s->cr[0x10]
  185 + | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
  186 + ;
  187 + vretr_end_line = s->cr[0x11] & 0xf;
  188 +
  189 +
  190 + div2 = (s->cr[0x17] >> 2) & 1;
  191 + sldiv2 = (s->cr[0x17] >> 3) & 1;
  192 +
  193 + clocking_mode = (s->sr[0x01] >> 3) & 1;
  194 + clock_sel = (s->msr >> 2) & 3;
  195 + dots = (s->msr & 1) ? 9 : 8;
  196 +
  197 + chars_per_sec = hz[clock_sel] / dots;
  198 +
  199 + htotal_chars <<= clocking_mode;
  200 +
  201 + r->total_chars = vtotal_lines * htotal_chars;
  202 + r->total_chars = (vretr_start_line + vretr_end_line + 1) * htotal_chars;
  203 + if (r->freq) {
  204 + r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
  205 + } else {
  206 + r->ticks_per_char = ticks_per_sec / chars_per_sec;
  207 + }
  208 +
  209 + r->vstart = vretr_start_line;
  210 + r->vend = r->vstart + vretr_end_line + 1;
  211 +
  212 + r->hstart = hretr_start_char + hretr_skew_chars;
  213 + r->hend = r->hstart + hretr_end_char + 1;
  214 + r->htotal = htotal_chars;
  215 +
  216 + printf("hz=%f\n",
  217 + (double) ticks_per_sec / (r->ticks_per_char * r->total_chars));
  218 +#if 0 /* def DEBUG_RETRACE */
  219 + printf("hz=%f\n",
  220 + (double) ticks_per_sec / (r->ticks_per_char * r->total_chars));
  221 + printf (
  222 + "htotal = %d\n"
  223 + "hretr_start = %d\n"
  224 + "hretr_skew = %d\n"
  225 + "hretr_end = %d\n"
  226 + "vtotal = %d\n"
  227 + "vretr_start = %d\n"
  228 + "vretr_end = %d\n"
  229 + "div2 = %d sldiv2 = %d\n"
  230 + "clocking_mode = %d\n"
  231 + "clock_sel = %d %d\n"
  232 + "dots = %d\n"
  233 + "ticks/char = %lld\n"
  234 + "\n",
  235 + htotal_chars,
  236 + hretr_start_char,
  237 + hretr_skew_chars,
  238 + hretr_end_char,
  239 + vtotal_lines,
  240 + vretr_start_line,
  241 + vretr_end_line,
  242 + div2, sldiv2,
  243 + clocking_mode,
  244 + clock_sel,
  245 + hz[clock_sel],
  246 + dots,
  247 + r->ticks_per_char
  248 + );
  249 +#endif
  250 +}
  251 +
  252 +static uint8_t vga_precise_retrace(VGAState *s)
  253 +{
  254 + struct vga_precise_retrace *r = &s->retrace_info.precise;
  255 + uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
  256 +
  257 + if (r->total_chars) {
  258 + int cur_line, cur_line_char, cur_char;
  259 + int64_t cur_tick;
  260 +
  261 + cur_tick = qemu_get_clock(vm_clock);
  262 +
  263 + cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
  264 + cur_line = cur_char / r->htotal;
  265 +
  266 + if (cur_line >= r->vstart && cur_line <= r->vend) {
  267 + val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
  268 + }
  269 +
  270 + cur_line_char = cur_char % r->htotal;
  271 + if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
  272 + val |= ST01_DISP_ENABLE;
  273 + }
  274 +
  275 + return val;
  276 + } else {
  277 + return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
  278 + }
  279 +}
  280 +
  281 +static uint8_t vga_dumb_retrace(VGAState *s)
  282 +{
  283 + return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
  284 +}
  285 +
152 286 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
153 287 {
154 288 VGAState *s = opaque;
... ... @@ -228,8 +362,7 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
228 362 case 0x3ba:
229 363 case 0x3da:
230 364 /* just toggle to fool polling */
231   - s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
232   - val = s->st01;
  365 + val = s->st01 = s->retrace(s);
233 366 s->ar_flip_flop = 0;
234 367 break;
235 368 default:
... ... @@ -291,6 +424,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
291 424 break;
292 425 case 0x3c2:
293 426 s->msr = val & ~0x10;
  427 + s->update_retrace_info(s);
294 428 break;
295 429 case 0x3c4:
296 430 s->sr_index = val & 7;
... ... @@ -300,6 +434,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
300 434 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
301 435 #endif
302 436 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
  437 + if (s->sr_index == 1) s->update_retrace_info(s);
303 438 break;
304 439 case 0x3c7:
305 440 s->dac_read_index = val;
... ... @@ -357,6 +492,18 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
357 492 s->cr[s->cr_index] = val;
358 493 break;
359 494 }
  495 +
  496 + switch(s->cr_index) {
  497 + case 0x00:
  498 + case 0x04:
  499 + case 0x05:
  500 + case 0x06:
  501 + case 0x07:
  502 + case 0x11:
  503 + case 0x17:
  504 + s->update_retrace_info(s);
  505 + break;
  506 + }
360 507 break;
361 508 case 0x3ba:
362 509 case 0x3da:
... ... @@ -2001,6 +2148,18 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
2001 2148 s->invalidate = vga_invalidate_display;
2002 2149 s->screen_dump = vga_screen_dump;
2003 2150 s->text_update = vga_update_text;
  2151 + switch (vga_retrace_method) {
  2152 + case VGA_RETRACE_DUMB:
  2153 + s->retrace = vga_dumb_retrace;
  2154 + s->update_retrace_info = vga_dumb_update_retrace_info;
  2155 + break;
  2156 +
  2157 + case VGA_RETRACE_PRECISE:
  2158 + s->retrace = vga_precise_retrace;
  2159 + s->update_retrace_info = vga_precise_update_retrace_info;
  2160 + memset(&s->retrace_info, 0, sizeof (s->retrace_info));
  2161 + break;
  2162 + }
2004 2163 }
2005 2164  
2006 2165 /* used by both ISA and PCI */
... ...
hw/vga_int.h
... ... @@ -79,6 +79,25 @@
79 79 #define CH_ATTR_SIZE (160 * 100)
80 80 #define VGA_MAX_HEIGHT 2048
81 81  
  82 +struct vga_precise_retrace {
  83 + int64_t ticks_per_char;
  84 + int64_t total_chars;
  85 + int htotal;
  86 + int hstart;
  87 + int hend;
  88 + int vstart;
  89 + int vend;
  90 + int freq;
  91 +};
  92 +
  93 +union vga_retrace {
  94 + struct vga_precise_retrace precise;
  95 +};
  96 +
  97 +struct VGAState;
  98 +typedef uint8_t (* vga_retrace_fn)(struct VGAState *s);
  99 +typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
  100 +
82 101 #define VGA_STATE_COMMON \
83 102 uint8_t *vram_ptr; \
84 103 unsigned long vram_offset; \
... ... @@ -147,7 +166,11 @@
147 166 void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \
148 167 /* tell for each page if it has been updated since the last time */ \
149 168 uint32_t last_palette[256]; \
150   - uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
  169 + uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ \
  170 + /* retrace */ \
  171 + vga_retrace_fn retrace; \
  172 + vga_update_retrace_info_fn update_retrace_info; \
  173 + union vga_retrace retrace_info;
151 174  
152 175  
153 176 typedef struct VGAState {
... ...
... ... @@ -174,6 +174,7 @@ int nb_drives;
174 174 /* point to the block driver where the snapshots are managed */
175 175 BlockDriverState *bs_snapshots;
176 176 int vga_ram_size;
  177 +enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
177 178 static DisplayState display_state;
178 179 int nographic;
179 180 int curses;
... ... @@ -8203,7 +8204,19 @@ static void select_vgahw (const char *p)
8203 8204 fprintf(stderr, "Unknown vga type: %s\n", p);
8204 8205 exit(1);
8205 8206 }
8206   - if (*opts) goto invalid_vga;
  8207 + while (*opts) {
  8208 + const char *nextopt;
  8209 +
  8210 + if (strstart(opts, ",retrace=", &nextopt)) {
  8211 + opts = nextopt;
  8212 + if (strstart(opts, "dumb", &nextopt))
  8213 + vga_retrace_method = VGA_RETRACE_DUMB;
  8214 + else if (strstart(opts, "precise", &nextopt))
  8215 + vga_retrace_method = VGA_RETRACE_PRECISE;
  8216 + else goto invalid_vga;
  8217 + } else goto invalid_vga;
  8218 + opts = nextopt;
  8219 + }
8207 8220 }
8208 8221  
8209 8222 #ifdef _WIN32
... ...