Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


From 294306ec5026ea691a4f1380598114688b061c99 Mon Sep 17 00:00:00 2001
Steven Jaconette [Thu, 27 Aug 2009 17:30:52 +0000 (12:30 -0500)]
Subject: [PATCH] Reorganized video card/virtual console

12 files changed:
Kconfig
palacios/include/devices/cga.h [copied from palacios/include/devices/video.h with 50% similarity]
palacios/include/devices/console.h [new file with mode: 0644]
palacios/include/devices/telnet_cons.h [moved from palacios/include/devices/video.h with 50% similarity]
palacios/src/devices/Kconfig
palacios/src/devices/Makefile
palacios/src/devices/cga.c [new file with mode: 0644]
palacios/src/devices/cirrus_gfx_card.c [new file with mode: 0644]
palacios/src/devices/telnet_cons.c [new file with mode: 0644]
palacios/src/devices/video.c [deleted file]
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_ctrl_regs.c

diff --git a/Kconfig b/Kconfig
index d682920..0b55661 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -55,6 +55,12 @@ config SYMBIOTIC_SWAP_TELEMETRY
          Enable the telemetry information for the symbiotic swap subsystem
 
 
+config PASSTHROUGH_VIDEO
+       bool "Enable Passthrough Video"
+       default y
+       help 
+         Configures Palacios to map a guest's framebuffer directly 
+         to the hardware framebuffer
 
 config INSTRUMENT_VMM
        bool "Enable VMM instrumentation"
similarity index 50%
copy from palacios/include/devices/video.h
copy to palacios/include/devices/cga.h
index cdb927d..b2c168c 100644 (file)
@@ -7,35 +7,26 @@
  * and the University of New Mexico.  You can find out more at 
  * http://www.v3vee.org
  *
- * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
- * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
- * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
- * Author: Robdert Deloatch <rtdeloatch@gmail.com>
- *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#ifndef __DEVICES_VIDEO_H__
-#define __DEVICES_VIDEO_H__
+#ifndef __DEVICES_CGA_H__
+#define __DEVICES_CGA_H__
 
 #ifdef __V3VEE__
 
+#include <devices/console.h>
 
-//#include <palacios/vm_dev.h>
 
-#include <palacios/vmm_dev_mgr.h>
+int v3_console_register_cga(struct vm_device * cga_dev, struct v3_console_ops * ops, void * private_data);
 
-//struct vm_device * v3_create_video();
-
-struct video_cfg {
-  char pci[32];
-};
-
-
-#endif // ! __V3VEE__
+#endif
 
 #endif
diff --git a/palacios/include/devices/console.h b/palacios/include/devices/console.h
new file mode 100644 (file)
index 0000000..70eeff7
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_CONSOLE_H__
+#define __DEVICES_CONSOLE_H__
+
+#ifdef __V3VEE__
+
+
+struct v3_console_ops {
+
+    // filled in by the backend device
+    int (*update_screen)(uint_t x, uint_t y, uint_t length, void * private_data);
+    int (*update_cursor)(uint_t x, uint_t y, void * private_data);
+    int (*scroll)(uint_t rows, void * private_data);
+};
+
+
+
+int v3_cons_get_fb(struct vm_device * frontend_dev, uint8_t * dst, uint_t offset, uint_t length);
+
+#endif // ! __V3VEE__
+
+
+#endif
similarity index 50%
rename from palacios/include/devices/video.h
rename to palacios/include/devices/telnet_cons.h
index cdb927d..afca897 100644 (file)
@@ -7,35 +7,30 @@
  * and the University of New Mexico.  You can find out more at 
  * http://www.v3vee.org
  *
- * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
- * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
- * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
- * Author: Robdert Deloatch <rtdeloatch@gmail.com>
- *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#ifndef __DEVICES_VIDEO_H__
-#define __DEVICES_VIDEO_H__
+#ifndef __DEVICES_TELNET_CONS_H__
+#define __DEVICES_TELNET_CONS_H__
 
 #ifdef __V3VEE__
 
 
-//#include <palacios/vm_dev.h>
 
