2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2009, Robert Deloatch <rtdeloatch@gmail.com>
11 * Copyright (c) 2009, Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
12 * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Robdert Deloatch <rtdeloatch@gmail.com>
16 * Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
23 #include <devices/video.h>
24 #include <palacios/vmm.h>
25 #include <palacios/vmm_emulator.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vm_guest_mem.h>
28 #include <palacios/vmm_decoder.h>
29 #include <palacios/vmm_paging.h>
30 #include <palacios/vmm_instr_emulator.h>
31 #include <palacios/vm_guest_mem.h>
32 #include <palacios/vmm_socket.h>
33 #include <palacios/vmm_host_events.h>
34 #include <devices/pci.h>
35 #include <devices/pci_types.h>
39 /* #ifndef DEBUG_VIDEO */
40 /* #undef PrintDebug */
41 /* #define PrintDebug(fmt, args...) */
45 #define START_ADDR 0xA0000 //0xB0000 //Attempting to hook entire region
46 #define END_ADDR 0xC0000 //0xC0000//(START_ADDR + ROWS * COLS * DEPTH)
48 #define SIZE_OF_REGION (END_ADDR-START_ADDR)
52 #define SEND_UPDATE_RAW 0
53 #define SEND_UPDATE_ALL_VT100 0
54 #define SEND_UPDATE_INCREMENTAL_VT100 1
55 #define SCROLLING_ENABLED 1
60 #define PORT_OFFSET 0x3B0
62 #define ESC_CHAR ((unsigned char)0x1b)
69 #define NO_KEY { NO_CODE, 0 }
71 static const struct key_code ascii_to_key_code[] = { // ASCII Value Serves as Index
72 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x00 - 0x03
73 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x04 - 0x07
74 { 0x0E, 0 }, { 0x0F, 0 }, NO_KEY, NO_KEY, // 0x08 - 0x0B
75 NO_KEY, { 0x1C, 0 }, NO_KEY, NO_KEY, // 0x0C - 0x0F
76 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x10 - 0x13
77 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x14 - 0x17
78 NO_KEY, NO_KEY, NO_KEY, { 0x01, 0 }, // 0x18 - 0x1B
79 NO_KEY, NO_KEY, NO_KEY, NO_KEY, // 0x1C - 0x1F
80 { 0x39, 0 }, { 0x02, 1 }, { 0x28, 1 }, { 0x04, 1 }, // 0x20 - 0x23
81 { 0x05, 1 }, { 0x06, 1 }, { 0x08, 1 }, { 0x28, 0 }, // 0x24 - 0x27
82 { 0x0A, 1 }, { 0x0B, 1 }, { 0x09, 1 }, { 0x0D, 1 }, // 0x28 - 0x2B
83 { 0x33, 0 }, { 0x0C, 0 }, { 0x34, 0 }, { 0x35, 0 }, // 0x2C - 0x2F
84 { 0x0B, 0 }, { 0x02, 0 }, { 0x03, 0 }, { 0x04, 0 }, // 0x30 - 0x33
85 { 0x05, 0 }, { 0x06, 0 }, { 0x07, 0 }, { 0x08, 0 }, // 0x34 - 0x37
86 { 0x09, 0 }, { 0x0A, 0 }, { 0x27, 1 }, { 0x27, 0 }, // 0x38 - 0x3B
87 { 0x33, 1 }, { 0x0D, 0 }, { 0x34, 1 }, { 0x35, 1 }, // 0x3C - 0x3F
88 { 0x03, 1 }, { 0x1E, 1 }, { 0x30, 1 }, { 0x2E, 1 }, // 0x40 - 0x43
89 { 0x20, 1 }, { 0x12, 1 }, { 0x21, 1 }, { 0x22, 1 }, // 0x44 - 0x47
90 { 0x23, 1 }, { 0x17, 1 }, { 0x24, 1 }, { 0x25, 1 }, // 0x48 - 0x4B
91 { 0x26, 1 }, { 0x32, 1 }, { 0x31, 1 }, { 0x18, 1 }, // 0x4C - 0x4F
92 { 0x19, 1 }, { 0x10, 1 }, { 0x13, 1 }, { 0x1F, 1 }, // 0x50 - 0x53
93 { 0x14, 1 }, { 0x16, 1 }, { 0x2F, 1 }, { 0x11, 1 }, // 0x54 - 0x57
94 { 0x2D, 1 }, { 0x15, 1 }, { 0x2C, 1 }, { 0x1A, 0 }, // 0x58 - 0x5B
95 { 0x2B, 0 }, { 0x1B, 0 }, { 0x07, 1 }, { 0x0C, 1 }, // 0x5C - 0x5F
96 { 0x29, 0 }, { 0x1E, 0 }, { 0x30, 0 }, { 0x2E, 0 }, // 0x60 - 0x63
97 { 0x20, 0 }, { 0x12, 0 }, { 0x21, 0 }, { 0x22, 0 }, // 0x64 - 0x67
98 { 0x23, 0 }, { 0x17, 0 }, { 0x24, 0 }, { 0x25, 0 }, // 0x68 - 0x6B
99 { 0x26, 0 }, { 0x32, 0 }, { 0x31, 0 }, { 0x18, 0 }, // 0x6C - 0x6F
100 { 0x19, 0 }, { 0x10, 0 }, { 0x13, 0 }, { 0x1F, 0 }, // 0x70 - 0x73
101 { 0x14, 0 }, { 0x16, 0 }, { 0x2F, 0 }, { 0x11, 0 }, // 0x74 - 0x77
102 { 0x2D, 0 }, { 0x15, 0 }, { 0x2C, 0 }, { 0x1A, 1 }, // 0x78 - 0x7B
103 { 0x2B, 1 }, { 0x1B, 1 }, { 0x29, 1 }, { 0x0E, 0 } // 0x7C - 0x7F
106 struct get_keys_arg {
107 struct guest_info * info;
111 struct video_internal {
112 addr_t video_memory_pa;
113 uchar_t * video_memory;
116 struct vm_device * pci_bus;
117 struct pci_device * pci_dev;
123 struct get_keys_arg key_arg;
125 uint_t screen_bottom;
127 uchar_t reg_3C4[0x100];
128 uchar_t reg_3CE[0x100];
129 ushort_t start_addr_offset;
130 ushort_t old_start_addr_offset;
131 ushort_t cursor_addr;
133 uchar_t reg_3D5[0x19];
139 void video_do_in(ushort_t port, void *src, uint_t length){
145 ((uchar_t*)src)[0] = v3_inb(port);
148 ((ushort_t*)src)[0] = v3_inw(port);
151 ((uint_t*)src)[0] = v3_indw(port);
154 for (i = 0; i < length; i++) {
155 ((uchar_t*)src)[i] = v3_inb(port);
161 void video_do_out(ushort_t port, void * src, uint_t length){
166 v3_outb(port,((uchar_t*)src)[0]);
169 v3_outw(port,((ushort_t*)src)[0]);
172 v3_outdw(port,((uint_t*)src)[0]);
175 for (i = 0; i < length; i++) {
176 v3_outb(port, ((uchar_t*)src)[i]);
182 static int deliver_scan_code(struct get_keys_arg * args, struct key_code * k) {
183 uint_t cap = k->capital;
184 struct v3_keyboard_event key_event;
185 key_event.status = 0;
186 key_event.scan_code = (unsigned char)k->scan_code;
187 PrintDebug("Scan code: 0x%x\n", key_event.scan_code);
188 struct v3_keyboard_event key_shift;
189 key_shift.status = 0;
190 key_shift.scan_code = (unsigned char)0x2A;
192 if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) {
193 PrintError("Video: Error delivering key event\n");
198 if(v3_deliver_keyboard_event(args->info, &key_event) == -1) {
199 PrintError("Video: Error delivering key event\n");
203 if(key_event.scan_code != 0x1c) {
204 key_event.scan_code = key_event.scan_code|0x80;
205 if(v3_deliver_keyboard_event(args->info, &key_event) == -1) {
206 PrintError("Video: Error delivering key event\n");
211 key_shift.scan_code = 0x2A|0x80;
212 if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) {
213 PrintError("Video: Error delivering key event\n");
217 PrintDebug("Finished with Key delivery\n");
221 static int get_keys(void * arg) {
222 struct get_keys_arg * args = &(((struct video_internal *)arg)->key_arg);
224 PrintDebug("Get keys loop start\n");
229 int recv = V3_Recv(args->fd, key, 1);
231 PrintError("Video: Error getting key from network\n");
234 PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
239 for(i = 0; i < 1; i++) {
241 uchar_t ascii = (uchar_t)key[i];
244 PrintDebug("Recieved ASCII NULL character\n");
248 PrintDebug("Character recieved: 0x%x\n", ascii);
250 key[i] = ascii_to_key_code[ascii].scan_code;
251 cap = ascii_to_key_code[ascii].capital;
253 // Special Terminal Escape Sequences (UP, DOWN, LEFT, RIGHT)
257 for(j = 0; j < 2; j++) {
258 int recv2 = V3_Recv(args->fd, key, 1);
260 PrintDebug("Video: Error getting key from network\n");
264 PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
271 if(esc == 1 && key[0] == 'A') {
272 struct key_code up = { 0x48, 0 };
273 deliver_scan_code(args, &up);
276 if(esc == 1 && key[0] == 'B') {
277 struct key_code down = { 0x50, 0 };
278 deliver_scan_code(args, &down);
281 if(esc == 1 && key[0] == 'C') {
282 struct key_code right = { 0x4D, 0 };
283 deliver_scan_code(args, &right);
286 if(esc == 1 && key[0] == 'D') {
287 struct key_code left = { 0x4B, 0 };
288 deliver_scan_code(args, &left);
293 else if(key[i] == 0x1D){
294 int recv2 = V3_Recv(args->fd, key, 1);
296 PrintDebug("Video: Error getting key from network\n");
299 PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
304 struct key_code k = { ascii_to_key_code[ascii].scan_code, ascii_to_key_code[ascii].capital };
305 deliver_scan_code(args, &k);
317 #if SEND_UPDATE_INCREMENTAL_VT100
318 static int send_all(struct video_internal * data, const int sock, const char * buf, const int len){
319 int bytes_left = len;
320 while(bytes_left != 0) {
322 if((written = V3_Send(sock, buf + (len-bytes_left), bytes_left)) == -1) {
325 bytes_left -= written;
331 // Translate attribute color into terminal escape sequence color
332 static unsigned char text_mode_fg_color[] = {
333 30, 34, 32, 36, 31, 35, 33, 37, 90, 94, 92, 96, 91, 95, 93, 97
336 static unsigned char text_mode_bg_color[] = {
337 40, 44, 42, 46, 41, 45, 43, 47, 100, 104, 102, 106, 101, 105, 103, 107
340 #if SEND_UPDATE_INCREMENTAL_VT100
341 static unsigned char * append_char_as_digits(unsigned char *s, unsigned char c)
356 static unsigned char * append_write_attribute_at(unsigned char *s, unsigned char x, unsigned char y, unsigned char c)
361 s = append_char_as_digits(s,y+1);
363 s = append_char_as_digits(s,x+1);
372 unsigned char fg_color = 0;
373 unsigned char bg_color = 0;
377 unsigned char low = c & 0x0F;
378 unsigned char high = (c & 0xF0) >> 4;
380 fg_color = text_mode_fg_color[low];
381 s = append_char_as_digits(s,fg_color);
384 bg_color = text_mode_bg_color[high];
385 s = append_char_as_digits(s,bg_color);
390 static unsigned char * append_write_char_at(unsigned char *s, unsigned char x, unsigned char y, unsigned char c) {
393 s = append_char_as_digits(s,y+1);
395 s = append_char_as_digits(s,x+1);
401 static int video_write_mem(addr_t guest_addr, void * dest, uint_t length, void * priv_data) {
402 PrintDebug("\n\nInside Video Write Memory.\n\n");
403 PrintDebug("Guest address: 0x%x length = %d\n", (uint_t)guest_addr, length);
405 struct vm_device * dev = (struct vm_device *) priv_data;
406 struct video_internal * data = (struct video_internal *) dev->private_data;
407 addr_t write_offset = guest_addr - START_ADDR;
410 PrintDebug("Write offset: 0x%p\n", (void*)write_offset);
414 PrintDebug("Video_Memory: ");
415 for(i = 0; i < length; i += 2){
416 PrintDebug("%c",((char *)(V3_VAddr((void*)guest_addr)))[i]);
421 memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length);
424 send_all(data, data->client_fd, (char *)(data->video_memory + write_offset), length);
427 #if SEND_UPDATE_INCREMENTAL_VT100
429 unsigned char buf[32];
432 uint_t difference = 0x18000;
439 for (offset=0;offset<l;offset+=2){
441 y = ((write_offset - difference - (data->start_addr_offset *2) + offset)/160) ;
443 // PrintDebug(" Video: Y value = %d ", y);
444 x = ((write_offset - difference + offset)%160)/2;
445 c = (data->video_memory + difference + data->start_addr_offset * 2)[y*160+x*2+1];
446 a = append_write_attribute_at(buf,x,y,c);
447 send_all(data,data->client_fd, (char*)buf, 32);
449 c = (data->video_memory + difference + data->start_addr_offset * 2)[y*160+x*2];
450 n = append_write_char_at(buf,x,y,c);
451 send_all(data,data->client_fd, (char *)buf, 32);
457 #if SEND_UPDATE_ALL_VT100
459 unsigned char buf[16];
466 c = data->video_memory[y*160+x*2];
467 n = append_write_char_at(buf,x,y,c);
468 send_all(data,data->client_fd, (char *)buf, n-buf);
472 PrintDebug(" Done.\n");
476 static int video_read_port(ushort_t port,
479 struct vm_device * dev) {
480 PrintDebug("Video: Read port 0x%x\n",port);
481 video_do_in(port, dest, length);
485 static int video_read_port_generic(ushort_t port,
488 struct vm_device * dev) {
489 memset(dest, 0, length);
490 video_do_in(port, dest, length);
495 static int video_write_port(ushort_t port,
498 struct vm_device * dev) {
500 PrintDebug("Video: write port 0x%x...Wrote: ", port);
502 for(i = 0; i < length; i++){
503 PrintDebug("%x", ((uchar_t*)src)[i]);
505 PrintDebug("...Done\n");
506 video_do_out(port, src, length);
510 static int video_write_port_store(ushort_t port,
513 struct vm_device * dev) {
515 PrintDebug("Entering video_write_port_store...port 0x%x\n", port);
517 for(i = 0; i < length; i++){
518 PrintDebug("%x", ((uchar_t*)src)[i]);
520 PrintDebug("...Done\n");
522 struct video_internal * video_state = (struct video_internal *)dev->private_data;
523 video_state->ports[port - PORT_OFFSET] = 0;
524 memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
525 video_do_out(port, src, length);
529 static int video_write_port_3D5(ushort_t port,
532 struct vm_device * dev) {
533 PrintDebug("Video: write port 0x%x...Wrote: ", port);
535 for(i = 0; i < length; i++){
536 PrintDebug("%x", ((uchar_t*)src)[i]);
538 PrintDebug("...Done\n");
539 struct video_internal * video_state = (struct video_internal *)dev->private_data;
540 video_state->ports[port - PORT_OFFSET] = 0;
541 memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
543 uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
544 memcpy(&(video_state->reg_3D5[index]), src, length);
548 video_state->old_start_addr_offset = video_state->start_addr_offset;
549 new_start = *((uchar_t *)src);
550 video_state->start_addr_offset = (new_start << 8);
553 new_start = *((uchar_t *)src);
554 video_state->start_addr_offset += new_start;
555 int diff = video_state->start_addr_offset - video_state->old_start_addr_offset;
557 for(diff /= 80; diff > 0; diff--){
558 unsigned char message[2];
559 memset(message, 0, 2);
560 message[0] = ESC_CHAR;
562 send_all(video_state,video_state->client_fd, (char *)message, 2);
568 new_start = *((uchar_t *)src);
569 video_state->cursor_addr = new_start << 8;
572 new_start = *((uchar_t *)src);
573 video_state->cursor_addr += new_start;
577 unsigned char *n = s;
580 n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1);
582 n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1);
584 send_all(video_state, video_state->client_fd, (char *)s, 16);
589 video_do_out(port, src, length);
594 static int video_write_port_3C5(ushort_t port,
597 struct vm_device * dev) {
598 PrintDebug("Entering write_port_3C5....port 0x%x\n", port);
600 for(i = 0; i < length; i++){
601 PrintDebug("%x", ((uchar_t*)src)[i]);
603 PrintDebug("...Done\n");
605 struct video_internal * video_state = (struct video_internal *)dev->private_data;
606 video_state->ports[port - PORT_OFFSET] = 0;
607 memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
609 uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
610 memcpy(&(video_state->reg_3C4[index]), src, length);
611 video_do_out(port, src, length);
615 static int video_write_port_3CF(ushort_t port,
618 struct vm_device * dev) {
619 PrintDebug("Entering write_port_3CF....port 0x%x\n", port);
621 for(i = 0; i < length; i++){
622 PrintDebug("%x", ((uchar_t*)src)[i]);
624 PrintDebug("...Done\n");
626 struct video_internal * video_state = (struct video_internal *)dev->private_data;
627 video_state->ports[port - PORT_OFFSET] = 0;
628 memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
630 uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
631 memcpy(&(video_state->reg_3CE[index]), src, length);
632 video_do_out(port, src, length);
636 static int video_write_port_3D4(ushort_t port, void *src, uint_t length,
637 struct vm_device *dev){
638 struct video_internal *video_state = (struct video_internal *) dev -> private_data;
643 video_state->ports[port - PORT_OFFSET] = 0;
644 memcpy(video_state->ports + (port - PORT_OFFSET), src, length);
646 else if(length == 2){
647 ushort_t new_start = 0;
648 ushort_t cursor_start = 0;
649 new_start = *((ushort_t *)src);
650 cursor_start = *((ushort_t *)src);
652 //Updating the cursor
653 if((cursor_start & 0x00FF) == 0x000E){
654 PrintDebug("Video: E Case cursor start = 0x%x\n", cursor_start);
655 cursor_start = (cursor_start & 0xFF00); //0x70
656 PrintDebug("Video: cursor start after and = 0x%x\n", cursor_start);
657 video_state->cursor_addr = cursor_start;
659 else if((cursor_start & 0x00FF) == 0x000F){
660 PrintDebug("Video: F Case cursor start = 0x%x\n", cursor_start);
661 PrintDebug("Cursor Address after: 0x%x\n", video_state->cursor_addr);
662 video_state->cursor_addr += ((cursor_start >> 8) & 0x00FF);
666 unsigned char *n = s;
669 n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1);
671 n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1);
673 PrintDebug("Cursor Address: 0x%x\n", video_state->cursor_addr);
674 PrintDebug("Cursor Y location should be: %d\n", ((video_state->cursor_addr)/80)+1);
675 PrintDebug("Cursor X location should be: %d\n",((video_state->cursor_addr % 80)/2)+1);
676 send_all(video_state, video_state->client_fd, (char *)s, 16);
678 //Checking to see if scrolling is needed
679 if((new_start & 0x00FF) == 0x000C){
680 video_state->old_start_addr_offset = video_state->start_addr_offset;
681 new_start = (new_start & 0xFF00);
682 video_state->start_addr_offset = new_start;
684 else if((new_start & 0x00FF) == 0x000D){
685 video_state->start_addr_offset += ((new_start >> 8) & 0x00FF);
686 int diff = video_state->start_addr_offset - video_state->old_start_addr_offset;
689 for(diff /= 80; diff > 0; diff--){
690 unsigned char message[2];
691 memset(message, 0, 2);
692 message[0] = ESC_CHAR;
694 send_all(video_state,video_state->client_fd, (char *)message, 2);
698 //Still need to handle scroll up
702 video_do_out(port, src, length);
709 static int video_write_mem_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){
711 struct vm_device * dev = (struct vm_device *) priv_data;
712 struct video_internal * data = (struct video_internal *) dev->private_data;
714 if(data->low_addr == 0){
715 data->low_addr = guest_addr;
716 //memset(V3_VAddr((void*)0xA0000),0,0x10000);
717 memset(V3_VAddr((void *)0xA000000),0, 0x4affc);
718 memset(V3_VAddr((void *)0xF0000000),0, 0x4affc);
721 if(guest_addr > data->high_addr){
722 data->high_addr = guest_addr;
724 if(guest_addr < data->low_addr){
725 data->low_addr = guest_addr;
729 PrintDebug("Video: Within video_write_mem_region\n");
731 PrintDebug("Length of write: %d\n", length);
732 PrintDebug("Guest Address of write: 0x%p\n", (void *)guest_addr);
733 //PrintDebug("\"Src Address\": 0x%p\n", (void *)src);
736 //PrintDebug("Write Mem Value: ");
737 // PrintDebug("0x%x",*((uint32_t *)(V3_VAddr((void*)guest_addr))));
738 // PrintDebug("0x%x",*((uint32_t *)src));
740 unsigned char message[4];
741 memset(message, 0, 4);
742 message[0] = (*((char *)(V3_VAddr((void*)guest_addr))));
743 message[1] = (*((char *)(V3_VAddr((void*)guest_addr) + 1)));
744 message[2] = (*((char *)(V3_VAddr((void*)guest_addr) + 2)));
745 message[3] = (*((char *)(V3_VAddr((void*)guest_addr) + 3)));
746 PrintDebug("Character Value: %s\n", message);
747 //send_all(data,data->client_fd, (char *)message, 4);
750 PrintDebug("\nLowest address written to...");
751 PrintDebug("0x%x",data->low_addr);
753 PrintDebug("\nHighest address written to...");
754 PrintDebug("0x%x\n",data->high_addr);
756 // memcpy(V3_VAddr((void*)0xF0000000), V3_VAddr((void*)guest_addr) , length);
757 //addr_t write_offset = guest_addr - 0xA000000;// % 0x20000; // (guest_addr - 0xA000000);// % 0x20000
758 // PrintDebug("0x%x",*((uint32_t *)(src + )));
759 //memcpy(V3_VAddr((void *)(0xF0000000 + write_offset)), src, length);
760 /*If(write_offset < 0x10000) {
761 memcpy(V3_VAddr((void *)(START_ADDR + write_offset)), V3_VAddr((void*)guest_addr) , length);
764 memset(V3_VAddr((void*)0xA0000),0,0x10000);
766 // memset(V3_VAddr((void *)(0xF0000000)), 5, 0x4affc);
767 //memset(V3_VAddr((void *)(0xF004affa)), 7, 0xF);
770 //PrintDebug("Write Mem Value: ");
771 //for(i = 0; i < length; i++){
772 // PrintDebug("%x",((char *)(V3_VAddr((void*)guest_addr)))[i]);
775 PrintDebug("\n...Done\n");
780 static int video_read_mem_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){
781 PrintDebug("Video: Within video_read_mem_region\n");
785 static int video_write_io_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){
786 PrintDebug("Video: Within video_write_io_region\n");
790 static int video_read_io_region(addr_t guest_addr, void * dest, uint_t length, void * priv_data){
791 PrintDebug("Video: Within video_read_io_region\n");
796 static int video_free(struct vm_device * dev) {
797 v3_unhook_mem(dev->vm, START_ADDR);
801 static int video_reset_device(struct vm_device * dev) {
802 PrintDebug("Video: reset device\n");
806 static int video_start_device(struct vm_device * dev) {
807 PrintDebug("Video: start device\n");
811 static int video_stop_device(struct vm_device * dev) {
812 PrintDebug("Video: stop device\n");
816 static struct v3_device_ops dev_ops = {
818 .reset = video_reset_device,
819 .start = video_start_device,
820 .stop = video_stop_device,
823 static int video_init(struct guest_info * vm, void * cfg_data){
824 PrintDebug("video: init_device\n");
825 struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
827 struct vm_device * dev = v3_allocate_device("VIDEO", &dev_ops, video_state);
829 if (v3_attach_device(vm, dev) == -1) {
830 PrintError("Could not attach device %s\n", "VIDEO");
834 PrintDebug("Num Pages=%d\n", SIZE_OF_REGION / 4096);
835 video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096);
836 video_state->video_memory = V3_VAddr((void*)video_state->video_memory_pa);
838 memset(video_state->video_memory, 0, SIZE_OF_REGION);
839 PrintDebug("Video: hook io ports\n");
841 v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
842 v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
843 v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
844 v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
845 v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
846 v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
847 v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
848 v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
849 v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
850 v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
851 v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
852 v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
853 v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port_store);
854 v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
855 v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port_store);
856 v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
857 v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port_store);
858 v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port_3C5);
859 v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port_store);
860 v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
861 v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port_store);
862 v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port_store);
863 v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
864 v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
865 v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
866 v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
867 v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port_store);
868 v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port_3CF);
869 v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
870 v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
871 v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
872 v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
873 v3_dev_hook_io(dev, 0x3d4, &video_read_port, &video_write_port_3D4);
874 v3_dev_hook_io(dev, 0x3d5, &video_read_port, &video_write_port_3D5);
875 v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
876 v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
877 v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
878 v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
879 v3_dev_hook_io(dev, 0x3da, &video_read_port_generic, &video_write_port);
880 v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
881 v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
882 v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
883 v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
884 v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
886 PrintDebug("Video: End i/o hooks\n");
887 struct guest_info * info = vm;
888 PrintDebug("PA of array: %p\n", (void*)video_state->video_memory_pa);
890 if(v3_hook_write_mem(info, START_ADDR, END_ADDR, START_ADDR, &video_write_mem, dev) == -1){
891 PrintDebug("\n\nVideo Hook failed.\n\n");
893 print_shadow_map(info);
896 // Testing out network stuff
897 video_state->socket_fd = V3_Create_TCP_Socket();
898 PrintDebug("Video: Socket File Descriptor: %d\n", video_state->socket_fd);
902 if(V3_Bind_Socket(video_state->socket_fd, PORT) == -1) {
903 PrintError("Video: Failed to bind to socket %d\n", PORT);
905 if(V3_Listen_Socket(video_state->socket_fd, 10) == -1) {
906 PrintError("Video: Failed to listen with socket %d\n", video_state->socket_fd);
908 const char * ip_string = "10.10.10.138";
909 PrintDebug("Video: IP Address in string form: %s\n", ip_string);
910 uint32_t ip_h = v3_inet_addr(ip_string);
911 PrintDebug("Video: IP Address in host integer form: %x\n", ip_h);
912 uint32_t ip_n = v3_htonl(ip_h);
913 PrintDebug("Video: IP Address in network integer form %x\n", ip_n);
914 uint32_t port = PORT;
915 unsigned int ip_ptr = (ip_n);
916 unsigned int port_ptr = (port);
917 if((video_state->client_fd = V3_Accept_Socket(video_state->socket_fd, &ip_ptr, &port_ptr)) == -1) {
918 PrintDebug("Video: Failed to accept connection on port %d", PORT);
920 PrintDebug("Video: Accept worked? FD= %d\n", video_state->client_fd);
923 video_state->key_arg.info = info;
924 video_state->key_arg.fd = video_state->client_fd;
925 V3_CREATE_THREAD(get_keys,(void *)video_state, "Get Keys from Network");
927 video_state->screen_bottom = 25;
928 PrintDebug("video: init complete\n");
933 if(video_state->pci_bus){
934 struct v3_pci_bar bars[6];
935 struct pci_device * pci_dev = NULL;
938 for(i = 0; i < 6; i++){
939 bars[i].type = PCI_BAR_NONE;
942 bars[0].type = PCI_BAR_MEM32;
943 bars[0].num_pages = /*0x20000/0x1000;*/ 0x2000000/0x1000;
944 bars[0].default_base_addr = (addr_t)V3_VAddr((void *)0xF0000000);//(addr_t)V3_VAddr(V3_AllocPages(bars[0].num_pages));
946 bars[0].mem_read = video_read_mem_region;
947 bars[0].mem_write = video_write_mem_region;
949 bars[1].type = PCI_BAR_MEM32;
950 bars[1].num_pages = 1;
951 bars[1].default_base_addr = (addr_t)V3_VAddr(V3_AllocPages(bars[1].num_pages));
953 bars[1].mem_read = video_read_io_region;
954 bars[1].mem_write = video_write_io_region;
955 //-1 Means autoassign
957 pci_dev = v3_pci_register_device(video_state->pci_bus, PCI_STD_DEVICE, 0,
958 //or0 1st null could be pci_config_update
959 -1, 0, "VIDEO", bars, NULL, NULL,
962 if (pci_dev == NULL) {
963 PrintError("Failed to register VIDEO %d with PCI\n", i);
967 PrintDebug("Registering PCI_VIDEO succeeded\n");
969 //Need to set some pci_dev->config_header.vendor_id type variables
971 pci_dev->config_header.vendor_id = 0x1013;
972 pci_dev->config_header.device_id = 0x00B8;
973 pci_dev->config_header.revision = 0x00;
975 //If we treat video as a VGA device than below is correct
976 //If treated as a VGA compatible controller, which has mapping
977 //0xA0000-0xB0000 and I/O addresses 0x3B0-0x3BB than change
978 //#define from VGA to 0
980 //pci_dev->config_header.class = 0x00;
981 //pci_dev->config_header.subclass = 0x01;
983 pci_dev->config_header.class = 0x03;
984 pci_dev->config_header.subclass = 0x00;
985 pci_dev->config_header.prog_if = 0x00;
988 //We have a subsystem ID, but optional to provide: 1AF4:1100
989 pci_dev->config_header.subsystem_vendor_id = 0x1AF4;
990 pci_dev->config_header.subsystem_id = 0x1100;
991 //pci_dev->config_header.header_type = 0x00;
992 pci_dev->config_header.command = 0x03;
993 video_state->pci_dev = pci_dev;
999 device_register("VIDEO", video_init)
1004 struct vm_device * v3_create_video(struct vm_device * pci_bus) {
1007 struct vm_device * v3_create_video() {
1009 PrintDebug("Video Print Debug in create\n");
1011 PrintDebug("Video, before initial \n");
1013 struct video_internal * video_state = NULL;
1015 video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
1017 PrintDebug("video: internal at %p\n", (void *)video_state);
1019 struct vm_device * device = v3_create_device("VIDEO", &dev_ops, video_state);
1022 if(pci_bus != NULL){
1023 video_state->pci_bus = pci_bus;