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"
* 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
--- /dev/null
+/*
+ * 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
* 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
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
+
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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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)
+++ /dev/null
-/*
- * 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;
-}
-*/
-
#include <devices/ram_hd.h>
#include <devices/net_hd.h>
-#include <devices/video.h>
+#include <devices/telnet_cons.h>
-#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;
*/
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
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"};
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);
#endif
-#ifndef CONFIG_VIDEO
+#ifdef CONFIG_PASTHROUGH_VIDEO
// Monitor graphics card operations
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),