-#include <palacios/vmm_dev_mgr.h>
-
-//struct vm_device * v3_create_video();
-
-struct video_cfg {
-  char pci[32];
+struct telnet_cons_cfg {
+    char frontend[32];
+    uint16_t port;
 };
 
 
-#endif // ! __V3VEE__
+
+#endif
 
 #endif
index e62b00c..6f63f23 100644 (file)
@@ -259,11 +259,20 @@ config SYM_SWAP
        help 
          Includes the symbiotic ram based swap disk
 
-config VIDEO
-       bool "VIDEO"
+config CGA
+       bool "CGA"
        default n
-       depends on PCI && EXPERIMENTAL
+       depends on !PASSTHROUGH_VIDEO
        help
-         Includes the Virtual Video Card Device
+         Includes the Virtual CGA video support
+
+
+config TELNET_CONSOLE
+       bool "Telnet Virtual Console"
+       default n
+       depends on CGA && !PASSTHROUGH_VIDEO
+       help
+         Includes the virtual telnet console 
 
 endmenu
+
index 1d6b0df..f720996 100644 (file)
@@ -23,4 +23,5 @@ obj-$(CONFIG_NE2K) += ne2k.o
 obj-$(CONFIG_NET_CD) += net_cd.o 
 obj-$(CONFIG_NET_HD) += net_hd.o 
 
-obj-$(CONFIG_VIDEO) += video.o
+obj-$(CONFIG_CGA) += cga.o
+obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
diff --git a/palacios/src/devices/cga.c b/palacios/src/devices/cga.c
new file mode 100644 (file)
index 0000000..aabe810
--- /dev/null
@@ -0,0 +1,410 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
+ * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Robdert Deloatch <rtdeloatch@gmail.com>
+ *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vmm_emulator.h>
+#include <palacios/vm_guest_mem.h>
+
+#include <devices/cga.h>
+
+
+
+/*
+#ifndef DEBUG_CGA
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+*/
+
+#define START_ADDR 0xB8000
+#define END_ADDR 0xC0000
+
+#define FRAMEBUF_SIZE (END_ADDR - START_ADDR)
+#define SCREEN_SIZE 4000
+
+#define BASE_CGA_PORT 0x3B0
+
+#define NUM_COLS 80
+#define NUM_ROWS 25
+#define BYTES_PER_ROW (NUM_COLS * 2)
+#define BYTES_PER_COL 2
+
+
+struct video_internal {
+    uint8_t * framebuf;
+
+    // These store the values for unhandled ports, in case of a read op
+    uint8_t port_store[44];
+
+
+    uint8_t crtc_index_reg;          // io port 3D4
+    uint8_t crtc_data_regs[25];      // io port 3D5
+
+    uint16_t screen_offset; // relative to the framebuffer
+    uint16_t cursor_offset; // relative to the framebuffer
+
+    // updating the screen offset is not atomic, 
+    // so we need a temp variable to hold the partial update
+    uint16_t tmp_screen_offset; 
+    
+
+    uint8_t passthrough;
+
+
+    struct v3_console_ops * ops;
+    void * private_data;
+
+
+
+};
+
+
+
+
+static void passthrough_in(uint16_t port, void * src, uint_t length) {
+    switch (length) {
+       case 1:
+           *(uint8_t *)src = v3_inb(port);
+           break;
+       case 2:
+           *(uint16_t *)src = v3_inw(port);
+           break;
+       case 4:
+           *(uint32_t *)src = v3_indw(port);
+           break;
+       default:
+           break;
+    }
+}
+
+
+static void passthrough_out(uint16_t port, void * src, uint_t length) {
+    switch (length) {
+       case 1:
+           v3_outb(port, *(uint8_t *)src);
+           break;
+       case 2:
+           v3_outw(port, *(uint16_t *)src);
+           break;
+       case 4:
+           v3_outdw(port, *(uint32_t *)src);
+           break;
+       default:
+           break;
+    }
+}
+
+static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) {
+    struct vm_device * dev = (struct vm_device *)priv_data;
+    struct video_internal * state = (struct video_internal *)dev->private_data;
+    uint_t fb_offset = guest_addr - START_ADDR;
+    uint_t screen_byte_offset = state->screen_offset * BYTES_PER_COL;
+
+    PrintDebug("Guest address: %p length = %d, fb_offset=%d, screen_offset=%d\n", 
+              (void *)guest_addr, length, fb_offset, screen_byte_offset);
+
+    if (state->passthrough) {
+       memcpy(state->framebuf + fb_offset, V3_VAddr((void *)guest_addr), length);
+    }
+
+    if ((fb_offset >= screen_byte_offset) && (fb_offset < (screen_byte_offset + SCREEN_SIZE))) {
+       uint_t screen_pos = fb_offset - screen_byte_offset;
+       uint_t x = (screen_pos % BYTES_PER_ROW) / BYTES_PER_COL;
+       uint_t y = screen_pos / BYTES_PER_ROW;
+       PrintDebug("Sending Screen update\n");
+       
+       if (state->ops) {
+           PrintDebug("\tcalling update_screen()\n");
+           state->ops->update_screen(x, y, length, state->private_data);
+       }
+    }
+
+    return length;
+}
+
+static int video_read_port(uint16_t port, void * dest, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+
+
+    PrintDebug("Video: Read port 0x%x\n", port);
+
+    if (video_state->passthrough) {
+       passthrough_in(port, dest, length);
+    }
+
+    return length;
+}
+
+
+
+static int video_write_port(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+
+
+    PrintDebug("Video: write port 0x%x...\n", port);
+
+    if (video_state->passthrough) {
+       passthrough_out(port, src, length);
+    } 
+
+    return length;
+}
+
+
+
+static int crtc_data_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    uint8_t val = *(uint8_t *)src;
+    uint_t index = video_state->crtc_index_reg;
+
+    if (length != 1) {
+       PrintError("Invalid write length for port 0x%x\n", port);
+       return -1;
+    }
+
+    PrintDebug("Video: write on port 0x%x... (val=0x%x)\n", port, val);
+
+    video_state->crtc_data_regs[index] = val;
+
+    switch (index) {
+       case 0x0c: { // scroll high byte
+           uint16_t tmp_val = val;
+           video_state->tmp_screen_offset = ((tmp_val << 8) & 0xff00);
+           break;
+       }
+       case 0x0d: {  // Scroll low byte
+           int diff = 0;
+
+           video_state->tmp_screen_offset += val;
+           diff = (video_state->tmp_screen_offset - video_state->screen_offset) / NUM_COLS;
+
+           // Update the true offset value
+           video_state->screen_offset = video_state->tmp_screen_offset;
+           video_state->tmp_screen_offset = 0;
+
+           PrintDebug("Scroll lines = %d, new screen offset=%d\n", 
+                      diff, video_state->screen_offset * BYTES_PER_COL);
+
+           if (video_state->ops) {
+               if (video_state->ops->scroll(diff, video_state->private_data) == -1) {
+                   PrintError("Error sending scroll event\n");
+                   return -1;
+               }
+           }
+           break;
+       }
+       case 0x0E: {  // Cursor adjustment High byte
+           uint16_t tmp_val = val;
+           video_state->cursor_offset = ((tmp_val << 8) & 0xff00);
+
+           break;
+       }
+       case 0x0F: { // cursor adjustment low byte
+           uint_t x = 0;
+           uint_t y = 0;
+           
+           video_state->cursor_offset += val;
+           
+           x = video_state->cursor_offset % NUM_COLS;
+           y = (video_state->cursor_offset - video_state->screen_offset) / NUM_COLS;
+           
+           PrintDebug("New Cursor Location; X=%d Y=%d\n", x, y);
+           
+           if (video_state->ops) {
+               if (video_state->ops->update_cursor(x, y, video_state->private_data) == -1) {
+                   PrintError("Error updating cursor\n");
+                   return -1;
+               }
+           } 
+
+           break;
+       }
+       default:
+           break;
+    }
+
+    if (video_state->passthrough) {
+       passthrough_out(port, src, length);
+    }
+
+    return length;
+}
+
+
+static int crtc_index_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    
+    if (length > 2) {
+       PrintError("Invalid write length for crtc index register port: %d (0x%x)\n",
+                  port, port);
+       return -1;
+    }
+                  
+
+    video_state->crtc_index_reg = *(uint8_t *)src;
+
+    // Only do the passthrough IO for the first byte
+    // the second byte will be done in the data register handler
+    if (video_state->passthrough) {
+       passthrough_out(port, src, 1);
+    }
+
+    if (length == 2) {
+       if (crtc_data_write(port + 1, src + 1, length - 1, dev) != (length - 1)) {
+           PrintError("could not handle implicit crtc data write\n");
+           return -1;
+       }
+    }
+
+    return length;
+}
+
+
+
+int v3_cons_get_fb(struct vm_device * frontend_dev, uint8_t * dst, uint_t offset, uint_t length) {
+    struct video_internal * state = (struct video_internal *)frontend_dev->private_data;
+    uint_t screen_byte_offset = state->screen_offset * BYTES_PER_COL;
+
+    PrintDebug("Getting framebuffer for screen; framebuf=%p, screen_offset=%d, offset=%d, length=%d\n", 
+              state->framebuf, screen_byte_offset, offset, length);
+
+    memcpy(dst, state->framebuf + screen_byte_offset + offset, length);
+
+    return 0;
+}
+
+
+
+static int free_device(struct vm_device * dev) {
+    v3_unhook_mem(dev->vm, START_ADDR);
+    return 0;
+}
+
+
+
+static struct v3_device_ops dev_ops = {
+    .free = free_device,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+static int cga_init(struct guest_info * vm, void * cfg_data) {
+    struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
+    addr_t frame_buf_pa = 0;
+    uint32_t enable_passthrough = (uint32_t)(addr_t)cfg_data;
+
+
+    PrintDebug("video: init_device\n");
+
+    struct vm_device * dev = v3_allocate_device("CGA_VIDEO", &dev_ops, video_state);
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", "CGA_VIDEO");
+       return -1;
+    }
+
+    frame_buf_pa = (addr_t)V3_AllocPages(FRAMEBUF_SIZE / 4096);
+
+    video_state->framebuf = V3_VAddr((void *)frame_buf_pa);
+    memset(video_state->framebuf, 0, FRAMEBUF_SIZE);
+
+    PrintDebug("PA of array: %p\n", (void *)frame_buf_pa);
+
+    video_state->passthrough = enable_passthrough;
+
+    video_state->ops = NULL;
+    video_state->private_data = NULL;
+
+    if (enable_passthrough) {
+       PrintDebug("Enabling CGA Passthrough\n");
+
+       if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1) {
+           PrintDebug("\n\nVideo Hook failed.\n\n");
+       }
+    } else {
+       if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, frame_buf_pa, &video_write_mem, dev) == -1) {
+           PrintDebug("\n\nVideo Hook failed.\n\n");
+       }
+    }
+
+
+    v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d4, &video_read_port, &crtc_index_write);
+    v3_dev_hook_io(dev, 0x3d5, &video_read_port, &crtc_data_write);
+    v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3da, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
+
+
+    return 0;
+}
+
+device_register("CGA_VIDEO", cga_init);
+
+
+int v3_console_register_cga(struct vm_device * cga_dev, struct v3_console_ops * ops, void * private_data) {
+    struct video_internal * video_state = (struct video_internal *)cga_dev->private_data;
+    
+    video_state->ops = ops;
+    video_state->private_data = private_data;
+
+    return 0;
+}
diff --git a/palacios/src/devices/cirrus_gfx_card.c b/palacios/src/devices/cirrus_gfx_card.c
new file mode 100644 (file)
index 0000000..a768007
--- /dev/null
@@ -0,0 +1,580 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
+ * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Robdert Deloatch <rtdeloatch@gmail.com>
+ *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#include <devices/cirrus_gfx_card.h>
+#include <palacios/vmm.h>
+#include <palacios/vmm_emulator.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_paging.h>
+#include <palacios/vmm_instr_emulator.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_socket.h>
+#include <palacios/vmm_host_events.h>
+#include <devices/pci.h>
+#include <devices/pci_types.h>
+
+#include "network_console.h"
+
+
+
+/* #ifndef DEBUG_CIRRUS_GFX_CARD
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif */
+
+
+#define START_ADDR 0xA0000
+#define END_ADDR 0xC0000
+
+#define SIZE_OF_REGION (END_ADDR - START_ADDR)
+
+#define PASSTHROUGH 1
+#define PORT_OFFSET 0x3B0
+
+struct video_internal {
+    addr_t video_memory_pa;
+    uint8_t * video_memory;
+    
+    struct vm_device * pci_bus;
+    struct pci_device * pci_dev;
+
+    int client_fd;
+
+    uint_t screen_bottom;
+    uint_t ports[44];
+    uint8_t reg_3C4[256];
+    uint8_t reg_3CE[256];
+    uint16_t start_addr_offset;
+    uint16_t old_start_addr_offset;
+    uint16_t cursor_addr;
+    uint8_t reg_3D5[25];
+    
+};
+
+void video_do_in(uint16_t port, void * src, uint_t length){
+#if PASSTHROUGH
+    uint_t i;
+    switch (length) {
+       case 1:
+           ((uint8_t *)src)[0] = v3_inb(port);
+           break;
+       case 2:
+           ((uint16_t *)src)[0] = v3_inw(port);
+           break;
+       case 4:
+           ((uint32_t *)src)[0] = v3_indw(port);
+           break;
+       default:
+           for (i = 0; i < length; i++) { 
+               ((uint8_t *)src)[i] = v3_inb(port);
+           }
+    }
+#endif
+}
+
+void video_do_out(uint16_t port, void * src, uint_t length){
+#if PASSTHROUGH
+    uint_t i;
+    switch (length) {
+       case 1:
+           v3_outb(port,((uint8_t *)src)[0]);
+           break;
+       case 2:
+           v3_outw(port,((uint16_t *)src)[0]);
+           break;
+       case 4:
+           v3_outdw(port,((uint32_t *)src)[0]);
+           break;
+       default:
+           for (i = 0; i < length; i++) { 
+               v3_outb(port, ((uint8_t *)src)[i]);
+           }
+    }
+#endif
+}
+
+static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) {
+    struct vm_device * dev = (struct vm_device *)priv_data;
+    struct video_internal * data = (struct video_internal *)dev->private_data;
+    addr_t write_offset = guest_addr - START_ADDR;
+    uint_t difference = 0x18000;
+    int i = 0;
+
+
+    PrintDebug("\n\nInside Video Write Memory.\n\n");
+    PrintDebug("Guest address: %p length = %d\n", (void *)guest_addr, length);
+
+    PrintDebug("Write offset: 0x%x\n", (uint_t)write_offset);
+    PrintDebug("Video_Memory: ");
+
+    for (i = 0; i < length; i += 2) {
+       PrintDebug("%c", ((char *)(V3_VAddr((void *)guest_addr)))[i]);
+    }
+
+#if PASSTHROUGH
+    memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length);
+#endif
+
+
+
+    if (send_update(data->client_fd, data->video_memory + difference, write_offset-difference, data->start_addr_offset, length) == -1) {
+       PrintError("Error sending update to client\n");
+       return -1;
+    }
+
+    PrintDebug(" Done.\n");
+    return length;
+}
+
+static int video_read_port(uint16_t port, void * dest, uint_t length, struct vm_device * dev) {
+    //PrintDebug("Video: Read port 0x%x\n",port);
+    video_do_in(port, dest, length);
+    return length;
+}
+
+static int video_read_port_generic(uint16_t port, void * dest, uint_t length, struct vm_device * dev) {
+    memset(dest, 0, length);
+    video_do_in(port, dest, length);
+    return length;
+}
+
+
+static int video_write_port(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    /*
+      PrintDebug("Video: write port 0x%x...Wrote: ", port);
+      uint_t i;
+      for(i = 0; i < length; i++){
+      PrintDebug("%x", ((uint8_t*)src)[i]);
+      }
+      PrintDebug("...Done\n"); */
+    video_do_out(port, src, length);
+    return length;
+}
+
+static int video_write_port_store(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    /*
+      PrintDebug("Entering video_write_port_store...port 0x%x\n", port);
+      uint_t i;
+      for(i = 0; i < length; i++){
+      PrintDebug("%x", ((uint8_t*)src)[i]);
+      }
+      PrintDebug("...Done\n"); 
+    */
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+
+    video_state->ports[port - PORT_OFFSET] = 0;
+    memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
+    video_do_out(port, src, length);
+
+    return length;
+}
+
+static int video_write_port_3D5(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    uint8_t new_start = 0;
+    uint_t index = 0;
+
+    PrintDebug("Video: write port 0x%x...Wrote: ", port);
+    {
+       uint_t i = 0;
+       for (i = 0; i < length; i++){
+           PrintDebug("%x", ((uint8_t*)src)[i]);
+       }
+       PrintDebug("...Done\n");
+    }
+
+    video_state->ports[port - PORT_OFFSET] = 0;
+
+    memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
+
+    memcpy(&(video_state->reg_3D5[index]), src, length);
+
+    index = video_state->ports[port - 1 - PORT_OFFSET];
+
+    // JRL: Add length check
+    new_start = *((uint8_t *)src);
+
+
+    switch (index) {
+       case 0x0c:
+           video_state->old_start_addr_offset = video_state->start_addr_offset;
+
+           video_state->start_addr_offset = (new_start << 8);
+
+           break;
+       case 0x0d: {
+           int diff = 0;
+
+           video_state->start_addr_offset += new_start;
+
+           diff = video_state->start_addr_offset - video_state->old_start_addr_offset;
+           diff /= 80;
+
+           PrintDebug("Scroll lines = %d\n", diff);
+
+           send_scroll(video_state->client_fd, diff, video_state->video_memory);
+
+           break;
+       }
+       case 0x0E:
+           video_state->cursor_addr = new_start << 8;
+
+           break;
+       case 0x0F: {
+           uint_t x = 0;
+           uint_t y = 0;
+
+           video_state->cursor_addr += new_start;
+          
+           x = ((video_state->cursor_addr) % 80) + 1;
+           y = (((video_state->cursor_addr) / 80) - ((video_state->start_addr_offset / 80))) + 1;
+           
+           PrintDebug("New Cursor Location; X=%d Y=%d\n", x, y);
+           
+           send_cursor_update(video_state->client_fd, x, y);
+           break;
+       }
+       default:
+           break;
+    }
+
+    video_do_out(port, src, length);
+
+    return length;
+}
+
+
+static int video_write_port_3C5(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+    uint_t index = 0;
+
+
+    PrintDebug("Entering write_port_3C5....port 0x%x\n", port);
+    {
+       uint_t i = 0;
+       for(i = 0; i < length; i++){
+           PrintDebug("%x", ((uint8_t*)src)[i]);
+       }
+       PrintDebug("...Done\n");
+    }
+
+    video_state->ports[port - PORT_OFFSET] = 0;
+    memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
+
+    index = video_state->ports[port - 1 - PORT_OFFSET];
+
+    memcpy(&(video_state->reg_3C4[index]), src, length);
+    video_do_out(port, src, length);
+
+    return length;
+}
+
+static int video_write_port_3CF(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+
+    PrintDebug("Entering write_port_3CF....port 0x%x\n", port);
+
+    {
+       uint_t i = 0;
+       for(i = 0; i < length; i++){
+           PrintDebug("%x", ((uint8_t*)src)[i]);
+       }
+       PrintDebug("...Done\n");
+    }
+
+    video_state->ports[port - PORT_OFFSET] = 0;
+    memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
+
+    uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
+    memcpy(&(video_state->reg_3CE[index]), src, length);
+    video_do_out(port, src, length);
+    return length;
+}
+
+static int video_write_port_3D4(uint16_t port, void * src, uint_t length, struct vm_device * dev){
+    struct video_internal * video_state = (struct video_internal *) dev -> private_data;
+
+#if 1
+    if (length == 1) {
+
+       video_state->ports[port - PORT_OFFSET] = 0;
+       memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
+
+    } else if (length == 2) {
+       uint16_t new_start = *((uint16_t *)src);
+       uint16_t cursor_start = *((uint16_t *)src);;
+
+       //Updating the cursor
+       if ((cursor_start & 0x00FF) == 0x000E) {
+
+           cursor_start = (cursor_start & 0xFF00);
+           video_state->cursor_addr = cursor_start;
+
+       } else if ((cursor_start & 0x00FF) == 0x000F) {
+           uint_t x = 0;
+           uint_t y = 0;
+
+           video_state->cursor_addr += ((cursor_start >> 8) & 0x00FF);
+
+           x = ((video_state->cursor_addr) % 80) + 1;
+           y = (((video_state->cursor_addr) / 80) - ((video_state->start_addr_offset / 80))) + 1;
+
+           PrintDebug("New Cursor Location; X=%d Y=%d\n", x, y);
+
+           send_cursor_update(video_state->client_fd, x, y);
+       }
+
+       //Checking to see if scrolling is needed
+       if ((new_start & 0x00FF) == 0x000C) {
+
+           video_state->old_start_addr_offset = video_state->start_addr_offset;
+           new_start = (new_start & 0xFF00);
+           video_state->start_addr_offset = new_start;
+
+       } else if ((new_start & 0x00FF) == 0x000D) {
+           int diff = 0;
+
+           video_state->start_addr_offset += ((new_start >> 8) & 0x00FF);
+
+           diff =  video_state->start_addr_offset - video_state->old_start_addr_offset;
+           diff /= 80;
+
+           PrintDebug("Scroll lines = %d\n", diff);
+
+           send_scroll(video_state->client_fd, diff, video_state->video_memory+0x18000);
+       }
+    } else {
+       // JRL ??
+       return -1;
+    }
+#endif 
+    video_do_out(port, src, length);
+    return length;
+}
+
+static int video_write_mem_region(addr_t guest_addr, void * src, uint_t length, void * priv_data) {;
+    PrintDebug("Video write mem region guest_addr: 0x%p, src: 0x%p, length: %d, Value?= %x\n", (void *)guest_addr, src, length, *((uint32_t *)V3_VAddr((void *)guest_addr)));
+    return length;
+}
+
+static int video_read_mem_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){
+    PrintDebug("Video:  Within video_read_mem_region\n");
+    return length;
+}
+
+static int video_write_io_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){
+    PrintDebug("Video:  Within video_write_io_region\n");
+    return length;
+}
+
+static int video_read_io_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){
+    PrintDebug("Video:  Within video_read_io_region\n");
+    return length;
+}
+
+static int cirrus_gfx_card_free(struct vm_device * dev) {
+    v3_unhook_mem(dev->vm, START_ADDR);
+    return 0;
+}
+
+static int cirrus_gfx_card_reset_device(struct vm_device * dev) {
+    PrintDebug("Video: reset device\n");
+    return 0;
+}
+
+static int cirrus_gfx_card_start_device(struct vm_device * dev) {
+    PrintDebug("Video: start device\n");
+    return 0;
+}
+
+static int cirrus_gfx_card_stop_device(struct vm_device * dev) {
+    PrintDebug("Video: stop device\n");
+    return 0;
+}
+
+static struct v3_device_ops dev_ops = {
+    .free = cirrus_gfx_card_free,
+    .reset = cirrus_gfx_card_reset_device,
+    .start = cirrus_gfx_card_start_device,
+    .stop = cirrus_gfx_card_stop_device,
+};
+
+static int cirrus_gfx_card_init(struct guest_info * vm, void * cfg_data){
+    struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
+    struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
+    struct vm_device * dev = v3_allocate_device("TEXT_GFX_CARD", &dev_ops, video_state);
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", "TEXT_GFX_CARD");
+       return -1;
+    }
+
+    PrintDebug("video: init_device\n");
+    PrintDebug("Num Pages=%d\n", SIZE_OF_REGION / 4096);
+
+    video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096);
+    video_state->video_memory = V3_VAddr((void *)video_state->video_memory_pa);
+
+    memset(video_state->video_memory, 0, SIZE_OF_REGION);
+
+
+    v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port_3C5);
+    v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port_store);
+    v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port_3CF);
+    v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d4, &video_read_port, &video_write_port_3D4);
+    v3_dev_hook_io(dev, 0x3d5, &video_read_port, &video_write_port_3D5);
+    v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3da, &video_read_port_generic, &video_write_port);
+    v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
+    v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
+
+
+    PrintDebug("PA of array: %p\n", (void *)video_state->video_memory_pa);
+
+
+#if PASSTHROUGH
+    if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1){
+       PrintDebug("\n\nVideo Hook failed.\n\n");
+    }
+#else
+    if (v3_hook_write_mem(vm, START_ADDR, END_ADDR, video_memory_pa, &video_write_mem, dev) == -1){
+       PrintDebug("\n\nVideo Hook failed.\n\n");
+    }
+#endif
+
+    PrintDebug("Video: Getting client connection\n");
+
+    video_state->client_fd = get_client_connection(vm);
+
+    PrintDebug("Video: Client connection established\n");
+
+    video_state->screen_bottom = 25;
+
+    video_state->pci_bus = pci_bus;
+
+    if (video_state->pci_bus == NULL) {
+       PrintError("Could not find PCI device\n");
+       return -1;
+    } else {
+       struct v3_pci_bar bars[6];
+       struct pci_device * pci_dev = NULL;
+
+       int i;
+       for (i = 0; i < 6; i++) {
+           bars[i].type = PCI_BAR_NONE;
+       }
+
+       bars[0].type = PCI_BAR_MEM32;
+       bars[0].num_pages = 8192;
+       bars[0].default_base_addr = 0xf0000000;
+
+       bars[0].mem_read = video_read_mem_region;
+       bars[0].mem_write = video_write_mem_region;
+
+       bars[1].type = PCI_BAR_MEM32;
+       bars[1].num_pages = 1;
+       bars[1].default_base_addr = 0xf2000000;
+    
+       bars[1].mem_read = video_read_io_region;
+       bars[1].mem_write = video_write_io_region;
+       //-1 Means autoassign
+       //                                                     Not sure if STD
+       pci_dev = v3_pci_register_device(video_state->pci_bus, PCI_STD_DEVICE, 0,
+                                        //or0  1st null could be pci_config_update
+                                        -1, 0, "CIRRUS_GFX_CARD", bars, NULL, NULL,
+                                        NULL, dev);
+
+       if (pci_dev == NULL) {
+           PrintError("Failed to register VIDEO %d with PCI\n", i);
+           return -1;
+       } else{
+           PrintDebug("Registering PCI_VIDEO succeeded\n");
+       }
+       //Need to set some pci_dev->config_header.vendor_id type variables
+
+       pci_dev->config_header.vendor_id = 0x1013;
+       pci_dev->config_header.device_id = 0x00B8;
+       pci_dev->config_header.revision = 0x00;
+
+       //If we treat video as a VGA device than below is correct
+       //If treated as a VGA compatible controller, which has mapping
+       //0xA0000-0xB0000 and I/O addresses 0x3B0-0x3BB than change
+       //#define from VGA to 0
+
+       //pci_dev->config_header.class = 0x00;
+       //pci_dev->config_header.subclass = 0x01;
+
+       pci_dev->config_header.class = 0x03;
+       pci_dev->config_header.subclass = 0x00;
+       pci_dev->config_header.prog_if = 0x00;
+
+
+       //We have a subsystem ID, but optional to provide:  1AF4:1100
+       pci_dev->config_header.subsystem_vendor_id = 0x1AF4;
+       pci_dev->config_header.subsystem_id = 0x1100;
+       //pci_dev->config_header.header_type = 0x00;
+       pci_dev->config_header.command = 0x03;
+       video_state->pci_dev = pci_dev;
+    }
+
+    PrintDebug("Video: init complete\n");
+    return 0;
+}
+
+device_register("CIRRUS_GFX_CARD", cirrus_gfx_card_init)
diff --git a/palacios/src/devices/telnet_cons.c b/palacios/src/devices/telnet_cons.c
new file mode 100644 (file)
index 0000000..4abe5a0
--- /dev/null
@@ -0,0 +1,552 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
+ * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Robdert Deloatch <rtdeloatch@gmail.com>
+ *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+/* Interface between virtual video card and client apps */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vmm_sprintf.h>
+#include <palacios/vmm_host_events.h>
+#include <palacios/vmm_lock.h>
+#include <palacios/vmm_string.h>
+#include <palacios/vmm_socket.h>
+
+#include <devices/cga.h>
+#include <devices/telnet_cons.h>
+
+#define NUM_ROWS 25
+#define NUM_COLS 80
+#define BYTES_PER_ROW (NUM_COLS * 2)
+#define BYTES_PER_COL 2
+
+
+#define SCREEN_SIZE 4000
+
+#define NO_KEY { 0, 0 }
+#define ESC_CHAR  ((uint8_t)0x1b)
+#define CR_CHAR   ((uint8_t)0x0d)
+
+#define ASCII_CTRL_CODE 0x1d
+
+
+struct cons_state {
+    int server_fd;
+    int client_fd;
+
+    uint16_t port;
+
+    int connected;
+
+    v3_lock_t cons_lock;
+
+    struct vm_device * frontend_dev;
+};
+
+struct key_code {
+    uint8_t scan_code;
+    uint8_t capital;
+};
+
+
+static const struct key_code ascii_to_key_code[] = {             // ASCII Value Serves as Index
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x00 - 0x03
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x04 - 0x07
+    { 0x0E, 0 },    { 0x0F, 0 },    { 0x1C, 0 },    NO_KEY,      // 0x08 - 0x0B
+    NO_KEY,         { 0x1C, 0 },    NO_KEY,         NO_KEY,      // 0x0C - 0x0F
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x10 - 0x13
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x14 - 0x17
+    NO_KEY,         NO_KEY,         NO_KEY,         { 0x01, 0 }, // 0x18 - 0x1B
+    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x1C - 0x1F
+    { 0x39, 0 },    { 0x02, 1 },    { 0x28, 1 },    { 0x04, 1 }, // 0x20 - 0x23
+    { 0x05, 1 },    { 0x06, 1 },    { 0x08, 1 },    { 0x28, 0 }, // 0x24 - 0x27
+    { 0x0A, 1 },    { 0x0B, 1 },    { 0x09, 1 },    { 0x0D, 1 }, // 0x28 - 0x2B
+    { 0x33, 0 },    { 0x0C, 0 },    { 0x34, 0 },    { 0x35, 0 }, // 0x2C - 0x2F
+    { 0x0B, 0 },    { 0x02, 0 },    { 0x03, 0 },    { 0x04, 0 }, // 0x30 - 0x33
+    { 0x05, 0 },    { 0x06, 0 },    { 0x07, 0 },    { 0x08, 0 }, // 0x34 - 0x37
+    { 0x09, 0 },    { 0x0A, 0 },    { 0x27, 1 },    { 0x27, 0 }, // 0x38 - 0x3B
+    { 0x33, 1 },    { 0x0D, 0 },    { 0x34, 1 },    { 0x35, 1 }, // 0x3C - 0x3F
+    { 0x03, 1 },    { 0x1E, 1 },    { 0x30, 1 },    { 0x2E, 1 }, // 0x40 - 0x43
+    { 0x20, 1 },    { 0x12, 1 },    { 0x21, 1 },    { 0x22, 1 }, // 0x44 - 0x47
+    { 0x23, 1 },    { 0x17, 1 },    { 0x24, 1 },    { 0x25, 1 }, // 0x48 - 0x4B
+    { 0x26, 1 },    { 0x32, 1 },    { 0x31, 1 },    { 0x18, 1 }, // 0x4C - 0x4F
+    { 0x19, 1 },    { 0x10, 1 },    { 0x13, 1 },    { 0x1F, 1 }, // 0x50 - 0x53
+    { 0x14, 1 },    { 0x16, 1 },    { 0x2F, 1 },    { 0x11, 1 }, // 0x54 - 0x57
+    { 0x2D, 1 },    { 0x15, 1 },    { 0x2C, 1 },    { 0x1A, 0 }, // 0x58 - 0x5B
+    { 0x2B, 0 },    { 0x1B, 0 },    { 0x07, 1 },    { 0x0C, 1 }, // 0x5C - 0x5F
+    { 0x29, 0 },    { 0x1E, 0 },    { 0x30, 0 },    { 0x2E, 0 }, // 0x60 - 0x63
+    { 0x20, 0 },    { 0x12, 0 },    { 0x21, 0 },    { 0x22, 0 }, // 0x64 - 0x67
+    { 0x23, 0 },    { 0x17, 0 },    { 0x24, 0 },    { 0x25, 0 }, // 0x68 - 0x6B
+    { 0x26, 0 },    { 0x32, 0 },    { 0x31, 0 },    { 0x18, 0 }, // 0x6C - 0x6F
+    { 0x19, 0 },    { 0x10, 0 },    { 0x13, 0 },    { 0x1F, 0 }, // 0x70 - 0x73
+    { 0x14, 0 },    { 0x16, 0 },    { 0x2F, 0 },    { 0x11, 0 }, // 0x74 - 0x77
+    { 0x2D, 0 },    { 0x15, 0 },    { 0x2C, 0 },    { 0x1A, 1 }, // 0x78 - 0x7B
+    { 0x2B, 1 },    { 0x1B, 1 },    { 0x29, 1 },    { 0x0E, 0 }  // 0x7C - 0x7F
+};
+
+
+
+static int deliver_scan_code(struct vm_device * dev, struct key_code * key) {
+    struct v3_keyboard_event key_event;
+    struct v3_keyboard_event key_shift;
+    uint_t cap = key->capital;
+
+    key_event.status = 0;
+    key_event.scan_code = (uint8_t)key->scan_code;
+
+    PrintDebug("Scan code: 0x%x\n", key_event.scan_code);
+
+
+    if (cap) {
+       key_shift.status = 0;
+       key_shift.scan_code = (uint8_t)0x2A;
+
+       if (v3_deliver_keyboard_event(dev->vm, &key_shift) == -1) {
+           PrintError("Video: Error delivering key event\n");
+           return -1;
+       }
+    }
+
+    // Press
+    if (v3_deliver_keyboard_event(dev->vm, &key_event) == -1) {
+       PrintError("Video: Error delivering key event\n");
+       return -1;
+    }
+
+    // Release
+    key_event.scan_code = key_event.scan_code | 0x80;
+  
+    if (v3_deliver_keyboard_event(dev->vm, &key_event) == -1) {
+       PrintError("Video: Error delivering key event\n");
+       return -1;
+    }
+
+
+    if (cap) {
+        key_shift.scan_code = 0x2A | 0x80;
+
+       if (v3_deliver_keyboard_event(dev->vm, &key_shift) == -1) {
+           PrintError("Video: Error delivering key event\n");
+           return -1;
+       }
+    }
+
+    PrintDebug("Finished with Key delivery\n");
+    return 0;
+}
+
+
+
+
+static int recv_all(int socket, char * buf, int length) {
+    int bytes_read = 0;
+    
+    PrintDebug("Reading %d bytes\n", length - bytes_read);
+    while (bytes_read < length) {
+        int tmp_bytes = V3_Recv(socket, buf + bytes_read, length - bytes_read);
+        PrintDebug("Received %d bytes\n", tmp_bytes);
+
+        if (tmp_bytes == 0) {
+            PrintError("Connection Closed unexpectedly\n");
+            return 0;
+        } else if (tmp_bytes == -1) {
+           PrintError("Socket Error in for V3_RECV\n");
+           return -1;
+       }
+
+        bytes_read += tmp_bytes;
+    }
+    
+    return bytes_read;
+}
+
+
+static int send_all(const int sock, const char * buf, const int len){
+    int bytes_left = len;
+
+    while (bytes_left != 0) {
+       int written = 0;
+
+       if ((written = V3_Send(sock, buf + (len - bytes_left), bytes_left)) == -1) {
+           return -1;
+       }
+
+       bytes_left -= written;
+    }
+    return 0;
+}
+
+// Translate attribute color into terminal escape sequence color
+static const uint8_t fg_color_map[] = {
+    30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97
+};
+
+static const uint8_t bg_color_map[] = {
+    40, 44, 42, 46, 41, 45, 43, 47, 100, 104, 102, 106, 101, 105, 103, 107
+};
+
+
+#define INT_TO_CHAR(index, buf, val)                                   \
+    do {                                                               \
+       uint8_t base = '0';                                             \
+       if ((val) >= 100) buf[(index)++] = base + ((val) / 100);        \
+       if ((val) >= 10)  buf[(index)++] = base + ((val) / 10);         \
+       buf[(index)++] = base + ((val) % 10);                           \
+    } while (0)
+
+
+static int send_update(struct vm_device * dev, uint8_t  x, uint8_t  y, uint8_t attrib, uint8_t val) {
+    struct cons_state * state = (struct cons_state *)dev->private_data;
+    uint8_t fg_color = fg_color_map[(attrib & 0x0f) % 16];
+    uint8_t bg_color = bg_color_map[(attrib & 0xf0) % 16];
+    uint8_t buf[32];
+    int ret = 0;
+    int i = 0;
+
+    memset(buf, 0, 32);
+
+    buf[i++] = ESC_CHAR;
+    buf[i++] = '[';
+
+    INT_TO_CHAR(i, buf, y + 1);
+
+    buf[i++] = ';';
+
+    INT_TO_CHAR(i, buf, x + 1);
+
+    buf[i++] = 'H';
+    buf[i++] = ESC_CHAR;
+    buf[i++] = '[';
+    buf[i++] = '0';
+    buf[i++] = 'm';
+    buf[i++] = ESC_CHAR;
+    buf[i++] = '[';
+
+    INT_TO_CHAR(i, buf, fg_color);
+
+    buf[i++] = ';';
+
+    INT_TO_CHAR(i, buf, bg_color);
+
+    buf[i++] = 'm';
+
+    // Add value
+
+    buf[i++] = ESC_CHAR;
+    buf[i++] = '[';
+    INT_TO_CHAR(i, buf, y + 1);
+    buf[i++] = ';';
+    INT_TO_CHAR(i, buf, x + 1);
+    buf[i++] = 'H';
+    buf[i++] = val;
+
+    PrintDebug("printing value '%c'\n", val);
+
+    if (state->connected) {
+       uint64_t start, end;
+
+       rdtscll(start);
+       ret =  send_all(state->client_fd, buf, 32);
+       rdtscll(end);
+
+       PrintDebug("Sendall latency=%d cycles\n", (uint32_t)(end - start));
+    }
+
+    return ret;
+}
+
+
+
+static int cursor_update(uint_t x, uint_t y, void * private_data) {
+    struct vm_device * dev = (struct vm_device *)private_data;
+    struct cons_state * state = (struct cons_state *)dev->private_data;
+    uint8_t buf[16];
+    int ret = 0;
+    addr_t irq_state = 0;
+    int i = 0;
+
+    memset(buf, 0, 16);
+
+    buf[i++] = ESC_CHAR;
+    buf[i++] = '[';
+    INT_TO_CHAR(i, buf, y + 1);
+    buf[i++] = ';';
+    INT_TO_CHAR(i, buf, x + 1);
+    buf[i++] = 'H';
+
+
+    irq_state = v3_lock_irqsave(state->cons_lock);
+
+    if (state->connected) {
+       ret = send_all(state->client_fd, buf, 16);
+    }
+
+    v3_unlock_irqrestore(state->cons_lock, irq_state);
+    
+    return ret;
+}
+
+
+static int screen_update(uint_t x, uint_t y, uint_t length, void * private_data) {
+    struct vm_device * dev = (struct vm_device *)private_data;
+    struct cons_state * state = (struct cons_state *)dev->private_data;
+    uint_t offset = (x * BYTES_PER_COL) + (y * BYTES_PER_ROW);
+    uint8_t fb_buf[length];
+    int i = 0;
+    uint_t cur_x = x;
+    uint_t cur_y = y;
+    addr_t irq_state = 0;
+    int ret = 0;
+
+    memset(fb_buf, 0, length);
+    
+
+
+    irq_state = v3_lock_irqsave(state->cons_lock);
+
+    v3_cons_get_fb(state->frontend_dev, fb_buf, offset, length);
+
+    v3_unlock_irqrestore(state->cons_lock, irq_state);
+
+
+    for (i = 0; i < length; i += 2) {
+       uint_t col_index = i;
+       uint8_t col[2];
+
+       col[0] = fb_buf[col_index];     // Character
+       col[1] = fb_buf[col_index + 1]; // Attribute
+
+       irq_state = v3_lock_irqsave(state->cons_lock);
+
+       if (send_update(dev, cur_x, cur_y, col[1], col[0]) == -1) {
+           PrintError("Could not send attribute to telnet session\n");
+           ret = -1;
+           break;
+       }
+
+       v3_unlock_irqrestore(state->cons_lock, irq_state);
+                                   
+
+       // CAUTION: the order of these statements is critical
+       // cur_y depends on the previous value of cur_x
+       cur_y = cur_y + ((cur_x + 1) / NUM_COLS);
+       cur_x = (cur_x + 1) % NUM_COLS;
+    }
+
+
+    return ret;
+}
+
+static int scroll(uint_t rows, void * private_data) {
+    struct vm_device * dev = (struct vm_device *)private_data;
+    struct cons_state * state = (struct cons_state *)dev->private_data;
+    addr_t irq_state = 0;
+    int ret = 0;
+
+    if (rows > 0) {
+       int i = 0;
+
+       irq_state = v3_lock_irqsave(state->cons_lock);
+
+       for (i = rows; i > 0; i--) {
+           uint8_t message[2] = { ESC_CHAR, 'D' };
+
+           if (state->connected) {
+               if (send_all(state->client_fd, message, sizeof(message)) == -1) {
+                   PrintError("Could not send scroll command\n");
+                   ret = -1;
+                   break;
+               }
+           }
+       }
+       
+       v3_unlock_irqrestore(state->cons_lock, irq_state);
+
+    } else if (rows < 0) {
+       ret = screen_update(0, 0, SCREEN_SIZE, private_data);
+    }
+
+    return ret;
+}
+
+
+
+static struct v3_console_ops cons_ops = {
+    .update_screen = screen_update, 
+    .update_cursor = cursor_update,
+    .scroll = scroll,
+};
+
+
+static struct v3_device_ops dev_ops = {
+    .free = NULL,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+
+static int key_handler(struct vm_device * dev, uint8_t ascii) {
+    struct cons_state * state = (struct cons_state *)dev->private_data;
+
+    PrintDebug("Character recieved: 0x%x\n", ascii);
+
+    // printable
+    if (ascii < 0x80) {
+       const struct key_code * key = &(ascii_to_key_code[ascii]);
+
+       if (deliver_scan_code(dev, (struct key_code *)key) == -1) {
+           PrintError("Could not deliver scan code to vm\n");
+           return -1;
+       }
+
+    } else if (ascii == ESC_CHAR) { // Escape Key
+       // This means that another 2 characters are pending
+       // receive it and deliver accordingly
+       char esc_seq[2] = {0, 0};
+
+       int recv = recv_all(state->client_fd, esc_seq, 2);
+
+       if (recv == -1) {
+           PrintError("Video: Error getting key from network\n");
+           return -1;
+       } else if (recv == 0) {
+           PrintDebug("Video: Client Disconnected\n");
+           return -1;
+       }
+
+
+       if (esc_seq[0] != '[') {
+           PrintDebug("Ignoring non handled escape sequence (codes = %d %d)\n", 
+                      esc_seq[0], esc_seq[1]);
+           return 0;
+       }
+
+
+       if (esc_seq[1] == 'A') {                // UP ARROW
+           struct key_code up = { 0x48, 0 };
+           deliver_scan_code(dev, &up);
+       } else if (esc_seq[1] == 'B') {         // DOWN ARROW
+           struct key_code down = { 0x50, 0 };
+           deliver_scan_code(dev, &down);
+       } else if (esc_seq[1] == 'C') {         // RIGHT ARROW
+           struct key_code right = { 0x4D, 0 };
+           deliver_scan_code(dev, &right);
+       } else if (esc_seq[1] == 'D') {         // LEFT ARROW
+           struct key_code left = { 0x4B, 0 };
+           deliver_scan_code(dev, &left);
+       }
+    } else {
+       PrintError("Invalid character received from network (%c) (code=%d)\n",
+                  ascii, ascii);
+       //      return 0;
+    }
+       
+    return 0;
+}
+
+static int cons_server(void * arg) {
+    struct vm_device * dev = (struct vm_device *)arg;
+    struct cons_state * state = (struct cons_state *)dev->private_data;
+    
+    state->server_fd = V3_Create_TCP_Socket();
+
+
+    PrintDebug("Video: Socket File Descriptor: %d\n", state->server_fd);
+
+    if (V3_Bind_Socket(state->server_fd, state->port) == -1) {
+       PrintError("Video: Failed to bind to socket %d\n", state->port);
+    }
+
+    if (V3_Listen_Socket(state->server_fd, 8) == -1) {
+       PrintError("Video: Failed to listen with socket %d\n", state->server_fd);
+    }
+
+    while (1) {
+       uint32_t client_ip;
+       uint32_t client_port;
+       uint8_t ascii_code = 0;
+       int recv = 0;
+
+       if ((state->client_fd = V3_Accept_Socket(state->server_fd, &client_ip,  &client_port)) == -1) {
+           PrintError("Video: Failed to accept connection on port %d\n", client_port);
+       }
+       PrintDebug("Accepted Telnet Console connection\n");
+       state->connected = 1;
+
+       screen_update(0, 0, SCREEN_SIZE, dev);
+
+       while (1) {
+           recv = recv_all(state->client_fd, &ascii_code, sizeof(ascii_code));
+
+           PrintDebug("Telnet console Received %d bytes\n", recv);
+
+           if (recv == -1) {
+               PrintError("Video: Error getting key from network\n");
+               break;
+           } else if (recv == 0) {
+               PrintDebug("Video: Client Disconnected\n");
+               break;
+           }
+
+           if (key_handler(dev, ascii_code) == -1) {
+               PrintError("Error in key handler\n");
+               break;
+           }
+       }
+
+       state->connected = 0;
+       V3_Close_Socket(state->client_fd);
+    }
+}
+
+
+static int cons_init(struct guest_info * vm, void * cfg_data) {
+    struct telnet_cons_cfg * cfg = (struct telnet_cons_cfg *)cfg_data;
+    struct cons_state * state = (struct cons_state *)V3_Malloc(sizeof(struct cons_state));
+    struct vm_device * frontend = v3_find_dev(vm, cfg->frontend);
+
+
+    state->server_fd = 0;
+    state->client_fd = 0;
+    state->frontend_dev = frontend;
+    state->port = cfg->port;
+    v3_lock_init(&(state->cons_lock));
+
+
+    struct vm_device * dev = v3_allocate_device("TELNET_CONS", &dev_ops, state);
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", "TELNET_CONS");
+       return -1;
+    }
+
+
+    v3_console_register_cga(frontend, &cons_ops, dev);
+
+    V3_CREATE_THREAD(cons_server, dev, "Telnet Console Network Server");
+
+    return 0;
+}
+
+
+
+device_register("TELNET_CONSOLE", cons_init)
diff --git a/palacios/src/devices/video.c b/palacios/src/devices/video.c
deleted file mode 100644 (file)
index 2c5ff2f..0000000
+++ /dev/null
@@ -1,1030 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
- * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu> 
- * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Robdert Deloatch <rtdeloatch@gmail.com>
- *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-
-#include <devices/video.h>
-#include <palacios/vmm.h>
-#include <palacios/vmm_emulator.h>
-#include <palacios/vmm_decoder.h>
-#include <palacios/vm_guest_mem.h>
-#include <palacios/vmm_decoder.h>
-#include <palacios/vmm_paging.h>
-#include <palacios/vmm_instr_emulator.h>
-#include <palacios/vm_guest_mem.h>
-#include <palacios/vmm_socket.h>
-#include <palacios/vmm_host_events.h>
-#include <devices/pci.h>
-#include <devices/pci_types.h>
-
-
-
-/* #ifndef DEBUG_VIDEO */
-/* #undef PrintDebug */
-/* #define PrintDebug(fmt, args...) */
-/* #endif */
-
-
-#define START_ADDR 0xA0000    //0xB0000   //Attempting to hook entire region
-#define END_ADDR 0xC0000     //0xC0000//(START_ADDR + ROWS * COLS * DEPTH) 
-
-#define SIZE_OF_REGION (END_ADDR-START_ADDR)
-
-#define PCI_ENABLED 1
-
-#define SEND_UPDATE_RAW       0
-#define SEND_UPDATE_ALL_VT100 0
-#define SEND_UPDATE_INCREMENTAL_VT100 1
-#define SCROLLING_ENABLED 1
-#define PASSTHROUGH 1
-#define PORT 19997
-
-#define NO_CODE 0
-#define PORT_OFFSET 0x3B0
-
-#define ESC_CHAR          ((unsigned char)0x1b)
-
-struct key_code {
-  char scan_code;
-  uint_t capital;
-};
-
-#define NO_KEY { NO_CODE, 0 }
-
-static const struct key_code ascii_to_key_code[] = {             // ASCII Value Serves as Index
-    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x00 - 0x03
-    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x04 - 0x07
-    { 0x0E, 0 },    { 0x0F, 0 },    NO_KEY,         NO_KEY,      // 0x08 - 0x0B
-    NO_KEY,         { 0x1C, 0 },    NO_KEY,         NO_KEY,      // 0x0C - 0x0F
-    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x10 - 0x13
-    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x14 - 0x17
-    NO_KEY,         NO_KEY,         NO_KEY,         { 0x01, 0 }, // 0x18 - 0x1B
-    NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x1C - 0x1F
-    { 0x39, 0 },    { 0x02, 1 },    { 0x28, 1 },    { 0x04, 1 }, // 0x20 - 0x23
-    { 0x05, 1 },    { 0x06, 1 },    { 0x08, 1 },    { 0x28, 0 }, // 0x24 - 0x27
-    { 0x0A, 1 },    { 0x0B, 1 },    { 0x09, 1 },    { 0x0D, 1 }, // 0x28 - 0x2B
-    { 0x33, 0 },    { 0x0C, 0 },    { 0x34, 0 },    { 0x35, 0 }, // 0x2C - 0x2F
-    { 0x0B, 0 },    { 0x02, 0 },    { 0x03, 0 },    { 0x04, 0 }, // 0x30 - 0x33
-    { 0x05, 0 },    { 0x06, 0 },    { 0x07, 0 },    { 0x08, 0 }, // 0x34 - 0x37
-    { 0x09, 0 },    { 0x0A, 0 },    { 0x27, 1 },    { 0x27, 0 }, // 0x38 - 0x3B
-    { 0x33, 1 },    { 0x0D, 0 },    { 0x34, 1 },    { 0x35, 1 }, // 0x3C - 0x3F
-    { 0x03, 1 },    { 0x1E, 1 },    { 0x30, 1 },    { 0x2E, 1 }, // 0x40 - 0x43
-    { 0x20, 1 },    { 0x12, 1 },    { 0x21, 1 },    { 0x22, 1 }, // 0x44 - 0x47
-    { 0x23, 1 },    { 0x17, 1 },    { 0x24, 1 },    { 0x25, 1 }, // 0x48 - 0x4B
-    { 0x26, 1 },    { 0x32, 1 },    { 0x31, 1 },    { 0x18, 1 }, // 0x4C - 0x4F
-    { 0x19, 1 },    { 0x10, 1 },    { 0x13, 1 },    { 0x1F, 1 }, // 0x50 - 0x53
-    { 0x14, 1 },    { 0x16, 1 },    { 0x2F, 1 },    { 0x11, 1 }, // 0x54 - 0x57
-    { 0x2D, 1 },    { 0x15, 1 },    { 0x2C, 1 },    { 0x1A, 0 }, // 0x58 - 0x5B
-    { 0x2B, 0 },    { 0x1B, 0 },    { 0x07, 1 },    { 0x0C, 1 }, // 0x5C - 0x5F
-    { 0x29, 0 },    { 0x1E, 0 },    { 0x30, 0 },    { 0x2E, 0 }, // 0x60 - 0x63
-    { 0x20, 0 },    { 0x12, 0 },    { 0x21, 0 },    { 0x22, 0 }, // 0x64 - 0x67
-    { 0x23, 0 },    { 0x17, 0 },    { 0x24, 0 },    { 0x25, 0 }, // 0x68 - 0x6B
-    { 0x26, 0 },    { 0x32, 0 },    { 0x31, 0 },    { 0x18, 0 }, // 0x6C - 0x6F
-    { 0x19, 0 },    { 0x10, 0 },    { 0x13, 0 },    { 0x1F, 0 }, // 0x70 - 0x73
-    { 0x14, 0 },    { 0x16, 0 },    { 0x2F, 0 },    { 0x11, 0 }, // 0x74 - 0x77
-    { 0x2D, 0 },    { 0x15, 0 },    { 0x2C, 0 },    { 0x1A, 1 }, // 0x78 - 0x7B
-    { 0x2B, 1 },    { 0x1B, 1 },    { 0x29, 1 },    { 0x0E, 0 }  // 0x7C - 0x7F
-};
-
-struct get_keys_arg {
-  struct guest_info * info;
-  int fd;
-};
-
-struct video_internal {
-  addr_t video_memory_pa;
-  uchar_t * video_memory;
-
-#if PCI_ENABLED
-  struct vm_device * pci_bus;
-  struct pci_device * pci_dev;
-#endif
-
-  int socket_fd;
-  int client_fd;
-
-  struct get_keys_arg key_arg;
-
-  uint_t screen_bottom;
-  uint_t ports[44];
-  uchar_t reg_3C4[0x100];
-  uchar_t reg_3CE[0x100];
-  ushort_t start_addr_offset;
-  ushort_t old_start_addr_offset;
-  ushort_t cursor_addr;
-  
-  uchar_t reg_3D5[0x19];
-
-  uint_t high_addr;
-  uint_t low_addr;
-};
-
-void video_do_in(ushort_t port, void *src, uint_t length){
-   #if PASSTHROUGH
-   uint_t i;
-    
-    switch (length) {
-       case 1:
-           ((uchar_t*)src)[0] = v3_inb(port);
-           break;
-       case 2:
-           ((ushort_t*)src)[0] = v3_inw(port);
-           break;
-       case 4:
-           ((uint_t*)src)[0] = v3_indw(port);
-           break;
-       default:
-           for (i = 0; i < length; i++) { 
-               ((uchar_t*)src)[i] = v3_inb(port);
-           }
-    }//switch length
-    #endif
-}
-
-void video_do_out(ushort_t port, void * src, uint_t length){
-  #if PASSTHROUGH
-  uint_t i;
-  switch (length) {
-       case 1:
-           v3_outb(port,((uchar_t*)src)[0]);
-           break;
-       case 2:
-           v3_outw(port,((ushort_t*)src)[0]);
-           break;
-       case 4:
-           v3_outdw(port,((uint_t*)src)[0]);
-           break;
-       default:
-           for (i = 0; i < length; i++) { 
-               v3_outb(port, ((uchar_t*)src)[i]);
-           }
-    } //switch length
-  #endif
-}
-
-static int deliver_scan_code(struct get_keys_arg * args, struct key_code * k) {
-   uint_t cap = k->capital;
-   struct v3_keyboard_event key_event;
-   key_event.status = 0;
-   key_event.scan_code = (unsigned char)k->scan_code;
-   PrintDebug("Scan code: 0x%x\n", key_event.scan_code);
-   struct v3_keyboard_event key_shift;
-   key_shift.status = 0;
-   key_shift.scan_code = (unsigned char)0x2A;
-   if(cap) {
-       if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) {
-           PrintError("Video: Error delivering key event\n");
-          return -1;
-       }
-   }
-   // Press
-   if(v3_deliver_keyboard_event(args->info, &key_event) == -1) {
-       PrintError("Video: Error delivering key event\n");
-       return -1;
-   }
-   // Release
-   if(key_event.scan_code != 0x1c) {
-       key_event.scan_code = key_event.scan_code|0x80;
-       if(v3_deliver_keyboard_event(args->info, &key_event) == -1) {
-           PrintError("Video: Error delivering key event\n");
-          return -1;
-       }
-    }
-    if(cap) {
-        key_shift.scan_code = 0x2A|0x80;
-       if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) {
-           PrintError("Video: Error delivering key event\n");
-           return -1;
-       }
-    }
-    PrintDebug("Finished with Key delivery\n");
-    return 0;
-}
-
-static int get_keys(void * arg) {
-  struct get_keys_arg * args =  &(((struct video_internal *)arg)->key_arg);
-  while(1) {
-    PrintDebug("Get keys loop start\n");
-    uint_t cap;
-    char key[1];
-    memset(key, 0, 1);
-
-    int recv = V3_Recv(args->fd, key, 1);
-    if(recv == -1){
-      PrintError("Video: Error getting key from network\n");
-    }
-    else if(recv == 0){
-      PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
-      break;
-    }
-
-    uint_t i;
-    for(i = 0; i < 1; i++) {
-      cap = 0;
-      uchar_t ascii = (uchar_t)key[i];
-      
-      if(ascii == 0) {
-       PrintDebug("Recieved ASCII NULL character\n");
-       break;
-      }
-
-      PrintDebug("Character recieved: 0x%x\n", ascii);
-      if(ascii < 0x80) {
-       key[i] = ascii_to_key_code[ascii].scan_code;
-       cap = ascii_to_key_code[ascii].capital;
-       if(key[i]) {
-         // Special Terminal Escape Sequences (UP, DOWN, LEFT, RIGHT) 
-         if(key[i] == 0x01) {
-           int j;
-           int esc = 0;
-           for(j = 0; j < 2; j++) {
-             int recv2 = V3_Recv(args->fd, key, 1);
-             if(recv2 == -1){
-               PrintDebug("Video: Error getting key from network\n");
-               break;
-             }
-             else if(recv2 == 0){
-               PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
-               break;
-             }
-             if(key[0] == '[') {
-               esc = 1;
-             }
-             // UP ARROW
-             if(esc == 1 && key[0] == 'A') {
-               struct key_code up = { 0x48, 0 };
-               deliver_scan_code(args, &up);
-             }
-             // DOWN ARROW
-             if(esc == 1 && key[0] == 'B') {
-                struct key_code down = { 0x50, 0 };
-               deliver_scan_code(args, &down);
-             }
-             // RIGHT ARROW
-             if(esc == 1 && key[0] == 'C') {
-               struct key_code right = { 0x4D, 0 };
-               deliver_scan_code(args, &right);
-             }
-             // LEFT ARROW
-             if(esc == 1 && key[0] == 'D') {
-               struct key_code left = { 0x4B, 0 };
-               deliver_scan_code(args, &left);
-             }
-           }
-           break;
-         }
-         else if(key[i] == 0x1D){
-           int recv2 = V3_Recv(args->fd, key, 1);
-           if(recv2 == -1){
-             PrintDebug("Video: Error getting key from network\n");
-           }
-           else if(recv2 == 0){
-             PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
-           }
-           break;
-         }
-         else {
-            struct key_code k = { ascii_to_key_code[ascii].scan_code, ascii_to_key_code[ascii].capital };
-           deliver_scan_code(args, &k);
-         }
-       }
-       else {
-         break;
-       }
-      }
-    }
-  }
-  return 0;
-}
-
-#if SEND_UPDATE_INCREMENTAL_VT100
-static int send_all(struct video_internal * data, const int sock, const char * buf, const int len){
-  int bytes_left = len;
-  while(bytes_left != 0) {
-    int written = 0;
-    if((written = V3_Send(sock, buf + (len-bytes_left), bytes_left)) == -1) {
-      return -1;
-    }
-    bytes_left -= written;
-  }
-  return 0;
-}
-#endif
-
-// Translate attribute color into terminal escape sequence color
-static unsigned char text_mode_fg_color[] = {
-  30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97
-};
-
-static unsigned char text_mode_bg_color[] = {
-  40, 44, 42, 46, 41, 45, 43, 47, 100, 104, 102, 106, 101, 105, 103, 107
-};
-
-#if SEND_UPDATE_INCREMENTAL_VT100
-static unsigned char * append_char_as_digits(unsigned char *s, unsigned char c)
-{
-  if (c/100) { 
-    *s++ = '0'+ c/100;
-  }
-  c %= 100;
-  if (c/10) { 
-    *s++= '0' + c/10;
-  }
-  c %= 10;
-  *s++ = '0'+ c;
-  return s;
-}
-
-
-static unsigned char * append_write_attribute_at(unsigned char *s, unsigned char  x, unsigned char  y, unsigned char c) 
-{
-  // Update cursor
-  *s++ = ESC_CHAR;
-  *s++ = '[';
-  s = append_char_as_digits(s,y+1);
-  *s++ = ';';
-  s = append_char_as_digits(s,x+1);
-  *s++ = 'H';
-  
-  *s++ = ESC_CHAR;
-  *s++ = '[';
-  *s++ = '0';
-  *s++ = 'm';
-
-  // Update attribute
-  unsigned char fg_color = 0;
-  unsigned char bg_color = 0;
-
-  *s++ = ESC_CHAR;
-  *s++ = '[';
-  unsigned char low = c & 0x0F;
-  unsigned char high = (c & 0xF0) >> 4;
-  low = low % 16;
-  fg_color = text_mode_fg_color[low];
-  s = append_char_as_digits(s,fg_color);
-  *s++ = '\x3b';
-  high = high % 16;
-  bg_color = text_mode_bg_color[high];
-  s = append_char_as_digits(s,bg_color);
-  *s++ = 'm';
-  return s;
-}
-
-static unsigned char * append_write_char_at(unsigned char *s, unsigned char x, unsigned char y, unsigned char c) {
-  *s++ = ESC_CHAR;
-  *s++ = '[';
-  s = append_char_as_digits(s,y+1);
-  *s++ = ';';
-  s = append_char_as_digits(s,x+1);
-  *s++ = 'H';
-  *s++ = c;
-  return s;
-}
-#endif
-static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) {
-  PrintDebug("\n\nInside Video Write Memory.\n\n");
-  PrintDebug("Guest address: 0x%x length = %d\n", (uint_t)guest_addr, length);
-
-  struct vm_device * dev = (struct vm_device *) priv_data;
-  struct video_internal * data = (struct video_internal *) dev->private_data;
-  addr_t write_offset = guest_addr - START_ADDR;
-
-#if 1  
-  PrintDebug("Write offset: 0x%p\n", (void*)write_offset);
-  
-  {
-    int i;
-    PrintDebug("Video_Memory: ");
-    for(i = 0; i < length; i += 2){
-      PrintDebug("%c",((char *)(V3_VAddr((void*)guest_addr)))[i]);
-    }
-  }
-#endif
-  memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length);
-
-#if SEND_UPDATE_RAW
-  send_all(data, data->client_fd, (char *)(data->video_memory + write_offset), length);
-#endif
-
-#if SEND_UPDATE_INCREMENTAL_VT100
-  unsigned char buf[32];
-  unsigned char *n;
-  unsigned char *a;
-  uint_t difference = 0x18000;
-
-
-  unsigned char x,y,c;
-  uint_t       offset;
-  uint_t l = length;
-
-  for (offset=0;offset<l;offset+=2){
-    memset(buf, 0, 32);
-    y = ((write_offset - difference - (data->start_addr_offset *2) + offset)/160) ;
-    if(y < 25){
-      //      PrintDebug("  Video: Y value = %d  ", y); 
-      x = ((write_offset - difference + offset)%160)/2;
-      c = (data->video_memory + difference + data->start_addr_offset * 2)[y*160+x*2+1];
-      a = append_write_attribute_at(buf,x,y,c);
-      send_all(data,data->client_fd, (char*)buf, 32);
-      memset(buf, 0, 32);
-      c = (data->video_memory + difference + data->start_addr_offset * 2)[y*160+x*2];
-      n = append_write_char_at(buf,x,y,c);
-      send_all(data,data->client_fd, (char *)buf, 32);
-    }
-  }
-
-#endif
-
-#if SEND_UPDATE_ALL_VT100
-  unsigned char buf[16];
-  unsigned char *n;
-
-  unsigned char x,y,c;
-  
-  for (y=0;y<25;y++) { 
-    for (x=0;x<80;x++) { 
-      c = data->video_memory[y*160+x*2];
-      n = append_write_char_at(buf,x,y,c);
-      send_all(data,data->client_fd, (char *)buf, n-buf);
-    }
-  }
-#endif
-  PrintDebug(" Done.\n"); 
-  return length;
-}
-
-static int video_read_port(ushort_t port,
-                                void * dest,
-                                uint_t length,
-                                struct vm_device * dev) {
-  PrintDebug("Video: Read port 0x%x\n",port);
-  video_do_in(port, dest, length);
-  return length;
-}
-
-static int video_read_port_generic(ushort_t port,
-                                void * dest,
-                                uint_t length,
-                                struct vm_device * dev) {
-  memset(dest, 0, length);
-  video_do_in(port, dest, length);
-  return length;
-}
-
-
-static int video_write_port(ushort_t port,
-                                void * src,
-                                uint_t length,
-                                struct vm_device * dev) {
-
-  PrintDebug("Video: write port 0x%x...Wrote: ", port);
-  uint_t i;
-  for(i = 0; i < length; i++){
-    PrintDebug("%x", ((uchar_t*)src)[i]);
-  }
-  PrintDebug("...Done\n");
-  video_do_out(port, src, length);
-  return length;
-}
-
-static int video_write_port_store(ushort_t port,
-                                void * src,
-                                uint_t length,
-                                struct vm_device * dev) {
-
-  PrintDebug("Entering video_write_port_store...port 0x%x\n", port);
-  uint_t i;
-  for(i = 0; i < length; i++){
-    PrintDebug("%x", ((uchar_t*)src)[i]);
-  }
-  PrintDebug("...Done\n"); 
-
-  struct video_internal * video_state = (struct video_internal *)dev->private_data;
-  video_state->ports[port - PORT_OFFSET] = 0;
-  memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
-  video_do_out(port, src, length);
-  return length;
-}
-
-static int video_write_port_3D5(ushort_t port,
-                                void * src,
-                                uint_t length,
-                                struct vm_device * dev) {
-  PrintDebug("Video: write port 0x%x...Wrote: ", port);
-  uint_t i;
-  for(i = 0; i < length; i++){
-    PrintDebug("%x", ((uchar_t*)src)[i]);
-  }
-  PrintDebug("...Done\n");
-  struct video_internal * video_state = (struct video_internal *)dev->private_data;
-  video_state->ports[port - PORT_OFFSET] = 0;
-  memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
-
-  uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
-  memcpy(&(video_state->reg_3D5[index]), src, length);
-  uchar_t new_start;
-  switch(index) {
-     case 0x0c:
-         video_state->old_start_addr_offset = video_state->start_addr_offset;
-        new_start = *((uchar_t *)src);
-        video_state->start_addr_offset = (new_start << 8);
-         break;
-     case 0x0d:
-         new_start = *((uchar_t *)src);
-        video_state->start_addr_offset += new_start;
-        int diff =  video_state->start_addr_offset - video_state->old_start_addr_offset;
-        if(diff > 0) {
-            for(diff /= 80; diff > 0; diff--){
-                unsigned char message[2];
-                memset(message, 0, 2);
-                message[0] = ESC_CHAR;
-                message[1] = 'D';
-                send_all(video_state,video_state->client_fd, (char *)message, 2);
-            }
-        }
-        // Scroll Up?
-         break;
-     case 0x0E:
-       new_start = *((uchar_t *)src);
-       video_state->cursor_addr = new_start << 8;
-       break;
-     case 0x0F:
-       new_start = *((uchar_t *)src);
-       video_state->cursor_addr += new_start;
-       // Update cursor
-       unsigned char s[16];
-       memset(s, 0, 16);
-       unsigned char *n = s;
-       *n++ = ESC_CHAR;
-       *n++ = '[';
-       n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1);
-       *n++ = ';';
-       n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1);
-       *n++ = 'H';
-       send_all(video_state, video_state->client_fd, (char *)s, 16);
-       break;
-     default:
-         break;
-  }
-  video_do_out(port, src, length);
-  return length;
-}
-
-
-static int video_write_port_3C5(ushort_t port,
-                                void * src,
-                                uint_t length,
-                               struct vm_device * dev) {
-  PrintDebug("Entering write_port_3C5....port 0x%x\n", port);
-  uint_t i;
-  for(i = 0; i < length; i++){
-    PrintDebug("%x", ((uchar_t*)src)[i]);
-  }
-  PrintDebug("...Done\n");
-
-  struct video_internal * video_state = (struct video_internal *)dev->private_data;
-  video_state->ports[port - PORT_OFFSET] = 0;
-  memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
-
-  uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
-  memcpy(&(video_state->reg_3C4[index]), src, length);
-  video_do_out(port, src, length);
-  return length;
-}
-
-static int video_write_port_3CF(ushort_t port,
-                                void * src,
-                                uint_t length,
-                                struct vm_device * dev) {
-  PrintDebug("Entering write_port_3CF....port 0x%x\n", port);
-  uint_t i;
-  for(i = 0; i < length; i++){
-    PrintDebug("%x", ((uchar_t*)src)[i]);
-  }
-  PrintDebug("...Done\n");
-
-  struct video_internal * video_state = (struct video_internal *)dev->private_data;
-  video_state->ports[port - PORT_OFFSET] = 0;
-  memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
-
-  uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
-  memcpy(&(video_state->reg_3CE[index]), src, length);
-  video_do_out(port, src, length);
-  return length;
-}
-
-static int video_write_port_3D4(ushort_t port, void *src, uint_t length,
-                               struct vm_device *dev){
-  struct video_internal *video_state = (struct video_internal *) dev -> private_data;
-
-#if 1
-
-  if(length == 1) {
-    video_state->ports[port - PORT_OFFSET] = 0;
-    memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
-  }
-  else if(length == 2){
-    ushort_t new_start = 0;
-    ushort_t cursor_start = 0;
-    new_start = *((ushort_t *)src);
-    cursor_start = *((ushort_t *)src);
-
-    //Updating the cursor
-    if((cursor_start & 0x00FF) == 0x000E){
-      PrintDebug("Video:  E Case cursor start = 0x%x\n", cursor_start);
-      cursor_start = (cursor_start & 0xFF00);  //0x70
-      PrintDebug("Video: cursor start after and = 0x%x\n", cursor_start);
-      video_state->cursor_addr = cursor_start;
-    }
-    else if((cursor_start & 0x00FF) == 0x000F){
-      PrintDebug("Video:  F Case cursor start = 0x%x\n", cursor_start);
-      PrintDebug("Cursor Address after: 0x%x\n", video_state->cursor_addr);
-      video_state->cursor_addr += ((cursor_start >> 8) & 0x00FF);
-      // Update cursor
-      unsigned char s[16];
-      memset(s, 0, 16);
-      unsigned char *n = s;
-      *n++ = ESC_CHAR;
-      *n++ = '[';
-      n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1);
-      *n++ = ';';
-      n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1);
-      *n++ = 'H';
-      PrintDebug("Cursor Address: 0x%x\n", video_state->cursor_addr);
-      PrintDebug("Cursor Y location should be:  %d\n", ((video_state->cursor_addr)/80)+1);
-      PrintDebug("Cursor X location should be:  %d\n",((video_state->cursor_addr % 80)/2)+1);
-      send_all(video_state, video_state->client_fd, (char *)s, 16);
-    }
-    //Checking to see if scrolling is needed
-    if((new_start & 0x00FF) == 0x000C){
-      video_state->old_start_addr_offset = video_state->start_addr_offset;
-      new_start = (new_start & 0xFF00);
-      video_state->start_addr_offset = new_start;
-    }
-    else if((new_start & 0x00FF) == 0x000D){
-      video_state->start_addr_offset += ((new_start >> 8) & 0x00FF);
-      int diff =  video_state->start_addr_offset - video_state->old_start_addr_offset;
-      if(diff > 0){
-#if 1
-       for(diff /= 80; diff > 0; diff--){
-         unsigned char message[2];
-         memset(message, 0, 2);
-         message[0] = ESC_CHAR;
-         message[1] = 'D';
-         send_all(video_state,video_state->client_fd, (char *)message, 2);
-       }
-#endif
-      }
-      //Still need to handle scroll up
-    }
-  }
-#endif 
-  video_do_out(port, src, length);
-  return length;
-}
-
-
-
-#if PCI_ENABLED
-static int video_write_mem_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){
-  struct vm_device * dev = (struct vm_device *) priv_data;
-  struct video_internal * data = (struct video_internal *) dev->private_data;
-  if(data->low_addr == 0){
-    data->low_addr = guest_addr;
-    //memset(V3_VAddr((void*)0xA0000),0,0x10000);
-    memset(V3_VAddr((void *)0xA000000),0, 0x4affc);
-    memset(V3_VAddr((void *)0xF0000000),0, 0x4affc);
-  }
-
-  if(guest_addr > data->high_addr){
-    data->high_addr = guest_addr;
-  }
-  if(guest_addr < data->low_addr){
-    data->low_addr = guest_addr;
-  }
-  
-
-  PrintDebug("Video:  Within video_write_mem_region\n");
-
-  PrintDebug("Length of write: %d\n", length);
-  PrintDebug("Guest Address of write: 0x%p\n", (void *)guest_addr);
-  //PrintDebug("\"Src Address\": 0x%p\n", (void *)src);
-
-
-  //PrintDebug("Write Mem Value: ");
-  // PrintDebug("0x%x",*((uint32_t *)(V3_VAddr((void*)guest_addr))));
-  // PrintDebug("0x%x",*((uint32_t *)src));
-  /* 
-  unsigned char message[4];
-  memset(message, 0, 4);
-  message[0] = (*((char *)(V3_VAddr((void*)guest_addr))));
-  message[1] = (*((char *)(V3_VAddr((void*)guest_addr) + 1)));
-  message[2] = (*((char *)(V3_VAddr((void*)guest_addr) + 2)));
-  message[3] = (*((char *)(V3_VAddr((void*)guest_addr) + 3)));
-  PrintDebug("Character Value: %s\n", message);
-  //send_all(data,data->client_fd, (char *)message, 4);
-  */
-
-  PrintDebug("\nLowest address written to...");
-  PrintDebug("0x%x",data->low_addr);
-
-  PrintDebug("\nHighest address written to...");
-  PrintDebug("0x%x\n",data->high_addr);
-
-  // memcpy(V3_VAddr((void*)0xF0000000), V3_VAddr((void*)guest_addr) , length);
-  //addr_t write_offset = guest_addr - 0xA000000;// % 0x20000; // (guest_addr - 0xA000000);// % 0x20000
-  // PrintDebug("0x%x",*((uint32_t *)(src + )));
-  //memcpy(V3_VAddr((void *)(0xF0000000 + write_offset)), src, length);
-  /*If(write_offset < 0x10000) {
-    memcpy(V3_VAddr((void *)(START_ADDR + write_offset)), V3_VAddr((void*)guest_addr) , length);
-  }
-  else {
-    memset(V3_VAddr((void*)0xA0000),0,0x10000);
-    }*/
-  // memset(V3_VAddr((void *)(0xF0000000)), 5, 0x4affc);
-  //memset(V3_VAddr((void *)(0xF004affa)), 7, 0xF);
-
-  //Int i;
-  //PrintDebug("Write Mem Value: ");
-  //for(i = 0; i < length; i++){
-  //  PrintDebug("%x",((char *)(V3_VAddr((void*)guest_addr)))[i]);
-  //}
-
-  PrintDebug("\n...Done\n");
-
-  return length;
-}
-
-static int video_read_mem_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){
-  PrintDebug("Video:  Within video_read_mem_region\n");
-  return length;
-}
-
-static int video_write_io_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){
-  PrintDebug("Video:  Within video_write_io_region\n");
-  return length;
-}
-
-static int video_read_io_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){
-  PrintDebug("Video:  Within video_read_io_region\n");
-  return length;
-}
-#endif
-
-static int video_free(struct vm_device * dev) {
-  v3_unhook_mem(dev->vm, START_ADDR);
-  return 0;
-}
-
-static int video_reset_device(struct vm_device * dev) {
-  PrintDebug("Video: reset device\n");
-  return 0;
-}
-
-static int video_start_device(struct vm_device * dev) {
-  PrintDebug("Video: start device\n");
-  return 0;
-}
-
-static int video_stop_device(struct vm_device * dev) {
-  PrintDebug("Video: stop device\n");
-  return 0;
-}
-
-static struct v3_device_ops dev_ops = {
-  .free = video_free,
-  .reset = video_reset_device,
-  .start = video_start_device,
-  .stop = video_stop_device,
-};
-
-static int video_init(struct guest_info * vm, void * cfg_data){
-  PrintDebug("video: init_device\n");
-struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
-
- struct vm_device * dev = v3_allocate_device("VIDEO", &dev_ops, video_state);
-
-   if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "VIDEO");
-       return -1;
-    }
-
-  PrintDebug("Num Pages=%d\n", SIZE_OF_REGION / 4096);
-  video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096);
-  video_state->video_memory = V3_VAddr((void*)video_state->video_memory_pa);
-
-  memset(video_state->video_memory, 0, SIZE_OF_REGION);
-  PrintDebug("Video: hook io ports\n");
-#if 1
-  v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port_3C5);
-  v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port_store);
-  v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port_3CF);
-  v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d4, &video_read_port, &video_write_port_3D4);
-  v3_dev_hook_io(dev, 0x3d5, &video_read_port, &video_write_port_3D5);
-  v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3da, &video_read_port_generic, &video_write_port);
-  v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
-  v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
-#endif
-   PrintDebug("Video: End i/o hooks\n");
-   struct guest_info * info = vm;
-   PrintDebug("PA of array: %p\n", (void*)video_state->video_memory_pa);
-
-   if(v3_hook_write_mem(info, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1){
-      PrintDebug("\n\nVideo Hook failed.\n\n");
-    }
-   print_shadow_map(info);
-
-
-  // Testing out network stuff
-  video_state->socket_fd = V3_Create_TCP_Socket();
-  PrintDebug("Video: Socket File Descriptor: %d\n", video_state->socket_fd);
-
-#if 1
-
-  if(V3_Bind_Socket(video_state->socket_fd, PORT) == -1) {
-    PrintError("Video: Failed to bind to socket %d\n", PORT);
-  }
-  if(V3_Listen_Socket(video_state->socket_fd, 10) == -1) {
-    PrintError("Video: Failed to listen with socket %d\n", video_state->socket_fd);
-  }
-  const char * ip_string = "10.10.10.138";
-  PrintDebug("Video: IP Address in string form: %s\n", ip_string);
-  uint32_t ip_h = v3_inet_addr(ip_string);
-  PrintDebug("Video: IP Address in host integer form: %x\n", ip_h);
-  uint32_t ip_n = v3_htonl(ip_h);
-  PrintDebug("Video: IP Address in network integer form %x\n", ip_n);
-  uint32_t port = PORT;
-  unsigned int ip_ptr = (ip_n);
-  unsigned int port_ptr = (port);
-  if((video_state->client_fd = V3_Accept_Socket(video_state->socket_fd, &ip_ptr, &port_ptr)) == -1) {
-    PrintDebug("Video: Failed to accept connection on port %d", PORT);
-  }
-  PrintDebug("Video: Accept worked? FD= %d\n", video_state->client_fd);
-#endif
-
-  video_state->key_arg.info = info;
-  video_state->key_arg.fd = video_state->client_fd;
-  V3_CREATE_THREAD(get_keys,(void *)video_state, "Get Keys from Network");
-
-  video_state->screen_bottom = 25;
-  PrintDebug("video: init complete\n");
-
-
-
-#if PCI_ENABLED
-  if(video_state->pci_bus){
-    struct v3_pci_bar bars[6];
-    struct pci_device * pci_dev = NULL;
-
-    int i;
-    for(i = 0; i < 6; i++){
-      bars[i].type = PCI_BAR_NONE;
-    }
-
-    bars[0].type = PCI_BAR_MEM32;
-    bars[0].num_pages = /*0x20000/0x1000;*/ 0x2000000/0x1000;
-    bars[0].default_base_addr = (addr_t)V3_VAddr((void *)0xF0000000);//(addr_t)V3_VAddr(V3_AllocPages(bars[0].num_pages));
-
-    bars[0].mem_read = video_read_mem_region;
-    bars[0].mem_write = video_write_mem_region;
-
-    bars[1].type = PCI_BAR_MEM32;
-    bars[1].num_pages = 1;
-    bars[1].default_base_addr = (addr_t)V3_VAddr(V3_AllocPages(bars[1].num_pages));
-    
-    bars[1].mem_read = video_read_io_region;
-    bars[1].mem_write = video_write_io_region;
-    //-1 Means autoassign
-    //                                                     Not sure if STD
-    pci_dev = v3_pci_register_device(video_state->pci_bus, PCI_STD_DEVICE, 0,
-                                    //or0  1st null could be pci_config_update
-                                    -1, 0, "VIDEO", bars, NULL, NULL,
-                                    NULL, dev);
-
-    if (pci_dev == NULL) {
-       PrintError("Failed to register VIDEO %d with PCI\n", i);
-       return -1;
-    }
-    else{
-      PrintDebug("Registering PCI_VIDEO succeeded\n");
-    }
-    //Need to set some pci_dev->config_header.vendor_id type variables
-
-    pci_dev->config_header.vendor_id = 0x1013;
-    pci_dev->config_header.device_id = 0x00B8;
-    pci_dev->config_header.revision = 0x00;
-
-    //If we treat video as a VGA device than below is correct
-    //If treated as a VGA compatible controller, which has mapping
-    //0xA0000-0xB0000 and I/O addresses 0x3B0-0x3BB than change
-    //#define from VGA to 0
-
-    //pci_dev->config_header.class = 0x00;
-    //pci_dev->config_header.subclass = 0x01;
-
-    pci_dev->config_header.class = 0x03;
-    pci_dev->config_header.subclass = 0x00;
-    pci_dev->config_header.prog_if = 0x00;
-
-
-    //We have a subsystem ID, but optional to provide:  1AF4:1100
-    pci_dev->config_header.subsystem_vendor_id = 0x1AF4;
-    pci_dev->config_header.subsystem_id = 0x1100;
-    //pci_dev->config_header.header_type = 0x00;
-    pci_dev->config_header.command = 0x03;
-    video_state->pci_dev = pci_dev;
-  }
-#endif
-  return 0;
-}
-
-device_register("VIDEO", video_init)
-
-
-/*
-#if PCI_ENABLED
-struct vm_device * v3_create_video(struct vm_device * pci_bus) {
-
-#else
-struct vm_device * v3_create_video() {
-#endif
-  PrintDebug("Video Print Debug in create\n");
-
-  PrintDebug("Video, before initial \n");
-
-  struct video_internal * video_state = NULL;
-
-  video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
-
-  PrintDebug("video: internal at %p\n", (void *)video_state);
-
- struct vm_device * device = v3_create_device("VIDEO", &dev_ops, video_state);
-
-#if PCI_ENABLED
-  if(pci_bus != NULL){
-    video_state->pci_bus = pci_bus;
-  }
-#endif
-
- return device;
-}
-*/
-
index af45a0a..1cadad7 100644 (file)
@@ -39,7 +39,7 @@
 #include <devices/ram_hd.h>
 #include <devices/net_hd.h>
 
