X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fvga.c;h=f5d5469b74d73caacd7bb6d5240855f775c4cf59;hb=ac376813b3a6e3fbb21d20418e7fc0c9a15474ac;hp=0aa991e57d279edc341dd61eed6da7bd2c37522a;hpb=959658e4651f2107602830510d0c4683353c767a;p=palacios-OLD.git diff --git a/palacios/src/devices/vga.c b/palacios/src/devices/vga.c index 0aa991e..f5d5469 100644 --- a/palacios/src/devices/vga.c +++ b/palacios/src/devices/vga.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "vga_regs.h" @@ -32,25 +33,12 @@ #define MAP_SIZE 65536 #define MAP_NUM 4 -typedef uint8_t *vga_map; // points to MAP_SIZE data - -/* HACK HACK HACK */ - -struct fb_info { - uint32_t rows; - uint32_t cols; - uint32_t bitsperpixel; -}; +#define UPDATES_PER_RENDER 100 -struct fb { - struct fb_info *info; - uint8_t * data; -}; - -//extern -struct fb *palacios_linux_fb_hack_pointer; +typedef uint8_t *vga_map; // points to MAP_SIZE data -/* HACK HACK HACK */ +#define VGA_MAXX 1024 +#define VGA_MAXY 768 #define VGA_MISC_OUT_READ 0x3cc @@ -283,6 +271,12 @@ 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; + + uint32_t updates_since_render; struct frame_buf *framebuf; // we render to this @@ -322,6 +316,79 @@ struct vga_internal { }; + +static int render(struct vga_internal *vga) +{ + vga->updates_since_render++; + + if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) { + // Draw some crap for testing for now + + void *fb; + struct v3_frame_buffer_spec *s; + + fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec)); + + s=&(vga->target_spec); + + if (0 && fb && s->height>=480 && s->width>=640 ) { + uint8_t color = (uint8_t)(vga->updates_since_render); + + uint32_t x, y; + + for (y=0;y<480;y++) { + for (x=0;x<640;x++) { + void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel); + uint8_t *red = pixel + s->red_offset; + uint8_t *green = pixel + s->green_offset; + uint8_t *blue = pixel + s->blue_offset; + + if (y<(480/4)) { + *red=color+x; + *green=0; + *blue=0; + } else if (y<(480/2)) { + *red=0; + *green=color+x; + *blue=0; + } else if (y<(3*(480/4))) { + *red=0; + *green=0; + *blue=color+x; + } else { + *red=*green=*blue=color+x; + } + } + } + } + + if (1 && fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) { + // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block + uint8_t m; + uint32_t x,y; + uint8_t *b; + + for (m=0;m<4;m++) { + b=(vga->map[m]); + for (y=480+32;y<768;y++) { + for (x=m*256;x<(m+1)*256;x++,b++) { + void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel); + uint8_t *red = pixel + s->red_offset; + uint8_t *green = pixel + s->green_offset; + uint8_t *blue = pixel + s->blue_offset; + + *red=*green=*blue=*b; + } + } + } + } + v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons); + } + + return 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) { @@ -371,9 +438,25 @@ static int vga_write(struct guest_info * core, PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length); if (vga->passthrough) { + PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr)); memcpy(V3_VAddr((void*)guest_addr),src,length); } +#if 0 + int i; + PrintDebug("vga: data written was 0x"); + for (i=0;i='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.'); + } + PrintDebug("\"\n"); +#endif + /* Write mode determine by Graphics Mode Register (Index 05h).writemode */ switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) { @@ -448,7 +531,7 @@ static int vga_write(struct guest_info * core, // 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])); + //PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset])); map[offset] = data; } else { // skip this map @@ -625,14 +708,15 @@ static int vga_write(struct guest_info * core, // There is no default } + + render(vga); return length; } - // PrintError("vga: vga_write UNIMPLEMENTED\n"); /* -up to 256K mapped through a window of 128K +up to 256K mapped through a window of 32 to 128K most cards support linear mode as well @@ -679,14 +763,11 @@ static int vga_read(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 read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length); - if (vga->passthrough) { - memcpy(dst,V3_VAddr((void*)guest_addr),length); - } - /* @@ -767,24 +848,33 @@ static int vga_read(struct guest_info * core, // there is no default } - return length; - -} + if (vga->passthrough) { + PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr)); + memcpy(dst,V3_VAddr((void*)guest_addr),length); + } +#if 0 + int i; + PrintDebug("vga: data read is 0x"); + for (i=0;i='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.'); + } + PrintDebug("\"\n"); +#endif -static int render(struct vga_internal *vga) -{ - PrintError("vga: render UNIMPLEMENTED\n"); + return length; - if (!palacios_linux_fb_hack_pointer) { - return 0; - } +} - return 0; -} #define ERR_WRONG_SIZE(op,reg,len,min,max) \ @@ -832,9 +922,13 @@ static inline void passthrough_io_out(uint16_t port, const void * src, uint_t le do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0) #define PASSTHROUGH_IO_OUT(vga,port,src,len) \ - do { if ((vga)->passthrough) { passthrough_io_in(port,src,len); } } while (0) - + do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0) +#define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \ + 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) static int misc_out_read(struct guest_info *core, uint16_t port, @@ -847,10 +941,12 @@ static int misc_out_read(struct guest_info *core, PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val); ERR_WRONG_SIZE("read","misc out",len,1,1); - + + *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest)); return len; } @@ -890,9 +986,11 @@ static int input_stat0_read(struct guest_info *core, ERR_WRONG_SIZE("read","input stat0",len,1,1); + *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest); return len; } @@ -912,7 +1010,6 @@ static int input_stat1_read(struct guest_info *core, ERR_WRONG_SIZE("read","input stat1",len,1,1); - PASSTHROUGH_IO_IN(vga,port,dest,len); *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val; @@ -922,6 +1019,10 @@ static int input_stat1_read(struct guest_info *core, vga->vga_attribute_controller.state=ATTR_ADDR; + PASSTHROUGH_IO_IN(vga,port,dest,len); + + PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest); + return len; } @@ -939,10 +1040,13 @@ static int feature_control_read(struct guest_info *core, ERR_WRONG_SIZE("read","feature control",len,1,1); - PASSTHROUGH_IO_IN(vga,port,dest,len); *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); + + PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest); + return len; } @@ -983,9 +1087,11 @@ static int video_subsys_enable_read(struct guest_info *core, ERR_WRONG_SIZE("read","video subsys enable",len,1,1); + *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest); return len; } @@ -1024,9 +1130,11 @@ static int sequencer_address_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1); + *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest); return len; } @@ -1051,7 +1159,12 @@ static int sequencer_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); - vga->vga_sequencer.vga_sequencer_regs[index] = data; + + if (index>=VGA_SEQUENCER_NUM) { + PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index); + } else { + vga->vga_sequencer.vga_sequencer_regs[index] = data; + } render(vga); @@ -1069,28 +1182,23 @@ 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", new_addr,len); + 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); ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2); - PASSTHROUGH_IO_OUT(vga,port,src,1); - - if (new_addr>VGA_SEQUENCER_NUM) { - PrintError("vga: ignoring change of sequencer address to %u (>%u)\n", - new_addr, VGA_SEQUENCER_NUM); - //return -1; - } else { - vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ; - if (len==2) { - // second byte is the data - if (sequencer_data_write(core,port,src+1,1,vga)!=1) { - PrintError("vga: write of data failed\n"); - return -1; - } + PASSTHROUGH_IO_OUT(vga,port,src,len); + + vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ; + + if (len==2) { + 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"); + return -1; } } - return len; } @@ -1105,16 +1213,24 @@ static int sequencer_data_read(struct guest_info *core, uint8_t data; index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably - data=vga->vga_sequencer.vga_sequencer_regs[index]; - + + if (index>=VGA_SEQUENCER_NUM) { + data=0; + PrintError("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", - index, data); + index, data); + + ERR_WRONG_SIZE("read","vga sequencer data",len,1,1); - ERR_WRONG_SIZE("read","vga sequenver data",len,1,1); + *((uint8_t*)dest) = data; PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = data; + PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest); return len; } @@ -1137,9 +1253,11 @@ static int crt_controller_address_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1); + *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest); return len; } @@ -1166,7 +1284,11 @@ static int crt_controller_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); - vga->vga_crt_controller.vga_crt_controller_regs[index] = data; + if (index>=VGA_CRT_CONTROLLER_NUM) { + PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index); + } else { + vga->vga_crt_controller.vga_crt_controller_regs[index] = data; + } render(vga); @@ -1186,28 +1308,23 @@ static int crt_controller_address_write(struct guest_info *core, PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n", port==0x3b4 ? "mono" : "color", - new_addr,len); + len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len); ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2); - PASSTHROUGH_IO_OUT(vga,port,src,1); + PASSTHROUGH_IO_OUT(vga,port,src,len); - if (new_addr>VGA_CRT_CONTROLLER_NUM) { - PrintError("vga: ignoring change of crt controller address to %u (>%u)\n", - new_addr, VGA_CRT_CONTROLLER_NUM); - //return -1; - } else { - vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ; - if (len==2) { - // second byte is the data - if (crt_controller_data_write(core,port,src+1,1,vga)!=1) { - PrintError("vga: write of data failed\n"); - return -1; - } + vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ; + + if (len==2) { + 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"); + return -1; } - } - + return len; } @@ -1222,17 +1339,23 @@ static int crt_controller_data_read(struct guest_info *core, uint8_t data; index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably - data=vga->vga_crt_controller.vga_crt_controller_regs[index]; - PrintDebug("vga: crt controller data (%s) read data (index=%d) = 0x%x\n", - port==0x3b5 ? "mono" : "color", - index, data); + if (index>=VGA_CRT_CONTROLLER_NUM) { + data=0; + PrintError("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); + ERR_WRONG_SIZE("read","vga crt controller data",len,1,1); + *((uint8_t*)dest) = data; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = data; + PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest); return len; } @@ -1252,9 +1375,11 @@ static int graphics_controller_address_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1); + *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest); return len; } @@ -1272,6 +1397,7 @@ static int graphics_controller_data_write(struct guest_info *core, data=*((uint8_t*)src); 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", index, data); @@ -1279,7 +1405,11 @@ static int graphics_controller_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); - vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data; + if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { + PrintError("vga: graphics controller write for illegal index %d ignored\n",index); + } else { + vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data; + } render(vga); @@ -1297,26 +1427,24 @@ 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", new_addr,len); + PrintDebug("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); - PASSTHROUGH_IO_OUT(vga,port,src,1); + PASSTHROUGH_IO_OUT(vga,port,src,len); + + vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ; - if (new_addr>VGA_GRAPHICS_CONTROLLER_NUM) { - PrintError("vga: ignoring change of graphics controller address to %u (>%u)\n", - new_addr, VGA_GRAPHICS_CONTROLLER_NUM); - //return -1; - } else { - vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ; - if (len==2) { - // second byte is the data - if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) { - PrintError("vga: write of data failed\n"); - return -1; - } + if (len==2) { + 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"); + return -1; } } + return len; } @@ -1331,17 +1459,26 @@ static int graphics_controller_data_read(struct guest_info *core, uint8_t data; index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably - data=vga->vga_graphics_controller.vga_graphics_controller_regs[index]; + + + if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { + data=0; + PrintError("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", index, data); ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1); - PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = data; + PASSTHROUGH_IO_IN(vga,port,dest,len); + + PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest); + return len; } @@ -1363,9 +1500,11 @@ static int attribute_controller_address_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1); + *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val; + PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest); // Reading the attribute controller does not change the state @@ -1391,13 +1530,8 @@ static int attribute_controller_address_and_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); - if (new_addr>VGA_ATTRIBUTE_CONTROLLER_NUM) { - PrintError("vga: ignoring change of attribute controller address to %u (>%u)\n", - new_addr, VGA_ATTRIBUTE_CONTROLLER_NUM); - //return -1; - } else { - vga->vga_attribute_controller.vga_attribute_controller_addr.val = *((uint8_t*)src) ; - } + vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr; + vga->vga_attribute_controller.state=ATTR_DATA; return len; @@ -1412,7 +1546,11 @@ static int attribute_controller_address_and_data_write(struct guest_info *core, PASSTHROUGH_IO_OUT(vga,port,src,len); - vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data; + if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { + PrintError("vga: attribute controller write to illegal index %d ignored\n",index); + } else { + vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data; + } vga->vga_attribute_controller.state=ATTR_ADDR; @@ -1434,16 +1572,24 @@ static int attribute_controller_data_read(struct guest_info *core, uint8_t data; index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably - data=vga->vga_attribute_controller.vga_attribute_controller_regs[index]; + + if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { + data=0; + PrintError("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", index, data); ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1); + *((uint8_t*)dest) = data; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = data; + PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest); return len; } @@ -1467,10 +1613,13 @@ static int dac_write_address_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga dac write addr",len,1,1); - PASSTHROUGH_IO_IN(vga,port,dest,len); *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr; + PASSTHROUGH_IO_IN(vga,port,dest,len); + + PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest); + // This read does not reset the state machine return len; @@ -1519,10 +1668,12 @@ static int dac_read_address_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga dac read addr",len,1,1); - PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr; + PASSTHROUGH_IO_IN(vga,port,dest,len); + + PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest); + // This read does not reset the state machine return len; @@ -1576,8 +1727,6 @@ static int dac_data_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga dac read data",len,1,1); - PASSTHROUGH_IO_IN(vga,port,dest,len); - curreg = vga->vga_dac.vga_dac_read_addr; curchannel = vga->vga_dac.channel; data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f; @@ -1589,6 +1738,10 @@ static int dac_data_read(struct guest_info *core, data); *((uint8_t*)dest) = data; + + PASSTHROUGH_IO_IN(vga,port,dest,len); + + PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest); curchannel = (curchannel+1)%3; vga->vga_dac.channel=curchannel; @@ -1670,9 +1823,11 @@ static int dac_pixel_mask_read(struct guest_info *core, ERR_WRONG_SIZE("read","vga pixel mask",len,1,1); + *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask; + PASSTHROUGH_IO_IN(vga,port,dest,len); - *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask; + PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest); return len; } @@ -1766,6 +1921,10 @@ static int free_vga(struct vga_internal *vga) ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK); + if (vga->host_cons) { + v3_graphics_console_close(vga->host_cons); + } + V3_Free(vga); return 0; @@ -1783,9 +1942,7 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { char * dev_id = v3_cfg_val(cfg, "ID"); char * passthrough = v3_cfg_val(cfg, "passthrough"); - - // DETERMINE THE FRAMEBUFFER AND SET IT EARLY - // FRAMEBUFFER IS SUPPLIED BY THE BACKEND + char * hostframebuf = v3_cfg_val(cfg, "hostframebuf"); PrintDebug("vga: init_device\n"); @@ -1801,8 +1958,48 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { if (passthrough && strcasecmp(passthrough,"enable")==0) { PrintDebug("vga: enabling passthrough\n"); vga->passthrough=true; + vga->skip_next_passthrough_out=false; + } + + + if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) { + struct v3_frame_buffer_spec req; + + PrintDebug("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)); + + req.height=VGA_MAXY; + req.width=VGA_MAXX; + req.bytes_per_pixel=4; + req.bits_per_channel=8; + req.red_offset=0; + req.green_offset=1; + req.blue_offset=2; + + + 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"); + 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); + + } } + if (!vga->passthrough && !vga->host_cons) { + V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n"); + } + + // No memory store is allocated since we will use a full memory hook // The VGA maps can be read as well as written // Reads also affect writes, since they are how you fill the latches @@ -1884,7 +2081,7 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { init_vga(vga); - PrintDebug("vga: successfully added and initialized, waiting for framebuffer attach\n"); + PrintDebug("vga: successfully added and initialized.\n"); return 0;