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
This commit is contained in:
		
							parent
							
								
									3893c124e7
								
							
						
					
					
						commit
						cb5a7aa8c3
					
				| 
						 | 
				
			
			@ -2744,8 +2744,7 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 | 
			
		|||
	case 0x3ba:
 | 
			
		||||
	case 0x3da:
 | 
			
		||||
	    /* just toggle to fool polling */
 | 
			
		||||
	    s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
 | 
			
		||||
	    val = s->st01;
 | 
			
		||||
	    val = s->st01 = s->retrace((VGAState *) s);
 | 
			
		||||
	    s->ar_flip_flop = 0;
 | 
			
		||||
	    break;
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			@ -2808,6 +2807,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		|||
	break;
 | 
			
		||||
    case 0x3c2:
 | 
			
		||||
	s->msr = val & ~0x10;
 | 
			
		||||
	s->update_retrace_info((VGAState *) s);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x3c4:
 | 
			
		||||
	s->sr_index = val;
 | 
			
		||||
| 
						 | 
				
			
			@ -2819,6 +2819,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		|||
	printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
 | 
			
		||||
#endif
 | 
			
		||||
	s->sr[s->sr_index] = val & sr_mask[s->sr_index];
 | 
			
		||||
	if (s->sr_index == 1) s->update_retrace_info((VGAState *) s);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x3c6:
 | 
			
		||||
	cirrus_write_hidden_dac(s, val);
 | 
			
		||||
