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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Peter Dinda <pdinda@northwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Peter Dinda <pdinda@northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
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>
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)
33 #define MAP_SIZE 65536
36 #define UPDATES_PER_RENDER 100
38 typedef uint8_t *vga_map; // points to MAP_SIZE data
44 #define VGA_MISC_OUT_READ 0x3cc
45 #define VGA_MISC_OUT_WRITE 0x3c2
47 #define VGA_INPUT_STAT0_READ 0x3c2
49 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
50 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
52 #define VGA_FEATURE_CONTROL_READ 0x3ca
53 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
54 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
56 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
58 #define VGA_SEQUENCER_ADDRESS 0x3c4
59 #define VGA_SEQUENCER_DATA 0x3c5
60 #define VGA_SEQUENCER_NUM 5
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
70 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
71 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
72 #define VGA_GRAPHICS_CONTROLLER_NUM 9
74 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
75 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
76 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
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
83 #define VGA_DAC_NUM_ENTRIES 256
86 #define VGA_FONT_WIDTH 8
87 #define VGA_MAX_FONT_HEIGHT 32
89 struct vga_misc_regs {
90 /* Read: 0x3cc; Write: 0x3c2 */
91 struct vga_misc_out_reg vga_misc_out;
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));
102 struct vga_sequencer_regs {
103 /* Address register is 0x3c4, data register is 0x3c5 */
105 struct vga_sequencer_addr_reg vga_sequencer_addr;
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 */
111 uint8_t vga_sequencer_regs[0];
114 struct vga_reset_reg vga_reset;
116 struct vga_clocking_mode_reg vga_clocking_mode;
118 struct vga_map_mask_reg vga_map_mask;
120 struct vga_char_map_select_reg vga_char_map_select;
122 struct vga_mem_mode_reg vga_mem_mode;
123 } __attribute__((packed));
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;
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 */
134 uint8_t vga_crt_controller_regs[0];
137 vga_horizontal_total_reg vga_horizontal_total;
139 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
141 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
143 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
145 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
147 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
149 vga_vertical_total_reg vga_vertical_total;
151 struct vga_overflow_reg vga_overflow;
153 struct vga_preset_row_scan_reg vga_preset_row_scan;
155 struct vga_max_row_scan_reg vga_max_row_scan;
157 struct vga_cursor_start_reg vga_cursor_start;
159 struct vga_cursor_end_reg vga_cursor_end;
161 vga_start_address_high_reg vga_start_address_high;
163 vga_start_address_low_reg vga_start_address_low;
165 vga_cursor_location_high_reg vga_cursor_location_high;
167 vga_cursor_location_low_reg vga_cursor_location_low;
169 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
171 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
173 vga_vertical_display_enable_end_reg vga_vertical_display_enable_end;
175 vga_offset_reg vga_offset;
177 struct vga_underline_location_reg vga_underline_location;
179 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
181 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
183 struct vga_crt_mode_control_reg vga_crt_mode_control;
185 vga_line_compare_reg vga_line_compare;
186 } __attribute__((packed));
188 struct vga_graphics_controller_regs {
189 /* Address: 0x3ce Data: 0x3cf */
192 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
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 */
198 uint8_t vga_graphics_controller_regs[0];
201 struct vga_set_reset_reg vga_set_reset;
203 struct vga_enable_set_reset_reg vga_enable_set_reset;
205 struct vga_color_compare_reg vga_color_compare;
207 struct vga_data_rotate_reg vga_data_rotate;
209 struct vga_read_map_select_reg vga_read_map_select;
211 struct vga_graphics_mode_reg vga_graphics_mode;
213 struct vga_misc_reg vga_misc;
215 struct vga_color_dont_care_reg vga_color_dont_care;
217 vga_bit_mask_reg vga_bit_mask;
218 } __attribute__((packed));
221 struct vga_attribute_contoller_regs {
223 Address AND WRITE: 0x3c0
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
230 IMPORTANT: write address, write data flips state back to write address
231 write address, read data DOES NOT
233 To reset to write address state, read input status register 1
235 enum { ATTR_ADDR, ATTR_DATA } state; //state of the flip flop
238 struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
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 */
246 uint8_t vga_attribute_controller_regs[0];
249 vga_internal_palette_regs vga_internal_palette;
251 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
253 vga_overscan_color_reg vga_overscan_color;
255 struct vga_color_plane_enable_reg vga_color_plane_enable;
257 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
259 struct vga_color_select_reg vga_color_select;
260 } __attribute__((packed));
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));
274 struct vga_internal {
275 struct vm_device *dev;
278 bool skip_next_passthrough_out; // for word access
280 struct v3_frame_buffer_spec target_spec;
281 v3_graphics_console_t host_cons;
283 uint32_t updates_since_render;
285 struct frame_buf *framebuf; // we render to this
287 // void *mem_store; // This is the region where the memory hooks will go
289 vga_map map[MAP_NUM]; // the maps that the host writes to
291 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
293 /* Range of I/O ports here for backward compat with MDA and CGA */
294 struct vga_misc_regs vga_misc;
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;
300 /* Address register is 0x3c4, data register is 0x3c5 */
301 struct vga_sequencer_regs vga_sequencer;
303 /* Address: 0x3ce Data: 0x3cf */
304 struct vga_graphics_controller_regs vga_graphics_controller;
307 Address AND WRITE: 0x3c0
311 struct vga_attribute_contoller_regs vga_attribute_controller;
314 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
315 address for writes: 0x3c8 ("")
317 pixel mask: 0x3c6 - do not write (init to 0xff)
319 struct vga_dac_regs vga_dac;
324 static void find_text_char_dim(struct vga_internal *vga, uint32_t *w, uint32_t *h)
326 *w = (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
328 *h = vga->vga_crt_controller.vga_max_row_scan.max_scan_line+1;
332 static void find_text_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
334 uint32_t vert_lsb, vert_msb;
338 *width = (vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
339 - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew;
341 vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
342 vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
343 + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
345 ph = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
347 find_text_char_dim(vga,&cw, &ch);
354 static void find_text_data_start(struct vga_internal *vga, void **data)
358 offset = vga->vga_crt_controller.vga_start_address_high;
360 offset += vga->vga_crt_controller.vga_start_address_low;
362 *data = vga->map[0]+offset;
366 static void find_text_attr_start(struct vga_internal *vga, void **data)
370 offset = vga->vga_crt_controller.vga_start_address_high;
372 offset += vga->vga_crt_controller.vga_start_address_low;
374 *data = vga->map[1]+offset;
378 static void find_text_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y, void **data)
385 find_text_res(vga,&w,&h);
387 find_text_data_start(vga,&buf);
389 offset = vga->vga_crt_controller.vga_cursor_location_high;
391 offset += vga->vga_crt_controller.vga_cursor_location_low;
393 *data = vga->map[0]+offset;
395 charsin = (uint32_t)(*data - buf);
403 static void find_text_font_start(struct vga_internal *vga, void **data, uint8_t char_map)
405 uint32_t mapa_offset, mapb_offset;
410 mapa_offset = (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb << 1)
411 + vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb ;
412 *data = vga->map[2] + mapa_offset;
416 mapb_offset = (vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb << 1)
417 + vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb ;
418 *data = vga->map[2] + mapb_offset;
421 PrintError("vga: unknown char_map given to find_text_font_start\n");
427 static int extended_fontset(struct vga_internal *vga)
429 if (vga->vga_sequencer.vga_mem_mode.extended_memory &&
430 ! ( (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb
431 == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb) &&
432 (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb
433 == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb))) {
441 static int blinking(struct vga_internal *vga)
443 return vga->vga_attribute_controller.vga_attribute_mode_control.enable_blink;
447 static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
449 uint32_t vert_lsb, vert_msb;
451 *width = ((vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
452 - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew);
454 *width *= (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
456 vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
457 vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
458 + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
460 *height = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
465 static void find_graphics_cursor_pos(struct vga_internal *vga, uint32_t *width, uint32_t *height)
470 static void render_graphics(struct vga_internal *vga, void *fb)
473 PrintDebug("vga: render_graphics is unimplemented\n");
476 // packed pixel 4 color
477 // packed pixel 256 color
479 find_graphics_cursor_pos(0,0,0);
483 static void render_text_cursor(struct vga_internal *vga, void *fb)
489 static void dac_lookup_24bit_color(struct vga_internal *vga,
495 // use internal or external palette?
497 vga_palette_reg *r = &(vga->vga_dac.vga_dac_palette[entry]);
499 // converting from 6 bits to 8 bits so << 2
500 *red = (*r & 0x3f) << 2;
501 *green = ((*r >> 8) & 0x3f) << 2;
502 *blue = ((*r >> 16) & 0x3f) << 2;
507 // A variant of this function could render to
508 // a text console interface as well
510 static void render_text(struct vga_internal *vga, void *fb)
512 // line graphics enable bit means to dupe column 8 to 9 when
513 // in 9 dot wide mode
514 // otherwise 9th dot is background
516 struct v3_frame_buffer_spec *spec = &(vga->target_spec);
518 uint32_t gw, gh; // graphics w/h
519 uint32_t tw, th; // text w/h
520 uint32_t rtw, rth; // rendered text w/h
521 uint32_t cw, ch; // char font w/h including 8/9
522 uint32_t fw, fh; // fb w/h
524 uint32_t px, py; // cursor position
526 uint32_t x, y, l, p; // text location, line and pixel within the char
527 uint32_t fx, fy; // pixel position within the frame buffer
530 uint8_t *text; // points to current char
531 uint8_t *attr; // and its matching attribute
532 uint8_t *curs; // to where the cursor is
533 uint8_t *font; // to where the current font is
535 uint8_t fg_entry; // foreground color entry
536 uint8_t bg_entry; // background color entry
537 uint8_t fgr,fgg,fgb; // looked up foreground colors
538 uint8_t bgr,bgg,bgb; // looked up bg colors
540 uint8_t ct, ca; // the current char and attribute
541 struct vga_attribute_byte a; // decoded attribute
543 void *pixel; // current pixel in the fb
544 uint8_t *red; // and the channels in the pixel
550 find_graphics_res(vga,&gw,&gh);
551 find_text_res(vga,&tw,&th);
552 find_text_char_dim(vga,&cw,&ch);
556 find_text_cursor_pos(vga,&px,&py,(void**)&curs);
557 find_text_data_start(vga,(void**)&text);
558 find_text_attr_start(vga,(void**)&attr);
560 find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr
562 PrintDebug("vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), "
563 "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p"
564 "graphics extension=%u, extended_fontset=%d, blinking=%d\n",
565 gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb,
566 vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code,
567 extended_fontset(vga), blinking(vga));
571 // First we need to clip to what we can actually show
572 rtw = tw < fw/cw ? tw : fw/cw;
573 rth = th < fh/ch ? th : fh/ch;
577 // Now let's scan by char across the whole thing
579 for (x=0;x<tw;x++, text++, attr++) {
580 if (x < rtw && y < rth) {
581 // grab the character and attribute for the position
586 // find the character's font bitmap (one byte per row)
587 find_text_font_start(vga,(void**)&font,
588 extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
590 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
592 // Now let's find out what colors we will be using
595 if (!extended_fontset(vga)) {
596 fg_entry = ((uint8_t)(a.foreground_intensity_or_font_select)) << 3;
602 dac_lookup_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
604 if (!blinking(vga)) {
605 bg_entry = ((uint8_t)(a.blinking_or_bg_intensity)) << 3;
611 dac_lookup_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
613 // Draw the character
614 for (l=0; l<ch; l++, font++) {
615 uint8_t frow = *font; // this is the row of of the font map
619 // a char can be 9 bits wide, but the font map
620 // is only 8 bits wide, which means we need to know where to
623 // We get it from the font map if
624 // its line line graphics mode and its a graphics char
625 // otherwise it's the background color
626 if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
627 && ct>=0xc0 && ct<=0xdf ) {
633 fbit= (frow >> (7-p) ) & 0x1;
636 // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
637 // For now, we will draw it as black/white
639 // find its position in the framebuffer;
642 pixel = fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
643 red = pixel + spec->red_offset;
644 green = pixel + spec->green_offset;
645 blue = pixel + spec->blue_offset;
647 // Are we on the cursor?
648 // if so, let's negate this pixel to invert the cell
652 // update the framebuffer
675 static void render_test(struct vga_internal *vga, void *fb)
677 struct v3_frame_buffer_spec *s;
679 s=&(vga->target_spec);
681 if (fb && s->height>=480 && s->width>=640 ) {
682 uint8_t color = (uint8_t)(vga->updates_since_render);
686 for (y=0;y<480;y++) {
687 for (x=0;x<640;x++) {
688 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
689 uint8_t *red = pixel + s->red_offset;
690 uint8_t *green = pixel + s->green_offset;
691 uint8_t *blue = pixel + s->blue_offset;
697 } else if (y<(480/2)) {
701 } else if (y<(3*(480/4))) {
706 *red=*green=*blue=color+x;
713 static void render_maps(struct vga_internal *vga, void *fb)
716 struct v3_frame_buffer_spec *s;
719 s=&(vga->target_spec);
721 if (fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) {
722 // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
729 for (y=480+32;y<768;y++) {
730 for (x=m*256;x<(m+1)*256;x++,b++) {
731 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
732 uint8_t *red = pixel + s->red_offset;
733 uint8_t *green = pixel + s->green_offset;
734 uint8_t *blue = pixel + s->blue_offset;
736 *red=*green=*blue=*b;
744 static int render(struct vga_internal *vga)
749 vga->updates_since_render++;
751 if (vga->updates_since_render%100) {
756 if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) {
758 fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
760 // Draw some crap for testing for now
761 if (0) { render_test(vga,fb);}
762 // Draw the maps for debugging
763 if (0) { render_maps(vga,fb);}
765 if (vga->vga_graphics_controller.vga_misc.graphics_mode) {
766 render_graphics(vga,fb);
769 render_text_cursor(vga,fb);
775 v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
782 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
784 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
804 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
806 uint64_t mem_start, mem_end;
811 get_mem_region(vga, &mem_start, &mem_end);
813 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
815 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
816 return (guest_addr-mem_start) % size;
819 return ((guest_addr-mem_start) >> 1 ) % size;
826 // Determines which maps should be enabled for this single byte write
827 // and what the increment (actually 1/increment for the copy loop
829 // memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
831 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
833 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
835 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
838 if (guest_addr & 0x1) {
839 return mm & 0xa; // 0x1010
841 return mm & 0x5; // 0x0101
846 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
848 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
851 return !(new_guest_addr & 0x1);
857 static int vga_write(struct guest_info * core,
863 struct vm_device *dev = (struct vm_device *)priv_data;
864 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
866 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
868 if (vga->passthrough) {
869 PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
870 memcpy(V3_VAddr((void*)guest_addr),src,length);
875 PrintDebug("vga: data written was 0x");
876 for (i=0;i<length;i++) {
877 uint8_t c= ((char*)src)[i];
878 PrintDebug("%.2x", c);
881 for (i=0;i<length;i++) {
882 char c= ((char*)src)[i];
883 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
888 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
890 // Probably need to add odd/even mode access here for text
892 PrintDebug("vga: write is with odd/even = %u\n", vga->vga_sequencer.vga_mem_mode.odd_even);
895 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
899 00b -- Write Mode 0: In this mode, the host data is first rotated
900 as per the Rotate Count field, then the Enable Set/Reset mechanism
901 selects data from this or the Set/Reset field. Then the selected
902 Logical Operation is performed on the resulting data and the data
903 in the latch register. Then the Bit Mask field is used to select
904 which bits come from the resulting data and which come
905 from the latch register. Finally, only the bit planes enabled by
906 the Memory Plane Write Enable field are written to memory.
914 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
915 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
917 offset = find_offset_write(vga, guest_addr);
919 PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
921 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
923 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
924 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
925 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
926 uint8_t mm = find_map_write(vga,guest_addr+i);
928 PrintDebug("vga: write i=%u, mm=0x%x, offset=0x%x\n",i,(unsigned int)mm,(unsigned int)offset);
930 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
931 vga_map map = vga->map[mapnum];
932 uint8_t data = ((uint8_t *)src)[i];
933 uint8_t latchval = vga->latch[mapnum];
936 data = (data>>ror) | data<<(8-ror);
938 // use SR bit if ESR is on for this map
940 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
958 // mux between latch and alu output
960 // use alu output, which is in data
969 //PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
983 01b -- Write Mode 1: In this mode, data is transferred directly
984 from the 32 bit latch register to display memory, affected only by
985 the Memory Plane Write Enable field. The host data is not used in this mode.
990 uint64_t offset = find_offset_write(vga,guest_addr);
992 PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
994 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
997 uint8_t mm = find_map_write(vga,guest_addr+i);
999 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1000 vga_map map = vga->map[mapnum];
1001 uint8_t latchval = vga->latch[mapnum];
1005 // write to this map
1006 map[offset] = latchval;
1017 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
1018 are replicated across all 8 bits of their respective planes.
1019 Then the selected Logical Operation is performed on the resulting
1020 data and the data in the latch register. Then the Bit Mask field is used to
1021 select which bits come from the resulting data and which come from
1022 the latch register. Finally, only the bit planes enabled by the
1023 Memory Plane Write Enable field are written to memory.
1029 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1031 offset = find_offset_write(vga, guest_addr);
1033 PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1035 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1037 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1038 uint8_t mm = find_map_write(vga,guest_addr+i);
1040 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
1041 vga_map map = vga->map[mapnum];
1042 uint8_t data = ((uint8_t *)src)[i];
1043 uint8_t latchval = vga->latch[mapnum];
1045 // expand relevant bit to 8 bit
1046 // it's basically esr=1, sr=bit from write
1047 data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7);
1064 // mux between latch and alu output
1066 // use alu output, which is in data
1074 // write to this map
1085 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
1086 as if the Enable Set/Reset field were set to 1111b. Then the host data is
1087 first rotated as per the Rotate Count field, then logical ANDed with the
1088 value of the Bit Mask field. The resulting value is used on the data
1089 obtained from the Set/Reset field in the same way that the Bit Mask field
1090 would ordinarily be used. to select which bits come from the expansion
1091 of the Set/Reset field and which come from the latch register. Finally,
1092 only the bit planes enabled by the Memory Plane Write Enable field
1093 are written to memory.
1100 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1102 offset = find_offset_write(vga, guest_addr);
1104 PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1106 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1108 uint8_t data = ((uint8_t *)src)[i];
1110 data = (data>>ror) | data<<(8-ror);
1112 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1113 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1114 uint8_t mm = find_map_write(vga,guest_addr+i);
1116 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
1117 vga_map map = vga->map[mapnum];
1118 uint8_t latchval = vga->latch[mapnum];
1120 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
1123 // mux between latch and alu output
1125 // use alu output, which is in data
1133 // write to this map
1144 // There is no default
1154 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1156 uint64_t mem_start, mem_end;
1159 mem_start=mem_end=0;
1161 get_mem_region(vga, &mem_start, &mem_end);
1163 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1165 if (!vga->vga_sequencer.vga_mem_mode.chain4) {
1166 return (guest_addr-mem_start) % size;
1169 return ((guest_addr - mem_start) >> 2) % size;
1173 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1176 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1177 return !(new_guest_addr & 0x3);
1184 static int vga_read(struct guest_info * core,
1190 struct vm_device *dev = (struct vm_device *)priv_data;
1191 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1194 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1199 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1201 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
1203 /* 0 - a byte from ONE of the 4 planes is returned;
1204 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
1209 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1211 offset = find_offset_read(vga,guest_addr);
1212 // address bytes select the map
1213 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1214 mapnum = (guest_addr+i) % 4;
1215 ((uint8_t*)dst)[i] = vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1218 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
1219 offset = find_offset_read(vga,guest_addr);
1221 if (offset>=65536) {
1222 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
1225 memcpy(dst,(vga->map[mapnum])+offset,length);
1227 // load the latches with the last item read
1228 for (mapnum=0;mapnum<4;mapnum++) {
1229 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1236 /* 1 - Compare video memory and reference color
1237 (in Color Compare, except those not set in Color Don't Care),
1238 each bit in returned result is one comparison between the reference color
1240 Ref color is *4* bits, and thus a one byte read returns a comparison
1246 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1247 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1254 offset = find_offset_read(vga,guest_addr);
1256 for (i=0;i<length;i++,offset++) {
1259 for (mapnum=0;mapnum<4;mapnum++) {
1260 map = vga->map[mapnum];
1261 if ( (dc>>mapnum)&0x1 ) { // don't care
1265 bits = (map[offset]&0xf) == cc;
1268 bits |= (((map[offset]>>4))&0xf) == cc;
1270 // not clear whether it is 0..k or k..0
1276 // load the latches with the last item read
1277 for (mapnum=0;mapnum<4;mapnum++) {
1278 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1283 // there is no default
1286 if (vga->passthrough) {
1287 PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1288 memcpy(dst,V3_VAddr((void*)guest_addr),length);
1294 PrintDebug("vga: data read is 0x");
1295 for (i=0;i<length;i++) {
1296 uint8_t c= ((char*)dst)[i];
1297 PrintDebug("%.2x", c);
1300 for (i=0;i<length;i++) {
1301 char c= ((char*)dst)[i];
1302 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1315 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
1316 if (((len)<(min)) || ((len)>(max))) { \
1317 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
1321 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1324 *(uint8_t *)dest = v3_inb(port);
1327 *(uint16_t *)dest = v3_inw(port);
1330 *(uint32_t *)dest = v3_indw(port);
1333 PrintError("vga: unsupported passthrough io in size %u\n",length);
1339 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1342 v3_outb(port, *(uint8_t *)src);
1345 v3_outw(port, *(uint16_t *)src);
1348 v3_outdw(port, *(uint32_t *)src);
1351 PrintError("vga: unsupported passthrough io out size %u\n",length);
1356 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
1357 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1359 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
1360 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1362 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
1363 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1365 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1366 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)
1368 static int misc_out_read(struct guest_info *core,
1374 struct vga_internal *vga = (struct vga_internal *) priv_data;
1376 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1378 ERR_WRONG_SIZE("read","misc out",len,1,1);
1380 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1382 PASSTHROUGH_IO_IN(vga,port,dest,len);
1384 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1389 static int misc_out_write(struct guest_info *core,
1395 struct vga_internal *vga = (struct vga_internal *) priv_data;
1397 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
1399 ERR_WRONG_SIZE("write","misc out",len,1,1);
1401 PASSTHROUGH_IO_OUT(vga,port,src,len);
1403 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
1412 static int input_stat0_read(struct guest_info *core,
1418 struct vga_internal *vga = (struct vga_internal *) priv_data;
1420 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1422 ERR_WRONG_SIZE("read","input stat0",len,1,1);
1424 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1426 PASSTHROUGH_IO_IN(vga,port,dest,len);
1428 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1434 static int input_stat1_read(struct guest_info *core,
1440 struct vga_internal *vga = (struct vga_internal *) priv_data;
1442 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
1443 port==0x3ba ? "mono" : "color",
1444 vga->vga_misc.vga_input_stat1.val);
1446 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1449 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1451 // Stunningly, reading stat1 is also a way to reset
1452 // the state of attribute controller address/data flipflop
1453 // That is some mighty fine crack the designers were smoking.
1455 vga->vga_attribute_controller.state=ATTR_ADDR;
1457 PASSTHROUGH_IO_IN(vga,port,dest,len);
1459 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1465 static int feature_control_read(struct guest_info *core,
1471 struct vga_internal *vga = (struct vga_internal *) priv_data;
1473 PrintDebug("vga: feature control read data=0x%x\n",
1474 vga->vga_misc.vga_feature_control.val);
1476 ERR_WRONG_SIZE("read","feature control",len,1,1);
1479 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1481 PASSTHROUGH_IO_IN(vga,port,dest,len);
1483 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1488 static int feature_control_write(struct guest_info *core,
1494 struct vga_internal *vga = (struct vga_internal *) priv_data;
1496 PrintDebug("vga: feature control (%s) write data=0x%x\n",
1497 port==0x3ba ? "mono" : "color",
1500 ERR_WRONG_SIZE("write","feature control",len,1,1);
1502 PASSTHROUGH_IO_OUT(vga,port,src,len);
1504 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1512 static int video_subsys_enable_read(struct guest_info *core,
1518 struct vga_internal *vga = (struct vga_internal *) priv_data;
1520 PrintDebug("vga: video subsys enable read data=0x%x\n",
1521 vga->vga_misc.vga_video_subsys_enable.val);
1523 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1525 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1527 PASSTHROUGH_IO_IN(vga,port,dest,len);
1529 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1534 static int video_subsys_enable_write(struct guest_info *core,
1540 struct vga_internal *vga = (struct vga_internal *) priv_data;
1542 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1544 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1546 PASSTHROUGH_IO_OUT(vga,port,src,len);
1548 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1555 static int sequencer_address_read(struct guest_info *core,
1561 struct vga_internal *vga = (struct vga_internal *) priv_data;
1563 PrintDebug("vga: sequencer address read data=0x%x\n",
1564 vga->vga_sequencer.vga_sequencer_addr.val);
1566 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1568 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1570 PASSTHROUGH_IO_IN(vga,port,dest,len);
1572 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1577 static int sequencer_data_write(struct guest_info *core,
1583 struct vga_internal *vga = (struct vga_internal *) priv_data;
1587 data=*((uint8_t*)src);
1588 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1590 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1593 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1595 PASSTHROUGH_IO_OUT(vga,port,src,len);
1598 if (index>=VGA_SEQUENCER_NUM) {
1599 PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index);
1601 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1609 static int sequencer_address_write(struct guest_info *core,
1615 struct vga_internal *vga = (struct vga_internal *) priv_data;
1618 new_addr=*((uint8_t*)src);
1620 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);
1622 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1624 PASSTHROUGH_IO_OUT(vga,port,src,len);
1626 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
1629 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1630 // second byte is the data
1631 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
1632 PrintError("vga: write of data failed\n");
1640 static int sequencer_data_read(struct guest_info *core,
1646 struct vga_internal *vga = (struct vga_internal *) priv_data;
1650 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1652 if (index>=VGA_SEQUENCER_NUM) {
1654 PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index);
1656 data=vga->vga_sequencer.vga_sequencer_regs[index];
1659 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
1662 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
1664 *((uint8_t*)dest) = data;
1666 PASSTHROUGH_IO_IN(vga,port,dest,len);
1668 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1677 static int crt_controller_address_read(struct guest_info *core,
1683 struct vga_internal *vga = (struct vga_internal *) priv_data;
1685 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
1686 port==0x3b4 ? "mono" : "color",
1687 vga->vga_crt_controller.vga_crt_addr.val);
1689 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
1691 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
1693 PASSTHROUGH_IO_IN(vga,port,dest,len);
1695 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
1700 static int crt_controller_data_write(struct guest_info *core,
1706 struct vga_internal *vga = (struct vga_internal *) priv_data;
1710 data=*((uint8_t*)src);
1712 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1714 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
1715 port==0x3b5 ? "mono" : "color",
1718 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
1720 PASSTHROUGH_IO_OUT(vga,port,src,len);
1722 if (index>=VGA_CRT_CONTROLLER_NUM) {
1723 PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index);
1725 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
1733 static int crt_controller_address_write(struct guest_info *core,
1739 struct vga_internal *vga = (struct vga_internal *) priv_data;
1742 new_addr=*((uint8_t*)src);
1744 PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n",
1745 port==0x3b4 ? "mono" : "color",
1746 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1748 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
1750 PASSTHROUGH_IO_OUT(vga,port,src,len);
1752 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
1755 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1756 // second byte is the data
1757 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
1758 PrintError("vga: write of data failed\n");
1766 static int crt_controller_data_read(struct guest_info *core,
1772 struct vga_internal *vga = (struct vga_internal *) priv_data;
1776 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1778 if (index>=VGA_CRT_CONTROLLER_NUM) {
1780 PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index);
1782 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
1785 PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data);
1787 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
1789 *((uint8_t*)dest) = data;
1791 PASSTHROUGH_IO_IN(vga,port,dest,len);
1793 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
1800 static int graphics_controller_address_read(struct guest_info *core,
1806 struct vga_internal *vga = (struct vga_internal *) priv_data;
1808 PrintDebug("vga: graphics controller address read data=0x%x\n",
1809 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
1811 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
1813 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
1815 PASSTHROUGH_IO_IN(vga,port,dest,len);
1817 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
1822 static int graphics_controller_data_write(struct guest_info *core,
1828 struct vga_internal *vga = (struct vga_internal *) priv_data;
1832 data=*((uint8_t*)src);
1833 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1836 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
1839 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
1841 PASSTHROUGH_IO_OUT(vga,port,src,len);
1843 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
1844 PrintError("vga: graphics controller write for illegal index %d ignored\n",index);
1846 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
1854 static int graphics_controller_address_write(struct guest_info *core,
1860 struct vga_internal *vga = (struct vga_internal *) priv_data;
1863 new_addr=*((uint8_t*)src);
1865 PrintDebug("vga: graphics controller address write data=0x%x len=%u\n",
1866 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1868 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
1870 PASSTHROUGH_IO_OUT(vga,port,src,len);
1872 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
1875 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1876 // second byte is the data
1877 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
1878 PrintError("vga: write of data failed\n");
1886 static int graphics_controller_data_read(struct guest_info *core,
1892 struct vga_internal *vga = (struct vga_internal *) priv_data;
1896 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1899 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
1901 PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index);
1903 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
1906 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
1909 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
1911 *((uint8_t*)dest) = data;
1913 PASSTHROUGH_IO_IN(vga,port,dest,len);
1915 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1923 /* Note that these guys have a bizarre protocol*/
1925 static int attribute_controller_address_read(struct guest_info *core,
1931 struct vga_internal *vga = (struct vga_internal *) priv_data;
1933 PrintDebug("vga: attribute controller address read data=0x%x\n",
1934 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
1936 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
1938 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
1940 PASSTHROUGH_IO_IN(vga,port,dest,len);
1942 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
1944 // Reading the attribute controller does not change the state
1949 static int attribute_controller_address_and_data_write(struct guest_info *core,
1955 struct vga_internal *vga = (struct vga_internal *) priv_data;
1958 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
1959 uint8_t new_addr = *((uint8_t*)src);
1960 // We are to treat this as an address write, and flip state
1961 // to expect data ON THIS SAME PORT
1962 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
1964 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
1966 PASSTHROUGH_IO_OUT(vga,port,src,len);
1968 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
1970 vga->vga_attribute_controller.state=ATTR_DATA;
1973 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
1975 uint8_t data = *((uint8_t*)src);
1976 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1978 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
1980 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
1982 PASSTHROUGH_IO_OUT(vga,port,src,len);
1984 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
1985 PrintError("vga: attribute controller write to illegal index %d ignored\n",index);
1987 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
1990 vga->vga_attribute_controller.state=ATTR_ADDR;
1999 static int attribute_controller_data_read(struct guest_info *core,
2005 struct vga_internal *vga = (struct vga_internal *) priv_data;
2009 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2011 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2013 PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index);
2015 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2018 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
2021 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2023 *((uint8_t*)dest) = data;
2025 PASSTHROUGH_IO_IN(vga,port,dest,len);
2027 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2034 Note that these guys also have a strange protocol
2035 since they need to squeeze 18 bits of data through
2038 static int dac_write_address_read(struct guest_info *core,
2044 struct vga_internal *vga = (struct vga_internal *) priv_data;
2046 PrintDebug("vga: dac write address read data=0x%x\n",
2047 vga->vga_dac.vga_dac_write_addr);
2049 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2052 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2054 PASSTHROUGH_IO_IN(vga,port,dest,len);
2056 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2058 // This read does not reset the state machine
2063 static int dac_write_address_write(struct guest_info *core,
2069 struct vga_internal *vga = (struct vga_internal *) priv_data;
2072 new_addr=*((uint8_t*)src);
2074 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
2076 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2078 PASSTHROUGH_IO_OUT(vga,port,src,len);
2080 // cannot be out of bounds since there are 256 regs
2082 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2084 // Now we also need to reset the state machine
2086 vga->vga_dac.state=DAC_WRITE;
2087 vga->vga_dac.channel=RED;
2093 static int dac_read_address_read(struct guest_info *core,
2099 struct vga_internal *vga = (struct vga_internal *) priv_data;
2101 PrintDebug("vga: dac read address read data=0x%x\n",
2102 vga->vga_dac.vga_dac_read_addr);
2104 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2106 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2108 PASSTHROUGH_IO_IN(vga,port,dest,len);
2110 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2112 // This read does not reset the state machine
2117 static int dac_read_address_write(struct guest_info *core,
2123 struct vga_internal *vga = (struct vga_internal *) priv_data;
2126 new_addr=*((uint8_t*)src);
2128 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
2130 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2132 PASSTHROUGH_IO_OUT(vga,port,src,len);
2134 // cannot be out of bounds since there are 256 regs
2136 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2138 // Now we also need to reset the state machine
2140 vga->vga_dac.state=DAC_READ;
2141 vga->vga_dac.channel=RED;
2147 static int dac_data_read(struct guest_info *core,
2153 struct vga_internal *vga = (struct vga_internal *) priv_data;
2158 if (vga->vga_dac.state!=DAC_READ) {
2159 PrintError("vga: dac data read while in other state\n");
2160 // results undefined, so we continue
2163 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2165 curreg = vga->vga_dac.vga_dac_read_addr;
2166 curchannel = vga->vga_dac.channel;
2167 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2169 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
2171 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2172 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2175 *((uint8_t*)dest) = data;
2177 PASSTHROUGH_IO_IN(vga,port,dest,len);
2179 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2181 curchannel = (curchannel+1)%3;
2182 vga->vga_dac.channel=curchannel;
2183 if (curchannel==0) {
2184 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2186 vga->vga_dac.vga_dac_read_addr = curreg;
2187 vga->vga_dac.state=DAC_READ;
2194 static int dac_data_write(struct guest_info *core,
2200 struct vga_internal *vga = (struct vga_internal *) priv_data;
2204 vga_palette_reg data32;
2205 vga_palette_reg mask32;
2207 if (vga->vga_dac.state!=DAC_WRITE) {
2208 PrintError("vga: dac data write while in other state\n");
2209 // results undefined, so we continue
2212 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2214 PASSTHROUGH_IO_OUT(vga,port,src,len);
2216 curreg = vga->vga_dac.vga_dac_write_addr;
2217 curchannel = vga->vga_dac.channel;
2218 data = *((uint8_t *)src);
2220 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
2222 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2223 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2226 data32 = data & 0x3f ;
2227 data32 <<= curchannel*8;
2228 mask32 = ~(0xff << (curchannel * 8));
2230 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2231 vga->vga_dac.vga_dac_palette[curreg] |= data32;
2233 curchannel = (curchannel+1)%3;
2234 vga->vga_dac.channel=curchannel;
2235 if (curchannel==0) {
2236 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2238 vga->vga_dac.vga_dac_write_addr = curreg;
2239 vga->vga_dac.state=DAC_WRITE;
2248 static int dac_pixel_mask_read(struct guest_info *core,
2254 struct vga_internal *vga = (struct vga_internal *) priv_data;
2256 PrintDebug("vga: dac pixel mask read data=0x%x\n",
2257 vga->vga_dac.vga_pixel_mask);
2259 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2261 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2263 PASSTHROUGH_IO_IN(vga,port,dest,len);
2265 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2270 static int dac_pixel_mask_write(struct guest_info *core,
2276 struct vga_internal *vga = (struct vga_internal *) priv_data;
2279 new_data=*((uint8_t*)src);
2281 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
2283 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2285 PASSTHROUGH_IO_OUT(vga,port,src,len);
2287 vga->vga_dac.vga_pixel_mask = new_data;
2292 static int init_vga(struct vga_internal *vga)
2294 // TODO: startup spec of register contents, if any
2295 PrintError("vga: init_vga is UNIMPLEMTED\n");
2299 static int free_vga(struct vga_internal *vga)
2303 struct vm_device *dev = vga->dev;
2305 // Framebuffer deletion is user's responsibility
2307 // if (vga->mem_store) {
2308 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2309 // vga->mem_store=0;
2312 for (i=0;i<MAP_NUM;i++) {
2314 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2319 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2323 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2324 // The following also covers VGA_INPUT_STAT0_READ
2325 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2326 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2327 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2328 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2329 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2330 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2332 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2334 /* Sequencer registers */
2335 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2336 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2338 /* CRT controller registers */
2339 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2340 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2341 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2342 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2344 /* graphics controller registers */
2345 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2346 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2348 /* attribute controller registers */
2349 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2350 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2352 /* video DAC palette registers */
2353 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2354 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2355 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2356 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2359 if (vga->host_cons) {
2360 v3_graphics_console_close(vga->host_cons);
2368 static struct v3_device_ops dev_ops = {
2369 .free = (int (*)(void *))free_vga,
2373 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2374 struct vga_internal *vga;
2378 char * dev_id = v3_cfg_val(cfg, "ID");
2379 char * passthrough = v3_cfg_val(cfg, "passthrough");
2380 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2382 PrintDebug("vga: init_device\n");
2384 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2387 PrintError("vga: cannot allocate\n");
2391 memset(vga, 0, sizeof(struct vga_internal));
2393 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2394 PrintDebug("vga: enabling passthrough\n");
2395 vga->passthrough=true;
2396 vga->skip_next_passthrough_out=false;
2400 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2401 struct v3_frame_buffer_spec req;
2403 PrintDebug("vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2405 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2406 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2408 req.height=VGA_MAXY;
2410 req.bytes_per_pixel=4;
2411 req.bits_per_channel=8;
2417 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2419 if (!vga->host_cons) {
2420 PrintError("vga: unable to open host OS's graphics console\n");
2425 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2426 PrintDebug("vga: warning: target spec differs from requested spec\n");
2427 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);
2428 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);
2433 if (!vga->passthrough && !vga->host_cons) {
2434 V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2438 // No memory store is allocated since we will use a full memory hook
2439 // The VGA maps can be read as well as written
2440 // Reads also affect writes, since they are how you fill the latches
2442 // Now allocate the maps
2443 for (i=0;i<MAP_NUM;i++) {
2444 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
2445 if (!(vga->map[i])) {
2446 PrintError("vga: cannot allocate maps\n");
2450 memset(vga->map[i],0,MAP_SIZE);
2453 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2456 PrintError("Could not attach device %s\n", dev_id);
2463 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2464 MEM_REGION_START, MEM_REGION_END,
2468 PrintError("vga: memory book failed\n");
2469 v3_remove_device(dev);
2475 /* Miscelaneous registers */
2476 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2477 // The following also covers VGA_INPUT_STAT0_READ
2478 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2479 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2480 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2481 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2482 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2483 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2485 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2487 /* Sequencer registers */
2488 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2489 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2491 /* CRT controller registers */
2492 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2493 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2494 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2495 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2497 /* graphics controller registers */
2498 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2499 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2501 /* attribute controller registers */
2502 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2503 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2505 /* video DAC palette registers */
2506 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2507 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2508 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2509 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2512 PrintError("vga: Error allocating VGA I/O ports\n");
2513 v3_remove_device(dev);
2519 PrintDebug("vga: successfully added and initialized.\n");
2525 device_register("VGA", vga_init);