-#include <devices/video.h>
+#include <devices/telnet_cons.h>
 
 
 
@@ -57,7 +57,7 @@ static int configure_generic(struct guest_info * info, struct v3_vm_config * con
 
 
 
-#ifndef CONFIG_VIDEO
+#ifdef CONFIG_PASSTHROUGH_VIDEO
 static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
 
     return length;
@@ -178,7 +178,7 @@ int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_
  */
 static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
 
-#ifndef CONFIG_VIDEO
+#ifdef CONFIG_PASSTHROUGH_VIDEO
     PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
     
     // VGA frame buffer
@@ -244,6 +244,11 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
     v3_create_device(info, "VMNET", NULL);
     
 
+    v3_create_device(info, "CGA_VIDEO", (void *)1);
+    {
+       struct telnet_cons_cfg cons_cfg = {"CGA_VIDEO", 19997};
+       v3_create_device(info, "TELNET_CONSOLE", &cons_cfg);
+    }
 
     if (config_ptr->enable_pci == 1) {
        struct ide_cfg ide_config = {"PCI", "PIIX3"};
@@ -258,8 +263,6 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
        v3_create_device(info, "LNX_VIRTIO_BALLOON", "PCI");
        v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK");
 
-       v3_create_device(info, "VIDEO", "PCI");
-
        v3_create_device(info, "IDE", &ide_config);
     } else {
        v3_create_device(info, "IDE", NULL);
@@ -447,7 +450,7 @@ static int configure_generic(struct guest_info * info, struct v3_vm_config * con
 
 #endif
 
-#ifndef CONFIG_VIDEO
+#ifdef CONFIG_PASTHROUGH_VIDEO
 
     // Monitor graphics card operations
     
index ba6e9c5..9ed9102 100644 (file)
@@ -327,7 +327,7 @@ int v3_handle_cr3_write(struct guest_info * info) {
                    PrintError("Failed to activate 32 bit shadow page table\n");
                    return -1;
                }
-           } 
+           }
            
            PrintDebug("New Shadow CR3=%p; New Guest CR3=%p\n", 
                       (void *)(addr_t)(info->ctrl_regs.cr3),