Palacios Public Git Repository

To checkout Palacios execute

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


telemetry updates
[palacios.git] / palacios / src / devices / video.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
14  *
15  * Author: Robdert Deloatch <rtdeloatch@gmail.com>
16  *         Steven Jaconette <stevenjaconette2007@u.northwestern.edu>
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22
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>
36
37
38
39 /* #ifndef DEBUG_VIDEO */
40 /* #undef PrintDebug */
41 /* #define PrintDebug(fmt, args...) */
42 /* #endif */
43
44
45 #define START_ADDR 0xA0000    //0xB0000   //Attempting to hook entire region
46 #define END_ADDR 0xC0000     //0xC0000//(START_ADDR + ROWS * COLS * DEPTH) 
47
48 #define SIZE_OF_REGION (END_ADDR-START_ADDR)
49
50 #define PCI_ENABLED 1
51
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
56 #define PASSTHROUGH 1
57 #define PORT 19997
58
59 #define NO_CODE 0
60 #define PORT_OFFSET 0x3B0
61
62 #define ESC_CHAR          ((unsigned char)0x1b)
63
64 struct key_code {
65   char scan_code;
66   uint_t capital;
67 };
68
69 #define NO_KEY { NO_CODE, 0 }
70
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
104 };
105
106 struct get_keys_arg {
107   struct guest_info * info;
108   int fd;
109 };
110
111 struct video_internal {
112   addr_t video_memory_pa;
113   uchar_t * video_memory;
114
115 #if PCI_ENABLED
116   struct vm_device * pci_bus;
117   struct pci_device * pci_dev;
118 #endif
119
120   int socket_fd;
121   int client_fd;
122
123   struct get_keys_arg key_arg;
124
125   uint_t screen_bottom;
126   uint_t ports[44];
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;
132   
133   uchar_t reg_3D5[0x19];
134
135   uint_t high_addr;
136   uint_t low_addr;
137 };
138
139 void video_do_in(ushort_t port, void *src, uint_t length){
140    #if PASSTHROUGH
141    uint_t i;
142     
143     switch (length) {
144         case 1:
145             ((uchar_t*)src)[0] = v3_inb(port);
146             break;
147         case 2:
148             ((ushort_t*)src)[0] = v3_inw(port);
149             break;
150         case 4:
151             ((uint_t*)src)[0] = v3_indw(port);
152             break;
153         default:
154             for (i = 0; i < length; i++) { 
155                 ((uchar_t*)src)[i] = v3_inb(port);
156             }
157     }//switch length
158     #endif
159 }
160
161 void video_do_out(ushort_t port, void * src, uint_t length){
162   #if PASSTHROUGH
163   uint_t i;
164   switch (length) {
165         case 1:
166             v3_outb(port,((uchar_t*)src)[0]);
167             break;
168         case 2:
169             v3_outw(port,((ushort_t*)src)[0]);
170             break;
171         case 4:
172             v3_outdw(port,((uint_t*)src)[0]);
173             break;
174         default:
175             for (i = 0; i < length; i++) { 
176                 v3_outb(port, ((uchar_t*)src)[i]);
177             }
178     } //switch length
179   #endif
180 }
181
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;
191    if(cap) {
192        if(v3_deliver_keyboard_event(args->info, &key_shift) == -1) {
193            PrintError("Video: Error delivering key event\n");
194            return -1;
195        }
196    }
197    // Press
198    if(v3_deliver_keyboard_event(args->info, &key_event) == -1) {
199        PrintError("Video: Error delivering key event\n");
200        return -1;
201    }
202    // Release
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");
207            return -1;
208        }
209     }
210     if(cap) {
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");
214             return -1;
215         }
216     }
217     PrintDebug("Finished with Key delivery\n");
218     return 0;
219 }
220
221 static int get_keys(void * arg) {
222   struct get_keys_arg * args =  &(((struct video_internal *)arg)->key_arg);
223   while(1) {
224     PrintDebug("Get keys loop start\n");
225     uint_t cap;
226     char key[1];
227     memset(key, 0, 1);
228
229     int recv = V3_Recv(args->fd, key, 1);
230     if(recv == -1){
231       PrintError("Video: Error getting key from network\n");
232     }
233     else if(recv == 0){
234       PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
235       break;
236     }
237
238     uint_t i;
239     for(i = 0; i < 1; i++) {
240       cap = 0;
241       uchar_t ascii = (uchar_t)key[i];
242       
243       if(ascii == 0) {
244         PrintDebug("Recieved ASCII NULL character\n");
245         break;
246       }
247
248       PrintDebug("Character recieved: 0x%x\n", ascii);
249       if(ascii < 0x80) {
250         key[i] = ascii_to_key_code[ascii].scan_code;
251         cap = ascii_to_key_code[ascii].capital;
252         if(key[i]) {
253           // Special Terminal Escape Sequences (UP, DOWN, LEFT, RIGHT) 
254           if(key[i] == 0x01) {
255             int j;
256             int esc = 0;
257             for(j = 0; j < 2; j++) {
258               int recv2 = V3_Recv(args->fd, key, 1);
259               if(recv2 == -1){
260                 PrintDebug("Video: Error getting key from network\n");
261                 break;
262               }
263               else if(recv2 == 0){
264                 PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
265                 break;
266               }
267               if(key[0] == '[') {
268                 esc = 1;
269               }
270               // UP ARROW
271               if(esc == 1 && key[0] == 'A') {
272                 struct key_code up = { 0x48, 0 };
273                 deliver_scan_code(args, &up);
274               }
275               // DOWN ARROW
276               if(esc == 1 && key[0] == 'B') {
277                 struct key_code down = { 0x50, 0 };
278                 deliver_scan_code(args, &down);
279               }
280               // RIGHT ARROW
281               if(esc == 1 && key[0] == 'C') {
282                 struct key_code right = { 0x4D, 0 };
283                 deliver_scan_code(args, &right);
284               }
285               // LEFT ARROW
286               if(esc == 1 && key[0] == 'D') {
287                 struct key_code left = { 0x4B, 0 };
288                 deliver_scan_code(args, &left);
289               }
290             }
291             break;
292           }
293           else if(key[i] == 0x1D){
294             int recv2 = V3_Recv(args->fd, key, 1);
295             if(recv2 == -1){
296               PrintDebug("Video: Error getting key from network\n");
297             }
298             else if(recv2 == 0){
299               PrintDebug("Video: Client Disconnected (FD=%d)\n", args->fd);
300             }
301             break;
302           }
303           else {
304             struct key_code k = { ascii_to_key_code[ascii].scan_code, ascii_to_key_code[ascii].capital };
305             deliver_scan_code(args, &k);
306           }
307         }
308         else {
309           break;
310         }
311       }
312     }
313   }
314   return 0;
315 }
316
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) {
321     int written = 0;
322     if((written = V3_Send(sock, buf + (len-bytes_left), bytes_left)) == -1) {
323       return -1;
324     }
325     bytes_left -= written;
326   }
327   return 0;
328 }
329 #endif
330
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
334 };
335
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
338 };
339
340 #if SEND_UPDATE_INCREMENTAL_VT100
341 static unsigned char * append_char_as_digits(unsigned char *s, unsigned char c)
342 {
343   if (c/100) { 
344     *s++ = '0'+ c/100;
345   }
346   c %= 100;
347   if (c/10) { 
348     *s++= '0' + c/10;
349   }
350   c %= 10;
351   *s++ = '0'+ c;
352   return s;
353 }
354
355
356 static unsigned char * append_write_attribute_at(unsigned char *s, unsigned char  x, unsigned char  y, unsigned char c) 
357 {
358   // Update cursor
359   *s++ = ESC_CHAR;
360   *s++ = '[';
361   s = append_char_as_digits(s,y+1);
362   *s++ = ';';
363   s = append_char_as_digits(s,x+1);
364   *s++ = 'H';
365   
366   *s++ = ESC_CHAR;
367   *s++ = '[';
368   *s++ = '0';
369   *s++ = 'm';
370
371   // Update attribute
372   unsigned char fg_color = 0;
373   unsigned char bg_color = 0;
374
375   *s++ = ESC_CHAR;
376   *s++ = '[';
377   unsigned char low = c & 0x0F;
378   unsigned char high = (c & 0xF0) >> 4;
379   low = low % 16;
380   fg_color = text_mode_fg_color[low];
381   s = append_char_as_digits(s,fg_color);
382   *s++ = '\x3b';
383   high = high % 16;
384   bg_color = text_mode_bg_color[high];
385   s = append_char_as_digits(s,bg_color);
386   *s++ = 'm';
387   return s;
388 }
389
390 static unsigned char * append_write_char_at(unsigned char *s, unsigned char x, unsigned char y, unsigned char c) {
391   *s++ = ESC_CHAR;
392   *s++ = '[';
393   s = append_char_as_digits(s,y+1);
394   *s++ = ';';
395   s = append_char_as_digits(s,x+1);
396   *s++ = 'H';
397   *s++ = c;
398   return s;
399 }
400 #endif
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);
404
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;
408
409 #if 1  
410   PrintDebug("Write offset: 0x%p\n", (void*)write_offset);
411   
412   {
413     int i;
414     PrintDebug("Video_Memory: ");
415     for(i = 0; i < length; i += 2){
416       PrintDebug("%c",((char *)(V3_VAddr((void*)guest_addr)))[i]);
417     }
418   }
419 #endif
420  
421   memcpy(data->video_memory + write_offset, V3_VAddr((void*)guest_addr), length);
422
423 #if SEND_UPDATE_RAW
424   send_all(data, data->client_fd, (char *)(data->video_memory + write_offset), length);
425 #endif
426
427 #if SEND_UPDATE_INCREMENTAL_VT100
428  
429   unsigned char buf[32];
430   unsigned char *n;
431   unsigned char *a;
432   uint_t difference = 0x18000;
433
434
435   unsigned char x,y,c;
436   uint_t       offset;
437   uint_t l = length;
438
439   for (offset=0;offset<l;offset+=2){
440     memset(buf, 0, 32);
441     y = ((write_offset - difference - (data->start_addr_offset *2) + offset)/160) ;
442     if(y < 25){
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);
448       memset(buf, 0, 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);
452     }
453   }
454
455 #endif
456
457 #if SEND_UPDATE_ALL_VT100
458  
459   unsigned char buf[16];
460   unsigned char *n;
461
462   unsigned char x,y,c;
463   
464   for (y=0;y<25;y++) { 
465     for (x=0;x<80;x++) { 
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);
469     }
470   }
471 #endif
472   PrintDebug(" Done.\n"); 
473   return length;
474 }
475
476 static int video_read_port(ushort_t port,
477                                  void * dest,
478                                  uint_t length,
479                                  struct vm_device * dev) {
480   PrintDebug("Video: Read port 0x%x\n",port);
481   video_do_in(port, dest, length);
482   return length;
483 }
484
485 static int video_read_port_generic(ushort_t port,
486                                  void * dest,
487                                  uint_t length,
488                                  struct vm_device * dev) {
489   memset(dest, 0, length);
490   video_do_in(port, dest, length);
491   return length;
492 }
493
494
495 static int video_write_port(ushort_t port,
496                                  void * src,
497                                  uint_t length,
498                                  struct vm_device * dev) {
499
500   PrintDebug("Video: write port 0x%x...Wrote: ", port);
501   uint_t i;
502   for(i = 0; i < length; i++){
503     PrintDebug("%x", ((uchar_t*)src)[i]);
504   }
505   PrintDebug("...Done\n");
506   video_do_out(port, src, length);
507   return length;
508 }
509
510 static int video_write_port_store(ushort_t port,
511                                  void * src,
512                                  uint_t length,
513                                  struct vm_device * dev) {
514
515   PrintDebug("Entering video_write_port_store...port 0x%x\n", port);
516   uint_t i;
517   for(i = 0; i < length; i++){
518     PrintDebug("%x", ((uchar_t*)src)[i]);
519   }
520   PrintDebug("...Done\n"); 
521
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);
526   return length;
527 }
528
529 static int video_write_port_3D5(ushort_t port,
530                                  void * src,
531                                  uint_t length,
532                                  struct vm_device * dev) {
533   PrintDebug("Video: write port 0x%x...Wrote: ", port);
534   uint_t i;
535   for(i = 0; i < length; i++){
536     PrintDebug("%x", ((uchar_t*)src)[i]);
537   }
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);
542
543   uint_t index = video_state->ports[port - 1 - PORT_OFFSET];
544   memcpy(&(video_state->reg_3D5[index]), src, length);
545   uchar_t new_start;
546   switch(index) {
547      case 0x0c:
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);
551          break;
552      case 0x0d:
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;
556          if(diff > 0) {
557              for(diff /= 80; diff > 0; diff--){
558                  unsigned char message[2];
559                  memset(message, 0, 2);
560                  message[0] = ESC_CHAR;
561                  message[1] = 'D';
562                  send_all(video_state,video_state->client_fd, (char *)message, 2);
563              }
564          }
565          // Scroll Up?
566          break;
567      case 0x0E:
568        new_start = *((uchar_t *)src);
569        video_state->cursor_addr = new_start << 8;
570        break;
571      case 0x0F:
572        new_start = *((uchar_t *)src);
573        video_state->cursor_addr += new_start;
574        // Update cursor
575        unsigned char s[16];
576        memset(s, 0, 16);
577        unsigned char *n = s;
578        *n++ = ESC_CHAR;
579        *n++ = '[';
580        n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1);
581        *n++ = ';';
582        n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1);
583        *n++ = 'H';
584        send_all(video_state, video_state->client_fd, (char *)s, 16);
585        break;
586      default:
587          break;
588   }
589   video_do_out(port, src, length);
590   return length;
591 }
592
593
594 static int video_write_port_3C5(ushort_t port,
595                                  void * src,
596                                  uint_t length,
597                                 struct vm_device * dev) {
598   PrintDebug("Entering write_port_3C5....port 0x%x\n", port);
599   uint_t i;
600   for(i = 0; i < length; i++){
601     PrintDebug("%x", ((uchar_t*)src)[i]);
602   }
603   PrintDebug("...Done\n");
604
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); 
608
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);
612   return length;
613 }
614
615 static int video_write_port_3CF(ushort_t port,
616                                  void * src,
617                                  uint_t length,
618                                  struct vm_device * dev) {
619   PrintDebug("Entering write_port_3CF....port 0x%x\n", port);
620   uint_t i;
621   for(i = 0; i < length; i++){
622     PrintDebug("%x", ((uchar_t*)src)[i]);
623   }
624   PrintDebug("...Done\n");
625
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); 
629
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);
633   return length;
634 }
635
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;
639
640 #if 1
641
642   if(length == 1) {
643     video_state->ports[port - PORT_OFFSET] = 0;
644     memcpy(video_state->ports + (port - PORT_OFFSET), src, length); 
645   }
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);
651
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;
658     }
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);
663       // Update cursor
664       unsigned char s[16];
665       memset(s, 0, 16);
666       unsigned char *n = s;
667       *n++ = ESC_CHAR;
668       *n++ = '[';
669       n = append_char_as_digits(n,(((video_state->cursor_addr)/80))+1);
670       *n++ = ';';
671       n = append_char_as_digits(n,((video_state->cursor_addr)% 80)+1);
672       *n++ = 'H';
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);
677     }
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;
683     }
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;
687       if(diff > 0){
688 #if 1
689         for(diff /= 80; diff > 0; diff--){
690           unsigned char message[2];
691           memset(message, 0, 2);
692           message[0] = ESC_CHAR;
693           message[1] = 'D';
694           send_all(video_state,video_state->client_fd, (char *)message, 2);
695         }
696 #endif
697       }
698       //Still need to handle scroll up
699     }
700   }
701 #endif 
702   video_do_out(port, src, length);
703   return length;
704 }
705
706
707
708 #if PCI_ENABLED
709 static int video_write_mem_region(addr_t guest_addr, void * src, uint_t length, void * priv_data){
710  
711   struct vm_device * dev = (struct vm_device *) priv_data;
712   struct video_internal * data = (struct video_internal *) dev->private_data;
713  
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);
719   }
720
721   if(guest_addr > data->high_addr){
722     data->high_addr = guest_addr;
723   }
724   if(guest_addr < data->low_addr){
725     data->low_addr = guest_addr;
726   }
727   
728
729   PrintDebug("Video:  Within video_write_mem_region\n");
730
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);
734
735
736   //PrintDebug("Write Mem Value: ");
737   // PrintDebug("0x%x",*((uint32_t *)(V3_VAddr((void*)guest_addr))));
738   // PrintDebug("0x%x",*((uint32_t *)src));
739   /* 
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);
748   */
749
750   PrintDebug("\nLowest address written to...");
751   PrintDebug("0x%x",data->low_addr);
752
753   PrintDebug("\nHighest address written to...");
754   PrintDebug("0x%x\n",data->high_addr);
755
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);
762   }
763   else {
764     memset(V3_VAddr((void*)0xA0000),0,0x10000);
765     }*/
766   // memset(V3_VAddr((void *)(0xF0000000)), 5, 0x4affc);
767   //memset(V3_VAddr((void *)(0xF004affa)), 7, 0xF);
768
769   //Int i;
770   //PrintDebug("Write Mem Value: ");
771   //for(i = 0; i < length; i++){
772   //  PrintDebug("%x",((char *)(V3_VAddr((void*)guest_addr)))[i]);
773   //}
774
775   PrintDebug("\n...Done\n");
776
777   return length;
778 }
779
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");
782   return length;
783 }
784
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");
787   return length;
788 }
789
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");
792   return length;
793 }
794 #endif
795
796 static int video_free(struct vm_device * dev) {
797   v3_unhook_mem(dev->vm, START_ADDR);
798   return 0;
799 }
800
801 static int video_reset_device(struct vm_device * dev) {
802   PrintDebug("Video: reset device\n");
803   return 0;
804 }
805
806 static int video_start_device(struct vm_device * dev) {
807   PrintDebug("Video: start device\n");
808   return 0;
809 }
810
811 static int video_stop_device(struct vm_device * dev) {
812   PrintDebug("Video: stop device\n");
813   return 0;
814 }
815
816 static struct v3_device_ops dev_ops = {
817   .free = video_free,
818   .reset = video_reset_device,
819   .start = video_start_device,
820   .stop = video_stop_device,
821 };
822
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));
826
827  struct vm_device * dev = v3_allocate_device("VIDEO", &dev_ops, video_state);
828
829    if (v3_attach_device(vm, dev) == -1) {
830         PrintError("Could not attach device %s\n", "VIDEO");
831         return -1;
832     }
833
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);
837
838   memset(video_state->video_memory, 0, SIZE_OF_REGION);
839   PrintDebug("Video: hook io ports\n");
840 #if 1
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);
885 #endif
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);
889
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");
892     }
893    print_shadow_map(info);
894
895
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);
899
900 #if 1
901
902   if(V3_Bind_Socket(video_state->socket_fd, PORT) == -1) {
903     PrintError("Video: Failed to bind to socket %d\n", PORT);
904   }
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);
907   }
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);
919   }
920   PrintDebug("Video: Accept worked? FD= %d\n", video_state->client_fd);
921 #endif
922
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");
926
927   video_state->screen_bottom = 25;
928   PrintDebug("video: init complete\n");
929
930
931
932 #if PCI_ENABLED
933   if(video_state->pci_bus){
934     struct v3_pci_bar bars[6];
935     struct pci_device * pci_dev = NULL;
936
937     int i;
938     for(i = 0; i < 6; i++){
939       bars[i].type = PCI_BAR_NONE;
940     }
941
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));
945
946     bars[0].mem_read = video_read_mem_region;
947     bars[0].mem_write = video_write_mem_region;
948
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));
952     
953     bars[1].mem_read = video_read_io_region;
954     bars[1].mem_write = video_write_io_region;
955     //-1 Means autoassign
956     //                                                     Not sure if STD
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,
960                                      NULL, dev);
961
962     if (pci_dev == NULL) {
963         PrintError("Failed to register VIDEO %d with PCI\n", i);
964         return -1;
965     }
966     else{
967       PrintDebug("Registering PCI_VIDEO succeeded\n");
968     }
969     //Need to set some pci_dev->config_header.vendor_id type variables
970
971     pci_dev->config_header.vendor_id = 0x1013;
972     pci_dev->config_header.device_id = 0x00B8;
973     pci_dev->config_header.revision = 0x00;
974
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
979
980     //pci_dev->config_header.class = 0x00;
981     //pci_dev->config_header.subclass = 0x01;
982
983     pci_dev->config_header.class = 0x03;
984     pci_dev->config_header.subclass = 0x00;
985     pci_dev->config_header.prog_if = 0x00;
986
987
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;
994   }
995 #endif
996   return 0;
997 }
998
999 device_register("VIDEO", video_init)
1000
1001
1002 /*
1003 #if PCI_ENABLED
1004 struct vm_device * v3_create_video(struct vm_device * pci_bus) {
1005
1006 #else
1007 struct vm_device * v3_create_video() {
1008 #endif
1009   PrintDebug("Video Print Debug in create\n");
1010
1011   PrintDebug("Video, before initial \n");
1012
1013   struct video_internal * video_state = NULL;
1014
1015   video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
1016
1017   PrintDebug("video: internal at %p\n", (void *)video_state);
1018
1019  struct vm_device * device = v3_create_device("VIDEO", &dev_ops, video_state);
1020
1021 #if PCI_ENABLED
1022   if(pci_bus != NULL){
1023     video_state->pci_bus = pci_bus;
1024   }
1025 #endif
1026
1027  return device;
1028 }
1029 */
1030