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.


037223ebcc3643a6b620ce50f972cb1ac582e545
[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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE, "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     PrintDebug(VM_NONE, VCORE_NONE, "\n");
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                 PrintDebug(VM_NONE, VCORE_NONE, "%c",ct);
846
847                 // find the character's font bitmap (one byte per row)
848                 find_text_font_start(vga,(void**)&font,
849                                      extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 ); 
850
851                 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
852
853                 // Now let's find out what colors we will be using
854                 // foreground
855                 
856                 if (!extended_fontset(vga)) { 
857                     fg_entry = a.foreground_intensity_or_font_select << 3;
858                 } else {
859                     fg_entry = 0;
860                 }
861                 fg_entry |= a.fore;
862
863                 find_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
864
865                 if (!blinking(vga)) { 
866                     bg_entry = a.blinking_or_bg_intensity << 3;
867                 } else {
868                     bg_entry = 0;
869                 }
870                 bg_entry |= a.back;
871                 
872                 find_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
873
874                 // Draw the character
875                 for (l=0; l<ch; l++, font++) {
876                     uint8_t frow = *font;  // this is the row of of the font map
877                     for (p=0;p<cw;p++) {
878                         uint8_t fbit;
879                         
880                         // a char can be 9 bits wide, but the font map
881                         // is only 8 bits wide, which means we need to know where to
882                         // get the 9th bit
883                         if (p >= 8) { 
884                             // We get it from the font map if
885                             // its line line graphics mode and its a graphics char
886                             // otherwise it's the background color
887                             if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
888                                 && ct>=0xc0 && ct<=0xdf ) { 
889                                 fbit = frow & 0x1;
890                             } else {
891                                 fbit = 0;
892                             }
893                         } else {
894                             fbit= (frow >> (7-p) ) & 0x1;
895                         }
896                         
897                         // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
898                         // For now, we will draw it as black/white
899
900                         // find its position in the framebuffer;
901                         fx = x*cw + p;
902                         fy = y*ch + l;
903                         pixel =  fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
904                         red = pixel + spec->red_offset;
905                         green = pixel + spec->green_offset;
906                         blue = pixel + spec->blue_offset;
907
908                         // Are we on the cursor?
909                         // if so, let's negate this pixel to invert the cell
910                         if (curs==text) { 
911                             fbit^=0x1;
912                         }
913                         // update the framebuffer
914                         if (fbit) { 
915                             *red=fgr; 
916                             *green=fgg;
917                             *blue=fgb;
918                         } else {
919                             *red=bgr;
920                             *green=bgg;
921                             *blue=bgb;
922                         }
923                     }
924                 }
925             }
926         }
927         PrintDebug(VM_NONE, VCORE_NONE, "\n");
928     }
929
930 }
931
932                         
933                         
934
935
936 static void render_test(struct vga_internal *vga, void *fb)
937 {
938     struct v3_frame_buffer_spec *s;
939
940     s=&(vga->target_spec);
941
942     if (fb && s->height>=480 && s->width>=640 ) { 
943         uint8_t color = (uint8_t)(vga->updates_since_render);
944         
945         uint32_t x, y;
946         
947         for (y=0;y<480;y++) {
948             for (x=0;x<640;x++) { 
949                 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
950                 uint8_t *red = pixel + s->red_offset;
951                 uint8_t *green = pixel + s->green_offset;
952                 uint8_t *blue = pixel + s->blue_offset;
953                 
954                 if (y<(480/4)) { 
955                     *red=color+x;
956                     *green=0;
957                     *blue=0;
958                 } else if (y<(480/2)) { 
959                     *red=0;
960                     *green=color+x;
961                     *blue=0;
962                 } else if (y<(3*(480/4))) { 
963                     *red=0;
964                     *green=0;
965                     *blue=color+x;
966                 } else {
967                     *red=*green=*blue=color+x;
968                 }
969             }
970         }
971     }
972 }
973
974 static void render_black(struct vga_internal *vga, void *fb)
975 {
976     struct v3_frame_buffer_spec *s;
977
978     s=&(vga->target_spec);
979
980     memset(fb,0,s->height*s->width*s->bytes_per_pixel);
981 }
982
983 static void render_maps(struct vga_internal *vga, void *fb)
984 {
985
986     struct v3_frame_buffer_spec *s;
987     
988
989     s=&(vga->target_spec);
990
991     if (fb && s->height>=768 && s->width>=1024 ) { 
992         // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
993         uint8_t m;
994         uint32_t x,y;
995         uint8_t *b;
996         
997         for (m=0;m<4;m++) { 
998             b=(vga->map[m]);
999             for (y=480+32;y<768;y++) { 
1000                 for (x=m*256;x<(m+1)*256;x++,b++) { 
1001                     void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
1002                     uint8_t *red = pixel + s->red_offset;
1003                     uint8_t *green = pixel + s->green_offset;
1004                     uint8_t *blue = pixel + s->blue_offset;
1005                     
1006                     *red=*green=*blue=*b;
1007                 }
1008             }
1009         }
1010     }
1011 }
1012
1013 static int render_core(struct vga_internal *vga)
1014 {
1015   void *fb;
1016
1017   PrintDebug(VM_NONE, VCORE_NONE, "vga: render on update %u\n",vga->updates_since_render);
1018   
1019   fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
1020   
1021   if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
1022     if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) { 
1023       render_graphics(vga,fb);
1024     } else {
1025           render_text(vga,fb);
1026           render_text_cursor(vga,fb);
1027         }
1028   } else {
1029     render_black(vga,fb);
1030   }
1031   
1032   if (0) { render_test(vga,fb); }
1033   
1034   // always render maps for now 
1035   render_maps(vga,fb);
1036   
1037   v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
1038   
1039   vga->updates_since_render=0;
1040   
1041   return 0;
1042
1043 }
1044     
1045
1046 static int render(struct vga_internal *vga)
1047 {
1048
1049     vga->updates_since_render++;
1050
1051
1052     if (vga->host_cons) { 
1053       int do_render=0;
1054       
1055       if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING)
1056           &&
1057           (vga->updates_since_render > vga->render_model.updates_before_render)) {
1058         PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to periodic\n");
1059         
1060         do_render = 1;
1061       }
1062       
1063       if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING) 
1064           &&
1065           (v3_graphics_console_inform_update(vga->host_cons) > 0) ) { 
1066
1067         PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to advisory\n");
1068
1069         do_render = 1;
1070       }
1071
1072       // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function
1073       
1074       if (do_render) { 
1075         return render_core(vga);
1076       } else {
1077         return 0;
1078       }
1079     }
1080     return 0;
1081     
1082 }
1083
1084
1085 static int render_callback(v3_graphics_console_t cons,
1086                            void *priv)
1087 {
1088   struct vga_internal *vga = (struct vga_internal *) priv;
1089   
1090   PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to callback\n");
1091
1092   return render_core(vga);
1093 }
1094
1095 static int update_callback(v3_graphics_console_t cons,
1096                            void *priv)
1097 {
1098   struct vga_internal *vga = (struct vga_internal *) priv;
1099   
1100   return vga->updates_since_render>0;
1101 }
1102
1103
1104
1105 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end) 
1106 {
1107     switch (vga->vga_graphics_controller.vga_misc.memory_map) { 
1108         case 0: 
1109             *mem_start=0xa0000;
1110             *mem_end=0xc0000;
1111             break;
1112         case 1:
1113             *mem_start=0xa0000;
1114             *mem_end=0xb0000;
1115             break;
1116         case 2:
1117             *mem_start=0xb0000;
1118             *mem_end=0xb8000;
1119             break;
1120         case 3:
1121             *mem_start=0xb8000;
1122             *mem_end=0xc0000;
1123             break;
1124     }
1125 }
1126
1127 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
1128 {
1129     uint64_t mem_start, mem_end;
1130     uint64_t size;
1131     
1132     mem_start=mem_end=0;
1133     
1134     get_mem_region(vga, &mem_start, &mem_end);
1135     
1136     size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); 
1137
1138     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
1139       // NOT odd/even mode
1140       return (guest_addr-mem_start) % size;
1141     } else {
1142         // odd/even mode
1143       return ((guest_addr-mem_start) >> 1 ) % size;
1144     }
1145 }
1146
1147
1148
1149     
1150 // Determines which maps should be enabled for this single byte write
1151 // and what the increment (actually 1/increment for the copy loop
1152 //
1153 //  memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
1154 //  
1155 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
1156 {
1157     uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
1158
1159     if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
1160       // NOT odd/even mode
1161       return mm;
1162     } else {
1163       // odd/even mode
1164       if (guest_addr & 0x1) { 
1165         return mm & 0xa;  // 0x1010
1166       } else {
1167         return mm & 0x5;  // 0x0101
1168       }
1169     }
1170 }
1171
1172 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
1173 {
1174   if (vga->vga_sequencer.vga_mem_mode.odd_even) { 
1175     // NOT odd/even mode
1176     return 1;
1177   } else {
1178     return !(new_guest_addr & 0x1);
1179   }
1180 }
1181
1182
1183
1184 static int vga_write(struct guest_info * core, 
1185                      addr_t guest_addr, 
1186                      void * src, 
1187                      uint_t length, 
1188                      void * priv_data)
1189 {
1190     struct vm_device *dev = (struct vm_device *)priv_data;
1191     struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1192
1193     PrintDebug(core->vm_info, core, "vga: memory write: guest_addr=0x%p len=%u write_mode=%d first_byte=0x%x\n",
1194                (void*)guest_addr, length, vga->vga_graphics_controller.vga_graphics_mode.write_mode, *(uint8_t*)src);
1195
1196     if (vga->passthrough) { 
1197         PrintDebug(core->vm_info, core, "vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
1198         memcpy(V3_VAddr((void*)guest_addr),src,length);
1199     }
1200     
1201 #if DEBUG_MEM_DATA
1202     int i;
1203     PrintDebug(core->vm_info, core, "vga: data written was 0x");
1204     for (i=0;i<length;i++) {
1205         uint8_t c= ((char*)src)[i];
1206         PrintDebug(core->vm_info, core, "%.2x", c);
1207     }
1208     PrintDebug(core->vm_info, core, " \"");
1209     for (i=0;i<length;i++) {
1210         char c= ((char*)src)[i];
1211         PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1212     }
1213     PrintDebug(core->vm_info, core, "\"\n");
1214 #endif
1215
1216     /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
1217
1218
1219     // probably could just reduce this to the datapath itself instead
1220     // of following the programmer's perspective... 
1221
1222     switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1223         case 0: {
1224             
1225             /* 
1226                00b -- Write Mode 0: In this mode, the host data is first rotated 
1227                as per the Rotate Count field, then the Enable Set/Reset mechanism 
1228                selects data from this or the Set/Reset field. Then the selected 
1229                Logical Operation is performed on the resulting data and the data 
1230                in the latch register. Then the Bit Mask field is used to select 
1231                which bits come from the resulting data and which come 
1232                from the latch register. Finally, only the bit planes enabled by 
1233                the Memory Plane Write Enable field are written to memory.
1234             */
1235
1236             int i;
1237
1238             uint8_t  mapnum;
1239             uint64_t offset;
1240
1241             uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1242             uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1243             
1244             offset = find_offset_write(vga, guest_addr);
1245
1246 #if DEBUG_DEEP_MEM
1247             PrintDebug(core->vm_info, core, "vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1248 #endif
1249
1250             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1251                 // now for each map
1252                 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1253                 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1254                 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1255                 uint8_t mm = find_map_write(vga,guest_addr+i);
1256
1257 #if DEBUG_DEEP_MEM
1258                 PrintDebug(core->vm_info, core, "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);
1259 #endif
1260
1261                 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) { 
1262                     vga_map map = vga->map[mapnum];
1263                     uint8_t data = ((uint8_t *)src)[i];
1264                     uint8_t latchval = vga->latch[mapnum];
1265                     
1266 #if DEBUG_DEEP_MEM
1267                     PrintDebug(core->vm_info, core, "vga: raw data=0x%x\n",data);
1268 #endif
1269                     // rotate data right
1270                     if (ror) { 
1271                         data = (data>>ror) | (data<<(8-ror));
1272                     }
1273                     
1274 #if DEBUG_DEEP_MEM
1275                     PrintDebug(core->vm_info, core, "vga: data after ror=0x%x\n",data);
1276 #endif
1277                     // use SR bit if ESR is on for this map
1278                     if (esr & 0x1) {
1279                         data = (sr&0x1) * -1;
1280                         
1281                     }
1282                     
1283 #if DEBUG_DEEP_MEM
1284                     PrintDebug(core->vm_info, core, "vga: data after esrr=0x%x\n",data);
1285 #endif
1286                     
1287                     // Apply function
1288                     switch (func) { 
1289                         case 0: // NOP
1290                             break;
1291                         case 1: // AND
1292                             data &= latchval;
1293                             break;
1294                         case 2: // OR
1295                             data |= latchval;
1296                             break;
1297                         case 3: // XOR
1298                             data ^= latchval;
1299                             break;
1300                     }
1301                     
1302 #if DEBUG_DEEP_MEM
1303                     PrintDebug(core->vm_info, core, "vga: data after func=0x%x\n",data);
1304 #endif
1305                     
1306                     // mux between the data byte and the latch byte on
1307                     // a per-bit basis
1308                     data = (bm & data) | ((~bm) & latchval);
1309                     
1310
1311 #if DEBUG_DEEP_MEM
1312                     PrintDebug(core->vm_info, core, "vga: data after bm mux=0x%x\n",data);
1313 #endif
1314                     
1315                     // selective write
1316                     if (mm & 0x1) { 
1317                         // write to this map
1318 #if DEBUG_DEEP_MEM
1319                         PrintDebug(core->vm_info, core, "vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
1320 #endif
1321                         map[offset] = data;
1322                     } else {
1323                         // skip this map
1324                     }
1325                 }
1326             }
1327         }
1328             break;
1329
1330
1331             
1332         case 1: {
1333             /* 
1334                01b -- Write Mode 1: In this mode, data is transferred directly 
1335                from the 32 bit latch register to display memory, affected only by 
1336                the Memory Plane Write Enable field. The host data is not used in this mode.
1337             */
1338
1339             int i;
1340
1341             uint64_t offset = find_offset_write(vga,guest_addr);
1342
1343 #if DEBUG_DEEP_MEM
1344             PrintDebug(core->vm_info, core, "vga: mode 1 write, offset=0x%llx\n", offset);
1345 #endif
1346
1347             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1348
1349                 uint8_t mapnum;
1350                 uint8_t mm = find_map_write(vga,guest_addr+i);
1351
1352                 for (mapnum=0;mapnum<4;mapnum++,  mm>>=1) { 
1353                     vga_map map = vga->map[mapnum];
1354                     uint8_t latchval = vga->latch[mapnum];
1355                         
1356                     // selective write
1357                     if (mm & 0x1) { 
1358                         // write to this map
1359                         map[offset] = latchval;
1360                     } else {
1361                         // skip this map
1362                     }
1363                 }
1364             }
1365         }
1366             break;
1367
1368         case 2: {
1369             /*
1370               10b -- Write Mode 2: In this mode, the bits 3-0 of the host data 
1371               are replicated across all 8 bits of their respective planes. 
1372               Then the selected Logical Operation is performed on the resulting 
1373               data and the data in the latch register. Then the Bit Mask field is used to 
1374               select which bits come from the resulting data and which come from 
1375               the latch register. Finally, only the bit planes enabled by the 
1376               Memory Plane Write Enable field are written to memory.
1377             */
1378             int i;
1379             uint8_t  mapnum;
1380             uint64_t offset;
1381
1382             uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1383             
1384             offset = find_offset_write(vga, guest_addr);
1385
1386 #if DEBUG_DEEP_MEM
1387             PrintDebug(core->vm_info, core, "vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1388 #endif
1389
1390             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1391                 // now for each map
1392                 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1393                 uint8_t mm = find_map_write(vga,guest_addr+i);
1394
1395                 for (mapnum=0;mapnum<4;mapnum++,  mm>>=1) { 
1396                     vga_map map = vga->map[mapnum];
1397                     uint8_t data = ((uint8_t *)src)[i];
1398                     uint8_t latchval = vga->latch[mapnum];
1399                         
1400                     // expand relevant bit to 8 bit
1401                     // it's basically esr=1, sr=bit from mode 0 write
1402                     data = ((data>>mapnum)&0x1) * -1;
1403                         
1404                     // Apply function
1405                     switch (func) { 
1406                         case 0: // NOP
1407                             break;
1408                         case 1: // AND
1409                             data &= latchval;
1410                             break;
1411                         case 2: // OR
1412                             data |= latchval;
1413                             break;
1414                         case 3: // XOR
1415                             data ^= latchval;
1416                             break;
1417                     }
1418
1419                     // mux between latch and alu output
1420                     data = (bm & data) | ((~bm) & latchval);
1421                     
1422                     // selective write
1423                     if (mm & 0x1) { 
1424                         // write to this map
1425                         map[offset] = data;
1426                     } else {
1427                         // skip this map
1428                     }
1429                 }
1430             }
1431         }
1432             break;
1433
1434         case 3: {
1435             /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used 
1436                as if the Enable Set/Reset field were set to 1111b. Then the host data is 
1437                first rotated as per the Rotate Count field, then logical ANDed with the 
1438                value of the Bit Mask field. The resulting value is used on the data 
1439                obtained from the Set/Reset field in the same way that the Bit Mask field 
1440                would ordinarily be used. to select which bits come from the expansion 
1441                of the Set/Reset field and which come from the latch register. Finally, 
1442                only the bit planes enabled by the Memory Plane Write Enable field 
1443                are written to memory.
1444             */
1445             int i;
1446
1447             uint8_t  mapnum;
1448             uint64_t offset;
1449
1450             uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1451             
1452             offset = find_offset_write(vga, guest_addr);
1453
1454             PrintDebug(core->vm_info, core, "vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1455
1456             for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) { 
1457                 // now for each map
1458                 uint8_t data = ((uint8_t *)src)[i];
1459
1460                 if (ror) {
1461                     data = (data>>ror) | (data<<(8-ror));
1462                 }
1463
1464                 // Note here that the bitmask is the register AND the data
1465                 // the data written by the system is used for no other purpose
1466                 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1467
1468                 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1469
1470                 uint8_t mm = find_map_write(vga,guest_addr+i);
1471
1472                 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, mm>>=1) { 
1473                     vga_map map = vga->map[mapnum];
1474                     uint8_t latchval = vga->latch[mapnum];
1475                         
1476                     // expand SR bit - that's the data we're going to use
1477                     data = (sr&0x1) * -1;
1478
1479                     // mux between latch and alu output
1480                     data = (bm & data) | ((~bm) & latchval);
1481                     
1482                     // selective write
1483                     if (mm & 0x1) { 
1484                         // write to this map
1485                         map[offset] = data;
1486                     } else {
1487                         // skip this map
1488                     }
1489                 }
1490             }
1491
1492         }
1493             break;
1494
1495             // There is no default
1496     }
1497
1498     render(vga);
1499     
1500     return length;
1501 }
1502
1503
1504
1505 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1506 {
1507     uint64_t mem_start, mem_end;
1508     uint64_t size;
1509     
1510     mem_start=mem_end=0;
1511     
1512     get_mem_region(vga, &mem_start, &mem_end);
1513     
1514     size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start)); 
1515
1516     if (!vga->vga_sequencer.vga_mem_mode.odd_even) { 
1517       // odd/even mode takes priority
1518       return ((guest_addr-mem_start) >> 1 ) % size;
1519     } 
1520
1521     if (vga->vga_sequencer.vga_mem_mode.chain4) {
1522       // otherwise chain4 if it's on
1523       return ((guest_addr - mem_start) >> 2) % size;
1524     }
1525
1526     // and what you would expect if neither are on
1527     return (guest_addr-mem_start) % size;
1528 }
1529
1530 // Given this address
1531 // which specific map should we write into?
1532 // Note that unlike with find_map_write, here we are looking
1533 // for a single map number, not a bit vector of maps to be selected
1534 static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr)
1535 {
1536     uint64_t mem_start, mem_end;
1537     
1538     mem_start=mem_end=0;
1539     
1540     get_mem_region(vga, &mem_start, &mem_end);
1541     
1542     if (!vga->vga_sequencer.vga_mem_mode.odd_even) { 
1543       // odd-even mode
1544       // last bit tells us map 0 or 1
1545       return (guest_addr-mem_start) & 0x1; 
1546     } 
1547
1548     if (vga->vga_sequencer.vga_mem_mode.chain4) {
1549       // otherwise chain4 if it's on
1550       // last two bits
1551       return (guest_addr - mem_start) & 0x3;
1552     }
1553
1554     // and what you would expect if neither are on
1555     // note that it's not the same as a write!
1556     return vga->vga_graphics_controller.vga_read_map_select.map_select;
1557 }
1558
1559 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1560 {
1561
1562   if (!vga->vga_sequencer.vga_mem_mode.odd_even) { 
1563     // odd-even mode
1564     return !(new_guest_addr & 0x1); 
1565   } 
1566
1567   if (vga->vga_sequencer.vga_mem_mode.chain4) { 
1568     return !(new_guest_addr & 0x3);
1569   } 
1570   return 1;
1571 }
1572
1573
1574 static int vga_read(struct guest_info * core, 
1575                     addr_t guest_addr, 
1576                     void * dst, 
1577                     uint_t length, 
1578                     void * priv_data)
1579 {
1580     struct vm_device *dev = (struct vm_device *)priv_data;
1581     struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1582     
1583
1584     PrintDebug(core->vm_info, core, "vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length,
1585                vga->vga_graphics_controller.vga_graphics_mode.read_mode);
1586
1587         
1588    
1589     /*
1590       Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1591     */
1592     switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) { 
1593         case 0: {
1594             /*      0 - a byte from ONE of the 4 planes is returned; 
1595                     which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
1596                     OR by odd/even chaining OR by chain4 chaining
1597             */
1598             uint8_t  mapnum;
1599             uint64_t offset;
1600             uint32_t i;
1601
1602             offset = find_offset_read(vga,guest_addr);
1603             
1604 #if DEBUG_DEEP_MEM
1605             PrintDebug(core->vm_info, core, "vga: mode 0 read, offset=0x%llx\n",offset);
1606 #endif
1607             for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) { 
1608
1609               mapnum = find_map_read(vga,guest_addr+i);
1610
1611               // the data returned
1612               ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1613               
1614               // need to load all latches even though we are 
1615               // returning data from only the selected map
1616               for (mapnum=0;mapnum<4;mapnum++) { 
1617                 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1618               }
1619
1620             }
1621         
1622         }
1623             break;
1624         case 1: {
1625             /*      1 - Compare video memory and reference color 
1626                     (in Color Compare, except those not set in Color Don't Care), 
1627                     each bit in returned result is one comparison between the reference color 
1628
1629                     Ref color is *4* bits, and thus a one byte read returns a comparison 
1630                     with 8 pixels
1631
1632             */
1633             int i;
1634             uint64_t offset;
1635             
1636             offset = find_offset_read(vga,guest_addr);
1637
1638 #if DEBUG_DEEP_MEM
1639             PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx\n",offset);
1640 #endif
1641                 
1642             for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) { 
1643               uint8_t mapnum;
1644               uint8_t mapcalc=0xff;
1645               
1646               uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1647               uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1648               
1649               for (mapnum=0;mapnum<4;mapnum++, cc>>=1, dc>>=1) { 
1650                 if (dc&0x1) {  // dc is active low; 1=we do care
1651                   mapcalc &= (cc * -1) & *(vga->map[mapnum]+offset);
1652                 }
1653                 // do latch load
1654                 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1655               }
1656               // write back the comparison result (for 8 pixels)
1657               ((uint8_t *)dst)[i]=mapcalc;
1658             }
1659
1660         }
1661
1662             break;
1663             // there is no default
1664     }
1665
1666     if (vga->passthrough) { 
1667         PrintDebug(core->vm_info, core, "vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1668         memcpy(dst,V3_VAddr((void*)guest_addr),length);
1669     }
1670
1671
1672 #if DEBUG_MEM_DATA
1673     int i;
1674     PrintDebug(core->vm_info, core, "vga: data read is 0x");
1675     for (i=0;i<length;i++) {
1676         uint8_t c= ((char*)dst)[i];
1677         PrintDebug(core->vm_info, core, "%.2x", c);
1678     }
1679     PrintDebug(core->vm_info, core, " \"");
1680     for (i=0;i<length;i++) {
1681         char c= ((char*)dst)[i];
1682         PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1683     }
1684     PrintDebug(core->vm_info, core, "\"\n");
1685 #endif
1686
1687     return length;
1688
1689 }
1690
1691
1692
1693
1694
1695 #define ERR_WRONG_SIZE(op,reg,len,min,max)      \
1696     if (((len)<(min)) || ((len)>(max))) {       \
1697         PrintError(core->vm_info, core, "vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
1698         return -1; \
1699 }
1700         
1701 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1702     switch (length) {
1703         case 1:
1704             *(uint8_t *)dest = v3_inb(port);
1705             break;
1706         case 2:
1707             *(uint16_t *)dest = v3_inw(port);
1708             break;
1709         case 4:
1710             *(uint32_t *)dest = v3_indw(port);
1711             break;
1712         default:
1713             PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io in size %u\n",length);
1714             break;
1715     }
1716 }
1717
1718
1719 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1720     switch (length) {
1721         case 1:
1722             v3_outb(port, *(uint8_t *)src);
1723             break;
1724         case 2:
1725             v3_outw(port, *(uint16_t *)src);
1726             break;
1727         case 4:
1728             v3_outdw(port, *(uint32_t *)src);
1729             break;
1730         default:
1731             PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io out size %u\n",length);
1732             break;
1733     }
1734 }
1735
1736 #define PASSTHROUGH_IO_IN(vga,port,dest,len)                            \
1737     do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1738
1739 #define PASSTHROUGH_IO_OUT(vga,port,src,len)                            \
1740     do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1741
1742 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga)                                       \
1743     do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1744                 
1745 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1746     do { if ((vga)->passthrough) { if ((inter)!=(pass)) { PrintError(core->vm_info, core, "vga: passthrough error: passthrough value read is 0x%x, but internal value read is 0x%x\n",(pass),(inter)); } } } while (0)
1747
1748 static int misc_out_read(struct guest_info *core, 
1749                          uint16_t port, 
1750                          void *dest,
1751                          uint_t len,
1752                          void *priv_data)
1753 {
1754     struct vga_internal *vga = (struct vga_internal *) priv_data;
1755
1756     PrintDebug(core->vm_info, core, "vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1757
1758     ERR_WRONG_SIZE("read","misc out",len,1,1);
1759    
1760     *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1761
1762     PASSTHROUGH_IO_IN(vga,port,dest,len);
1763
1764     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1765
1766     return len;
1767 }
1768
1769 static int misc_out_write(struct guest_info *core, 
1770                           uint16_t port, 
1771                           void *src,
1772                           uint_t len,
1773                           void *priv_data)
1774 {
1775     struct vga_internal *vga = (struct vga_internal *) priv_data;
1776     
1777     PrintDebug(core->vm_info, core, "vga: misc out write data=0x%x\n", *((uint8_t*)src));
1778         
1779     ERR_WRONG_SIZE("write","misc out",len,1,1);
1780
1781     PASSTHROUGH_IO_OUT(vga,port,src,len);
1782
1783     vga->vga_misc.vga_misc_out.val =  *((uint8_t*)src) ;
1784     
1785     render(vga);
1786     
1787     return len;
1788 }
1789
1790
1791
1792 static int input_stat0_read(struct guest_info *core, 
1793                             uint16_t port, 
1794                             void *dest,
1795                             uint_t len,
1796                             void *priv_data)
1797 {
1798     struct vga_internal *vga = (struct vga_internal *) priv_data;
1799
1800     PrintDebug(core->vm_info, core, "vga: input stat0  read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1801
1802     ERR_WRONG_SIZE("read","input stat0",len,1,1);
1803
1804     *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1805
1806     PASSTHROUGH_IO_IN(vga,port,dest,len);
1807
1808     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1809
1810     return len;
1811 }
1812
1813
1814 static int input_stat1_read(struct guest_info *core, 
1815                             uint16_t port, 
1816                             void *dest,
1817                             uint_t len,
1818                             void *priv_data)
1819 {
1820     struct vga_internal *vga = (struct vga_internal *) priv_data;
1821
1822     PrintDebug(core->vm_info, core, "vga: input stat0 (%s) read data=0x%x\n", 
1823                port==0x3ba ? "mono" : "color",
1824                vga->vga_misc.vga_input_stat1.val);
1825
1826     ERR_WRONG_SIZE("read","input stat1",len,1,1);
1827
1828
1829     *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1830
1831     // Pretend that horizontal and vertical blanking
1832     // is occurring
1833     if (!vga->vga_misc.vga_input_stat1.disp_en) {
1834
1835         // if not blanking, start horizontal blanking
1836         vga->vga_misc.vga_input_stat1.disp_en = 1;
1837         vga->vga_misc.vga_input_stat1.vert_retrace = 0;
1838
1839     } else {
1840
1841         if (!vga->vga_misc.vga_input_stat1.vert_retrace) {
1842             // if not vertical blanking, then now vertical blanking
1843             vga->vga_misc.vga_input_stat1.disp_en = 1;
1844             vga->vga_misc.vga_input_stat1.vert_retrace = 1;
1845         } else { 
1846             // if vertical blanking, now not blanking
1847             vga->vga_misc.vga_input_stat1.disp_en = 0;
1848             vga->vga_misc.vga_input_stat1.vert_retrace = 0;
1849         }
1850
1851     }
1852
1853     // Stunningly, reading stat1 is also a way to reset
1854     // the state of attribute controller address/data flipflop
1855     // That is some mighty fine crack the designers were smoking.
1856     
1857     vga->vga_attribute_controller.state=ATTR_ADDR;
1858
1859     PASSTHROUGH_IO_IN(vga,port,dest,len);
1860
1861     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1862
1863     return len;
1864 }
1865                          
1866
1867 static int feature_control_read(struct guest_info *core, 
1868                                 uint16_t port, 
1869                                 void *dest,
1870                                 uint_t len,
1871                                 void *priv_data)
1872 {
1873     struct vga_internal *vga = (struct vga_internal *) priv_data;
1874
1875     PrintDebug(core->vm_info, core, "vga: feature control  read data=0x%x\n", 
1876                vga->vga_misc.vga_feature_control.val);
1877
1878     ERR_WRONG_SIZE("read","feature control",len,1,1);
1879
1880
1881     *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1882
1883     PASSTHROUGH_IO_IN(vga,port,dest,len);
1884
1885     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1886
1887     return len;
1888 }
1889
1890 static int feature_control_write(struct guest_info *core, 
1891                                  uint16_t port, 
1892                                  void *src,
1893                                  uint_t len,
1894                                  void *priv_data)
1895 {
1896     struct vga_internal *vga = (struct vga_internal *) priv_data;
1897     
1898     PrintDebug(core->vm_info, core, "vga: feature control (%s) write data=0x%x\n", 
1899                port==0x3ba ? "mono" : "color",
1900                *((uint8_t*)src));
1901         
1902     ERR_WRONG_SIZE("write","feature control",len,1,1);
1903     
1904     PASSTHROUGH_IO_OUT(vga,port,src,len);
1905
1906     vga->vga_misc.vga_feature_control.val =  *((uint8_t*)src) ;
1907     
1908     render(vga);
1909     
1910     return len;
1911 }
1912
1913
1914 static int video_subsys_enable_read(struct guest_info *core, 
1915                                     uint16_t port, 
1916                                     void *dest,
1917                                     uint_t len,
1918                                     void *priv_data)
1919 {
1920     struct vga_internal *vga = (struct vga_internal *) priv_data;
1921
1922     PrintDebug(core->vm_info, core, "vga: video subsys enable read data=0x%x\n", 
1923                vga->vga_misc.vga_video_subsys_enable.val);
1924
1925     ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1926
1927     *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1928
1929     PASSTHROUGH_IO_IN(vga,port,dest,len);
1930
1931     PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1932
1933     return len;
1934 }
1935
1936 static int video_subsys_enable_write(struct guest_info *core, 
1937                                      uint16_t port, 
1938                                      void *src,
1939                                      uint_t len,
1940                                      void *priv_data)
1941 {
1942     struct vga_internal *vga = (struct vga_internal *) priv_data;
1943     
1944     PrintDebug(core->vm_info, core, "vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1945         
1946     ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1947     
1948     PASSTHROUGH_IO_OUT(vga,port,src,len);
1949
1950     vga->vga_misc.vga_video_subsys_enable.val =  *((uint8_t*)src) ;
1951     
1952     render(vga);
1953     
1954     return len;
1955 }
1956
1957 static int sequencer_address_read(struct guest_info *core, 
1958                                   uint16_t port, 
1959                                   void *dest,
1960                                   uint_t len,
1961                                   void *priv_data)
1962 {
1963     struct vga_internal *vga = (struct vga_internal *) priv_data;
1964
1965     PrintDebug(core->vm_info, core, "vga: sequencer address read data=0x%x\n", 
1966                vga->vga_sequencer.vga_sequencer_addr.val);
1967
1968     ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1969
1970     *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1971
1972     PASSTHROUGH_IO_IN(vga,port,dest,len);
1973
1974     PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1975
1976     return len;
1977 }
1978
1979 static int sequencer_data_write(struct guest_info *core, 
1980                                uint16_t port, 
1981                                void *src,
1982                                uint_t len,
1983                                void *priv_data)
1984 {
1985     struct vga_internal *vga = (struct vga_internal *) priv_data;
1986     uint8_t index;
1987     uint8_t data;
1988     
1989     data=*((uint8_t*)src);
1990     index=vga->vga_sequencer.vga_sequencer_addr.val;  // should mask probably
1991     
1992     PrintDebug(core->vm_info, core, "vga: sequencer write data (index=%d) with 0x%x\n", 
1993                index, data);
1994     
1995     ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1996     
1997     PASSTHROUGH_IO_OUT(vga,port,src,len);
1998
1999
2000     if (index>=VGA_SEQUENCER_NUM) { 
2001         PrintError(core->vm_info, core, "vga: sequencer data write is for invalid index %d, ignoring\n",index);
2002     } else {
2003         vga->vga_sequencer.vga_sequencer_regs[index] = data;
2004     }
2005
2006     render(vga);
2007     
2008     return len;
2009 }
2010
2011 static int sequencer_address_write(struct guest_info *core, 
2012                                   uint16_t port, 
2013                                   void *src,
2014                                   uint_t len,
2015                                   void *priv_data)
2016 {
2017     struct vga_internal *vga = (struct vga_internal *) priv_data;
2018     uint8_t new_addr;
2019
2020     new_addr=*((uint8_t*)src);
2021
2022     PrintDebug(core->vm_info, core, "vga: sequencer address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2023
2024     ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
2025
2026     PASSTHROUGH_IO_OUT(vga,port,src,len);
2027     
2028     vga->vga_sequencer.vga_sequencer_addr.val =  *((uint8_t*)src) ;
2029     
2030     if (len==2) { 
2031         PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2032         // second byte is the data
2033         if (sequencer_data_write(core,port,src+1,1,vga)!=1) { 
2034             PrintError(core->vm_info, core, "vga: write of data failed\n");
2035             return -1;
2036         }
2037     }
2038
2039     return len;
2040 }
2041
2042 static int sequencer_data_read(struct guest_info *core, 
2043                               uint16_t port, 
2044                               void *dest,
2045                               uint_t len,
2046                               void *priv_data)
2047 {
2048     struct vga_internal *vga = (struct vga_internal *) priv_data;
2049     uint8_t index;
2050     uint8_t data;
2051
2052     index=vga->vga_sequencer.vga_sequencer_addr.val;  // should mask probably
2053
2054     if (index>=VGA_SEQUENCER_NUM) { 
2055         data=0;
2056         PrintError(core->vm_info, core, "vga: sequencer data read at invalid index %d, returning zero\n",index);
2057     } else {
2058         data=vga->vga_sequencer.vga_sequencer_regs[index];
2059     }
2060
2061     PrintDebug(core->vm_info, core, "vga: sequencer data read data (index=%d) = 0x%x\n", 
2062                    index, data);
2063     
2064     ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2065
2066     *((uint8_t*)dest) = data;
2067
2068     PASSTHROUGH_IO_IN(vga,port,dest,len);
2069
2070     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2071
2072     return len;
2073 }
2074
2075  
2076  
2077
2078
2079 static int crt_controller_address_read(struct guest_info *core, 
2080                                         uint16_t port, 
2081                                         void *dest,
2082                                         uint_t len,
2083                                         void *priv_data)
2084 {
2085     struct vga_internal *vga = (struct vga_internal *) priv_data;
2086
2087     PrintDebug(core->vm_info, core, "vga: crt controller (%s) address read data=0x%x\n", 
2088                port==0x3b4 ? "mono" : "color",
2089                vga->vga_crt_controller.vga_crt_addr.val);
2090
2091     ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2092
2093     *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2094
2095     PASSTHROUGH_IO_IN(vga,port,dest,len);
2096
2097     PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2098
2099     return len;
2100 }
2101
2102 static int crt_controller_data_write(struct guest_info *core, 
2103                                      uint16_t port, 
2104                                      void *src,
2105                                      uint_t len,
2106                                      void *priv_data)
2107 {
2108     struct vga_internal *vga = (struct vga_internal *) priv_data;
2109     uint8_t index;
2110     uint8_t data;
2111
2112     data=*((uint8_t*)src);
2113
2114     index=vga->vga_crt_controller.vga_crt_addr.val;  // should mask probably
2115     
2116     PrintDebug(core->vm_info, core, "vga: crt controller (%s) write data (index=%d) with 0x%x\n", 
2117                port==0x3b5 ? "mono" : "color",
2118                index, data);
2119
2120     ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2121
2122     PASSTHROUGH_IO_OUT(vga,port,src,len);
2123
2124     if (index>=VGA_CRT_CONTROLLER_NUM) { 
2125         PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
2126     } else {
2127         vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2128         if (index == 17) {
2129             if (vga->vga_crt_controller.vga_vertical_retrace_end.enable_vertical_interrupt) {
2130                 PrintError(core->vm_info, core, "vga: vertical_retrace_interrupt_enabled is unsupported -- no interrupts will occur!\n");
2131             }
2132         }
2133     }
2134
2135     render(vga);
2136
2137     return len;
2138 }
2139
2140 static int crt_controller_address_write(struct guest_info *core, 
2141                                         uint16_t port, 
2142                                         void *src,
2143                                         uint_t len,
2144                                         void *priv_data)
2145 {
2146     struct vga_internal *vga = (struct vga_internal *) priv_data;
2147     uint8_t new_addr;
2148
2149     new_addr=*((uint8_t*)src);
2150
2151     PrintDebug(core->vm_info, core, "vga: crt controller (%s) address write data=0x%x len=%u\n", 
2152                port==0x3b4 ? "mono" : "color",
2153                len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2154
2155     ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2156
2157     PASSTHROUGH_IO_OUT(vga,port,src,len);
2158
2159     vga->vga_crt_controller.vga_crt_addr.val =  *((uint8_t*)src) ;
2160         
2161     if (len==2) { 
2162         PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2163         // second byte is the data
2164         if (crt_controller_data_write(core,port,src+1,1,vga)!=1) { 
2165             PrintError(core->vm_info, core, "vga: write of data failed\n");
2166             return -1;
2167         }
2168     }
2169     
2170     return len;
2171 }
2172
2173 static int crt_controller_data_read(struct guest_info *core, 
2174                                     uint16_t port, 
2175                                     void *dest,
2176                                     uint_t len,
2177                                     void *priv_data)
2178 {
2179     struct vga_internal *vga = (struct vga_internal *) priv_data;
2180     uint8_t index;
2181     uint8_t data;
2182
2183     index=vga->vga_crt_controller.vga_crt_addr.val;  // should mask probably
2184     
2185     if (index>=VGA_CRT_CONTROLLER_NUM) { 
2186         data=0;
2187         PrintError(core->vm_info, core, "vga: crt controller data read for illegal index %d, returning zero\n",index);
2188     } else {
2189         data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2190     }
2191
2192     PrintDebug(core->vm_info, core, "vga: crt controller data (index=%d) = 0x%x\n",index,data);
2193     
2194     ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2195
2196     *((uint8_t*)dest) = data;
2197
2198     PASSTHROUGH_IO_IN(vga,port,dest,len);
2199
2200     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2201
2202     return len;
2203 }
2204
2205
2206
2207 static int graphics_controller_address_read(struct guest_info *core, 
2208                                             uint16_t port, 
2209                                             void *dest,
2210                                             uint_t len,
2211                                             void *priv_data)
2212 {
2213     struct vga_internal *vga = (struct vga_internal *) priv_data;
2214     
2215     PrintDebug(core->vm_info, core, "vga: graphics controller address read data=0x%x\n", 
2216                vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2217
2218     ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2219
2220     *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2221
2222     PASSTHROUGH_IO_IN(vga,port,dest,len);
2223
2224     PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2225
2226     return len;
2227 }
2228
2229 static int graphics_controller_data_write(struct guest_info *core, 
2230                                           uint16_t port, 
2231                                           void *src,
2232                                           uint_t len,
2233                                           void *priv_data)
2234 {
2235     struct vga_internal *vga = (struct vga_internal *) priv_data;
2236     uint8_t index;
2237     uint8_t data;
2238     
2239     data=*((uint8_t*)src);
2240     index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;  // should mask probably
2241     
2242
2243     PrintDebug(core->vm_info, core, "vga: graphics_controller write data (index=%d) with 0x%x\n", 
2244                index, data);
2245     
2246     ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2247     
2248     PASSTHROUGH_IO_OUT(vga,port,src,len);
2249
2250     if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { 
2251         PrintError(core->vm_info, core, "vga: graphics controller write for illegal index %d ignored\n",index);
2252     } else {
2253         vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2254     }
2255
2256     render(vga);
2257     
2258     return len;
2259 }
2260
2261 static int graphics_controller_address_write(struct guest_info *core, 
2262                                              uint16_t port, 
2263                                              void *src,
2264                                              uint_t len,
2265                                              void *priv_data)
2266 {
2267     struct vga_internal *vga = (struct vga_internal *) priv_data;
2268     uint8_t new_addr;
2269
2270     new_addr=*((uint8_t*)src);
2271
2272     PrintDebug(core->vm_info, core, "vga: graphics controller address write data=0x%x len=%u\n", 
2273                len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2274
2275     ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2276
2277     PASSTHROUGH_IO_OUT(vga,port,src,len);
2278
2279     vga->vga_graphics_controller.vga_graphics_ctrl_addr.val =  *((uint8_t*)src) ;
2280
2281     if (len==2) { 
2282         PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2283         // second byte is the data
2284         if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) { 
2285             PrintError(core->vm_info, core, "vga: write of data failed\n");
2286             return -1;
2287         }
2288     }
2289
2290     return len;
2291 }
2292
2293 static int graphics_controller_data_read(struct guest_info *core, 
2294                                          uint16_t port, 
2295                                          void *dest,
2296                                          uint_t len,
2297                                          void *priv_data)
2298 {
2299     struct vga_internal *vga = (struct vga_internal *) priv_data;
2300     uint8_t index;
2301     uint8_t data;
2302
2303     index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;  // should mask probably
2304
2305
2306     if (index>=VGA_GRAPHICS_CONTROLLER_NUM) { 
2307         data=0;
2308         PrintError(core->vm_info, core, "vga: graphics controller data read from illegal index %d, returning zero\n",index);
2309     } else {
2310         data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2311     }
2312     
2313     PrintDebug(core->vm_info, core, "vga: graphics controller data read data (index=%d) = 0x%x\n", 
2314                index, data);
2315
2316     ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2317
2318     *((uint8_t*)dest) = data;
2319
2320     PASSTHROUGH_IO_IN(vga,port,dest,len);
2321
2322     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2323     
2324     return len;
2325 }
2326
2327
2328
2329
2330 /* Note that these guys have a bizarre protocol*/
2331
2332 static int attribute_controller_address_read(struct guest_info *core, 
2333                                              uint16_t port, 
2334                                              void *dest,
2335                                              uint_t len,
2336                                              void *priv_data)
2337 {
2338     struct vga_internal *vga = (struct vga_internal *) priv_data;
2339     
2340     PrintDebug(core->vm_info, core, "vga: attribute controller address read data=0x%x\n", 
2341                vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2342
2343     ERR_WRONG_SIZE("read","vga attribute  controller addr",len,1,1);
2344
2345     *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2346
2347     PASSTHROUGH_IO_IN(vga,port,dest,len);
2348
2349     PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2350
2351     // Reading the attribute controller does not change the state
2352
2353     return len;
2354 }
2355
2356 static int attribute_controller_address_and_data_write(struct guest_info *core, 
2357                                                        uint16_t port, 
2358                                                        void *src,
2359                                                        uint_t len,
2360                                                        void *priv_data)
2361 {
2362     struct vga_internal *vga = (struct vga_internal *) priv_data;
2363
2364
2365     if (vga->vga_attribute_controller.state==ATTR_ADDR) { 
2366         uint8_t new_addr = *((uint8_t*)src);
2367         // We are to treat this as an address write, and flip state
2368         // to expect data ON THIS SAME PORT
2369         PrintDebug(core->vm_info, core, "vga: attribute controller address write data=0x%x\n", new_addr);
2370         
2371         ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2372
2373         PASSTHROUGH_IO_OUT(vga,port,src,len);
2374
2375         vga->vga_attribute_controller.vga_attribute_controller_addr.val =  new_addr;
2376
2377         vga->vga_attribute_controller.state=ATTR_DATA;
2378         return len;
2379
2380     } else if (vga->vga_attribute_controller.state==ATTR_DATA) { 
2381
2382         uint8_t data = *((uint8_t*)src);
2383         uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val;  // should mask probably
2384
2385         PrintDebug(core->vm_info, core, "vga: attribute controller data write index %d with data=0x%x\n", index,data);
2386         
2387         ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2388
2389         PASSTHROUGH_IO_OUT(vga,port,src,len);
2390         
2391         if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { 
2392             PrintError(core->vm_info, core, "vga: attribute controller write to illegal index %d ignored\n",index);
2393         } else {
2394             vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2395         }
2396         
2397         vga->vga_attribute_controller.state=ATTR_ADDR;
2398         
2399         return len;
2400     }
2401     
2402     return -1;
2403         
2404 }
2405
2406 static int attribute_controller_data_read(struct guest_info *core, 
2407                                           uint16_t port, 
2408                                           void *dest,
2409                                           uint_t len,
2410                                           void *priv_data)
2411 {
2412     struct vga_internal *vga = (struct vga_internal *) priv_data;
2413     uint8_t index;
2414     uint8_t data;
2415
2416     index=vga->vga_attribute_controller.vga_attribute_controller_addr.val;  // should mask probably
2417
2418     if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) { 
2419         data=0;
2420         PrintError(core->vm_info, core, "vga: attribute controller read of illegal index %d, returning zero\n",index);
2421     } else {
2422         data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2423     }
2424     
2425     PrintDebug(core->vm_info, core, "vga: attribute controller data read data (index=%d) = 0x%x\n", 
2426                index, data);
2427
2428     ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2429
2430     *((uint8_t*)dest) = data;
2431
2432     PASSTHROUGH_IO_IN(vga,port,dest,len);
2433
2434     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2435
2436     return len;
2437 }
2438
2439
2440 /*
2441    Note that these guys also have a strange protocol
2442    since they need to squeeze 18 bits of data through
2443    an 8 bit port 
2444 */
2445 static int dac_write_address_read(struct guest_info *core, 
2446                                   uint16_t port, 
2447                                   void *dest,
2448                                   uint_t len,
2449                                   void *priv_data)
2450 {
2451     struct vga_internal *vga = (struct vga_internal *) priv_data;
2452     
2453     PrintDebug(core->vm_info, core, "vga: dac write address read data=0x%x\n", 
2454                vga->vga_dac.vga_dac_write_addr);
2455
2456     ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2457
2458
2459     *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2460
2461     PASSTHROUGH_IO_IN(vga,port,dest,len);
2462     
2463     PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2464
2465     // This read does not reset the state machine
2466
2467     return len;
2468 }
2469
2470 static int dac_write_address_write(struct guest_info *core, 
2471                                    uint16_t port, 
2472                                    void *src,
2473                                    uint_t len,
2474                                    void *priv_data)
2475 {
2476     struct vga_internal *vga = (struct vga_internal *) priv_data;
2477     uint8_t new_addr;
2478
2479     new_addr=*((uint8_t*)src);
2480
2481     PrintDebug(core->vm_info, core, "vga: dac write address write data=0x%x\n", new_addr);
2482
2483     ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2484
2485     PASSTHROUGH_IO_OUT(vga,port,src,len);
2486
2487     // cannot be out of bounds since there are 256 regs
2488
2489     vga->vga_dac.vga_dac_write_addr =  *((uint8_t*)src) ;
2490
2491     // Now we also need to reset the state machine
2492     
2493     vga->vga_dac.state=DAC_WRITE;
2494     vga->vga_dac.channel=RED;
2495
2496     return len;
2497 }
2498
2499
2500 static int dac_read_address_read(struct guest_info *core, 
2501                                  uint16_t port, 
2502                                  void *dest,
2503                                  uint_t len,
2504                                  void *priv_data)
2505 {
2506     struct vga_internal *vga = (struct vga_internal *) priv_data;
2507     
2508     PrintDebug(core->vm_info, core, "vga: dac read address read data=0x%x\n", 
2509                vga->vga_dac.vga_dac_read_addr);
2510
2511     ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2512
2513     *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2514
2515     PASSTHROUGH_IO_IN(vga,port,dest,len);
2516
2517     PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2518     
2519     // This read does not reset the state machine
2520
2521     return len;
2522 }
2523
2524 static int dac_read_address_write(struct guest_info *core, 
2525                                   uint16_t port, 
2526                                   void *src,
2527                                   uint_t len,
2528                                   void *priv_data)
2529 {
2530     struct vga_internal *vga = (struct vga_internal *) priv_data;
2531     uint8_t new_addr;
2532
2533     new_addr=*((uint8_t*)src);
2534
2535     PrintDebug(core->vm_info, core, "vga: dac read address write data=0x%x\n", new_addr);
2536
2537     ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2538
2539     PASSTHROUGH_IO_OUT(vga,port,src,len);
2540
2541     // cannot be out of bounds since there are 256 regs
2542
2543     vga->vga_dac.vga_dac_read_addr =  *((uint8_t*)src) ;
2544
2545     // Now we also need to reset the state machine
2546     
2547     vga->vga_dac.state=DAC_READ;
2548     vga->vga_dac.channel=RED;
2549
2550     return len;
2551 }
2552
2553
2554 static int dac_data_read(struct guest_info *core, 
2555                          uint16_t port, 
2556                          void *dest,
2557                          uint_t len,
2558                          void *priv_data)
2559 {
2560     struct vga_internal *vga = (struct vga_internal *) priv_data;
2561     uint8_t curreg;
2562     uint8_t curchannel;
2563     uint8_t data;
2564     
2565     if (vga->vga_dac.state!=DAC_READ) { 
2566         PrintError(core->vm_info, core, "vga: dac data read while in other state\n");
2567         // results undefined, so we continue
2568     }
2569
2570     ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2571
2572     curreg = vga->vga_dac.vga_dac_read_addr;
2573     curchannel = vga->vga_dac.channel;
2574     data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2575
2576     PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] = 0x%x\n",
2577                curreg, 
2578                curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN" 
2579                           : curchannel==2 ? "BLUE" : "BAD CHANNEL", 
2580                data);
2581
2582     *((uint8_t*)dest) = data;
2583
2584     PASSTHROUGH_IO_IN(vga,port,dest,len);
2585
2586     PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2587     
2588     curchannel = (curchannel+1)%3;
2589     vga->vga_dac.channel=curchannel;
2590     if (curchannel==0) { 
2591         curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2592     } 
2593     vga->vga_dac.vga_dac_read_addr = curreg;
2594     vga->vga_dac.state=DAC_READ;
2595
2596     return len;
2597 }
2598
2599
2600
2601 static int dac_data_write(struct guest_info *core, 
2602                           uint16_t port, 
2603                           void *src,
2604                           uint_t len,
2605                           void *priv_data)
2606 {
2607     struct vga_internal *vga = (struct vga_internal *) priv_data;
2608     uint8_t curreg;
2609     uint8_t curchannel;
2610     uint8_t data;
2611     vga_palette_reg data32;
2612     vga_palette_reg mask32;
2613     
2614     if (vga->vga_dac.state!=DAC_WRITE) { 
2615         PrintError(core->vm_info, core, "vga: dac data write while in other state\n");
2616         // results undefined, so we continue
2617     }
2618
2619     ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2620
2621     PASSTHROUGH_IO_OUT(vga,port,src,len);
2622
2623     curreg = vga->vga_dac.vga_dac_write_addr;
2624     curchannel = vga->vga_dac.channel;
2625     data = *((uint8_t *)src);
2626
2627     PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] write with 0x%x\n",
2628                curreg, 
2629                curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN" 
2630                           : curchannel==2 ? "BLUE" : "BAD CHANNEL", 
2631                data);
2632
2633     data32 = data & 0x3f ;
2634     data32 <<= curchannel*8;
2635     mask32 = ~(0xff << (curchannel * 8));
2636
2637     vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2638     vga->vga_dac.vga_dac_palette[curreg] |= data32;
2639
2640     curchannel = (curchannel+1)%3;
2641     vga->vga_dac.channel=curchannel;
2642     if (curchannel==0) { 
2643         curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2644     } 
2645     vga->vga_dac.vga_dac_write_addr = curreg;
2646     vga->vga_dac.state=DAC_WRITE;
2647
2648     render(vga);
2649
2650     return len;
2651 }
2652
2653  
2654
2655 static int dac_pixel_mask_read(struct guest_info *core, 
2656                                uint16_t port, 
2657                                void *dest,
2658                                uint_t len,
2659                                void *priv_data)
2660 {
2661     struct vga_internal *vga = (struct vga_internal *) priv_data;
2662     
2663     PrintDebug(core->vm_info, core, "vga: dac pixel mask read data=0x%x\n", 
2664                vga->vga_dac.vga_pixel_mask);
2665
2666     ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2667
2668     *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2669
2670     PASSTHROUGH_IO_IN(vga,port,dest,len);
2671
2672     PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2673
2674     return len;
2675 }
2676
2677 static int dac_pixel_mask_write(struct guest_info *core, 
2678                                 uint16_t port, 
2679                                 void *src,
2680                                 uint_t len,
2681                                 void *priv_data)
2682 {
2683     struct vga_internal *vga = (struct vga_internal *) priv_data;
2684     uint8_t new_data;
2685
2686     new_data=*((uint8_t*)src);
2687
2688     PrintDebug(core->vm_info, core, "vga: dac pixel mask write data=0x%x\n", new_data);
2689
2690     ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2691
2692     PASSTHROUGH_IO_OUT(vga,port,src,len);
2693
2694     vga->vga_dac.vga_pixel_mask =  new_data;
2695
2696     return len;
2697 }
2698
2699 static int init_vga(struct vga_internal *vga)
2700 {
2701   // TODO: startup spec of register contents, if any
2702   vga->vga_misc.vga_input_stat1.val = 0x1;  // display enable, not in retrace
2703
2704   return 0;
2705 }
2706
2707 static int free_vga(struct vga_internal *vga) 
2708 {
2709     int i;
2710     int ret;
2711     struct vm_device *dev = vga->dev;
2712
2713     // Framebuffer deletion is user's responsibility
2714
2715     //    if (vga->mem_store) {
2716     //  V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2717     //  vga->mem_store=0;
2718     //}
2719     
2720     for (i=0;i<MAP_NUM;i++) { 
2721         if (vga->map[i]) { 
2722             V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2723             vga->map[i]=0;
2724         }
2725     }
2726
2727     v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2728
2729     ret = 0;
2730
2731     ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2732     // The following also covers VGA_INPUT_STAT0_READ
2733     ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2734     // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2735     ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2736     // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2737     ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2738     ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2739     
2740     ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2741
2742     /* Sequencer registers */
2743     ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2744     ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2745
2746     /* CRT controller registers */
2747     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2748     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2749     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2750     ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2751
2752     /* graphics controller registers */
2753     ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2754     ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2755
2756     /* attribute controller registers */
2757     ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2758     ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2759
2760     /* video DAC palette registers */
2761     ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2762     ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2763     ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2764     ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2765
2766
2767     if (vga->host_cons) { 
2768         v3_graphics_console_close(vga->host_cons);
2769     }
2770
2771     V3_Free(vga);
2772
2773     return 0;
2774 }
2775
2776 static struct v3_device_ops dev_ops = {
2777     .free = (int (*)(void *))free_vga,
2778 };
2779
2780
2781 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2782     struct vga_internal *vga;
2783     int i;
2784     int ret;
2785
2786     char * dev_id = v3_cfg_val(cfg, "ID");
2787     char * passthrough = v3_cfg_val(cfg, "passthrough");
2788     char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2789
2790     PrintDebug(vm, VCORE_NONE, "vga: init_device\n");
2791
2792     vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2793
2794     if (!vga) { 
2795         PrintError(vm, VCORE_NONE, "vga: cannot allocate\n");
2796         return -1;
2797     }
2798
2799     memset(vga, 0, sizeof(struct vga_internal));
2800
2801     vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2802     vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2803
2804     if (passthrough && strcasecmp(passthrough,"enable")==0) {
2805         PrintDebug(vm, VCORE_NONE, "vga: enabling passthrough\n");
2806         vga->passthrough=true;
2807         vga->skip_next_passthrough_out=false;
2808     }
2809
2810
2811     if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) { 
2812         struct v3_frame_buffer_spec req;
2813
2814         PrintDebug(vm, VCORE_NONE, "vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2815
2816         memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2817         memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2818
2819         req.height=VGA_MAXY;
2820         req.width=VGA_MAXX;
2821         req.bytes_per_pixel=4;
2822         req.bits_per_channel=8;
2823         req.red_offset=0;
2824         req.green_offset=1;
2825         req.blue_offset=2;
2826         
2827
2828         vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2829
2830         if (!vga->host_cons) { 
2831             PrintError(vm, VCORE_NONE, "vga: unable to open host OS's graphics console\n");
2832             free_vga(vga);
2833             return -1;
2834         }
2835
2836         if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2837             PrintDebug(vm, VCORE_NONE, "vga: warning: target spec differs from requested spec\n");
2838             PrintDebug(vm, VCORE_NONE, "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);
2839             PrintDebug(vm, VCORE_NONE, "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);
2840
2841         }
2842
2843         if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) { 
2844           V3_Print(vm, VCORE_NONE, "vga: enabling console-driven rendering\n");
2845           if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) { 
2846             PrintError(vm, VCORE_NONE, "vga: cannot enable console-driven rendering\n");
2847             free_vga(vga);
2848             return -1;
2849           }
2850         }
2851         
2852         V3_Print(vm, VCORE_NONE, "vga: enabling console inquiry for updates\n");
2853         if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) { 
2854           PrintError(vm, VCORE_NONE, "vga: cannot enable console inquiry for updates\n");
2855           free_vga(vga);
2856           return -1;
2857         }
2858    }
2859
2860     if (!vga->passthrough && !vga->host_cons) { 
2861         V3_Print(vm, VCORE_NONE, "vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2862     }
2863
2864
2865     // No memory store is allocated since we will use a full memory hook
2866     // The VGA maps can be read as well as written
2867     // Reads also affect writes, since they are how you fill the latches
2868
2869     // Now allocate the maps
2870     for (i=0;i<MAP_NUM;i++) { 
2871         void *temp;
2872
2873         temp = (void*)V3_AllocPages(MAP_SIZE/4096);
2874         if (!temp) { 
2875             PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
2876             free_vga(vga);
2877             return -1;
2878         }
2879
2880         vga->map[i] = (vga_map) V3_VAddr(temp);
2881
2882         memset(vga->map[i],0,MAP_SIZE);
2883     }
2884     
2885     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2886     
2887     if (dev == NULL) {
2888         PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
2889         free_vga(vga);
2890         return -1;
2891     }
2892     
2893     vga->dev = dev;
2894     
2895     if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY, 
2896                          MEM_REGION_START, MEM_REGION_END,
2897                          &vga_read, 
2898                          &vga_write,
2899                          dev) == -1) {
2900         PrintError(vm, VCORE_NONE, "vga: memory book failed\n");
2901         v3_remove_device(dev);
2902         return -1;
2903     }
2904
2905     ret = 0;
2906     
2907     /* Miscelaneous registers */
2908     ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2909     // The following also covers VGA_INPUT_STAT0_READ
2910     ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2911     // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2912     ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2913     // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2914     ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2915     ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2916     
2917     ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2918
2919     /* Sequencer registers */
2920     ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2921     ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2922
2923     /* CRT controller registers */
2924     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2925     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2926     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2927     ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2928
2929     /* graphics controller registers */
2930     ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2931     ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2932
2933     /* attribute controller registers */
2934     ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2935     ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2936
2937     /* video DAC palette registers */
2938     ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2939     ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2940     ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2941     ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2942
2943     if (ret != 0) {
2944         PrintError(vm, VCORE_NONE, "vga: Error allocating VGA I/O ports\n");
2945         v3_remove_device(dev);
2946         return -1;
2947     }
2948
2949     init_vga(vga);
2950
2951     PrintDebug(vm, VCORE_NONE, "vga: successfully added and initialized.\n");
2952
2953     return 0;
2954
2955 }
2956
2957 device_register("VGA", vga_init);