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.


VGA support for host-driven rendering
[palacios.git] / palacios / src / devices / vga.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) 2011, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Peter Dinda <pdinda@northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_dev_mgr.h>
22 #include <palacios/vmm_types.h>
23 #include <palacios/vm_guest_mem.h>
24 #include <palacios/vmm_io.h>
25 #include <interfaces/vmm_graphics_console.h>
26
27 #include "vga_regs.h"
28
29 #ifndef V3_CONFIG_DEBUG_VGA
30 #undef PrintDebug
31 #define PrintDebug(fmt, args...)
32 #endif
33
34 #define DEBUG_MEM_DATA    0
35 #define DEBUG_DEEP_MEM    0
36 #define DEBUG_DEEP_RENDER 0
37
38
39 #define MEM_REGION_START 0xa0000
40 #define MEM_REGION_END   0xc0000
41 #define MEM_REGION_NUM_PAGES (((MEM_REGION_END)-(MEM_REGION_START))/4096)
42
43 #define MAP_SIZE 65536
44 #define MAP_NUM  4
45
46
47 typedef uint8_t *vga_map; // points to MAP_SIZE data
48
49 #define VGA_MAXX 1024
50 #define VGA_MAXY 768
51
52
53 #define VGA_MISC_OUT_READ 0x3cc
54 #define VGA_MISC_OUT_WRITE 0x3c2
55
56 #define VGA_INPUT_STAT0_READ 0x3c2
57
58 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
59 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
60
61 #define VGA_FEATURE_CONTROL_READ 0x3ca
62 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
63 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
64
65 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
66
67 #define VGA_SEQUENCER_ADDRESS 0x3c4
68 #define VGA_SEQUENCER_DATA 0x3c5
69 #define VGA_SEQUENCER_NUM 5
70
71
72 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
73 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
74 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
75 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
76 #define VGA_CRT_CONTROLLER_NUM 25
77
78
79 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
80 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
81 #define VGA_GRAPHICS_CONTROLLER_NUM 9
82
83 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
84 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
85 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
86
87 #define VGA_DAC_WRITE_ADDR 0x3c8
88 #define VGA_DAC_READ_ADDR 0x3c7
89 #define VGA_DAC_DATA 0x3c9
90 #define VGA_DAC_PIXEL_MASK 0x3c6
91
92 #define VGA_DAC_NUM_ENTRIES 256
93
94
95 #define VGA_FONT_WIDTH      8
96 #define VGA_MAX_FONT_HEIGHT 32
97
98 struct vga_render_model {
99   uint32_t   model;  // composite the following
100
101 #define VGA_DRIVEN_PERIODIC_RENDERING 0x1  // render after n GPU updates
102 #define CONSOLE_ADVISORY_RENDERING    0x2  // ask console if we should render following an update
103 #define CONSOLE_DRIVEN_RENDERING      0x4  // have console tell us when to render
104
105   uint32_t   updates_before_render;   // defaults to the following
106
107 #define DEFAULT_UPDATES_BEFORE_RENDER   1000
108 };
109
110 struct vga_misc_regs {
111     /* Read: 0x3cc; Write: 0x3c2 */
112     struct vga_misc_out_reg        vga_misc_out;
113     /* Read: 0x3c2 */
114     struct vga_input_stat0_reg     vga_input_stat0;
115     /* Read: 0x3?a  3ba for mono; 3da for cga set by misc.io_addr_sel */
116     struct vga_input_stat1_reg     vga_input_stat1; 
117     /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
118     struct vga_feature_control_reg vga_feature_control;
119     /* Read: 0x3c3; Write: 0x3c3 */
120     struct vga_video_subsys_enable_reg vga_video_subsys_enable;
121 } __attribute__((packed));
122
123 struct vga_sequencer_regs {
124     /*   Address register is 0x3c4, data register is 0x3c5 */
125     /* 0x3c4 */
126     struct vga_sequencer_addr_reg vga_sequencer_addr;
127
128     /* these can be accessed via the index, offset on start 
129        or via the specific regs.   For this reason, it is essential
130        that this is all packed and that the order does not change */
131     
132     uint8_t  vga_sequencer_regs[0];
133
134     /* Index 0 */
135     struct vga_reset_reg   vga_reset;
136     /* Index 1 */
137     struct vga_clocking_mode_reg vga_clocking_mode;
138     /* Index 2 */
139     struct vga_map_mask_reg vga_map_mask;
140     /* Index 3 */
141     struct vga_char_map_select_reg vga_char_map_select;
142     /* Index 4 */
143     struct vga_mem_mode_reg  vga_mem_mode;
144 } __attribute__((packed));
145
146 struct vga_crt_controller_regs {
147     /* Address Register is 0x3b4 or 0x3d4 */
148     /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
149     struct vga_crt_addr_reg vga_crt_addr;
150
151     /* these can be accessed via the index, offset on start 
152        or via the specific regs.   For this reason, it is essential
153        that this is all packed and that the order does not change */
154     
155     uint8_t  vga_crt_controller_regs[0];
156
157     /* index 0 */
158     vga_horizontal_total_reg vga_horizontal_total;
159     /* index 1 */
160     vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
161     /* index 2 */
162     vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
163     /* index 3 */
164     struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
165     /* index 4 */
166     vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
167     /* index 5 */
168     struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
169     /* index 6 */
170     vga_vertical_total_reg vga_vertical_total;
171     /* index 7 */
172     struct vga_overflow_reg vga_overflow;
173     /* index 8 */
174     struct vga_preset_row_scan_reg vga_preset_row_scan;
175     /* index 9 */
176     struct vga_max_row_scan_reg vga_max_row_scan;
177     /* index 10 */
178     struct vga_cursor_start_reg vga_cursor_start;
179     /* index 11 */
180     struct vga_cursor_end_reg vga_cursor_end;
181     /* index 12 */
182     vga_start_address_high_reg vga_start_address_high;
183     /* index 13 */
184     vga_start_address_low_reg vga_start_address_low;
185     /* index 14 */
186     vga_cursor_location_high_reg vga_cursor_location_high;
187     /* index 15 */
188     vga_cursor_location_low_reg vga_cursor_location_low;
189     /* index 16 */
190     vga_vertical_retrace_start_reg vga_vertical_retrace_start;
191     /* index 17 */
192     struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
193     /* index 18 */
194     vga_vertical_display_enable_end_reg vga_vertical_display_enable_end;
195     /* index 19 */
196     vga_offset_reg vga_offset;
197     /* index 20 */
198     struct vga_underline_location_reg vga_underline_location;
199     /* index 21 */
200     vga_start_vertical_blanking_reg vga_start_vertical_blanking;
201     /* index 22 */
202     vga_end_vertical_blanking_reg vga_end_vertical_blanking;
203     /* index 23 */
204     struct vga_crt_mode_control_reg vga_crt_mode_control;
205     /* index 24 */
206     vga_line_compare_reg vga_line_compare;
207 } __attribute__((packed));
208
209 struct vga_graphics_controller_regs {
210     /*   Address: 0x3ce    Data: 0x3cf */
211
212     /* 0x3ce */
213     struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
214
215     /* these can be accessed via the index, offset on start 
216        or via the specific regs.   For this reason, it is essential
217        that this is all packed and that the order does not change */
218     
219     uint8_t  vga_graphics_controller_regs[0];
220
221     /* Index 0 */
222     struct vga_set_reset_reg vga_set_reset;
223     /* Index 1 */
224     struct vga_enable_set_reset_reg vga_enable_set_reset;
225     /* Index 2 */
226     struct vga_color_compare_reg vga_color_compare;
227     /* Index 3 */
228     struct vga_data_rotate_reg vga_data_rotate;
229     /* Index 4 */
230     struct vga_read_map_select_reg vga_read_map_select;
231     /* Index 5 */
232     struct vga_graphics_mode_reg vga_graphics_mode;
233     /* Index 6 */
234     struct vga_misc_reg vga_misc;
235     /* Index 7 */
236     struct vga_color_dont_care_reg vga_color_dont_care;
237     /* Index 8 */
238     vga_bit_mask_reg vga_bit_mask;
239 } __attribute__((packed));
240
241
242 struct vga_attribute_contoller_regs {
243     /*
244       Address AND WRITE: 0x3c0
245       Read: 0x3c1
246
247       The write protocol is to write the index to 0x3c0 followed by 
248       the data.  The read protocol is to write the index to 0x3c0
249       and then read from 0x3c1
250   
251       IMPORTANT: write address, write data flips state back to write address
252       write address, read data DOES NOT
253
254       To reset to write address state, read input status register 1
255 */
256     enum { ATTR_ADDR, ATTR_DATA }  state;  //state of the flip flop
257
258     /* 0x3c0 */
259     struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
260
261
262     
263     /* these can be accessed via the index, offset on start 
264        or via the specific regs.   For this reason, it is essential
265        that this is all packed and that the order does not change */
266     
267     uint8_t  vga_attribute_controller_regs[0];
268
269     /* Indices 0..15 */
270     vga_internal_palette_regs   vga_internal_palette;
271     /* Index 16 */
272     struct vga_attribute_mode_control_reg vga_attribute_mode_control;
273     /* Index 17 */
274     vga_overscan_color_reg vga_overscan_color;
275     /* Index 18 */
276     struct vga_color_plane_enable_reg vga_color_plane_enable;
277     /* Index 19 */
278     struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
279     /* Index 20 */
280     struct vga_color_select_reg vga_color_select;
281 } __attribute__((packed));
282
283 struct vga_dac_regs {
284     enum {DAC_READ=0, DAC_WRITE} state;
285     enum {RED=0,GREEN,BLUE} channel;
286     vga_dac_pixel_mask_reg vga_pixel_mask;
287     vga_dac_write_addr_reg vga_dac_write_addr;
288     vga_dac_read_addr_reg vga_dac_read_addr;
289     // the dac_data register is used only to access the registers
290     // and thus has no representation here
291     vga_palette_reg vga_dac_palette[VGA_DAC_NUM_ENTRIES];
292 } __attribute__((packed));
293     
294
295 struct vga_internal {
296     struct vm_device *dev; 
297
298     bool passthrough;
299     bool skip_next_passthrough_out; // for word access 
300
301     struct v3_frame_buffer_spec  target_spec;
302     v3_graphics_console_t host_cons;
303     struct vga_render_model render_model;
304
305     uint32_t updates_since_render;
306
307     struct frame_buf *framebuf; // we render to this
308     
309     //    void *mem_store;     // This is the region where the memory hooks will go
310
311     vga_map  map[MAP_NUM];  // the maps that the host writes to
312
313     uint8_t  latch[MAP_NUM];  // written to in any read, used during writes
314
315     /* Range of I/O ports here for backward compat with MDA and CGA */
316     struct vga_misc_regs  vga_misc;
317
318     /* Address Register is 0x3b4 or 0x3d4 */
319     /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
320     struct vga_crt_controller_regs vga_crt_controller;
321
322     /*   Address register is 0x3c4, data register is 0x3c5 */
323     struct vga_sequencer_regs vga_sequencer;
324
325     /*   Address: 0x3ce    Data: 0x3cf */
326     struct vga_graphics_controller_regs vga_graphics_controller;
327
328     /*
329       Address AND WRITE: 0x3c0
330       Read: 0x3c1
331       Flip-Flop
332     */
333     struct vga_attribute_contoller_regs vga_attribute_controller;
334
335     /*
336       address for reads: 0x3c7 (also resets state machine for access to 18 bit regs 
337       address for writes: 0x3c8 ("")
338       data: 0x3c9
339       pixel mask: 0x3c6 - do not write (init to 0xff)
340     */
341     struct vga_dac_regs vga_dac;
342 };
343
344
345 typedef enum {PLANAR_SHIFT, PACKED_SHIFT, C256_SHIFT} shift_mode_t;
346
347
348 static void find_text_char_dim(struct vga_internal *vga, uint32_t *w, uint32_t *h)
349 {
350     *w = (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
351
352     *h = vga->vga_crt_controller.vga_max_row_scan.max_scan_line+1;
353
354 }
355
356 static void find_text_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
357 {
358     uint32_t vert_lsb, vert_msb;
359     uint32_t ph;
360     uint32_t ch, cw;
361
362     *width = (vga->vga_crt_controller.vga_horizontal_display_enable_end + 1) 
363         - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew;
364
365     vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
366     vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1)  // 2 bits here
367         + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
368                
369     ph  = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
370
371     find_text_char_dim(vga,&cw, &ch);
372
373     *height = ph / ch; 
374
375 }
376
377
378 static void find_text_data_start(struct vga_internal *vga, void **data)
379 {
380     uint32_t offset;
381
382     offset = vga->vga_crt_controller.vga_start_address_high;
383     offset <<= 8;
384     offset += vga->vga_crt_controller.vga_start_address_low;
385
386     *data = vga->map[0]+offset;
387
388 }
389
390
391 static void find_text_attr_start(struct vga_internal *vga, void **data)
392 {
393     uint32_t offset;
394
395     offset = vga->vga_crt_controller.vga_start_address_high;
396     offset <<= 8;
397     offset += vga->vga_crt_controller.vga_start_address_low;
398
399     *data = vga->map[1]+offset;
400
401 }
402
403 static void find_text_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y, void **data)
404 {
405     uint32_t w,h;
406     uint32_t offset;
407     uint32_t charsin;
408     void *buf;
409
410     find_text_res(vga,&w,&h);
411
412     find_text_data_start(vga,&buf);
413
414     offset = vga->vga_crt_controller.vga_cursor_location_high;
415     offset <<= 8;
416     offset += vga->vga_crt_controller.vga_cursor_location_low;
417
418     *data = vga->map[0]+offset;
419
420     charsin = (uint32_t)(*data - buf);
421     
422     *x = charsin % w;
423     *y = charsin / w;
424         
425 }
426
427
428 static void find_text_font_start(struct vga_internal *vga, void **data, uint8_t char_map)
429 {
430     uint32_t mapa_offset, mapb_offset;
431
432
433     switch (char_map) { 
434         case 0:
435             mapa_offset = (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb << 1)
436                            + vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb ;
437             *data = vga->map[2] + mapa_offset;
438             break;
439             
440         case 1:
441             mapb_offset = (vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb << 1)
442                            + vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb ;
443             *data = vga->map[2] + mapb_offset;
444             break;
445         default:
446             PrintError("vga: unknown char_map given to find_text_font_start\n");
447             break;
448             
449     }
450 }
451
452 static int extended_fontset(struct vga_internal *vga)
453 {
454     if (vga->vga_sequencer.vga_mem_mode.extended_memory &&
455         ! ( (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb 
456              == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb) &&
457             (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb 
458              == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb))) { 
459         return 1;
460     } else {
461         return 0;
462     }
463
464 }
465
466 static int blinking(struct vga_internal *vga)
467 {
468     return vga->vga_attribute_controller.vga_attribute_mode_control.enable_blink;
469 }
470
471
472 static void find_graphics_data_starting_offset(struct vga_internal *vga, uint32_t *offset)
473 {
474
475     *offset = vga->vga_crt_controller.vga_start_address_high;
476     *offset <<= 8;
477     *offset += vga->vga_crt_controller.vga_start_address_low;
478 }
479
480
481 static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode)
482 {
483     if (vga->vga_graphics_controller.vga_graphics_mode.c256) { 
484         *mode=C256_SHIFT;
485     } else {
486         if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) {
487             *mode=PACKED_SHIFT;
488         } else {
489             *mode=PLANAR_SHIFT;
490         }
491     }
492 }
493
494
495 static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
496 {
497     uint32_t vert_lsb, vert_msb;
498
499     *width = ((vga->vga_crt_controller.vga_horizontal_display_enable_end + 1) 
500               - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew);
501
502     *width *= (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
503
504     vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
505     vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1)  // 2 bits here
506         + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
507                
508     *height  = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
509
510     // At this point we have the resolution in dot clocks across and scanlines top-to-bottom
511     // This is usually the resolution in pixels, but it can be monkeyed with
512     // at least in the following ways
513
514     // vga sequencer dot clock divide by two 
515     if (vga->vga_sequencer.vga_clocking_mode.dot_clock) { 
516         *width/=2;
517         *height/=2;
518     }
519
520     // crt_controller.max_row_scan.double_scan => each row twice for 200=>400
521     if (vga->vga_crt_controller.vga_max_row_scan.double_scan) { 
522         *height/=2;
523     }
524     
525     // crt_controller.crt_mode_control.count_by_two => pixels twice as wide as normal
526     if (vga->vga_crt_controller.vga_crt_mode_control.count_by_two) { 
527         *width /= 2;
528     }
529
530     // crt_controller.crt_mode_control.horizontal_retrace_select => pixels twice as tall as normal
531     if (vga->vga_crt_controller.vga_crt_mode_control.horizontal_retrace_select) { 
532         *height /= 2;
533     }
534     
535 }
536
537
538 static void find_graphics_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y)
539 {
540     // todo
541     *x=*y=0;
542 }
543
544
545 static void dac_lookup_24bit_color(struct vga_internal *vga,
546                                    uint8_t entry,
547                                    uint8_t *red,
548                                    uint8_t *green,
549                                    uint8_t *blue)
550 {
551     // use internal or external palette?
552
553     vga_palette_reg *r = &(vga->vga_dac.vga_dac_palette[entry]);
554
555     // converting from 6 bits to 8 bits so << 2
556     *red = (*r & 0x3f) << 2;
557     *green = ((*r >> 8) & 0x3f) << 2;
558     *blue = ((*r >> 16) & 0x3f) << 2;
559
560 }
561
562
563 /*
564   Colors work like this:
565
566   4 bit modes:   index is to the internal palette on the attribute controller
567                  that supplies 6 bits, but we need 8 to index the dac
568                  2 more (the msbs) are supplied from the color select register
569                  we can optionally overwrite bits 5 and 4 from the color
570                  select register as well, depending on a selection bit
571                  in the mode control register.   The result of all this is
572                  8 bit index for the dac
573
574   8 bit modes:   the attribute controller passes the index straight through
575                  to the DAC.
576
577
578   The DAC translates from the 8 bit index into 6 bits per color channel
579   (18 bit color).   We mulitply by 4 to get 24 bit color.
580 */
581
582 static void find_24bit_color(struct vga_internal *vga, 
583                              uint8_t val,
584                              uint8_t *red,
585                              uint8_t *green,
586                              uint8_t *blue)
587 {
588     uint8_t di;  // ultimate dac index
589
590     if (vga->vga_attribute_controller.vga_attribute_mode_control.pixel_width) { 
591         // 8 bit mode does right to the DAC
592         di=val;
593     } else {
594         struct vga_internal_palette_reg pr = vga->vga_attribute_controller.vga_internal_palette[val%16];
595         di = pr.palette_data;
596         
597         // Fix bits 5-4 if needed
598         if (vga->vga_attribute_controller.vga_attribute_mode_control.p54_select) { 
599             di &= ~0x30;  // clear 5-4
600             di |= vga->vga_attribute_controller.vga_color_select.sc4 << 4;
601             di |= vga->vga_attribute_controller.vga_color_select.sc5 << 5;
602         }
603
604         // We must always produce bits 6 and 7
605         di &= ~0xc0; // clear 7-6
606         di |= vga->vga_attribute_controller.vga_color_select.sc6 << 6;
607         di |= vga->vga_attribute_controller.vga_color_select.sc7 << 7;
608     }
609         
610     dac_lookup_24bit_color(vga,di,red,green,blue);
611 }
612         
613 static void render_graphics(struct vga_internal *vga, void *fb)
614 {
615
616     struct v3_frame_buffer_spec *spec = &(vga->target_spec);
617
618     uint32_t gw, gh; // graphics w/h
619     uint32_t fw, fh; // fb w/h
620     uint32_t rgw, rgh;  // region we can actually show on the frame buffer
621     
622
623     uint32_t fx, fy;     // pixel position within the frame buffer
624     
625     uint32_t offset;     // offset into the maps
626     uint8_t  m;        // map
627     uint8_t  p;          // pixel in the current map byte  (0..7)
628
629     uint8_t r,g,b;  // looked up colors for entry
630
631     void    *pixel;   // current pixel in the fb
632     uint8_t *red;     // and the channels in the pixel
633     uint8_t *green;   //
634     uint8_t *blue;    //
635
636     uint8_t db[4]; // 4 bytes read at a time
637     uint8_t pb[8]; // 8 pixels assembled at a time
638
639     shift_mode_t sm;   // shift mode
640
641     uint32_t cur_x, cur_y;
642     
643
644     find_graphics_res(vga,&gw,&gh);
645
646     find_shift_mode(vga,&sm);
647
648     find_graphics_cursor_pos(vga,&cur_x,&cur_y);
649
650     find_graphics_data_starting_offset(vga,&offset);
651
652     fw = spec->width;
653     fh = spec->height;
654
655
656     PrintDebug("vga: attempting graphics render (%s): graphics_res=(%u,%u), fb_res=(%u,%u), "
657                "fb=0x%p offset=0x%x\n",
658                sm == PLANAR_SHIFT ? "planar shift" : 
659                sm == PACKED_SHIFT ? "packed shift" : 
660                sm == C256_SHIFT ? "color256 shift" : "UNKNOWN",
661                gw,gh,fw,fh,fb,offset);
662
663     // First we need to clip to what we can actually show
664     rgw = gw < fw ? gw : fw;
665     rgh = gh < fh ? gh : fh;
666
667     if (gw%8) { 
668         PrintError("vga: warning: graphics width is not a multiple of 8\n");
669     }
670
671
672
673     // Now we scan across by row
674     for (fy=0;fy<gh;fy++) { 
675         // by column
676         for (fx=0;fx<gw;
677              fx += (sm==C256_SHIFT ? 4 : 8) , offset++ ) { 
678
679             // if any of these pixels are in the rendger region
680             if (fy < rgh && fx < rgw) {
681                 // assemble all 4 or 8 pixels
682                 
683                 // fetch the data bytes
684                 for (m=0;m<4;m++) { 
685                     db[m]=*((uint8_t*)(vga->map[m]+offset));
686                 }
687                  
688                 // assemble
689                 switch (sm) { 
690                     case PLANAR_SHIFT:
691                         for (p=0;p<8;p++) { 
692                             pb[p]= 
693                                 (( db[0] >> 7) & 0x1) |
694                                 (( db[1] >> 6) & 0x2) |
695                                 (( db[2] >> 5) & 0x4) |
696                                 (( db[3] >> 4) & 0x8) ;
697                             
698                             for (m=0;m<4;m++) { 
699                                 db[m] <<= 1;
700                             }
701                         }
702                         break;
703                         
704                     case PACKED_SHIFT:
705                         // first 4 pixels use planes 0 and 2
706                         for (p=0;p<4;p++) { 
707                             pb[p] = 
708                                 ((db[2] >> 4) & 0xc) |
709                                 ((db[0] >> 6) & 0x3) ;
710                             db[2] <<= 2;
711                             db[0] <<= 2;
712                         }
713                         break;
714                         
715                         // next 4 pixels use planes 1 and 3
716                         for (p=4;p<8;p++) { 
717                             pb[p] = 
718                                 ((db[3] >> 4) & 0xc) |
719                                 ((db[1] >> 6) & 0x3) ;
720                             db[3] <<= 2;
721                             db[1] <<= 2;
722                         }
723                         break;
724
725                     case C256_SHIFT:
726                         // this one is either very bizarre or as simple as this
727                         for (p=0;p<4;p++) { 
728                             pb[p] = db[p];
729                         }
730                         break;
731                 }
732
733                 // draw each pixel
734                 for (p=0;p< (sm==C256_SHIFT ? 4 : 8);p++) { 
735                     
736                     // find its color
737                     find_24bit_color(vga,pb[p],&r,&g,&b);
738                 
739                     // find its position in the framebuffer;
740                     pixel =  fb + (((fx + p) + (fy*spec->width)) * spec->bytes_per_pixel);
741                     red = pixel + spec->red_offset;
742                     green = pixel + spec->green_offset;
743                     blue = pixel + spec->blue_offset;
744
745                     // draw it
746                     *red=r;
747                     *green=g;
748                     *blue=b;
749                 }
750             }
751         }
752     }
753     
754     PrintDebug("vga: render done\n");
755 }
756
757
758 static void render_text_cursor(struct vga_internal *vga, void *fb)
759 {
760 }
761
762
763
764
765 //
766 // A variant of this function could render to
767 // a text console interface as well
768 //
769 static void render_text(struct vga_internal *vga, void *fb)
770 {
771     // line graphics enable bit means to  dupe column 8 to 9 when
772     // in 9 dot wide mode
773     // otherwise 9th dot is background
774
775     struct v3_frame_buffer_spec *spec = &(vga->target_spec);
776
777     uint32_t gw, gh; // graphics w/h
778     uint32_t tw, th; // text w/h
779     uint32_t rtw, rth; // rendered text w/h
780     uint32_t cw, ch; // char font w/h including 8/9
781     uint32_t fw, fh; // fb w/h
782
783     uint32_t px, py; // cursor position
784     
785     uint32_t x, y, l, p; // text location, line and pixel within the char
786     uint32_t fx, fy;     // pixel position within the frame buffer
787     
788     uint8_t *text_start; 
789     uint8_t *text;    // points to current char
790     uint8_t *attr;    // and its matching attribute
791     uint8_t *curs;    // to where the cursor is
792     uint8_t *font;    // to where the current font is
793
794     uint8_t fg_entry; // foreground color entry
795     uint8_t bg_entry; // background color entry
796     uint8_t fgr,fgg,fgb;    // looked up  foreground colors
797     uint8_t bgr,bgg,bgb;    // looked up  bg colors
798
799     uint8_t ct, ca;   // the current char and attribute
800     struct vga_attribute_byte a; // decoded attribute
801
802     void *pixel;      // current pixel in the fb
803     uint8_t *red;     // and the channels in the pixel
804     uint8_t *green;   //
805     uint8_t *blue;    //
806
807     
808
809     find_graphics_res(vga,&gw,&gh);
810     find_text_res(vga,&tw,&th);
811     find_text_char_dim(vga,&cw,&ch);
812     fw = spec->width;
813     fh = spec->height;
814
815     find_text_cursor_pos(vga,&px,&py,(void**)&curs);
816     find_text_data_start(vga,(void**)&text);
817     find_text_attr_start(vga,(void**)&attr);
818
819     find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr
820
821     PrintDebug("vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), "
822                "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p"
823                "graphics extension=%u, extended_fontset=%d, blinking=%d\n",
824                gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb,
825                vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code,
826                extended_fontset(vga), blinking(vga));
827
828     text_start=text;
829
830     // First we need to clip to what we can actually show
831     rtw = tw < fw/cw ? tw : fw/cw;
832     rth = th < fh/ch ? th : fh/ch;
833
834     
835
836     // Now let's scan by char across the whole thing
837     for (y=0;y<th;y++) { 
838         for (x=0;x<tw;x++, text++, attr++) { 
839             if (x < rtw && y < rth) { 
840                 // grab the character and attribute for the position
841                 ct = *text; 
842                 ca = *attr;  
843                 a.val = ca;
844
845                 // find the character's font bitmap (one byte per row)
846                 find_text_font_start(vga,(void**)&font,
847                                      extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 ); 
848
849                 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
850
851                 // Now let's find out what colors we will be using
852                 // foreground
853                 
854                 if (!extended_fontset(vga)) { 
855                     fg_entry = a.foreground_intensity_or_font_select << 3;
856                 } else {
857                     fg_entry = 0;
858                 }
859                 fg_entry |= a.fore;
860
861                 find_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
862
863                 if (!blinking(vga)) { 
864                     bg_entry = a.blinking_or_bg_intensity << 3;
865                 } else {
866                     bg_entry = 0;
867                 }
868                 bg_entry |= a.back;
869                 
870                 find_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
871
872                 // Draw the character
873                 for (l=0; l<ch; l++, font++) {
874                     uint8_t frow = *font;  // this is the row of of the font map
875                     for (p=0;p<cw;p++) {
876                         uint8_t fbit;
877                         
878                         // a char can be 9 bits wide, but the font map
879                         // is only 8 bits wide, which means we need to know where to
880                         // get the 9th bit
881                         if (p >= 8) { 
882                             // We get it from the font map if
883                             // its line line graphics mode and its a graphics char
884                             // otherwise it's the background color
885                             if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
886                                 && ct>=0xc0 && ct<=0xdf ) { 
887                                 fbit = frow & 0x1;
888                             } else {
889                                 fbit = 0;
890                             }
891                         } else {
892                             fbit= (frow >> (7-p) ) & 0x1;
893                         }
894                         
895                         // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
896                         // For now, we will draw it as black/white
897
898                         // find its position in the framebuffer;
899                         fx = x*cw + p;
900                         fy = y*ch + l;
901                         pixel =  fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
902                         red = pixel + spec->red_offset;
903                         green = pixel + spec->green_offset;
904                         blue = pixel + spec->blue_offset;
905
906                         // Are we on the cursor?
907                         // if so, let's negate this pixel to invert the cell
908                         if (curs==text) { 
909                             fbit^=0x1;
910                         }
911                         // update the framebuffer
912                         if (fbit) { 
913                             *red=fgr; 
914                             *green=fgg;
915                             *blue=fgb;
916                         } else {
917                             *red=bgr;
918                             *green=bgg;
919                             *blue=bgb;
920                         }
921                     }
922                 }
923             }
924         }
925         PrintDebug("\n");
926     }
927
928 }
929
930                         
931                         
932
933
934 static void render_test(struct vga_internal *vga, void *fb)
935 {
936     struct v3_frame_buffer_spec *s;
937
938     s=&(vga->target_spec);
939
940     if (fb && s->height>=480 && s->width>=640 ) { 
941         uint8_t color = (uint8_t)(vga->updates_since_render);
942         
943         uint32_t x, y;
944         
945         for (y=0;y<480;y++) {
946             for (x=0;x<640;x++) { 
947                 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
948                 uint8_t *red = pixel + s->red_offset;
949                 uint8_t *green = pixel + s->green_offset;
950                 uint8_t *blue = pixel + s->blue_offset;
951                 
952                 if (y<(480/4)) { 
953                     *red=color+x;
954                     *green=0;
955                     *blue=0;
956                 } else if (y<(480/2)) { 
957                     *red=0;
958                     *green=color+x;
959                     *blue=0;
960                 } else if (y<(3*(480/4))) { 
961                     *red=0;
962                     *green=0;
963                     *blue=color+x;
964                 } else {
965                     *red=*green=*blue=color+x;
966                 }
967             }
968         }
969     }
970 }
971
972 static void render_black(struct vga_internal *vga, void *fb)
973 {
974     struct v3_frame_buffer_spec *s;
975
976     s=&(vga->target_spec);
977
978     memset(fb,0,s->height*s->width*s->bytes_per_pixel);
979 }
980
981 static void render_maps(struct vga_internal *vga, void *fb)
982 {
983
984     struct v3_frame_buffer_spec *s;
985     
986
987     s=&(vga->target_spec);
988
989     if (fb && s->height>=768 && s->width>=1024 ) { 
990         // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
991         uint8_t m;
992         uint32_t x,y;
993         uint8_t *b;
994         
995         for (m=0;m<4;m++) { 
996             b=(vga->map[m]);
997             for (y=480+32;y<768;y++) { 
998                 for (x=m*256;x<(m+1)*256;x++,b++) { 
999                     void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
1000                     uint8_t *red = pixel + s->red_offset;
1001                     uint8_t *green = pixel + s->green_offset;
1002                     uint8_t *blue = pixel + s->blue_offset;
1003                     
1004                     *red=*green=*blue=*b;
1005                 }
1006             }
1007         }
1008     }
1009 }
1010
1011 static int render_core(struct vga_internal *vga)
1012 {
1013   void *fb;
1014
1015   PrintDebug("vga: render on update %u\n",vga->updates_since_render);
1016   
1017   fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
1018   
1019   if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
1020     if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) { 
1021       render_graphics(vga,fb);
1022     } else {
1023           render_text(vga,fb);
1024           render_text_cursor(vga,fb);
1025         }
1026   } else {
1027     render_black(vga,fb);
1028   }
1029   
1030   if (0) { render_test(vga,fb); }
1031   
1032   // always render maps for now 
1033   render_maps(vga,fb);
1034   
1035   v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
1036   
1037   vga->updates_since_render=0;
1038   
1039   return 0;
1040
1041 }
1042     
1043
1044 static int render(struct vga_internal *vga)
1045 {
1046
1047     vga->updates_since_render++;
1048
1049
1050     if (vga->host_cons) { 
1051       int do_render=0;
1052       
1053       if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING)
1054           &&
1055           (vga->updates_since_render > vga->render_model.updates_before_render)) {
1056         PrintDebug("vga: render due to periodic\n");
1057         
1058         do_render = 1;
1059       }
1060       
1061       if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING) 
1062           &&
1063           (v3_graphics_console_inform_update(vga->host_cons) > 0) ) { 
1064
1065         PrintDebug("vga: render due to advisory\n");
1066
1067         do_render = 1;
1068       }
1069
1070       // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function
1071       
1072       if (do_render) { 
1073         return render_core(vga);
1074       } else {
1075         return 0;
1076       }
1077     }
1078     return 0;
1079     
1080 }
1081
1082
1083 static int render_callback(v3_graphics_console_t cons,
1084                            void *priv)
1085 {
1086   struct vga_internal *vga = (struct vga_internal *) priv;
1087   
1088   PrintDebug("vga: render due to callback\n");
1089
1090   return render_core(vga);
1091 }
1092
1093 static int update_callback(v3_graphics_console_t cons,
1094                            void *priv)
1095 {
1096   struct vga_internal *vga = (struct vga_internal *) priv;
1097   
1098   return vga->updates_since_render>0;
1099 }
1100
1101
1102
1103 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end) 
1104 {
1105     switch (vga->vga_graphics_controller.vga_misc.memory_map) { 
1106         case 0: 
1107             *mem_start=0xa0000;
1108             *mem_end=0xc0000;
1109             break;
1110         case 1:
1111             *mem_start=0xa0000;
1112             *mem_end=0xb0000;
1113             break;
1114         case 2:
1115             *mem_start=0xb0000;
1116             *mem_end=0xb8000;
1117             break;
1118         case 3:
1119             *mem_start=0xb8000;
1120             *mem_end=0xc0000;
1121             break;
1122     }
1123 }
1124
1125 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
1126 {
1127     uint64_t mem_start, mem_end;
1128     uint64_t size;
1129     
1130     mem_start=mem_end=0;
1131     
1132     get_mem_region(vga, &mem_start, &mem_end);
1133     
1134     size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); 
1135
1136     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
1137         return (guest_addr-mem_start) % size;
1138     } else {
1139         // odd/even mode
1140         return ((guest_addr-mem_start) >> 1 ) % size;
1141     }
1142 }
1143
1144
1145
1146     
1147 // Determines which maps should be enabled for this single byte write
1148 // and what the increment (actually 1/increment for the copy loop
1149 //
1150 //  memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
1151 //  
1152 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
1153 {
1154     uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
1155
1156     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
1157         return mm;
1158     } else {
1159         if (guest_addr & 0x1) { 
1160             return mm & 0xa;  // 0x1010
1161         } else {
1162             return mm & 0x5;  // 0x0101
1163         }
1164     }
1165 }
1166
1167 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
1168 {
1169     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
1170         return 1;
1171     } else {
1172         return !(new_guest_addr & 0x1);
1173     }
1174 }
1175
1176
1177
1178 static int vga_write(struct guest_info * core, 
1179                      addr_t guest_addr, 
1180                      void * src, 
1181                      uint_t length, 
1182                      void * priv_data)
1183 {
1184     struct vm_device *dev = (struct vm_device *)priv_data;
1185     struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1186
1187     PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1188
1189     if (vga->passthrough) { 
1190         PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
1191         memcpy(V3_VAddr((void*)guest_addr),src,length);
1192     }
1193     
1194 #if DEBUG_MEM_DATA
1195     int i;
1196     PrintDebug("vga: data written was 0x");
1197     for (i=0;i<length;i++) {
1198         uint8_t c= ((char*)src)[i];
1199         PrintDebug("%.2x", c);
1200     }
1201     PrintDebug(" \"");
1202     for (i=0;i<length;i++) {
1203         char c= ((char*)src)[i];
1204         PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1205     }
1206     PrintDebug("\"\n");
1207 #endif
1208
1209     /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
1210
1211
1212     switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1213         case 0: {
1214             
1215             /* 
1216                00b -- Write Mode 0: In this mode, the host data is first rotated 
1217                as per the Rotate Count field, then the Enable Set/Reset mechanism 
1218                selects data from this or the Set/Reset field. Then the selected 
1219                Logical Operation is performed on the resulting data and the data 
1220                in the latch register. Then the Bit Mask field is used to select 
1221                which bits come from the resulting data and which come 
1222                from the latch register. Finally, only the bit planes enabled by 
1223                the Memory Plane Write Enable field are written to memory.
1224             */
1225
1226             int i;
1227
1228             uint8_t  mapnum;
1229             uint64_t offset;
1230
1231             uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1232             uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1233             
1234             offset = find_offset_write(vga, guest_addr);
1235
1236 #if DEBUG_DEEP_MEM
1237             PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1238 #endif
1239
1240             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1241                 // now for each map
1242                 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1243                 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1244                 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1245                 uint8_t mm = find_map_write(vga,guest_addr+i);
1246
1247 #if DEBUG_DEEP_MEM
1248                 PrintDebug("vga: write i=%u, mm=0x%x, bm=0x%x sr=0x%x esr=0x%x offset=0x%x\n",i,(unsigned int)mm,(unsigned int)bm, (unsigned int)sr, (unsigned int)esr,(unsigned int)offset);
1249 #endif
1250
1251                 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) { 
1252                     vga_map map = vga->map[mapnum];
1253                     uint8_t data = ((uint8_t *)src)[i];
1254                     uint8_t latchval = vga->latch[mapnum];
1255                     
1256 #if DEBUG_DEEP_MEM
1257                     PrintDebug("vga: raw data=0x%x\n",data);
1258 #endif
1259                     // rotate data right
1260                     if (ror) { 
1261                         data = (data>>ror) | (data<<(8-ror));
1262                     }
1263                     
1264 #if DEBUG_DEEP_MEM
1265                     PrintDebug("vga: data after ror=0x%x\n",data);
1266 #endif
1267                     // use SR bit if ESR is on for this map
1268                     if (esr & 0x1) {
1269                         data = (sr&0x1) * -1;
1270                         
1271                     }
1272                     
1273 #if DEBUG_DEEP_MEM
1274                     PrintDebug("vga: data after esrr=0x%x\n",data);
1275 #endif
1276                     
1277                     // Apply function
1278                     switch (func) { 
1279                         case 0: // NOP
1280                             break;
1281                         case 1: // AND
1282                             data &= latchval;
1283                             break;
1284                         case 2: // OR
1285                             data |= latchval;
1286                             break;
1287                         case 3: // XOR
1288                             data ^= latchval;
1289                             break;
1290                     }
1291                     
1292 #if DEBUG_DEEP_MEM
1293                     PrintDebug("vga: data after func=0x%x\n",data);
1294 #endif
1295                     
1296                     // mux between the data byte and the latch byte on
1297                     // a per-bit basis
1298                     data = (bm & data) | ((~bm) & latchval);
1299                     
1300
1301 #if DEBUG_DEEP_MEM
1302                     PrintDebug("vga: data after bm mux=0x%x\n",data);
1303 #endif
1304                     
1305                     // selective write
1306                     if (mm & 0x1) { 
1307                         // write to this map
1308 #if DEBUG_DEEP_MEM
1309                         PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
1310 #endif
1311                         map[offset] = data;
1312                     } else {
1313                         // skip this map
1314                     }
1315                 }
1316             }
1317         }
1318             break;
1319
1320
1321             
1322         case 1: {
1323             /* 
1324                01b -- Write Mode 1: In this mode, data is transferred directly 
1325                from the 32 bit latch register to display memory, affected only by 
1326                the Memory Plane Write Enable field. The host data is not used in this mode.
1327             */
1328
1329             int i;
1330
1331             uint64_t offset = find_offset_write(vga,guest_addr);
1332
1333 #if DEBUG_DEEP_MEM
1334             PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
1335 #endif
1336
1337             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1338
1339                 uint8_t mapnum;
1340                 uint8_t mm = find_map_write(vga,guest_addr+i);
1341
1342                 for (mapnum=0;mapnum<4;mapnum++,  mm>>=1) { 
1343                     vga_map map = vga->map[mapnum];
1344                     uint8_t latchval = vga->latch[mapnum];
1345                         
1346                     // selective write
1347                     if (mm & 0x1) { 
1348                         // write to this map
1349                         map[offset] = latchval;
1350                     } else {
1351                         // skip this map
1352                     }
1353                 }
1354             }
1355         }
1356             break;
1357
1358         case 2: {
1359             /*
1360               10b -- Write Mode 2: In this mode, the bits 3-0 of the host data 
1361               are replicated across all 8 bits of their respective planes. 
1362               Then the selected Logical Operation is performed on the resulting 
1363               data and the data in the latch register. Then the Bit Mask field is used to 
1364               select which bits come from the resulting data and which come from 
1365               the latch register. Finally, only the bit planes enabled by the 
1366               Memory Plane Write Enable field are written to memory.
1367             */
1368             int i;
1369             uint8_t  mapnum;
1370             uint64_t offset;
1371
1372             uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1373             
1374             offset = find_offset_write(vga, guest_addr);
1375
1376 #if DEBUG_DEEP_MEM
1377             PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1378 #endif
1379
1380             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1381                 // now for each map
1382                 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1383                 uint8_t mm = find_map_write(vga,guest_addr+i);
1384
1385                 for (mapnum=0;mapnum<4;mapnum++,  bm>>=1, mm>>=1) { 
1386                     vga_map map = vga->map[mapnum];
1387                     uint8_t data = ((uint8_t *)src)[i];
1388                     uint8_t latchval = vga->latch[mapnum];
1389                         
1390                     // expand relevant bit to 8 bit
1391                     // it's basically esr=1, sr=bit from mode 0 write
1392                     data = ((data>>mapnum)&0x1) * -1;
1393                         
1394                     // Apply function
1395                     switch (func) { 
1396                         case 0: // NOP
1397                             break;
1398                         case 1: // AND
1399                             data &= latchval;
1400                             break;
1401                         case 2: // OR
1402                             data |= latchval;
1403                             break;
1404                         case 3: // XOR
1405                             data ^= latchval;
1406                             break;
1407                     }
1408
1409                     // mux between latch and alu output
1410                     data = (bm & data) | ((~bm) & latchval);
1411                     
1412                     // selective write
1413                     if (mm & 0x1) { 
1414                         // write to this map
1415                         map[offset] = data;
1416                     } else {
1417                         // skip this map
1418                     }
1419                 }
1420             }
1421         }
1422             break;
1423
1424         case 3: {
1425             /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used 
1426                as if the Enable Set/Reset field were set to 1111b. Then the host data is 
1427                first rotated as per the Rotate Count field, then logical ANDed with the 
1428                value of the Bit Mask field. The resulting value is used on the data 
1429                obtained from the Set/Reset field in the same way that the Bit Mask field 
1430                would ordinarily be used. to select which bits come from the expansion 
1431                of the Set/Reset field and which come from the latch register. Finally, 
1432                only the bit planes enabled by the Memory Plane Write Enable field 
1433                are written to memory.
1434             */
1435             int i;
1436
1437             uint8_t  mapnum;
1438             uint64_t offset;
1439
1440             uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1441             
1442             offset = find_offset_write(vga, guest_addr);
1443
1444             PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1445
1446             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1447                 // now for each map
1448                 uint8_t data = ((uint8_t *)src)[i];
1449
1450                 if (ror) {
1451                     data = (data>>ror) | (data<<(8-ror));
1452                 }
1453
1454                 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1455                 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1456                 uint8_t mm = find_map_write(vga,guest_addr+i);
1457
1458                 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) { 
1459                     vga_map map = vga->map[mapnum];
1460                     uint8_t latchval = vga->latch[mapnum];
1461                         
1462                     // expand SR bit
1463                     data = (sr&0x1) * -1;
1464
1465                     // mux between latch and alu output
1466                     data = (bm & data) | ((~bm) & latchval);
1467                     
1468                     // selective write
1469                     if (mm & 0x1) { 
1470                         // write to this map
1471                         map[offset] = data;
1472                     } else {
1473                         // skip this map
1474                     }
1475                 }
1476             }
1477
1478         }
1479             break;
1480
1481             // There is no default
1482     }
1483
1484     render(vga);
1485     
1486     return length;
1487 }
1488
1489
1490
1491 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1492 {
1493     uint64_t mem_start, mem_end;
1494     uint64_t size;
1495     
1496     mem_start=mem_end=0;
1497     
1498     get_mem_region(vga, &mem_start, &mem_end);
1499     
1500     size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); 
1501
1502     if (!vga->vga_sequencer.vga_mem_mode.chain4) { 
1503         return (guest_addr-mem_start) % size;
1504     } else {
1505         // chain4 mode
1506         return ((guest_addr - mem_start) >> 2) % size;
1507     }
1508 }
1509
1510 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1511 {
1512
1513     if (vga->vga_sequencer.vga_mem_mode.chain4) { 
1514         return !(new_guest_addr & 0x3);
1515     } else {
1516         return 1;
1517     }
1518 }
1519
1520
1521 static int vga_read(struct guest_info * core, 
1522                     addr_t guest_addr, 
1523                     void * dst, 
1524                     uint_t length, 
1525                     void * priv_data)
1526 {
1527     struct vm_device *dev = (struct vm_device *)priv_data;
1528     struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1529     
1530
1531     PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1532
1533         
1534    
1535     /*
1536       Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1537     */
1538     switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) { 
1539         case 0: {
1540             /*      0 - a byte from ONE of the 4 planes is returned; 
1541                     which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
1542             uint8_t  mapnum;
1543             uint64_t offset;
1544
1545
1546             if (vga->vga_sequencer.vga_mem_mode.chain4) { 
1547                 uint32_t i;
1548                 offset = find_offset_read(vga,guest_addr);
1549                 // address bytes select the map
1550                 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) { 
1551                     mapnum = (guest_addr+i) % 4;
1552 #if DEBUG_DEEP_MEM
1553                     PrintDebug("vga: mode 0 read, chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
1554 #endif
1555                     ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1556
1557                     // presumably all the latches are to be reloaded, not just the selected one?
1558                     for (mapnum=0;mapnum<4;mapnum++) { 
1559                         vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1560                     }
1561                 }
1562             } else {
1563                 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
1564                 offset = find_offset_read(vga,guest_addr);
1565                 
1566                 if (offset>=65536) { 
1567                     PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
1568                 }
1569                 
1570 #if DEBUG_DEEP_MEM
1571                 PrintDebug("vga: mode 0 read, not-chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
1572 #endif
1573
1574                 memcpy(dst,(vga->map[mapnum])+offset,length);
1575                 
1576                 // load the latches with the last item read
1577                 for (mapnum=0;mapnum<4;mapnum++) { 
1578                     vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1579                 }
1580             }
1581         
1582         }
1583             break;
1584         case 1: {
1585             /*      1 - Compare video memory and reference color 
1586                     (in Color Compare, except those not set in Color Don't Care), 
1587                     each bit in returned result is one comparison between the reference color 
1588
1589                     Ref color is *4* bits, and thus a one byte read returns a comparison 
1590                     with 8 pixels
1591
1592             */
1593             int i;
1594
1595             uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1596             uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1597
1598             uint8_t  mapnum;
1599             uint64_t offset;
1600             uint8_t  byte;
1601             uint8_t  bits;
1602             
1603             offset = find_offset_read(vga,guest_addr);
1604
1605 #if DEBUG_DEEP_MEM
1606             PrintDebug("vga: mode 1 read, offset=0x%llx, cc=0x%x, dc-0x%x\n",offset,cc,dc);
1607 #endif
1608                 
1609             
1610             for (i=0;i<length;i++,offset++) { 
1611                 vga_map map;
1612                 byte=0;
1613                 for (mapnum=0;mapnum<4;mapnum++) { 
1614                     map = vga->map[mapnum];
1615                     if ( (dc>>mapnum)&0x1 ) { // don't care
1616                         bits=0;
1617                     } else {
1618                         // lower 4 bits
1619                         bits = (map[offset]&0xf) == cc;
1620                         bits <<= 1;
1621                         // upper 4 bits
1622                         bits |= (((map[offset]>>4))&0xf) == cc;
1623                     }
1624                     // not clear whether it is 0..k or k..0
1625                     byte<<=2;
1626                     byte|=bits;
1627                 }
1628             }
1629
1630             // load the latches with the last item read
1631             for (mapnum=0;mapnum<4;mapnum++) { 
1632                 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1633             }
1634
1635         }
1636             break;
1637             // there is no default
1638     }
1639
1640     if (vga->passthrough) { 
1641         PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1642         memcpy(dst,V3_VAddr((void*)guest_addr),length);
1643     }
1644
1645
1646 #if DEBUG_MEM_DATA
1647     int i;
1648     PrintDebug("vga: data read is 0x");
1649     for (i=0;i<length;i++) {
1650         uint8_t c= ((char*)dst)[i];
1651         PrintDebug("%.2x", c);
1652     }
1653     PrintDebug(" \"");
1654     for (i=0;i<length;i++) {
1655         char c= ((char*)dst)[i];
1656         PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1657     }
1658     PrintDebug("\"\n");
1659 #endif
1660
1661     return length;
1662
1663 }
1664
1665
1666
1667
1668
1669 #define ERR_WRONG_SIZE(op,reg,len,min,max)      \
1670     if (((len)<(min)) || ((len)>(max))) {       \
1671         PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
1672         return -1; \
1673 }
1674         
1675 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1676     switch (length) {
1677         case 1:
1678             *(uint8_t *)dest = v3_inb(port);
1679             break;
1680         case 2:
1681             *(uint16_t *)dest = v3_inw(port);
1682             break;
1683         case 4:
1684             *(uint32_t *)dest = v3_indw(port);
1685             break;
1686         default:
1687             PrintError("vga: unsupported passthrough io in size %u\n",length);
1688             break;
1689     }
1690 }
1691
1692
1693 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1694     switch (length) {
1695         case 1:
1696             v3_outb(port, *(uint8_t *)src);
1697             break;
1698         case 2:
1699             v3_outw(port, *(uint16_t *)src);
1700             break;
1701         case 4:
1702             v3_outdw(port, *(uint32_t *)src);
1703             break;
1704         default:
1705             PrintError("vga: unsupported passthrough io out size %u\n",length);
1706             break;
1707     }
1708 }
1709
1710 #define PASSTHROUGH_IO_IN(vga,port,dest,len)                            \
1711     do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1712
1713 #define PASSTHROUGH_IO_OUT(vga,port,src,len)                            \
1714     do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1715
1716 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga)                                       \
1717     do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1718                 
1719 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1720     do { if ((vga)->passthrough) { if ((inter)!=(pass)) { PrintError("vga: passthrough error: passthrough value read is 0x%x, but internal value read is 0x%x\n",(pass),(inter)); } } } while (0)
1721
1722 static int misc_out_read(struct guest_info *core, 
1723                          uint16_t port, 
1724                          void *dest,
1725                          uint_t len,
1726                          void *priv_data)
1727 {
1728     struct vga_internal *vga = (struct vga_internal *) priv_data;
1729
1730     PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1731
1732     ERR_WRONG_SIZE("read","misc out",len,1,1);
1733    
1734     *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1735
1736     PASSTHROUGH_IO_IN(vga,port,dest,len);
1737
1738     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1739
1740     return len;
1741 }
1742
1743 static int misc_out_write(struct guest_info *core, 
1744                           uint16_t port, 
1745                           void *src,
1746                           uint_t len,
1747                           void *priv_data)
1748 {
1749     struct vga_internal *vga = (struct vga_internal *) priv_data;
1750     
1751     PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
1752         
1753     ERR_WRONG_SIZE("write","misc out",len,1,1);
1754
1755     PASSTHROUGH_IO_OUT(vga,port,src,len);
1756
1757     vga->vga_misc.vga_misc_out.val =  *((uint8_t*)src) ;
1758     
1759     render(vga);
1760     
1761     return len;
1762 }
1763
1764
1765
1766 static int input_stat0_read(struct guest_info *core, 
1767                             uint16_t port, 
1768                             void *dest,
1769                             uint_t len,
1770                             void *priv_data)
1771 {
1772     struct vga_internal *vga = (struct vga_internal *) priv_data;
1773
1774     PrintDebug("vga: input stat0  read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1775
1776     ERR_WRONG_SIZE("read","input stat0",len,1,1);
1777
1778     *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1779
1780     PASSTHROUGH_IO_IN(vga,port,dest,len);
1781
1782     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1783
1784     return len;
1785 }
1786
1787
1788 static int input_stat1_read(struct guest_info *core, 
1789                             uint16_t port, 
1790                             void *dest,
1791                             uint_t len,
1792                             void *priv_data)
1793 {
1794     struct vga_internal *vga = (struct vga_internal *) priv_data;
1795
1796     PrintDebug("vga: input stat0 (%s) read data=0x%x\n", 
1797                port==0x3ba ? "mono" : "color",
1798                vga->vga_misc.vga_input_stat1.val);
1799
1800     ERR_WRONG_SIZE("read","input stat1",len,1,1);
1801
1802
1803     *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1804
1805     // Stunningly, reading stat1 is also a way to reset
1806     // the state of attribute controller address/data flipflop
1807     // That is some mighty fine crack the designers were smoking.
1808     
1809     vga->vga_attribute_controller.state=ATTR_ADDR;
1810
1811     PASSTHROUGH_IO_IN(vga,port,dest,len);
1812
1813     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1814
1815     return len;
1816 }
1817                          
1818
1819 static int feature_control_read(struct guest_info *core, 
1820                                 uint16_t port, 
1821                                 void *dest,
1822                                 uint_t len,
1823                                 void *priv_data)
1824 {
1825     struct vga_internal *vga = (struct vga_internal *) priv_data;
1826
1827     PrintDebug("vga: feature control  read data=0x%x\n", 
1828                vga->vga_misc.vga_feature_control.val);
1829
1830     ERR_WRONG_SIZE("read","feature control",len,1,1);
1831
1832
1833     *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1834
1835     PASSTHROUGH_IO_IN(vga,port,dest,len);
1836
1837     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1838
1839     return len;
1840 }
1841
1842 static int feature_control_write(struct guest_info *core, 
1843                                  uint16_t port, 
1844                                  void *src,
1845                                  uint_t len,
1846                                  void *priv_data)
1847 {
1848     struct vga_internal *vga = (struct vga_internal *) priv_data;
1849     
1850     PrintDebug("vga: feature control (%s) write data=0x%x\n", 
1851                port==0x3ba ? "mono" : "color",
1852                *((uint8_t*)src));
1853         
1854     ERR_WRONG_SIZE("write","feature control",len,1,1);
1855     
1856     PASSTHROUGH_IO_OUT(vga,port,src,len);
1857
1858     vga->vga_misc.vga_feature_control.val =  *((uint8_t*)src) ;
1859     
1860     render(vga);
1861     
1862     return len;
1863 }
1864
1865
1866 static int video_subsys_enable_read(struct guest_info *core, 
1867                                     uint16_t port, 
1868                                     void *dest,
1869                                     uint_t len,
1870                                     void *priv_data)
1871 {
1872     struct vga_internal *vga = (struct vga_internal *) priv_data;
1873
1874     PrintDebug("vga: video subsys enable read data=0x%x\n", 
1875                vga->vga_misc.vga_video_subsys_enable.val);
1876
1877     ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1878
1879     *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1880
1881     PASSTHROUGH_IO_IN(vga,port,dest,len);
1882
1883     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1884
1885     return len;
1886 }
1887
1888 static int video_subsys_enable_write(struct guest_info *core, 
1889                                      uint16_t port, 
1890                                      void *src,
1891                                      uint_t len,
1892                                      void *priv_data)
1893 {
1894     struct vga_internal *vga = (struct vga_internal *) priv_data;
1895     
1896     PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1897         
1898     ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1899     
1900     PASSTHROUGH_IO_OUT(vga,port,src,len);
1901
1902     vga->vga_misc.vga_video_subsys_enable.val =  *((uint8_t*)src) ;
1903     
1904     render(vga);
1905     
1906     return len;
1907 }
1908
1909 static int sequencer_address_read(struct guest_info *core, 
1910                                   uint16_t port, 
1911                                   void *dest,
1912                                   uint_t len,
1913                                   void *priv_data)
1914 {
1915     struct vga_internal *vga = (struct vga_internal *) priv_data;
1916
1917     PrintDebug("vga: sequencer address read data=0x%x\n", 
1918                vga->vga_sequencer.vga_sequencer_addr.val);
1919
1920     ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1921
1922     *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1923
1924     PASSTHROUGH_IO_IN(vga,port,dest,len);
1925
1926     PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1927
1928     return len;
1929 }
1930
1931 static int sequencer_data_write(struct guest_info *core, 
1932                                uint16_t port, 
1933                                void *src,
1934                                uint_t len,
1935                                void *priv_data)
1936 {
1937     struct vga_internal *vga = (struct vga_internal *) priv_data;
1938     uint8_t index;
1939     uint8_t data;
1940     
1941     data=*((uint8_t*)src);
1942     index=vga->vga_sequencer.vga_sequencer_addr.val;  // should mask probably
1943     
1944     PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n", 
1945                index, data);
1946     
1947     ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1948     
1949     PASSTHROUGH_IO_OUT(vga,port,src,len);
1950
1951
1952     if (index>=VGA_SEQUENCER_NUM) { 
1953         PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index);
1954     } else {
1955         vga->vga_sequencer.vga_sequencer_regs[index] = data;
1956     }
1957
1958     render(vga);
1959     
1960     return len;
1961 }
1962
1963 static int sequencer_address_write(struct guest_info *core, 
1964                                   uint16_t port, 
1965                                   void *src,
1966                                   uint_t len,
1967                                   void *priv_data)
1968 {
1969     struct vga_internal *vga = (struct vga_internal *) priv_data;
1970     uint8_t new_addr;
1971
1972     new_addr=*((uint8_t*)src);
1973
1974     PrintDebug("vga: sequencer address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1975
1976     ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1977
1978     PASSTHROUGH_IO_OUT(vga,port,src,len);
1979     
1980     vga->vga_sequencer.vga_sequencer_addr.val =  *((uint8_t*)src) ;
1981     
1982     if (len==2) { 
1983         PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1984         // second byte is the data
1985         if (sequencer_data_write(core,port,src+1,1,vga)!=1) { 
1986             PrintError("vga: write of data failed\n");
1987             return -1;
1988         }
1989     }
1990
1991     return len;
1992 }
1993
1994 static int sequencer_data_read(struct guest_info *core, 
1995                               uint16_t port, 
1996                               void *dest,
1997                               uint_t len,
1998                               void *priv_data)
1999 {
2000     struct vga_internal *vga = (struct vga_internal *) priv_data;
2001     uint8_t index;
2002     uint8_t data;
2003
2004     index=vga->vga_sequencer.vga_sequencer_addr.val;  // should mask probably
2005
2006     if (index>=VGA_SEQUENCER_NUM) { 
2007         data=0;
2008         PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index);
2009     } else {
2010         data=vga->vga_sequencer.vga_sequencer_regs[index];
2011     }
2012
2013     PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n", 
2014                    index, data);
2015     
2016     ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2017
2018     *((uint8_t*)dest) = data;
2019
2020     PASSTHROUGH_IO_IN(vga,port,dest,len);
2021
2022     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2023
2024     return len;
2025 }
2026
2027  
2028  
2029
2030
2031 static int crt_controller_address_read(struct guest_info *core, 
2032                                         uint16_t port, 
2033                                         void *dest,
2034                                         uint_t len,
2035                                         void *priv_data)
2036 {
2037     struct vga_internal *vga = (struct vga_internal *) priv_data;
2038
2039     PrintDebug("vga: crt controller (%s) address read data=0x%x\n", 
2040                port==0x3b4 ? "mono" : "color",
2041                vga->vga_crt_controller.vga_crt_addr.val);
2042
2043     ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2044
2045     *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2046
2047     PASSTHROUGH_IO_IN(vga,port,dest,len);
2048
2049     PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2050
2051     return len;
2052 }
2053
2054 static int crt_controller_data_write(struct guest_info *core, 
2055                                      uint16_t port, 
2056                                      void *src,
2057                                      uint_t len,
2058                                      void *priv_data)
2059 {
2060     struct vga_internal *vga = (struct vga_internal *) priv_data;
2061     uint8_t index;
2062     uint8_t data;
2063
2064     data=*((uint8_t*)src);
2065
2066     index=vga->vga_crt_controller.vga_crt_addr.val;  // should mask probably
2067     
2068     PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n", 
2069                port==0x3b5 ? "mono" : "color",
2070                index, data);
2071
2072     ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2073
2074     PASSTHROUGH_IO_OUT(vga,port,src,len);
2075
2076     if (index>=VGA_CRT_CONTROLLER_NUM) { 
2077         PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index);
2078     } else {
2079         vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2080     }
2081
2082     render(vga);
2083
2084     return len;
2085 }
2086
2087 static int crt_controller_address_write(struct guest_info *core, 
2088                                         uint16_t port, 
2089                                         void *src,
2090                                         uint_t len,
2091                                         void *priv_data)
2092 {
2093     struct vga_internal *vga = (struct vga_internal *) priv_data;
2094     uint8_t new_addr;
2095
2096     new_addr=*((uint8_t*)src);
2097
2098     PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n", 
2099                port==0x3b4 ? "mono" : "color",
2100                len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2101
2102     ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2103
2104     PASSTHROUGH_IO_OUT(vga,port,src,len);
2105
2106     vga->vga_crt_controller.vga_crt_addr.val =  *((uint8_t*)src) ;
2107         
2108     if (len==2) { 
2109         PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2110         // second byte is the data
2111         if (crt_controller_data_write(core,port,src+1,1,vga)!=1) { 
2112             PrintError("vga: write of data failed\n");
2113             return -1;
2114         }
2115     }
2116     
2117     return len;
2118 }
2119
2120 static int crt_controller_data_read(struct guest_info *core, 
2121                                     uint16_t port, 
2122                                     void *dest,
2123                                     uint_t len,
2124                                     void *priv_data)
2125 {
2126     struct vga_internal *vga = (struct vga_internal *) priv_data;
2127     uint8_t index;
2128     uint8_t data;
2129
2130     index=vga->vga_crt_controller.vga_crt_addr.val;  // should mask probably
2131     
2132     if (index>=VGA_CRT_CONTROLLER_NUM) { 
2133         data=0;
2134         PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index);
2135     } else {
2136         data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2137     }
2138
2139     PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data);
2140     
2141     ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2142
2143     *((uint8_t*)dest) = data;
2144
2145     PASSTHROUGH_IO_IN(vga,port,dest,len);
2146
2147     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2148
2149     return len;
2150 }
2151
2152
2153
2154 static int graphics_controller_address_read(struct guest_info *core, 
2155                                             uint16_t port, 
2156                                             void *dest,
2157                                             uint_t len,
2158                                             void *priv_data)
2159 {
2160     struct vga_internal *vga = (struct vga_internal *) priv_data;
2161     
2162     PrintDebug("vga: graphics controller address read data=0x%x\n", 
2163                vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2164
2165     ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2166
2167     *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2168
2169     PASSTHROUGH_IO_IN(vga,port,dest,len);
2170
2171     PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2172
2173     return len;
2174 }
2175
2176 static int graphics_controller_data_write(struct guest_info *core, 
2177                                           uint16_t port, 
2178                                           void *src,
2179                                           uint_t len,
2180                                           void *priv_data)
2181 {
2182     struct vga_internal *vga = (struct vga_internal *) priv_data;
2183     uint8_t index;
2184     uint8_t data;
2185     
2186     data=*((uint8_t*)src);
2187     index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;  // should mask probably
2188     
2189
2190     PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n", 
2191                index, data);
2192     
2193     ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2194     
2195     PASSTHROUGH_IO_OUT(vga,port,src,len);
2196
2197     if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { 
2198         PrintError("vga: graphics controller write for illegal index %d ignored\n",index);
2199     } else {
2200         vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2201     }
2202
2203     render(vga);
2204     
2205     return len;
2206 }
2207
2208 static int graphics_controller_address_write(struct guest_info *core, 
2209                                              uint16_t port, 
2210                                              void *src,
2211                                              uint_t len,
2212                                              void *priv_data)
2213 {
2214     struct vga_internal *vga = (struct vga_internal *) priv_data;
2215     uint8_t new_addr;
2216
2217     new_addr=*((uint8_t*)src);
2218
2219     PrintDebug("vga: graphics controller address write data=0x%x len=%u\n", 
2220                len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2221
2222     ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2223
2224     PASSTHROUGH_IO_OUT(vga,port,src,len);
2225
2226     vga->vga_graphics_controller.vga_graphics_ctrl_addr.val =  *((uint8_t*)src) ;
2227
2228     if (len==2) { 
2229         PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2230         // second byte is the data
2231         if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) { 
2232             PrintError("vga: write of data failed\n");
2233             return -1;
2234         }
2235     }
2236
2237     return len;
2238 }
2239
2240 static int graphics_controller_data_read(struct guest_info *core, 
2241                                          uint16_t port, 
2242                                          void *dest,
2243                                          uint_t len,
2244                                          void *priv_data)
2245 {
2246     struct vga_internal *vga = (struct vga_internal *) priv_data;
2247     uint8_t index;
2248     uint8_t data;
2249
2250     index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;  // should mask probably
2251
2252
2253     if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { 
2254         data=0;
2255         PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index);
2256     } else {
2257         data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2258     }
2259     
2260     PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n", 
2261                index, data);
2262
2263     ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2264
2265     *((uint8_t*)dest) = data;
2266
2267     PASSTHROUGH_IO_IN(vga,port,dest,len);
2268
2269     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2270     
2271     return len;
2272 }
2273
2274
2275
2276
2277 /* Note that these guys have a bizarre protocol*/
2278
2279 static int attribute_controller_address_read(struct guest_info *core, 
2280                                              uint16_t port, 
2281                                              void *dest,
2282                                              uint_t len,
2283                                              void *priv_data)
2284 {
2285     struct vga_internal *vga = (struct vga_internal *) priv_data;
2286     
2287     PrintDebug("vga: attribute controller address read data=0x%x\n", 
2288                vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2289
2290     ERR_WRONG_SIZE("read","vga attribute  controller addr",len,1,1);
2291
2292     *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2293
2294     PASSTHROUGH_IO_IN(vga,port,dest,len);
2295
2296     PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2297
2298     // Reading the attribute controller does not change the state
2299
2300     return len;
2301 }
2302
2303 static int attribute_controller_address_and_data_write(struct guest_info *core, 
2304                                                        uint16_t port, 
2305                                                        void *src,
2306                                                        uint_t len,
2307                                                        void *priv_data)
2308 {
2309     struct vga_internal *vga = (struct vga_internal *) priv_data;
2310
2311
2312     if (vga->vga_attribute_controller.state==ATTR_ADDR) { 
2313         uint8_t new_addr = *((uint8_t*)src);
2314         // We are to treat this as an address write, and flip state
2315         // to expect data ON THIS SAME PORT
2316         PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
2317         
2318         ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2319
2320         PASSTHROUGH_IO_OUT(vga,port,src,len);
2321
2322         vga->vga_attribute_controller.vga_attribute_controller_addr.val =  new_addr;
2323
2324         vga->vga_attribute_controller.state=ATTR_DATA;
2325         return len;
2326
2327     } else if (vga->vga_attribute_controller.state==ATTR_DATA) { 
2328
2329         uint8_t data = *((uint8_t*)src);
2330         uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val;  // should mask probably
2331
2332         PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
2333         
2334         ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2335
2336         PASSTHROUGH_IO_OUT(vga,port,src,len);
2337         
2338         if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { 
2339             PrintError("vga: attribute controller write to illegal index %d ignored\n",index);
2340         } else {
2341             vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2342         }
2343         
2344         vga->vga_attribute_controller.state=ATTR_ADDR;
2345         
2346         return len;
2347     }
2348     
2349     return -1;
2350         
2351 }
2352
2353 static int attribute_controller_data_read(struct guest_info *core, 
2354                                           uint16_t port, 
2355                                           void *dest,
2356                                           uint_t len,
2357                                           void *priv_data)
2358 {
2359     struct vga_internal *vga = (struct vga_internal *) priv_data;
2360     uint8_t index;
2361     uint8_t data;
2362
2363     index=vga->vga_attribute_controller.vga_attribute_controller_addr.val;  // should mask probably
2364
2365     if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { 
2366         data=0;
2367         PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index);
2368     } else {
2369         data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2370     }
2371     
2372     PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n", 
2373                index, data);
2374
2375     ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2376
2377     *((uint8_t*)dest) = data;
2378
2379     PASSTHROUGH_IO_IN(vga,port,dest,len);
2380
2381     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2382
2383     return len;
2384 }
2385
2386
2387 /*
2388    Note that these guys also have a strange protocol
2389    since they need to squeeze 18 bits of data through
2390    an 8 bit port 
2391 */
2392 static int dac_write_address_read(struct guest_info *core, 
2393                                   uint16_t port, 
2394                                   void *dest,
2395                                   uint_t len,
2396                                   void *priv_data)
2397 {
2398     struct vga_internal *vga = (struct vga_internal *) priv_data;
2399     
2400     PrintDebug("vga: dac write address read data=0x%x\n", 
2401                vga->vga_dac.vga_dac_write_addr);
2402
2403     ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2404
2405
2406     *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2407
2408     PASSTHROUGH_IO_IN(vga,port,dest,len);
2409     
2410     PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2411
2412     // This read does not reset the state machine
2413
2414     return len;
2415 }
2416
2417 static int dac_write_address_write(struct guest_info *core, 
2418                                    uint16_t port, 
2419                                    void *src,
2420                                    uint_t len,
2421                                    void *priv_data)
2422 {
2423     struct vga_internal *vga = (struct vga_internal *) priv_data;
2424     uint8_t new_addr;
2425
2426     new_addr=*((uint8_t*)src);
2427
2428     PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
2429
2430     ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2431
2432     PASSTHROUGH_IO_OUT(vga,port,src,len);
2433
2434     // cannot be out of bounds since there are 256 regs
2435
2436     vga->vga_dac.vga_dac_write_addr =  *((uint8_t*)src) ;
2437
2438     // Now we also need to reset the state machine
2439     
2440     vga->vga_dac.state=DAC_WRITE;
2441     vga->vga_dac.channel=RED;
2442
2443     return len;
2444 }
2445
2446
2447 static int dac_read_address_read(struct guest_info *core, 
2448                                  uint16_t port, 
2449                                  void *dest,
2450                                  uint_t len,
2451                                  void *priv_data)
2452 {
2453     struct vga_internal *vga = (struct vga_internal *) priv_data;
2454     
2455     PrintDebug("vga: dac read address read data=0x%x\n", 
2456                vga->vga_dac.vga_dac_read_addr);
2457
2458     ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2459
2460     *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2461
2462     PASSTHROUGH_IO_IN(vga,port,dest,len);
2463
2464     PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2465     
2466     // This read does not reset the state machine
2467
2468     return len;
2469 }
2470
2471 static int dac_read_address_write(struct guest_info *core, 
2472                                   uint16_t port, 
2473                                   void *src,
2474                                   uint_t len,
2475                                   void *priv_data)
2476 {
2477     struct vga_internal *vga = (struct vga_internal *) priv_data;
2478     uint8_t new_addr;
2479
2480     new_addr=*((uint8_t*)src);
2481
2482     PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
2483
2484     ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2485
2486     PASSTHROUGH_IO_OUT(vga,port,src,len);
2487
2488     // cannot be out of bounds since there are 256 regs
2489
2490     vga->vga_dac.vga_dac_read_addr =  *((uint8_t*)src) ;
2491
2492     // Now we also need to reset the state machine
2493     
2494     vga->vga_dac.state=DAC_READ;
2495     vga->vga_dac.channel=RED;
2496
2497     return len;
2498 }
2499
2500
2501 static int dac_data_read(struct guest_info *core, 
2502                          uint16_t port, 
2503                          void *dest,
2504                          uint_t len,
2505                          void *priv_data)
2506 {
2507     struct vga_internal *vga = (struct vga_internal *) priv_data;
2508     uint8_t curreg;
2509     uint8_t curchannel;
2510     uint8_t data;
2511     
2512     if (vga->vga_dac.state!=DAC_READ) { 
2513         PrintError("vga: dac data read while in other state\n");
2514         // results undefined, so we continue
2515     }
2516
2517     ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2518
2519     curreg = vga->vga_dac.vga_dac_read_addr;
2520     curchannel = vga->vga_dac.channel;
2521     data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2522
2523     PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
2524                curreg, 
2525                curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN" 
2526                           : curchannel==2 ? "BLUE" : "BAD CHANNEL", 
2527                data);
2528
2529     *((uint8_t*)dest) = data;
2530
2531     PASSTHROUGH_IO_IN(vga,port,dest,len);
2532
2533     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2534     
2535     curchannel = (curchannel+1)%3;
2536     vga->vga_dac.channel=curchannel;
2537     if (curchannel==0) { 
2538         curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2539     } 
2540     vga->vga_dac.vga_dac_read_addr = curreg;
2541     vga->vga_dac.state=DAC_READ;
2542
2543     return len;
2544 }
2545
2546
2547
2548 static int dac_data_write(struct guest_info *core, 
2549                           uint16_t port, 
2550                           void *src,
2551                           uint_t len,
2552                           void *priv_data)
2553 {
2554     struct vga_internal *vga = (struct vga_internal *) priv_data;
2555     uint8_t curreg;
2556     uint8_t curchannel;
2557     uint8_t data;
2558     vga_palette_reg data32;
2559     vga_palette_reg mask32;
2560     
2561     if (vga->vga_dac.state!=DAC_WRITE) { 
2562         PrintError("vga: dac data write while in other state\n");
2563         // results undefined, so we continue
2564     }
2565
2566     ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2567
2568     PASSTHROUGH_IO_OUT(vga,port,src,len);
2569
2570     curreg = vga->vga_dac.vga_dac_write_addr;
2571     curchannel = vga->vga_dac.channel;
2572     data = *((uint8_t *)src);
2573
2574     PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
2575                curreg, 
2576                curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN" 
2577                           : curchannel==2 ? "BLUE" : "BAD CHANNEL", 
2578                data);
2579
2580     data32 = data & 0x3f ;
2581     data32 <<= curchannel*8;
2582     mask32 = ~(0xff << (curchannel * 8));
2583
2584     vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2585     vga->vga_dac.vga_dac_palette[curreg] |= data32;
2586
2587     curchannel = (curchannel+1)%3;
2588     vga->vga_dac.channel=curchannel;
2589     if (curchannel==0) { 
2590         curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2591     } 
2592     vga->vga_dac.vga_dac_write_addr = curreg;
2593     vga->vga_dac.state=DAC_WRITE;
2594
2595     render(vga);
2596
2597     return len;
2598 }
2599
2600  
2601
2602 static int dac_pixel_mask_read(struct guest_info *core, 
2603                                uint16_t port, 
2604                                void *dest,
2605                                uint_t len,
2606                                void *priv_data)
2607 {
2608     struct vga_internal *vga = (struct vga_internal *) priv_data;
2609     
2610     PrintDebug("vga: dac pixel mask read data=0x%x\n", 
2611                vga->vga_dac.vga_pixel_mask);
2612
2613     ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2614
2615     *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2616
2617     PASSTHROUGH_IO_IN(vga,port,dest,len);
2618
2619     PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2620
2621     return len;
2622 }
2623
2624 static int dac_pixel_mask_write(struct guest_info *core, 
2625                                 uint16_t port, 
2626                                 void *src,
2627                                 uint_t len,
2628                                 void *priv_data)
2629 {
2630     struct vga_internal *vga = (struct vga_internal *) priv_data;
2631     uint8_t new_data;
2632
2633     new_data=*((uint8_t*)src);
2634
2635     PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
2636
2637     ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2638
2639     PASSTHROUGH_IO_OUT(vga,port,src,len);
2640
2641     vga->vga_dac.vga_pixel_mask =  new_data;
2642
2643     return len;
2644 }
2645
2646 static int init_vga(struct vga_internal *vga)
2647 {
2648     // TODO: startup spec of register contents, if any
2649     PrintError("vga: init_vga is UNIMPLEMTED\n");
2650     return 0;
2651 }
2652
2653 static int free_vga(struct vga_internal *vga) 
2654 {
2655     int i;
2656     int ret;
2657     struct vm_device *dev = vga->dev;
2658
2659     // Framebuffer deletion is user's responsibility
2660
2661     //    if (vga->mem_store) {
2662     //  V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2663     //  vga->mem_store=0;
2664     //}
2665     
2666     for (i=0;i<MAP_NUM;i++) { 
2667         if (vga->map[i]) { 
2668             V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2669             vga->map[i]=0;
2670         }
2671     }
2672
2673     v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2674
2675     ret = 0;
2676
2677     ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2678     // The following also covers VGA_INPUT_STAT0_READ
2679     ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2680     // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2681     ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2682     // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2683     ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2684     ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2685     
2686     ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2687
2688     /* Sequencer registers */
2689     ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2690     ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2691
2692     /* CRT controller registers */
2693     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2694     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2695     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2696     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2697
2698     /* graphics controller registers */
2699     ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2700     ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2701
2702     /* attribute controller registers */
2703     ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2704     ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2705
2706     /* video DAC palette registers */
2707     ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2708     ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2709     ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2710     ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2711
2712
2713     if (vga->host_cons) { 
2714         v3_graphics_console_close(vga->host_cons);
2715     }
2716
2717     V3_Free(vga);
2718
2719     return 0;
2720 }
2721
2722 static struct v3_device_ops dev_ops = {
2723     .free = (int (*)(void *))free_vga,
2724 };
2725
2726
2727 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2728     struct vga_internal *vga;
2729     int i;
2730     int ret;
2731
2732     char * dev_id = v3_cfg_val(cfg, "ID");
2733     char * passthrough = v3_cfg_val(cfg, "passthrough");
2734     char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2735
2736     PrintDebug("vga: init_device\n");
2737
2738     vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2739
2740     if (!vga) { 
2741         PrintError("vga: cannot allocate\n");
2742         return -1;
2743     }
2744
2745     memset(vga, 0, sizeof(struct vga_internal));
2746
2747     vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2748     vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2749
2750     if (passthrough && strcasecmp(passthrough,"enable")==0) {
2751         PrintDebug("vga: enabling passthrough\n");
2752         vga->passthrough=true;
2753         vga->skip_next_passthrough_out=false;
2754     }
2755
2756
2757     if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) { 
2758         struct v3_frame_buffer_spec req;
2759
2760         PrintDebug("vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2761
2762         memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2763         memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2764
2765         req.height=VGA_MAXY;
2766         req.width=VGA_MAXX;
2767         req.bytes_per_pixel=4;
2768         req.bits_per_channel=8;
2769         req.red_offset=0;
2770         req.green_offset=1;
2771         req.blue_offset=2;
2772         
2773
2774         vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2775
2776         if (!vga->host_cons) { 
2777             PrintError("vga: unable to open host OS's graphics console\n");
2778             free_vga(vga);
2779             return -1;
2780         }
2781
2782         if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2783             PrintDebug("vga: warning: target spec differs from requested spec\n");
2784             PrintDebug("vga: request: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", req.width, req.height, req.bytes_per_pixel, req.bits_per_channel, req.red_offset, req.green_offset, req.blue_offset);
2785             PrintDebug("vga: response: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", vga->target_spec.width, vga->target_spec.height, vga->target_spec.bytes_per_pixel, vga->target_spec.bits_per_channel, vga->target_spec.red_offset, vga->target_spec.green_offset, vga->target_spec.blue_offset);
2786
2787         }
2788
2789         if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) { 
2790           V3_Print("vga: enabling console-driven rendering\n");
2791           if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) { 
2792             PrintError("vga: cannot enable console-driven rendering\n");
2793             free_vga(vga);
2794             return -1;
2795           }
2796         }
2797         
2798         V3_Print("vga: enabling console inquiry for updates\n");
2799         if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) { 
2800           PrintError("vga: cannot enable console inquiry for updates\n");
2801           free_vga(vga);
2802           return -1;
2803         }
2804    }
2805
2806     if (!vga->passthrough && !vga->host_cons) { 
2807         V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2808     }
2809
2810
2811     // No memory store is allocated since we will use a full memory hook
2812     // The VGA maps can be read as well as written
2813     // Reads also affect writes, since they are how you fill the latches
2814
2815     // Now allocate the maps
2816     for (i=0;i<MAP_NUM;i++) { 
2817         vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
2818         if (!(vga->map[i])) {
2819             PrintError("vga: cannot allocate maps\n");
2820             free_vga(vga);
2821             return -1;
2822         }
2823         memset(vga->map[i],0,MAP_SIZE);
2824     }
2825     
2826     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2827     
2828     if (dev == NULL) {
2829         PrintError("Could not attach device %s\n", dev_id);
2830         free_vga(vga);
2831         return -1;
2832     }
2833     
2834     vga->dev = dev;
2835     
2836     if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY, 
2837                          MEM_REGION_START, MEM_REGION_END,
2838                          &vga_read, 
2839                          &vga_write,
2840                          dev) == -1) {
2841         PrintError("vga: memory book failed\n");
2842         v3_remove_device(dev);
2843         return -1;
2844     }
2845
2846     ret = 0;
2847     
2848     /* Miscelaneous registers */
2849     ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2850     // The following also covers VGA_INPUT_STAT0_READ
2851     ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2852     // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2853     ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2854     // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2855     ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2856     ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2857     
2858     ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2859
2860     /* Sequencer registers */
2861     ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2862     ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2863
2864     /* CRT controller registers */
2865     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2866     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2867     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2868     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2869
2870     /* graphics controller registers */
2871     ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2872     ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2873
2874     /* attribute controller registers */
2875     ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2876     ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2877
2878     /* video DAC palette registers */
2879     ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2880     ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2881     ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2882     ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2883
2884     if (ret != 0) {
2885         PrintError("vga: Error allocating VGA I/O ports\n");
2886         v3_remove_device(dev);
2887         return -1;
2888     }
2889
2890     init_vga(vga);
2891
2892     PrintDebug("vga: successfully added and initialized.\n");
2893
2894     return 0;
2895
2896 }
2897
2898 device_register("VGA", vga_init);