X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fvga.c;h=b7b0a360bb1324763f00f5ea74dddded85c7b76e;hb=0a7690f54cb5bda83780dac26ce433ad24b1d766;hp=b5258cd5bd023f1e8ad12ae48d11ca3999fed16d;hpb=1ad0e892e8e3886c3bab0d6ec127abca337711ac;p=palacios.git diff --git a/palacios/src/devices/vga.c b/palacios/src/devices/vga.c index b5258cd..b7b0a36 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" @@ -36,23 +37,8 @@ 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; -}; - -struct fb { - struct fb_info *info; - uint8_t * data; -}; - -//extern -struct fb *palacios_linux_fb_hack_pointer; - -/* HACK HACK HACK */ +#define VGA_MAXX 1024 +#define VGA_MAXY 768 #define VGA_MISC_OUT_READ 0x3cc @@ -285,6 +271,10 @@ 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; @@ -331,20 +321,47 @@ static int render(struct vga_internal *vga) { vga->updates_since_render++; - if (vga->updates_since_renderhost_cons && v3_graphics_console_inform_update(vga->host_cons)>0) { + // Draw some crap for testing for now - // PrintError("vga: render UNIMPLEMENTED\n"); + void *fb; + struct v3_frame_buffer_spec *s; - vga->updates_since_render=0; + fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec)); - if (!palacios_linux_fb_hack_pointer) { - return 0; - } + s=&(vga->target_spec); - + if (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; + } + } + } + } + } return 0; } @@ -869,7 +886,10 @@ 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_out(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) @@ -1130,11 +1150,12 @@ static int sequencer_address_write(struct guest_info *core, ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2); - PASSTHROUGH_IO_OUT(vga,port,src,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"); @@ -1255,11 +1276,12 @@ static int crt_controller_address_write(struct guest_info *core, 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); 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"); @@ -1374,11 +1396,12 @@ static int graphics_controller_address_write(struct guest_info *core, 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 (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"); @@ -1862,6 +1885,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; @@ -1879,9 +1906,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"); @@ -1897,8 +1922,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 @@ -1980,7 +2045,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;