Palacios Public Git Repository

To checkout Palacios execute

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


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