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