X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fvga.c;h=1cf1179ee10fdaade9334c466faab294513fd858;hb=6d3926e16dc1ba6ca0144e65b737e432c48aaa91;hp=de6bc66c6300fb49c37789a6221ad251d1315ff5;hpb=56b88e037fb1b9e313e642682a08267b866e70bb;p=palacios.git diff --git a/palacios/src/devices/vga.c b/palacios/src/devices/vga.c index de6bc66..1cf1179 100644 --- a/palacios/src/devices/vga.c +++ b/palacios/src/devices/vga.c @@ -26,6 +26,16 @@ #include "vga_regs.h" +#ifndef V3_CONFIG_DEBUG_VGA +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif + +#define DEBUG_MEM_DATA 0 +#define DEBUG_DEEP_MEM 0 +#define DEBUG_DEEP_RENDER 0 + + #define MEM_REGION_START 0xa0000 #define MEM_REGION_END 0xc0000 #define MEM_REGION_NUM_PAGES (((MEM_REGION_END)-(MEM_REGION_START))/4096) @@ -33,7 +43,6 @@ #define MAP_SIZE 65536 #define MAP_NUM 4 -#define UPDATES_PER_RENDER 100 typedef uint8_t *vga_map; // points to MAP_SIZE data @@ -86,6 +95,18 @@ typedef uint8_t *vga_map; // points to MAP_SIZE data #define VGA_FONT_WIDTH 8 #define VGA_MAX_FONT_HEIGHT 32 +struct vga_render_model { + uint32_t model; // composite the following + +#define VGA_DRIVEN_PERIODIC_RENDERING 0x1 // render after n GPU updates +#define CONSOLE_ADVISORY_RENDERING 0x2 // ask console if we should render following an update +#define CONSOLE_DRIVEN_RENDERING 0x4 // have console tell us when to render + + uint32_t updates_before_render; // defaults to the following + +#define DEFAULT_UPDATES_BEFORE_RENDER 1000 +}; + struct vga_misc_regs { /* Read: 0x3cc; Write: 0x3c2 */ struct vga_misc_out_reg vga_misc_out; @@ -273,12 +294,13 @@ struct vga_dac_regs { struct vga_internal { struct vm_device *dev; - + bool passthrough; bool skip_next_passthrough_out; // for word access struct v3_frame_buffer_spec target_spec; v3_graphics_console_t host_cons; + struct vga_render_model render_model; uint32_t updates_since_render; @@ -365,6 +387,7 @@ static void find_text_data_start(struct vga_internal *vga, void **data) } + static void find_text_attr_start(struct vga_internal *vga, void **data) { uint32_t offset; @@ -420,7 +443,7 @@ static void find_text_font_start(struct vga_internal *vga, void **data, uint8_t *data = vga->map[2] + mapb_offset; break; default: - PrintError("vga: unknown char_map given to find_text_font_start\n"); + PrintError(VM_NONE, VCORE_NONE, "vga: unknown char_map given to find_text_font_start\n"); break; } @@ -446,6 +469,29 @@ static int blinking(struct vga_internal *vga) } +static void find_graphics_data_starting_offset(struct vga_internal *vga, uint32_t *offset) +{ + + *offset = vga->vga_crt_controller.vga_start_address_high; + *offset <<= 8; + *offset += vga->vga_crt_controller.vga_start_address_low; +} + + +static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode) +{ + if (vga->vga_graphics_controller.vga_graphics_mode.c256) { + *mode=C256_SHIFT; + } else { + if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) { + *mode=PACKED_SHIFT; + } else { + *mode=PLANAR_SHIFT; + } + } +} + + static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height) { uint32_t vert_lsb, vert_msb; @@ -460,6 +506,31 @@ static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_ + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8); *height = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines) + + // At this point we have the resolution in dot clocks across and scanlines top-to-bottom + // This is usually the resolution in pixels, but it can be monkeyed with + // at least in the following ways + + // vga sequencer dot clock divide by two + if (vga->vga_sequencer.vga_clocking_mode.dot_clock) { + *width/=2; + *height/=2; + } + + // crt_controller.max_row_scan.double_scan => each row twice for 200=>400 + if (vga->vga_crt_controller.vga_max_row_scan.double_scan) { + *height/=2; + } + + // crt_controller.crt_mode_control.count_by_two => pixels twice as wide as normal + if (vga->vga_crt_controller.vga_crt_mode_control.count_by_two) { + *width /= 2; + } + + // crt_controller.crt_mode_control.horizontal_retrace_select => pixels twice as tall as normal + if (vga->vga_crt_controller.vga_crt_mode_control.horizontal_retrace_select) { + *height /= 2; + } } @@ -471,19 +542,6 @@ static void find_graphics_cursor_pos(struct vga_internal *vga, uint32_t *x, uint } -static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode) -{ - if (vga->vga_graphics_controller.vga_graphics_mode.c256) { - *mode=C256_SHIFT; - } else { - if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) { - *mode=PACKED_SHIFT; - } else { - *mode=PLANAR_SHIFT; - } - } -} - static void dac_lookup_24bit_color(struct vga_internal *vga, uint8_t entry, uint8_t *red, @@ -589,26 +647,28 @@ static void render_graphics(struct vga_internal *vga, void *fb) find_graphics_cursor_pos(vga,&cur_x,&cur_y); + find_graphics_data_starting_offset(vga,&offset); + fw = spec->width; fh = spec->height; - PrintDebug("vga: attempting graphics render (%s): graphics_res=(%u,%u), fb_res=(%u,%u), " - "fb=0x%p (16 color mode)\n", + PrintDebug(VM_NONE, VCORE_NONE, "vga: attempting graphics render (%s): graphics_res=(%u,%u), fb_res=(%u,%u), " + "fb=0x%p offset=0x%x\n", sm == PLANAR_SHIFT ? "planar shift" : sm == PACKED_SHIFT ? "packed shift" : sm == C256_SHIFT ? "color256 shift" : "UNKNOWN", - gw,gh,fw,fh, fb); + gw,gh,fw,fh,fb,offset); // First we need to clip to what we can actually show rgw = gw < fw ? gw : fw; - rgh = gh < fh ? gh : gw; + rgh = gh < fh ? gh : fh; if (gw%8) { - PrintError("vga: warning: graphics width is not a multiple of 8\n"); + PrintError(VM_NONE, VCORE_NONE, "vga: warning: graphics width is not a multiple of 8\n"); } - offset=0; // do we always start at zero in the map? + // Now we scan across by row for (fy=0;fy> 7) | - ( db[1] >> 6) | - ( db[2] >> 5) | - ( db[3] >> 4) ; + (( db[0] >> 7) & 0x1) | + (( db[1] >> 6) & 0x2) | + (( db[2] >> 5) & 0x4) | + (( db[3] >> 4) & 0x8) ; for (m=0;m<4;m++) { db[m] <<= 1; @@ -645,18 +705,17 @@ static void render_graphics(struct vga_internal *vga, void *fb) // first 4 pixels use planes 0 and 2 for (p=0;p<4;p++) { pb[p] = - ( db[2] >> 4) | - ( db[0] >> 6) ; + ((db[2] >> 4) & 0xc) | + ((db[0] >> 6) & 0x3) ; db[2] <<= 2; db[0] <<= 2; } - break; // next 4 pixels use planes 1 and 3 for (p=4;p<8;p++) { pb[p] = - ( db[3] >> 4) | - ( db[1] >> 6) ; + ((db[3] >> 4) & 0xc) | + ((db[1] >> 6) & 0x3) ; db[3] <<= 2; db[1] <<= 2; } @@ -674,7 +733,7 @@ static void render_graphics(struct vga_internal *vga, void *fb) for (p=0;p< (sm==C256_SHIFT ? 4 : 8);p++) { // find its color - find_24bit_color(vga,db[p],&r,&g,&b); + find_24bit_color(vga,pb[p],&r,&g,&b); // find its position in the framebuffer; pixel = fb + (((fx + p) + (fy*spec->width)) * spec->bytes_per_pixel); @@ -691,7 +750,7 @@ static void render_graphics(struct vga_internal *vga, void *fb) } } - PrintDebug("vga: render done\n"); + PrintDebug(VM_NONE, VCORE_NONE, "vga: render done\n"); } @@ -758,7 +817,7 @@ static void render_text(struct vga_internal *vga, void *fb) find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr - PrintDebug("vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), " + PrintDebug(VM_NONE, VCORE_NONE, "vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), " "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p" "graphics extension=%u, extended_fontset=%d, blinking=%d\n", gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb, @@ -771,7 +830,7 @@ static void render_text(struct vga_internal *vga, void *fb) rtw = tw < fw/cw ? tw : fw/cw; rth = th < fh/ch ? th : fh/ch; - + PrintDebug(VM_NONE, VCORE_NONE, "\n"); // Now let's scan by char across the whole thing for (y=0;ytarget_spec); + + memset(fb,0,s->height*s->width*s->bytes_per_pixel); +} + static void render_maps(struct vga_internal *vga, void *fb) { @@ -917,7 +987,7 @@ static void render_maps(struct vga_internal *vga, void *fb) s=&(vga->target_spec); - if (fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) { + if (fb && s->height>=768 && s->width>=1024 ) { // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block uint8_t m; uint32_t x,y; @@ -939,41 +1009,98 @@ static void render_maps(struct vga_internal *vga, void *fb) } } +static int render_core(struct vga_internal *vga) +{ + void *fb; + + PrintDebug(VM_NONE, VCORE_NONE, "vga: render on update %u\n",vga->updates_since_render); + + fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec)); + + if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) { + if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) { + render_graphics(vga,fb); + } else { + render_text(vga,fb); + render_text_cursor(vga,fb); + } + } else { + render_black(vga,fb); + } + + if (0) { render_test(vga,fb); } + + // always render maps for now + render_maps(vga,fb); + + v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons); + + vga->updates_since_render=0; + + return 0; + +} + static int render(struct vga_internal *vga) { - void *fb; - vga->updates_since_render++; - if (vga->updates_since_render%100) { - // skip render + + if (vga->host_cons) { + int do_render=0; + + if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING) + && + (vga->updates_since_render > vga->render_model.updates_before_render)) { + PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to periodic\n"); + + do_render = 1; + } + + if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING) + && + (v3_graphics_console_inform_update(vga->host_cons) > 0) ) { + + PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to advisory\n"); + + do_render = 1; + } + + // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function + + if (do_render) { + return render_core(vga); + } else { return 0; + } } + return 0; + +} - if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) { - - fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec)); - - if (vga->vga_graphics_controller.vga_misc.graphics_mode) { - render_graphics(vga,fb); - } else { - render_text(vga,fb); - render_text_cursor(vga,fb); - } - - if (0) { render_test(vga,fb); } - render_maps(vga,fb); +static int render_callback(v3_graphics_console_t cons, + void *priv) +{ + struct vga_internal *vga = (struct vga_internal *) priv; + + PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to callback\n"); - v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons); - } + return render_core(vga); +} - return 0; +static int update_callback(v3_graphics_console_t cons, + void *priv) +{ + struct vga_internal *vga = (struct vga_internal *) priv; + + return vga->updates_since_render>0; } + static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end) { switch (vga->vga_graphics_controller.vga_misc.memory_map) { @@ -1008,10 +1135,11 @@ static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr) size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); if (vga->vga_sequencer.vga_mem_mode.odd_even) { - return (guest_addr-mem_start) % size; + // NOT odd/even mode + return (guest_addr-mem_start) % size; } else { // odd/even mode - return ((guest_addr-mem_start) >> 1 ) % size; + return ((guest_addr-mem_start) >> 1 ) % size; } } @@ -1028,23 +1156,26 @@ static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr) uint8_t mm = vga->vga_sequencer.vga_map_mask.val; if (vga->vga_sequencer.vga_mem_mode.odd_even) { - return mm; + // NOT odd/even mode + return mm; } else { - if (guest_addr & 0x1) { - return mm & 0xa; // 0x1010 - } else { - return mm & 0x5; // 0x0101 - } + // odd/even mode + if (guest_addr & 0x1) { + return mm & 0xa; // 0x1010 + } else { + return mm & 0x5; // 0x0101 + } } } static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr) { - if (vga->vga_sequencer.vga_mem_mode.odd_even) { - return 1; - } else { - return !(new_guest_addr & 0x1); - } + if (vga->vga_sequencer.vga_mem_mode.odd_even) { + // NOT odd/even mode + return 1; + } else { + return !(new_guest_addr & 0x1); + } } @@ -1058,31 +1189,35 @@ static int vga_write(struct guest_info * core, struct vm_device *dev = (struct vm_device *)priv_data; struct vga_internal *vga = (struct vga_internal *) dev->private_data; - PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length); + PrintDebug(core->vm_info, core, "vga: memory write: guest_addr=0x%p len=%u write_mode=%d first_byte=0x%x\n", + (void*)guest_addr, length, vga->vga_graphics_controller.vga_graphics_mode.write_mode, *(uint8_t*)src); if (vga->passthrough) { - PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr)); + PrintDebug(core->vm_info, core, "vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr)); memcpy(V3_VAddr((void*)guest_addr),src,length); } -#if 0 +#if DEBUG_MEM_DATA int i; - PrintDebug("vga: data written was 0x"); + PrintDebug(core->vm_info, core, "vga: data written was 0x"); for (i=0;ivm_info, core, "%.2x", c); } - PrintDebug(" \""); + PrintDebug(core->vm_info, core, " \""); for (i=0;i='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.'); + PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.'); } - PrintDebug("\"\n"); + PrintDebug(core->vm_info, core, "\"\n"); #endif /* Write mode determine by Graphics Mode Register (Index 05h).writemode */ + // probably could just reduce this to the datapath itself instead + // of following the programmer's perspective... + switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) { case 0: { @@ -1107,7 +1242,9 @@ static int vga_write(struct guest_info * core, offset = find_offset_write(vga, guest_addr); - PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func); +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func); +#endif for (i=0;ivga_graphics_controller.vga_bit_mask; uint8_t mm = find_map_write(vga,guest_addr+i); - //PrintDebug("vga: write i=%u, mm=0x%x, offset=0x%x\n",i,(unsigned int)mm,(unsigned int)offset); +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: write i=%u, mm=0x%x, bm=0x%x sr=0x%x esr=0x%x offset=0x%x\n",i,(unsigned int)mm,(unsigned int)bm, (unsigned int)sr, (unsigned int)esr,(unsigned int)offset); +#endif - for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) { + for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) { vga_map map = vga->map[mapnum]; uint8_t data = ((uint8_t *)src)[i]; uint8_t latchval = vga->latch[mapnum]; - + +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: raw data=0x%x\n",data); +#endif // rotate data right - data = (data>>ror) | data<<(8-ror); - + if (ror) { + data = (data>>ror) | (data<<(8-ror)); + } + +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: data after ror=0x%x\n",data); +#endif // use SR bit if ESR is on for this map - if (esr & 0x1) { - data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit + if (esr & 0x1) { + data = (sr&0x1) * -1; + } +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: data after esrr=0x%x\n",data); +#endif + // Apply function switch (func) { case 0: // NOP @@ -1145,19 +1297,26 @@ static int vga_write(struct guest_info * core, data ^= latchval; break; } - - // mux between latch and alu output - if (bm & 0x1) { - // use alu output, which is in data - } else { - // use latch value - data=latchval; - } + +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: data after func=0x%x\n",data); +#endif + + // mux between the data byte and the latch byte on + // a per-bit basis + data = (bm & data) | ((~bm) & latchval); + + +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: data after bm mux=0x%x\n",data); +#endif // selective write if (mm & 0x1) { // write to this map - //PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset])); +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset])); +#endif map[offset] = data; } else { // skip this map @@ -1180,7 +1339,9 @@ static int vga_write(struct guest_info * core, uint64_t offset = find_offset_write(vga,guest_addr); - PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset); +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: mode 1 write, offset=0x%llx\n", offset); +#endif for (i=0;ivm_info, core, "vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func); +#endif for (i=0;ivga_graphics_controller.vga_bit_mask; uint8_t mm = find_map_write(vga,guest_addr+i); - for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) { + for (mapnum=0;mapnum<4;mapnum++, mm>>=1) { vga_map map = vga->map[mapnum]; uint8_t data = ((uint8_t *)src)[i]; uint8_t latchval = vga->latch[mapnum]; // expand relevant bit to 8 bit - // it's basically esr=1, sr=bit from write - data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7); - + // it's basically esr=1, sr=bit from mode 0 write + data = ((data>>mapnum)&0x1) * -1; + // Apply function switch (func) { case 0: // NOP @@ -1251,14 +1414,9 @@ static int vga_write(struct guest_info * core, data ^= latchval; break; } - + // mux between latch and alu output - if (bm & 0x1) { - // use alu output, which is in data - } else { - // use latch value - data=latchval; - } + data = (bm & data) | ((~bm) & latchval); // selective write if (mm & 0x1) { @@ -1292,32 +1450,33 @@ static int vga_write(struct guest_info * core, offset = find_offset_write(vga, guest_addr); - PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror); + PrintDebug(core->vm_info, core, "vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror); for (i=0;i>ror) | data<<(8-ror); + if (ror) { + data = (data>>ror) | (data<<(8-ror)); + } + // Note here that the bitmask is the register AND the data + // the data written by the system is used for no other purpose uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data; + uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf; + uint8_t mm = find_map_write(vga,guest_addr+i); - for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) { + for (mapnum=0;mapnum<4;mapnum++, sr>>=1, mm>>=1) { vga_map map = vga->map[mapnum]; uint8_t latchval = vga->latch[mapnum]; - data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit - - + // expand SR bit - that's the data we're going to use + data = (sr&0x1) * -1; + // mux between latch and alu output - if (bm & 0x1) { - // use alu output, which is in data - } else { - // use latch value - data=latchval; - } + data = (bm & data) | ((~bm) & latchval); // selective write if (mm & 0x1) { @@ -1353,22 +1512,61 @@ static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr) size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); - if (!vga->vga_sequencer.vga_mem_mode.chain4) { - return (guest_addr-mem_start) % size; - } else { - // chain4 mode - return ((guest_addr - mem_start) >> 2) % size; + if (!vga->vga_sequencer.vga_mem_mode.odd_even) { + // odd/even mode takes priority + return ((guest_addr-mem_start) >> 1 ) % size; + } + + if (vga->vga_sequencer.vga_mem_mode.chain4) { + // otherwise chain4 if it's on + return ((guest_addr - mem_start) >> 2) % size; } + + // and what you would expect if neither are on + return (guest_addr-mem_start) % size; } -static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr) +// Given this address +// which specific map should we write into? +// Note that unlike with find_map_write, here we are looking +// for a single map number, not a bit vector of maps to be selected +static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr) { + uint64_t mem_start, mem_end; + + mem_start=mem_end=0; + + get_mem_region(vga, &mem_start, &mem_end); + + if (!vga->vga_sequencer.vga_mem_mode.odd_even) { + // odd-even mode + // last bit tells us map 0 or 1 + return (guest_addr-mem_start) & 0x1; + } - if (vga->vga_sequencer.vga_mem_mode.chain4) { - return !(new_guest_addr & 0x3); - } else { - return 1; + if (vga->vga_sequencer.vga_mem_mode.chain4) { + // otherwise chain4 if it's on + // last two bits + return (guest_addr - mem_start) & 0x3; } + + // and what you would expect if neither are on + // note that it's not the same as a write! + return vga->vga_graphics_controller.vga_read_map_select.map_select; +} + +static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr) +{ + + if (!vga->vga_sequencer.vga_mem_mode.odd_even) { + // odd-even mode + return !(new_guest_addr & 0x1); + } + + if (vga->vga_sequencer.vga_mem_mode.chain4) { + return !(new_guest_addr & 0x3); + } + return 1; } @@ -1382,7 +1580,8 @@ static int vga_read(struct guest_info * core, struct vga_internal *vga = (struct vga_internal *) dev->private_data; - PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length); + PrintDebug(core->vm_info, core, "vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length, + vga->vga_graphics_controller.vga_graphics_mode.read_mode); @@ -1392,33 +1591,31 @@ static int vga_read(struct guest_info * core, switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) { case 0: { /* 0 - a byte from ONE of the 4 planes is returned; - which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */ + which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) + OR by odd/even chaining OR by chain4 chaining + */ uint8_t mapnum; uint64_t offset; + uint32_t i; + offset = find_offset_read(vga,guest_addr); + +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: mode 0 read, offset=0x%llx\n",offset); +#endif + for (i=0;imap[mapnum]+offset); + + // need to load all latches even though we are + // returning data from only the selected map + for (mapnum=0;mapnum<4;mapnum++) { + vga->latch[mapnum] = *(vga->map[mapnum]+offset); + } - if (vga->vga_sequencer.vga_mem_mode.chain4) { - uint32_t i; - offset = find_offset_read(vga,guest_addr); - // address bytes select the map - for (i=0;ilatch[mapnum] = *(vga->map[mapnum]+offset); - } - } else { - mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select; - offset = find_offset_read(vga,guest_addr); - - if (offset>=65536) { - PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length); - } - - memcpy(dst,(vga->map[mapnum])+offset,length); - - // load the latches with the last item read - for (mapnum=0;mapnum<4;mapnum++) { - vga->latch[mapnum] = vga->map[mapnum][offset+length-1]; - } } } @@ -1433,66 +1630,57 @@ static int vga_read(struct guest_info * core, */ int i; - - uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ; - uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf; - - uint8_t mapnum; uint64_t offset; - uint8_t byte; - uint8_t bits; - + offset = find_offset_read(vga,guest_addr); - - for (i=0;imap[mapnum]; - if ( (dc>>mapnum)&0x1 ) { // don't care - bits=0; - } else { - // lower 4 bits - bits = (map[offset]&0xf) == cc; - bits <<= 1; - // upper 4 bits - bits |= (((map[offset]>>4))&0xf) == cc; - } - // not clear whether it is 0..k or k..0 - byte<<=2; - byte|=bits; - } - } - // load the latches with the last item read - for (mapnum=0;mapnum<4;mapnum++) { - vga->latch[mapnum] = vga->map[mapnum][offset+length-1]; +#if DEBUG_DEEP_MEM + PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx\n",offset); +#endif + + for (i=0;ivga_graphics_controller.vga_color_compare.val & 0xf ; + uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf; + + for (mapnum=0;mapnum<4;mapnum++, cc>>=1, dc>>=1) { + if (dc&0x1) { // dc is active low; 1=we do care + mapcalc &= (cc * -1) & *(vga->map[mapnum]+offset); + } + // do latch load + vga->latch[mapnum] = *(vga->map[mapnum]+offset); + } + // write back the comparison result (for 8 pixels) + ((uint8_t *)dst)[i]=mapcalc; } } + break; // there is no default } if (vga->passthrough) { - PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr)); + PrintDebug(core->vm_info, core, "vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr)); memcpy(dst,V3_VAddr((void*)guest_addr),length); } -#if 0 +#if DEBUG_MEM_DATA int i; - PrintDebug("vga: data read is 0x"); + PrintDebug(core->vm_info, core, "vga: data read is 0x"); for (i=0;ivm_info, core, "%.2x", c); } - PrintDebug(" \""); + PrintDebug(core->vm_info, core, " \""); for (i=0;i='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.'); + PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.'); } - PrintDebug("\"\n"); + PrintDebug(core->vm_info, core, "\"\n"); #endif return length; @@ -1505,7 +1693,7 @@ static int vga_read(struct guest_info * core, #define ERR_WRONG_SIZE(op,reg,len,min,max) \ if (((len)<(min)) || ((len)>(max))) { \ - PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \ + PrintError(core->vm_info, core, "vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \ return -1; \ } @@ -1521,7 +1709,7 @@ static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) *(uint32_t *)dest = v3_indw(port); break; default: - PrintError("vga: unsupported passthrough io in size %u\n",length); + PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io in size %u\n",length); break; } } @@ -1539,7 +1727,7 @@ static inline void passthrough_io_out(uint16_t port, const void * src, uint_t le v3_outdw(port, *(uint32_t *)src); break; default: - PrintError("vga: unsupported passthrough io out size %u\n",length); + PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io out size %u\n",length); break; } } @@ -1554,7 +1742,7 @@ static inline void passthrough_io_out(uint16_t port, const void * src, uint_t le do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0) #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \ - do { if ((vga)->passthrough) { if ((inter)!=(pass)) { PrintError("vga: passthrough error: passthrough value read is 0x%x, but internal value read is 0x%x\n",(pass),(inter)); } } } while (0) + do { if ((vga)->passthrough) { if ((inter)!=(pass)) { PrintError(core->vm_info, core, "vga: passthrough error: passthrough value read is 0x%x, but internal value read is 0x%x\n",(pass),(inter)); } } } while (0) static int misc_out_read(struct guest_info *core, uint16_t port, @@ -1564,7 +1752,7 @@ static int misc_out_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val); + PrintDebug(core->vm_info, core, "vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val); ERR_WRONG_SIZE("read","misc out",len,1,1); @@ -1585,7 +1773,7 @@ static int misc_out_write(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src)); + PrintDebug(core->vm_info, core, "vga: misc out write data=0x%x\n", *((uint8_t*)src)); ERR_WRONG_SIZE("write","misc out",len,1,1); @@ -1608,7 +1796,7 @@ static int input_stat0_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val); + PrintDebug(core->vm_info, core, "vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val); ERR_WRONG_SIZE("read","input stat0",len,1,1); @@ -1630,7 +1818,7 @@ static int input_stat1_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: input stat0 (%s) read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: input stat0 (%s) read data=0x%x\n", port==0x3ba ? "mono" : "color", vga->vga_misc.vga_input_stat1.val); @@ -1639,6 +1827,28 @@ static int input_stat1_read(struct guest_info *core, *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val; + // Pretend that horizontal and vertical blanking + // is occurring + if (!vga->vga_misc.vga_input_stat1.disp_en) { + + // if not blanking, start horizontal blanking + vga->vga_misc.vga_input_stat1.disp_en = 1; + vga->vga_misc.vga_input_stat1.vert_retrace = 0; + + } else { + + if (!vga->vga_misc.vga_input_stat1.vert_retrace) { + // if not vertical blanking, then now vertical blanking + vga->vga_misc.vga_input_stat1.disp_en = 1; + vga->vga_misc.vga_input_stat1.vert_retrace = 1; + } else { + // if vertical blanking, now not blanking + vga->vga_misc.vga_input_stat1.disp_en = 0; + vga->vga_misc.vga_input_stat1.vert_retrace = 0; + } + + } + // Stunningly, reading stat1 is also a way to reset // the state of attribute controller address/data flipflop // That is some mighty fine crack the designers were smoking. @@ -1661,7 +1871,7 @@ static int feature_control_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: feature control read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: feature control read data=0x%x\n", vga->vga_misc.vga_feature_control.val); ERR_WRONG_SIZE("read","feature control",len,1,1); @@ -1684,7 +1894,7 @@ static int feature_control_write(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: feature control (%s) write data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: feature control (%s) write data=0x%x\n", port==0x3ba ? "mono" : "color", *((uint8_t*)src)); @@ -1708,7 +1918,7 @@ static int video_subsys_enable_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: video subsys enable read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: video subsys enable read data=0x%x\n", vga->vga_misc.vga_video_subsys_enable.val); ERR_WRONG_SIZE("read","video subsys enable",len,1,1); @@ -1730,7 +1940,7 @@ static int video_subsys_enable_write(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src)); + PrintDebug(core->vm_info, core, "vga: video subsys enable write data=0x%x\n", *((uint8_t*)src)); ERR_WRONG_SIZE("write","video subsys enable",len,1,1); @@ -1751,7 +1961,7 @@ static int sequencer_address_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: sequencer address read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: sequencer address read data=0x%x\n", vga->vga_sequencer.vga_sequencer_addr.val); ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1); @@ -1778,7 +1988,7 @@ static int sequencer_data_write(struct guest_info *core, data=*((uint8_t*)src); index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably - PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n", + PrintDebug(core->vm_info, core, "vga: sequencer write data (index=%d) with 0x%x\n", index, data); ERR_WRONG_SIZE("write","vga sequencer data",len,1,1); @@ -1787,7 +1997,7 @@ static int sequencer_data_write(struct guest_info *core, if (index>=VGA_SEQUENCER_NUM) { - PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index); + PrintError(core->vm_info, core, "vga: sequencer data write is for invalid index %d, ignoring\n",index); } else { vga->vga_sequencer.vga_sequencer_regs[index] = data; } @@ -1808,7 +2018,7 @@ static int sequencer_address_write(struct guest_info *core, new_addr=*((uint8_t*)src); - PrintDebug("vga: sequencer address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len); + PrintDebug(core->vm_info, core, "vga: sequencer address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len); ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2); @@ -1820,7 +2030,7 @@ static int sequencer_address_write(struct guest_info *core, PASSTHROUGH_IO_SKIP_NEXT_OUT(vga); // second byte is the data if (sequencer_data_write(core,port,src+1,1,vga)!=1) { - PrintError("vga: write of data failed\n"); + PrintError(core->vm_info, core, "vga: write of data failed\n"); return -1; } } @@ -1842,12 +2052,12 @@ static int sequencer_data_read(struct guest_info *core, if (index>=VGA_SEQUENCER_NUM) { data=0; - PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index); + PrintError(core->vm_info, core, "vga: sequencer data read at invalid index %d, returning zero\n",index); } else { data=vga->vga_sequencer.vga_sequencer_regs[index]; } - PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n", + PrintDebug(core->vm_info, core, "vga: sequencer data read data (index=%d) = 0x%x\n", index, data); ERR_WRONG_SIZE("read","vga sequencer data",len,1,1); @@ -1873,7 +2083,7 @@ static int crt_controller_address_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: crt controller (%s) address read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: crt controller (%s) address read data=0x%x\n", port==0x3b4 ? "mono" : "color", vga->vga_crt_controller.vga_crt_addr.val); @@ -1902,7 +2112,7 @@ static int crt_controller_data_write(struct guest_info *core, index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably - PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n", + PrintDebug(core->vm_info, core, "vga: crt controller (%s) write data (index=%d) with 0x%x\n", port==0x3b5 ? "mono" : "color", index, data); @@ -1911,9 +2121,14 @@ static int crt_controller_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); if (index>=VGA_CRT_CONTROLLER_NUM) { - PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index); + PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index); } else { - vga->vga_crt_controller.vga_crt_controller_regs[index] = data; + vga->vga_crt_controller.vga_crt_controller_regs[index] = data; + if (index == 17) { + if (vga->vga_crt_controller.vga_vertical_retrace_end.enable_vertical_interrupt) { + PrintError(core->vm_info, core, "vga: vertical_retrace_interrupt_enabled is unsupported -- no interrupts will occur!\n"); + } + } } render(vga); @@ -1932,7 +2147,7 @@ static int crt_controller_address_write(struct guest_info *core, new_addr=*((uint8_t*)src); - PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n", + PrintDebug(core->vm_info, core, "vga: crt controller (%s) address write data=0x%x len=%u\n", port==0x3b4 ? "mono" : "color", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len); @@ -1946,7 +2161,7 @@ static int crt_controller_address_write(struct guest_info *core, PASSTHROUGH_IO_SKIP_NEXT_OUT(vga); // second byte is the data if (crt_controller_data_write(core,port,src+1,1,vga)!=1) { - PrintError("vga: write of data failed\n"); + PrintError(core->vm_info, core, "vga: write of data failed\n"); return -1; } } @@ -1968,12 +2183,12 @@ static int crt_controller_data_read(struct guest_info *core, if (index>=VGA_CRT_CONTROLLER_NUM) { data=0; - PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index); + PrintError(core->vm_info, core, "vga: crt controller data read for illegal index %d, returning zero\n",index); } else { data=vga->vga_crt_controller.vga_crt_controller_regs[index]; } - PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data); + PrintDebug(core->vm_info, core, "vga: crt controller data (index=%d) = 0x%x\n",index,data); ERR_WRONG_SIZE("read","vga crt controller data",len,1,1); @@ -1996,7 +2211,7 @@ static int graphics_controller_address_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: graphics controller address read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: graphics controller address read data=0x%x\n", vga->vga_graphics_controller.vga_graphics_ctrl_addr.val); ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1); @@ -2024,7 +2239,7 @@ static int graphics_controller_data_write(struct guest_info *core, index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably - PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n", + PrintDebug(core->vm_info, core, "vga: graphics_controller write data (index=%d) with 0x%x\n", index, data); ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1); @@ -2032,7 +2247,7 @@ static int graphics_controller_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { - PrintError("vga: graphics controller write for illegal index %d ignored\n",index); + PrintError(core->vm_info, core, "vga: graphics controller write for illegal index %d ignored\n",index); } else { vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data; } @@ -2053,7 +2268,7 @@ static int graphics_controller_address_write(struct guest_info *core, new_addr=*((uint8_t*)src); - PrintDebug("vga: graphics controller address write data=0x%x len=%u\n", + PrintDebug(core->vm_info, core, "vga: graphics controller address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len); ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2); @@ -2066,7 +2281,7 @@ static int graphics_controller_address_write(struct guest_info *core, PASSTHROUGH_IO_SKIP_NEXT_OUT(vga); // second byte is the data if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) { - PrintError("vga: write of data failed\n"); + PrintError(core->vm_info, core, "vga: write of data failed\n"); return -1; } } @@ -2089,12 +2304,12 @@ static int graphics_controller_data_read(struct guest_info *core, if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { data=0; - PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index); + PrintError(core->vm_info, core, "vga: graphics controller data read from illegal index %d, returning zero\n",index); } else { data=vga->vga_graphics_controller.vga_graphics_controller_regs[index]; } - PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n", + PrintDebug(core->vm_info, core, "vga: graphics controller data read data (index=%d) = 0x%x\n", index, data); ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1); @@ -2121,7 +2336,7 @@ static int attribute_controller_address_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: attribute controller address read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: attribute controller address read data=0x%x\n", vga->vga_attribute_controller.vga_attribute_controller_addr.val); ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1); @@ -2150,7 +2365,7 @@ static int attribute_controller_address_and_data_write(struct guest_info *core, uint8_t new_addr = *((uint8_t*)src); // We are to treat this as an address write, and flip state // to expect data ON THIS SAME PORT - PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr); + PrintDebug(core->vm_info, core, "vga: attribute controller address write data=0x%x\n", new_addr); ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1); @@ -2166,14 +2381,14 @@ static int attribute_controller_address_and_data_write(struct guest_info *core, uint8_t data = *((uint8_t*)src); uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably - PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data); + PrintDebug(core->vm_info, core, "vga: attribute controller data write index %d with data=0x%x\n", index,data); ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1); PASSTHROUGH_IO_OUT(vga,port,src,len); if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { - PrintError("vga: attribute controller write to illegal index %d ignored\n",index); + PrintError(core->vm_info, core, "vga: attribute controller write to illegal index %d ignored\n",index); } else { vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data; } @@ -2201,12 +2416,12 @@ static int attribute_controller_data_read(struct guest_info *core, if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { data=0; - PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index); + PrintError(core->vm_info, core, "vga: attribute controller read of illegal index %d, returning zero\n",index); } else { data=vga->vga_attribute_controller.vga_attribute_controller_regs[index]; } - PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n", + PrintDebug(core->vm_info, core, "vga: attribute controller data read data (index=%d) = 0x%x\n", index, data); ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1); @@ -2234,7 +2449,7 @@ static int dac_write_address_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: dac write address read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: dac write address read data=0x%x\n", vga->vga_dac.vga_dac_write_addr); ERR_WRONG_SIZE("read","vga dac write addr",len,1,1); @@ -2262,7 +2477,7 @@ static int dac_write_address_write(struct guest_info *core, new_addr=*((uint8_t*)src); - PrintDebug("vga: dac write address write data=0x%x\n", new_addr); + PrintDebug(core->vm_info, core, "vga: dac write address write data=0x%x\n", new_addr); ERR_WRONG_SIZE("write","vga dac write addr",len,1,1); @@ -2289,7 +2504,7 @@ static int dac_read_address_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: dac read address read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: dac read address read data=0x%x\n", vga->vga_dac.vga_dac_read_addr); ERR_WRONG_SIZE("read","vga dac read addr",len,1,1); @@ -2316,7 +2531,7 @@ static int dac_read_address_write(struct guest_info *core, new_addr=*((uint8_t*)src); - PrintDebug("vga: dac read address write data=0x%x\n", new_addr); + PrintDebug(core->vm_info, core, "vga: dac read address write data=0x%x\n", new_addr); ERR_WRONG_SIZE("write","vga dac read addr",len,1,1); @@ -2347,7 +2562,7 @@ static int dac_data_read(struct guest_info *core, uint8_t data; if (vga->vga_dac.state!=DAC_READ) { - PrintError("vga: dac data read while in other state\n"); + PrintError(core->vm_info, core, "vga: dac data read while in other state\n"); // results undefined, so we continue } @@ -2357,7 +2572,7 @@ static int dac_data_read(struct guest_info *core, curchannel = vga->vga_dac.channel; data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f; - PrintDebug("vga: dac reg %u [%s] = 0x%x\n", + PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] = 0x%x\n", curreg, curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN" : curchannel==2 ? "BLUE" : "BAD CHANNEL", @@ -2396,7 +2611,7 @@ static int dac_data_write(struct guest_info *core, vga_palette_reg mask32; if (vga->vga_dac.state!=DAC_WRITE) { - PrintError("vga: dac data write while in other state\n"); + PrintError(core->vm_info, core, "vga: dac data write while in other state\n"); // results undefined, so we continue } @@ -2408,7 +2623,7 @@ static int dac_data_write(struct guest_info *core, curchannel = vga->vga_dac.channel; data = *((uint8_t *)src); - PrintDebug("vga: dac reg %u [%s] write with 0x%x\n", + PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] write with 0x%x\n", curreg, curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN" : curchannel==2 ? "BLUE" : "BAD CHANNEL", @@ -2444,7 +2659,7 @@ static int dac_pixel_mask_read(struct guest_info *core, { struct vga_internal *vga = (struct vga_internal *) priv_data; - PrintDebug("vga: dac pixel mask read data=0x%x\n", + PrintDebug(core->vm_info, core, "vga: dac pixel mask read data=0x%x\n", vga->vga_dac.vga_pixel_mask); ERR_WRONG_SIZE("read","vga pixel mask",len,1,1); @@ -2469,7 +2684,7 @@ static int dac_pixel_mask_write(struct guest_info *core, new_data=*((uint8_t*)src); - PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data); + PrintDebug(core->vm_info, core, "vga: dac pixel mask write data=0x%x\n", new_data); ERR_WRONG_SIZE("write","pixel mask",len,1,1); @@ -2482,9 +2697,10 @@ static int dac_pixel_mask_write(struct guest_info *core, static int init_vga(struct vga_internal *vga) { - // TODO: startup spec of register contents, if any - PrintError("vga: init_vga is UNIMPLEMTED\n"); - return 0; + // TODO: startup spec of register contents, if any + vga->vga_misc.vga_input_stat1.val = 0x1; // display enable, not in retrace + + return 0; } static int free_vga(struct vga_internal *vga) @@ -2570,19 +2786,22 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { char * passthrough = v3_cfg_val(cfg, "passthrough"); char * hostframebuf = v3_cfg_val(cfg, "hostframebuf"); - PrintDebug("vga: init_device\n"); + PrintDebug(vm, VCORE_NONE, "vga: init_device\n"); vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal)); if (!vga) { - PrintError("vga: cannot allocate\n"); + PrintError(vm, VCORE_NONE, "vga: cannot allocate\n"); return -1; } memset(vga, 0, sizeof(struct vga_internal)); + vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING; + vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER; + if (passthrough && strcasecmp(passthrough,"enable")==0) { - PrintDebug("vga: enabling passthrough\n"); + PrintDebug(vm, VCORE_NONE, "vga: enabling passthrough\n"); vga->passthrough=true; vga->skip_next_passthrough_out=false; } @@ -2591,7 +2810,7 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) { struct v3_frame_buffer_spec req; - PrintDebug("vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n"); + PrintDebug(vm, VCORE_NONE, "vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n"); memset(&req,0,sizeof(struct v3_frame_buffer_spec)); memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec)); @@ -2608,21 +2827,37 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec)); if (!vga->host_cons) { - PrintError("vga: unable to open host OS's graphics console\n"); + PrintError(vm, VCORE_NONE, "vga: unable to open host OS's graphics console\n"); free_vga(vga); return -1; } if (memcmp(&req,&(vga->target_spec),sizeof(req))) { - PrintDebug("vga: warning: target spec differs from requested spec\n"); - PrintDebug("vga: request: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", req.width, req.height, req.bytes_per_pixel, req.bits_per_channel, req.red_offset, req.green_offset, req.blue_offset); - PrintDebug("vga: response: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", vga->target_spec.width, vga->target_spec.height, vga->target_spec.bytes_per_pixel, vga->target_spec.bits_per_channel, vga->target_spec.red_offset, vga->target_spec.green_offset, vga->target_spec.blue_offset); + PrintDebug(vm, VCORE_NONE, "vga: warning: target spec differs from requested spec\n"); + PrintDebug(vm, VCORE_NONE, "vga: request: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", req.width, req.height, req.bytes_per_pixel, req.bits_per_channel, req.red_offset, req.green_offset, req.blue_offset); + PrintDebug(vm, VCORE_NONE, "vga: response: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", vga->target_spec.width, vga->target_spec.height, vga->target_spec.bytes_per_pixel, vga->target_spec.bits_per_channel, vga->target_spec.red_offset, vga->target_spec.green_offset, vga->target_spec.blue_offset); } - } + + if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) { + V3_Print(vm, VCORE_NONE, "vga: enabling console-driven rendering\n"); + if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) { + PrintError(vm, VCORE_NONE, "vga: cannot enable console-driven rendering\n"); + free_vga(vga); + return -1; + } + } + + V3_Print(vm, VCORE_NONE, "vga: enabling console inquiry for updates\n"); + if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) { + PrintError(vm, VCORE_NONE, "vga: cannot enable console inquiry for updates\n"); + free_vga(vga); + return -1; + } + } if (!vga->passthrough && !vga->host_cons) { - V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n"); + V3_Print(vm, VCORE_NONE, "vga: neither passthrough nor host console are enabled - no way to display anything!\n"); } @@ -2632,19 +2867,24 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { // Now allocate the maps for (i=0;imap[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096)); - if (!(vga->map[i])) { - PrintError("vga: cannot allocate maps\n"); + void *temp; + + temp = (void*)V3_AllocPages(MAP_SIZE/4096); + if (!temp) { + PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n"); free_vga(vga); return -1; } + + vga->map[i] = (vga_map) V3_VAddr(temp); + memset(vga->map[i],0,MAP_SIZE); } struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga); if (dev == NULL) { - PrintError("Could not attach device %s\n", dev_id); + PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id); free_vga(vga); return -1; } @@ -2656,7 +2896,7 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { &vga_read, &vga_write, dev) == -1) { - PrintError("vga: memory book failed\n"); + PrintError(vm, VCORE_NONE, "vga: memory book failed\n"); v3_remove_device(dev); return -1; } @@ -2700,14 +2940,14 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write); if (ret != 0) { - PrintError("vga: Error allocating VGA I/O ports\n"); + PrintError(vm, VCORE_NONE, "vga: Error allocating VGA I/O ports\n"); v3_remove_device(dev); return -1; } init_vga(vga); - PrintDebug("vga: successfully added and initialized.\n"); + PrintDebug(vm, VCORE_NONE, "vga: successfully added and initialized.\n"); return 0;