📄 vga.c
字号:
ret = 0; } return ret;}static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight){ int width, height; #ifdef CONFIG_BOCHS_VBE if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { width = s->vbe_regs[VBE_DISPI_INDEX_XRES]; height = s->vbe_regs[VBE_DISPI_INDEX_YRES]; } else #endif { width = (s->cr[0x01] + 1) * 8; height = s->cr[0x12] | ((s->cr[0x07] & 0x02) << 7) | ((s->cr[0x07] & 0x40) << 3); height = (height + 1); } *pwidth = width; *pheight = height;}void vga_invalidate_scanlines(VGAState *s, int y1, int y2){ int y; if (y1 >= VGA_MAX_HEIGHT) return; if (y2 >= VGA_MAX_HEIGHT) y2 = VGA_MAX_HEIGHT; for(y = y1; y < y2; y++) { s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); }}/* * graphic modes */static void vga_draw_graphic(VGAState *s, int full_update){ int y1, y, update, linesize, y_start, double_scan, mask, depth; int width, height, shift_control, line_offset, bwidth, ds_depth, bits; ram_addr_t page0, page1; int disp_width, multi_scan, multi_run; uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; ram_addr_t page_min, page_max; unsigned long start, end; full_update |= update_basic_params(s); s->get_resolution(s, &width, &height); disp_width = width; shift_control = (s->gr[0x05] >> 5) & 3; double_scan = (s->cr[0x09] >> 7); if (shift_control != 1) { multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; } else { /* in CGA modes, multi_scan is ignored */ /* XXX: is it correct ? */ multi_scan = double_scan; } multi_run = multi_scan; if (shift_control != s->shift_control || double_scan != s->double_scan) { full_update = 1; s->shift_control = shift_control; s->double_scan = double_scan; } if (shift_control == 1 && (s->sr[0x01] & 8)) { disp_width <<= 1; } ds_depth = s->ds->depth; depth = s->get_bpp(s); if (s->ds->dpy_resize_shared) { if (s->line_offset != s->last_line_offset || disp_width != s->last_width || height != s->last_height || s->last_depth != depth) { dpy_resize_shared(s->ds, disp_width, height, depth, s->line_offset, s->vram_ptr + (s->start_addr * 4)); s->last_scr_width = disp_width; s->last_scr_height = height; s->last_width = disp_width; s->last_height = height; s->last_line_offset = s->line_offset; s->last_depth = depth; full_update = 1; } else if (s->ds->shared_buf && (full_update || s->ds->data != s->vram_ptr + (s->start_addr * 4))) s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4)); } else if (disp_width != s->last_width || height != s->last_height) { dpy_resize(s->ds, disp_width, height); s->last_scr_width = disp_width; s->last_scr_height = height; s->last_width = disp_width; s->last_height = height; full_update = 1; } s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; if (shift_control == 0) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE4D2; } else { v = VGA_DRAW_LINE4; } bits = 4; } else if (shift_control == 1) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE2D2; } else { v = VGA_DRAW_LINE2; } bits = 4; } else { switch(s->get_bpp(s)) { default: case 0: full_update |= update_palette256(s); v = VGA_DRAW_LINE8D2; bits = 4; break; case 8: full_update |= update_palette256(s); v = VGA_DRAW_LINE8; bits = 8; break; case 15: v = VGA_DRAW_LINE15; bits = 16; break; case 16: v = VGA_DRAW_LINE16; bits = 16; break; case 24: v = VGA_DRAW_LINE24; bits = 24; break; case 32: v = VGA_DRAW_LINE32; bits = 32; break; } } vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; if (!s->ds->shared_buf && s->cursor_invalidate) s->cursor_invalidate(s); line_offset = s->line_offset;#if 0 printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);#endif if (s->lfb_addr) { if (height - 1 > s->line_compare || multi_run || (s->cr[0x17] & 3) != 3) { /* Tricky things happen, just track all video memory */ start = 0; end = s->vram_size; } else { /* Tricky things won't have any effect, i.e. we are in the very simple * (and very usual) case of a linear buffer. */ /* use page table dirty bit tracking for the LFB plus border */ start = (s->start_addr * 4) & TARGET_PAGE_MASK; end = ((s->start_addr * 4 + height * line_offset) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK; } for (y = 0 ; y < start; y += TARGET_PAGE_SIZE) /* We will not read that anyway. */ cpu_physical_memory_set_dirty(s->vram_offset + y); { unsigned long npages = (end - y) / TARGET_PAGE_SIZE; const int width = sizeof(unsigned long) * 8; unsigned long bitmap[(npages + width - 1) / width]; int err; if (!(err = xc_hvm_track_dirty_vram(xc_handle, domid, (s->lfb_addr + y) / TARGET_PAGE_SIZE, npages, bitmap))) { int i, j; for (i = 0; i < sizeof(bitmap) / sizeof(*bitmap); i++) { unsigned long map = bitmap[i]; for (j = i * width; map && j < npages; map >>= 1, j++) if (map & 1) cpu_physical_memory_set_dirty(s->vram_offset + y + j * TARGET_PAGE_SIZE); } y += npages * TARGET_PAGE_SIZE; } else { /* ENODATA just means we have changed mode and will succeed * next time */ if (errno != ENODATA) fprintf(stderr, "track_dirty_vram(%lx, %lx) failed (%d, %d)\n", s->lfb_addr + y, npages, err, errno); } } for ( ; y < s->vram_size; y += TARGET_PAGE_SIZE) /* We will not read that anyway. */ cpu_physical_memory_set_dirty(s->vram_offset + y); } addr1 = (s->start_addr * 4); bwidth = (width * bits + 7) / 8; y_start = -1; page_min = 0; page_max = 0; d = s->ds->data; linesize = s->ds->linesize; y1 = 0; for(y = 0; y < height; y++) { addr = addr1; if (!(s->cr[0x17] & 1)) { int shift; /* CGA compatibility handling */ shift = 14 + ((s->cr[0x17] >> 6) & 1); addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift); } if (!(s->cr[0x17] & 2)) { addr = (addr & ~0x8000) | ((y1 & 2) << 14); } page0 = s->vram_offset + (addr & TARGET_PAGE_MASK); page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK); update = full_update | cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) | cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG); if ((page1 - page0) > TARGET_PAGE_SIZE) { /* if wide line, can use another page */ update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); } /* explicit invalidation for the hardware cursor */ update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; if (update) { if (y_start < 0) y_start = y; if (page_min == 0 || page0 < page_min) page_min = page0; if (page_max == 0 || page1 > page_max) page_max = page1; if (!s->ds->shared_buf) { vga_draw_line(s, d, s->vram_ptr + addr, width); if (s->cursor_draw_line) s->cursor_draw_line(s, d, y); } } else { if (y_start >= 0) { /* flush to display */ dpy_update(s->ds, 0, y_start, disp_width, y - y_start); y_start = -1; } } if (!multi_run) { mask = (s->cr[0x17] & 3) ^ 3; if ((y1 & mask) == mask) addr1 += line_offset; y1++; multi_run = multi_scan; } else { multi_run--; } /* line compare acts on the displayed lines */ if (y == s->line_compare) addr1 = 0; d += linesize; } if (y_start >= 0) { /* flush to display */ dpy_update(s->ds, 0, y_start, disp_width, y - y_start); } /* reset modified pages */ if (page_max != -1) { cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); } memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);}static void vga_draw_blank(VGAState *s, int full_update){ int i, w, val; uint8_t *d; if (!full_update) return; if (s->last_scr_width <= 0 || s->last_scr_height <= 0) return; /* Disable dirty bit tracking */ xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL); s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; if (s->ds->depth == 8) val = s->rgb_to_pixel(0, 0, 0); else val = 0; w = s->last_scr_width * ((s->ds->depth + 7) >> 3); d = s->ds->data; for(i = 0; i < s->last_scr_height; i++) { memset(d, val, w); d += s->ds->linesize; } dpy_update(s->ds, 0, 0, s->last_scr_width, s->last_scr_height);}#define GMODE_TEXT 0#define GMODE_GRAPH 1#define GMODE_BLANK 2 static void vga_update_display(void *opaque){ VGAState *s = (VGAState *)opaque; int full_update, graphic_mode; if (s->ds->depth == 0) { /* nothing to do */ } else { full_update = 0; if (!(s->ar_index & 0x20)) { graphic_mode = GMODE_BLANK; } else { graphic_mode = s->gr[6] & 1; } if (graphic_mode != s->graphic_mode) { s->graphic_mode = graphic_mode; full_update = 1; } switch(graphic_mode) { case GMODE_TEXT: vga_draw_text(s, full_update); break; case GMODE_GRAPH: vga_draw_graphic(s, full_update); break; case GMODE_BLANK: default: vga_draw_blank(s, full_update); break; } }}/* force a full display refresh */static void vga_invalidate_display(void *opaque){ VGAState *s = (VGAState *)opaque; s->last_width = -1; s->last_height = -1;}static void vga_reset(VGAState *s){ memset(s, 0, sizeof(VGAState)); s->graphic_mode = -1; /* force full update */}static CPUReadMemoryFunc *vga_mem_read[3] = { vga_mem_readb, vga_mem_readw, vga_mem_readl,};static CPUWriteMemoryFunc *vga_mem_write[3] = { vga_mem_writeb, vga_mem_writew, vga_mem_writel,};static void vga_save(QEMUFile *f, void *opaque){ VGAState *s = opaque; uint32_t vram_size;#ifdef CONFIG_BOCHS_VBE int i;#endif if (s->pci_dev) pci_device_save(s->pci_dev, f); qemu_put_be32s(f, &s->latch); qemu_put_8s(f, &s->sr_index); qemu_put_buffer(f, s->sr, 8); qemu_put_8s(f, &s->gr_index); qemu_put_buffer(f, s->gr, 16); qemu_put_8s(f, &s->ar_index); qemu_put_buffer(f, s->ar, 21); qemu_put_be32s(f, &s->ar_flip_flop); qemu_put_8s(f, &s->cr_index); qemu_put_buffer(f, s->cr, 256); qemu_put_8s(f, &s->msr); qemu_put_8s(f, &s->fcr); qemu_put_8s(f, &s->st00); qemu_put_8s(f, &s->st01); qemu_put_8s(f, &s->dac_state); qemu_put_8s(f, &s->dac_sub_index); qemu_put_8s(f, &s->dac_read_index); qemu_put_8s(f, &s->dac_write_index); qemu_put_buffer(f, s->dac_cache, 3); qemu_put_buffer(f, s->palette, 768); qemu_put_be32s(f, &s->bank_offset);#ifdef CONFIG_BOCHS_VBE qemu_put_byte(f, 1); qemu_put_be16s(f, &s->vbe_index); for(i = 0; i < VBE_DISPI_INDEX_NB; i++) qemu_put_be16s(f, &s->vbe_regs[i]); qemu_put_be32s(f, &s->vbe_start_addr); qemu_put_be32s(f, &s->vbe_line_offset); qemu_put_be32s(f, &s->vbe_bank_mask);#else qemu_put_byte(f, 0);#endif vram_size = s->vram_size; qemu_put_be32s(f, &vram_size); qemu_put_buffer(f, s->vram_ptr, s->vram_size); }static int vga_load(QEMUFile *f, void *opaque, int version_id){ VGAState *s = opaque; int is_vbe, ret; uint32_t vram_size;#ifdef CONFIG_BOCHS_VBE int i;#endif if (version_id > 3) return -EINVAL; if (s->pci_dev && version_id >= 2) { ret = pci_device_load(s->pci_dev, f); if (ret < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -