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.


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