| 
						 | 
				
			
			@ -2886,6 +2887,18 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		|||
	    s->cr[s->cr_index] = val;
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch(s->cr_index) {
 | 
			
		||||
	case 0x00:
 | 
			
		||||
	case 0x04:
 | 
			
		||||
	case 0x05:
 | 
			
		||||
	case 0x06:
 | 
			
		||||
	case 0x07:
 | 
			
		||||
	case 0x11:
 | 
			
		||||
	case 0x17:
 | 
			
		||||
	    s->update_retrace_info((VGAState *) s);
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x3ba:
 | 
			
		||||
    case 0x3da:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								hw/pc.h
								
								
								
								
							
							
						
						
									
										6
									
								
								hw/pc.h
								
								
								
								
							| 
						 | 
				
			
			@ -108,6 +108,12 @@ void i440fx_init_memory_mappings(PCIDevice *d);
 | 
			
		|||
int piix4_init(PCIBus *bus, int devfn);
 | 
			
		||||
 | 
			
		||||
/* vga.c */
 | 
			
		||||
enum vga_retrace_method {
 | 
			
		||||
    VGA_RETRACE_DUMB,
 | 
			
		||||
    VGA_RETRACE_PRECISE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern enum vga_retrace_method vga_retrace_method;
 | 
			
		||||
 | 
			
		||||
#ifndef TARGET_SPARC
 | 
			
		||||
#define VGA_RAM_SIZE (8192 * 1024)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										163
									
								
								hw/vga.c
								
								
								
								
							
							
						
						
									
										163
									
								
								hw/vga.c
								
								
								
								
							| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
#include "pci.h"
 | 
			
		||||
#include "vga_int.h"
 | 
			
		||||
#include "pixel_ops.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_VGA
 | 
			
		||||
//#define DEBUG_VGA_MEM
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +150,139 @@ static uint8_t expand4to8[16];
 | 
			
		|||
 | 
			
		||||
static void vga_screen_dump(void *opaque, const char *filename);
 | 
			
		||||
 | 
			
		||||
static void vga_dumb_update_retrace_info(VGAState *s)
 | 
			
		||||
{
 | 
			
		||||
    (void) s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vga_precise_update_retrace_info(VGAState *s)
 | 
			
		||||
{
 | 
			
		||||
    int htotal_chars;
 | 
			
		||||
    int hretr_start_char;
 | 
			
		||||
    int hretr_skew_chars;
 | 
			
		||||
    int hretr_end_char;
 | 
			
		||||
 | 
			
		||||
    int vtotal_lines;
 | 
			
		||||
    int vretr_start_line;
 | 
			
		||||
    int vretr_end_line;
 | 
			
		||||
 | 
			
		||||
    int div2, sldiv2, dots;
 | 
			
		||||
    int clocking_mode;
 | 
			
		||||
    int clock_sel;
 | 
			
		||||
    const int hz[] = {25175000, 28322000, 25175000, 25175000};
 | 
			
		||||
    int64_t chars_per_sec;
 | 
			
		||||
    struct vga_precise_retrace *r = &s->retrace_info.precise;
 | 
			
		||||
 | 
			
		||||
    htotal_chars = s->cr[0x00] + 5;
 | 
			
		||||
    hretr_start_char = s->cr[0x04];
 | 
			
		||||
    hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
 | 
			
		||||
    hretr_end_char = s->cr[0x05] & 0x1f;
 | 
			
		||||
 | 
			
		||||
    vtotal_lines = (s->cr[0x06]
 | 
			
		||||
                    | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
 | 
			
		||||
        ;
 | 
			
		||||
    vretr_start_line = s->cr[0x10]
 | 
			
		||||
        | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
 | 
			
		||||
        ;
 | 
			
		||||
    vretr_end_line = s->cr[0x11] & 0xf;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    div2 = (s->cr[0x17] >> 2) & 1;
 | 
			
		||||
    sldiv2 = (s->cr[0x17] >> 3) & 1;
 | 
			
		||||
 | 
			
		||||
    clocking_mode = (s->sr[0x01] >> 3) & 1;
 | 
			
		||||
    clock_sel = (s->msr >> 2) & 3;
 | 
			
		||||
    dots = (s->msr & 1) ? 9 : 8;
 | 
			
		||||
 | 
			
		||||
    chars_per_sec = hz[clock_sel] / dots;
 | 
			
		||||
 | 
			
		||||
    htotal_chars <<= clocking_mode;
 | 
			
		||||
 | 
			
		||||
    r->total_chars = vtotal_lines * htotal_chars;
 | 
			
		||||
    r->total_chars = (vretr_start_line + vretr_end_line + 1) * htotal_chars;
 | 
			
		||||
    if (r->freq) {
 | 
			
		||||
        r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
 | 
			
		||||
    } else {
 | 
			
		||||
        r->ticks_per_char = ticks_per_sec / chars_per_sec;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r->vstart = vretr_start_line;
 | 
			
		||||
    r->vend = r->vstart + vretr_end_line + 1;
 | 
			
		||||
 | 
			
		||||
    r->hstart = hretr_start_char + hretr_skew_chars;
 | 
			
		||||
    r->hend = r->hstart + hretr_end_char + 1;
 | 
			
		||||
    r->htotal = htotal_chars;
 | 
			
		||||
 | 
			
		||||
    printf("hz=%f\n",
 | 
			
		||||
           (double) ticks_per_sec / (r->ticks_per_char * r->total_chars));
 | 
			
		||||
#if 0 /* def DEBUG_RETRACE */
 | 
			
		||||
    printf("hz=%f\n",
 | 
			
		||||
           (double) ticks_per_sec / (r->ticks_per_char * r->total_chars));
 | 
			
		||||
    printf (
 | 
			
		||||
        "htotal = %d\n"
 | 
			
		||||
        "hretr_start = %d\n"
 | 
			
		||||
        "hretr_skew = %d\n"
 | 
			
		||||
        "hretr_end = %d\n"
 | 
			
		||||
        "vtotal = %d\n"
 | 
			
		||||
        "vretr_start = %d\n"
 | 
			
		||||
        "vretr_end = %d\n"
 | 
			
		||||
        "div2 = %d sldiv2 = %d\n"
 | 
			
		||||
        "clocking_mode = %d\n"
 | 
			
		||||
        "clock_sel = %d %d\n"
 | 
			
		||||
        "dots = %d\n"
 | 
			
		||||
        "ticks/char = %lld\n"
 | 
			
		||||
        "\n",
 | 
			
		||||
        htotal_chars,
 | 
			
		||||
        hretr_start_char,
 | 
			
		||||
        hretr_skew_chars,
 | 
			
		||||
        hretr_end_char,
 | 
			
		||||
        vtotal_lines,
 | 
			
		||||
        vretr_start_line,
 | 
			
		||||
        vretr_end_line,
 | 
			
		||||
        div2, sldiv2,
 | 
			
		||||
        clocking_mode,
 | 
			
		||||
        clock_sel,
 | 
			
		||||
        hz[clock_sel],
 | 
			
		||||
        dots,
 | 
			
		||||
        r->ticks_per_char
 | 
			
		||||
        );
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t vga_precise_retrace(VGAState *s)
 | 
			
		||||
{
 | 
			
		||||
    struct vga_precise_retrace *r = &s->retrace_info.precise;
 | 
			
		||||
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
 | 
			
		||||
 | 
			
		||||
    if (r->total_chars) {
 | 
			
		||||
        int cur_line, cur_line_char, cur_char;
 | 
			
		||||
        int64_t cur_tick;
 | 
			
		||||
 | 
			
		||||
        cur_tick = qemu_get_clock(vm_clock);
 | 
			
		||||
 | 
			
		||||
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
 | 
			
		||||
        cur_line = cur_char / r->htotal;
 | 
			
		||||
 | 
			
		||||
        if (cur_line >= r->vstart && cur_line <= r->vend) {
 | 
			
		||||
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        cur_line_char = cur_char % r->htotal;
 | 
			
		||||
        if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
 | 
			
		||||
            val |= ST01_DISP_ENABLE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return val;
 | 
			
		||||
    } else {
 | 
			
		||||
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t vga_dumb_retrace(VGAState *s)
 | 
			
		||||
{
 | 
			
		||||
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    VGAState *s = opaque;
 | 
			
		||||
| 
						 | 
				
			
			@ -228,8 +362,7 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 | 
			
		|||
        case 0x3ba:
 | 
			
		||||
        case 0x3da:
 | 
			
		||||
            /* just toggle to fool polling */
 | 
			
		||||
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
 | 
			
		||||
            val = s->st01;
 | 
			
		||||
            val = s->st01 = s->retrace(s);
 | 
			
		||||
            s->ar_flip_flop = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
| 
						 | 
				
			
			@ -291,6 +424,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		|||
        break;
 | 
			
		||||
    case 0x3c2:
 | 
			
		||||
        s->msr = val & ~0x10;
 | 
			
		||||
        s->update_retrace_info(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x3c4:
 | 
			
		||||
        s->sr_index = val & 7;
 | 
			
		||||
| 
						 | 
				
			
			@ -300,6 +434,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		|||
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
 | 
			
		||||
#endif
 | 
			
		||||
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
 | 
			
		||||
        if (s->sr_index == 1) s->update_retrace_info(s);
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x3c7:
 | 
			
		||||
        s->dac_read_index = val;
 | 
			
		||||
| 
						 | 
				
			
			@ -357,6 +492,18 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		|||
            s->cr[s->cr_index] = val;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        switch(s->cr_index) {
 | 
			
		||||
        case 0x00:
 | 
			
		||||
        case 0x04:
 | 
			
		||||
        case 0x05:
 | 
			
		||||
        case 0x06:
 | 
			
		||||
        case 0x07:
 | 
			
		||||
        case 0x11:
 | 
			
		||||
        case 0x17:
 | 
			
		||||
            s->update_retrace_info(s);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 0x3ba:
 | 
			
		||||
    case 0x3da:
 | 
			
		||||
| 
						 | 
				
			
			@ -2001,6 +2148,18 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
 | 
			
		|||
    s->invalidate = vga_invalidate_display;
 | 
			
		||||
    s->screen_dump = vga_screen_dump;
 | 
			
		||||
    s->text_update = vga_update_text;
 | 
			
		||||
    switch (vga_retrace_method) {
 | 
			
		||||
    case VGA_RETRACE_DUMB:
 | 
			
		||||
        s->retrace = vga_dumb_retrace;
 | 
			
		||||
        s->update_retrace_info = vga_dumb_update_retrace_info;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case VGA_RETRACE_PRECISE:
 | 
			
		||||
        s->retrace = vga_precise_retrace;
 | 
			
		||||
        s->update_retrace_info = vga_precise_update_retrace_info;
 | 
			
		||||
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* used by both ISA and PCI */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										25
									
								
								hw/vga_int.h
								
								
								
								
							
							
						
						
									
										25
									
								
								hw/vga_int.h
								
								
								
								
							| 
						 | 
				
			
			@ -79,6 +79,25 @@
 | 
			
		|||
#define CH_ATTR_SIZE (160 * 100)
 | 
			
		||||
#define VGA_MAX_HEIGHT 2048
 | 
			
		||||
 | 
			
		||||
struct vga_precise_retrace {
 | 
			
		||||
    int64_t ticks_per_char;
 | 
			
		||||
    int64_t total_chars;
 | 
			
		||||
    int htotal;
 | 
			
		||||
    int hstart;
 | 
			
		||||
    int hend;
 | 
			
		||||
    int vstart;
 | 
			
		||||
    int vend;
 | 
			
		||||
    int freq;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
union vga_retrace {
 | 
			
		||||
    struct vga_precise_retrace precise;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct VGAState;
 | 
			
		||||
typedef uint8_t (* vga_retrace_fn)(struct VGAState *s);
 | 
			
		||||
typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
 | 
			
		||||
 | 
			
		||||
#define VGA_STATE_COMMON                                                \
 | 
			
		||||
    uint8_t *vram_ptr;                                                  \
 | 
			
		||||
    unsigned long vram_offset;                                          \
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +166,11 @@
 | 
			
		|||
    void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y);    \
 | 
			
		||||
    /* tell for each page if it has been updated since the last time */ \
 | 
			
		||||
    uint32_t last_palette[256];                                         \
 | 
			
		||||
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
 | 
			
		||||
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */     \
 | 
			
		||||
    /* retrace */                                                       \
 | 
			
		||||
    vga_retrace_fn retrace;                                             \
 | 
			
		||||
    vga_update_retrace_info_fn update_retrace_info;                     \
 | 
			
		||||
    union vga_retrace retrace_info;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct VGAState {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								vl.c
								
								
								
								
							
							
						
						
									
										15
									
								
								vl.c
								
								
								
								
							| 
						 | 
				
			
			@ -174,6 +174,7 @@ int nb_drives;
 | 
			
		|||
/* point to the block driver where the snapshots are managed */
 | 
			
		||||
BlockDriverState *bs_snapshots;
 | 
			
		||||
int vga_ram_size;
 | 
			
		||||
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 | 
			
		||||
static DisplayState display_state;
 | 
			
		||||
int nographic;
 | 
			
		||||
int curses;
 | 
			
		||||
| 
						 | 
				
			
			@ -8203,7 +8204,19 @@ static void select_vgahw (const char *p)
 | 
			
		|||
        fprintf(stderr, "Unknown vga type: %s\n", p);
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    if (*opts) goto invalid_vga;
 | 
			
		||||
    while (*opts) {
 | 
			
		||||
        const char *nextopt;
 | 
			
		||||
 | 
			
		||||
        if (strstart(opts, ",retrace=", &nextopt)) {
 | 
			
		||||
            opts = nextopt;
 | 
			
		||||
            if (strstart(opts, "dumb", &nextopt))
 | 
			
		||||
                vga_retrace_method = VGA_RETRACE_DUMB;
 | 
			
		||||
            else if (strstart(opts, "precise", &nextopt))
 | 
			
		||||
                vga_retrace_method = VGA_RETRACE_PRECISE;
 | 
			
		||||
            else goto invalid_vga;
 | 
			
		||||
        } else goto invalid_vga;
 | 
			
		||||
        opts = nextopt;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue