From: Steven Jaconette Date: Mon, 17 Aug 2009 19:48:41 +0000 (-0500) Subject: Virtual Console X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=701c70aa5e0c3122fb51e1b0f524d6e6b7be5e74 Virtual Console --- diff --git a/palacios/include/devices/video.h b/palacios/include/devices/video.h new file mode 100644 index 0000000..cdb927d --- /dev/null +++ b/palacios/include/devices/video.h @@ -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) 2009, Robert Deloatch + * Copyright (c) 2009, Steven Jaconette + * Copyright (c) 2009, The V3VEE Project + * All rights reserved. + * + * Author: Robdert Deloatch + * Steven Jaconette + * + * 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__ + +#ifdef __V3VEE__ + + +//#include + +#include + +//struct vm_device * v3_create_video(); + +struct video_cfg { + char pci[32]; +}; + + +#endif // ! __V3VEE__ + +#endif diff --git a/palacios/src/devices/video.c b/palacios/src/devices/video.c new file mode 100644 index 0000000..2c5ff2f --- /dev/null +++ b/palacios/src/devices/video.c @@ -0,0 +1,1030 @@ +/* + * 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 + * Copyright (c) 2009, Steven Jaconette + * Copyright (c) 2009, The V3VEE Project + * All rights reserved. + * + * Author: Robdert Deloatch + * Steven Jaconette + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +/* #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;offsetstart_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; +} +*/ +