#include <palacios/vmm_types.h>
#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_io.h>
+#include <interfaces/vmm_graphics_console.h>
#include "vga_regs.h"
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
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;
{
vga->updates_since_render++;
- if (vga->updates_since_render<UPDATES_PER_RENDER) {
- return 0;
- }
+ if (vga->host_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 (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;
}
uint_t length,
void * priv_data)
{
- int i;
struct vm_device *dev = (struct vm_device *)priv_data;
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
memcpy(V3_VAddr((void*)guest_addr),src,length);
}
- PrintDebug("vga: data written was \"");
+#if 0
+ int i;
+ PrintDebug("vga: data written was 0x");
+ for (i=0;i<length;i++) {
+ uint8_t c= ((char*)src)[i];
+ PrintDebug("%.2x", c);
+ }
+ PrintDebug(" \"");
for (i=0;i<length;i++) {
char c= ((char*)src)[i];
- PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ? c : '.');
+ PrintDebug("%c", (c>='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 */
uint_t length,
void * priv_data)
{
- int i;
struct vm_device *dev = (struct vm_device *)priv_data;
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
}
- PrintDebug("vga: data read is \"");
+#if 0
+ int i;
+ PrintDebug("vga: data read is 0x");
+ for (i=0;i<length;i++) {
+ uint8_t c= ((char*)dst)[i];
+ PrintDebug("%.2x", c);
+ }
+ PrintDebug(" \"");
for (i=0;i<length;i++) {
char c= ((char*)dst)[i];
- PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ? c : '.');
+ PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
}
PrintDebug("\"\n");
+#endif
return length;
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)
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");
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");
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");
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;
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");
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
init_vga(vga);
- PrintDebug("vga: successfully added and initialized, waiting for framebuffer attach\n");
+ PrintDebug("vga: successfully added and initialized.\n");
return 0;