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 #ifndef V3_CONFIG_DEBUG_VGA
31 #define PrintDebug(fmt, args...)
34 #define DEBUG_MEM_DATA 0
35 #define DEBUG_DEEP_MEM 0
36 #define DEBUG_DEEP_RENDER 0
39 #define MEM_REGION_START 0xa0000
40 #define MEM_REGION_END 0xc0000
41 #define MEM_REGION_NUM_PAGES (((MEM_REGION_END)-(MEM_REGION_START))/4096)
43 #define MAP_SIZE 65536
47 typedef uint8_t *vga_map; // points to MAP_SIZE data
53 #define VGA_MISC_OUT_READ 0x3cc
54 #define VGA_MISC_OUT_WRITE 0x3c2
56 #define VGA_INPUT_STAT0_READ 0x3c2
58 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
59 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
61 #define VGA_FEATURE_CONTROL_READ 0x3ca
62 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
63 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
65 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
67 #define VGA_SEQUENCER_ADDRESS 0x3c4
68 #define VGA_SEQUENCER_DATA 0x3c5
69 #define VGA_SEQUENCER_NUM 5
72 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
73 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
74 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
75 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
76 #define VGA_CRT_CONTROLLER_NUM 25
79 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
80 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
81 #define VGA_GRAPHICS_CONTROLLER_NUM 9
83 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
84 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
85 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
87 #define VGA_DAC_WRITE_ADDR 0x3c8
88 #define VGA_DAC_READ_ADDR 0x3c7
89 #define VGA_DAC_DATA 0x3c9
90 #define VGA_DAC_PIXEL_MASK 0x3c6
92 #define VGA_DAC_NUM_ENTRIES 256
95 #define VGA_FONT_WIDTH 8
96 #define VGA_MAX_FONT_HEIGHT 32
98 struct vga_render_model {
99 uint32_t model; // composite the following
101 #define VGA_DRIVEN_PERIODIC_RENDERING 0x1 // render after n GPU updates
102 #define CONSOLE_ADVISORY_RENDERING 0x2 // ask console if we should render following an update
103 #define CONSOLE_DRIVEN_RENDERING 0x4 // have console tell us when to render
105 uint32_t updates_before_render; // defaults to the following
107 #define DEFAULT_UPDATES_BEFORE_RENDER 1000
110 struct vga_misc_regs {
111 /* Read: 0x3cc; Write: 0x3c2 */
112 struct vga_misc_out_reg vga_misc_out;
114 struct vga_input_stat0_reg vga_input_stat0;
115 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
116 struct vga_input_stat1_reg vga_input_stat1;
117 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
118 struct vga_feature_control_reg vga_feature_control;
119 /* Read: 0x3c3; Write: 0x3c3 */
120 struct vga_video_subsys_enable_reg vga_video_subsys_enable;
121 } __attribute__((packed));
123 struct vga_sequencer_regs {
124 /* Address register is 0x3c4, data register is 0x3c5 */
126 struct vga_sequencer_addr_reg vga_sequencer_addr;
128 /* these can be accessed via the index, offset on start
129 or via the specific regs. For this reason, it is essential
130 that this is all packed and that the order does not change */
132 uint8_t vga_sequencer_regs[0];
135 struct vga_reset_reg vga_reset;
137 struct vga_clocking_mode_reg vga_clocking_mode;
139 struct vga_map_mask_reg vga_map_mask;
141 struct vga_char_map_select_reg vga_char_map_select;
143 struct vga_mem_mode_reg vga_mem_mode;
144 } __attribute__((packed));
146 struct vga_crt_controller_regs {
147 /* Address Register is 0x3b4 or 0x3d4 */
148 /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
149 struct vga_crt_addr_reg vga_crt_addr;
151 /* these can be accessed via the index, offset on start
152 or via the specific regs. For this reason, it is essential
153 that this is all packed and that the order does not change */
155 uint8_t vga_crt_controller_regs[0];
158 vga_horizontal_total_reg vga_horizontal_total;
160 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
162 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
164 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
166 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
168 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
170 vga_vertical_total_reg vga_vertical_total;
172 struct vga_overflow_reg vga_overflow;
174 struct vga_preset_row_scan_reg vga_preset_row_scan;
176 struct vga_max_row_scan_reg vga_max_row_scan;
178 struct vga_cursor_start_reg vga_cursor_start;
180 struct vga_cursor_end_reg vga_cursor_end;
182 vga_start_address_high_reg vga_start_address_high;
184 vga_start_address_low_reg vga_start_address_low;
186 vga_cursor_location_high_reg vga_cursor_location_high;
188 vga_cursor_location_low_reg vga_cursor_location_low;
190 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
192 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
194 vga_vertical_display_enable_end_reg vga_vertical_display_enable_end;
196 vga_offset_reg vga_offset;
198 struct vga_underline_location_reg vga_underline_location;
200 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
202 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
204 struct vga_crt_mode_control_reg vga_crt_mode_control;
206 vga_line_compare_reg vga_line_compare;
207 } __attribute__((packed));
209 struct vga_graphics_controller_regs {
210 /* Address: 0x3ce Data: 0x3cf */
213 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
215 /* these can be accessed via the index, offset on start
216 or via the specific regs. For this reason, it is essential
217 that this is all packed and that the order does not change */
219 uint8_t vga_graphics_controller_regs[0];
222 struct vga_set_reset_reg vga_set_reset;
224 struct vga_enable_set_reset_reg vga_enable_set_reset;
226 struct vga_color_compare_reg vga_color_compare;
228 struct vga_data_rotate_reg vga_data_rotate;
230 struct vga_read_map_select_reg vga_read_map_select;
232 struct vga_graphics_mode_reg vga_graphics_mode;
234 struct vga_misc_reg vga_misc;
236 struct vga_color_dont_care_reg vga_color_dont_care;
238 vga_bit_mask_reg vga_bit_mask;
239 } __attribute__((packed));
242 struct vga_attribute_contoller_regs {
244 Address AND WRITE: 0x3c0
247 The write protocol is to write the index to 0x3c0 followed by
248 the data. The read protocol is to write the index to 0x3c0
249 and then read from 0x3c1
251 IMPORTANT: write address, write data flips state back to write address
252 write address, read data DOES NOT
254 To reset to write address state, read input status register 1
256 enum { ATTR_ADDR, ATTR_DATA } state; //state of the flip flop
259 struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
263 /* these can be accessed via the index, offset on start
264 or via the specific regs. For this reason, it is essential
265 that this is all packed and that the order does not change */
267 uint8_t vga_attribute_controller_regs[0];
270 vga_internal_palette_regs vga_internal_palette;
272 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
274 vga_overscan_color_reg vga_overscan_color;
276 struct vga_color_plane_enable_reg vga_color_plane_enable;
278 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
280 struct vga_color_select_reg vga_color_select;
281 } __attribute__((packed));
283 struct vga_dac_regs {
284 enum {DAC_READ=0, DAC_WRITE} state;
285 enum {RED=0,GREEN,BLUE} channel;
286 vga_dac_pixel_mask_reg vga_pixel_mask;
287 vga_dac_write_addr_reg vga_dac_write_addr;
288 vga_dac_read_addr_reg vga_dac_read_addr;
289 // the dac_data register is used only to access the registers
290 // and thus has no representation here
291 vga_palette_reg vga_dac_palette[VGA_DAC_NUM_ENTRIES];
292 } __attribute__((packed));
295 struct vga_internal {
296 struct vm_device *dev;
299 bool skip_next_passthrough_out; // for word access
301 struct v3_frame_buffer_spec target_spec;
302 v3_graphics_console_t host_cons;
303 struct vga_render_model render_model;
305 uint32_t updates_since_render;
307 struct frame_buf *framebuf; // we render to this
309 // void *mem_store; // This is the region where the memory hooks will go
311 vga_map map[MAP_NUM]; // the maps that the host writes to
313 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
315 /* Range of I/O ports here for backward compat with MDA and CGA */
316 struct vga_misc_regs vga_misc;
318 /* Address Register is 0x3b4 or 0x3d4 */
319 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
320 struct vga_crt_controller_regs vga_crt_controller;
322 /* Address register is 0x3c4, data register is 0x3c5 */
323 struct vga_sequencer_regs vga_sequencer;
325 /* Address: 0x3ce Data: 0x3cf */
326 struct vga_graphics_controller_regs vga_graphics_controller;
329 Address AND WRITE: 0x3c0
333 struct vga_attribute_contoller_regs vga_attribute_controller;
336 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
337 address for writes: 0x3c8 ("")
339 pixel mask: 0x3c6 - do not write (init to 0xff)
341 struct vga_dac_regs vga_dac;
345 typedef enum {PLANAR_SHIFT, PACKED_SHIFT, C256_SHIFT} shift_mode_t;
348 static void find_text_char_dim(struct vga_internal *vga, uint32_t *w, uint32_t *h)
350 *w = (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
352 *h = vga->vga_crt_controller.vga_max_row_scan.max_scan_line+1;
356 static void find_text_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
358 uint32_t vert_lsb, vert_msb;
362 *width = (vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
363 - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew;
365 vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
366 vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
367 + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
369 ph = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
371 find_text_char_dim(vga,&cw, &ch);
378 static void find_text_data_start(struct vga_internal *vga, void **data)
382 offset = vga->vga_crt_controller.vga_start_address_high;
384 offset += vga->vga_crt_controller.vga_start_address_low;
386 *data = vga->map[0]+offset;
391 static void find_text_attr_start(struct vga_internal *vga, void **data)
395 offset = vga->vga_crt_controller.vga_start_address_high;
397 offset += vga->vga_crt_controller.vga_start_address_low;
399 *data = vga->map[1]+offset;
403 static void find_text_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y, void **data)
410 find_text_res(vga,&w,&h);
412 find_text_data_start(vga,&buf);
414 offset = vga->vga_crt_controller.vga_cursor_location_high;
416 offset += vga->vga_crt_controller.vga_cursor_location_low;
418 *data = vga->map[0]+offset;
420 charsin = (uint32_t)(*data - buf);
428 static void find_text_font_start(struct vga_internal *vga, void **data, uint8_t char_map)
430 uint32_t mapa_offset, mapb_offset;
435 mapa_offset = (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb << 1)
436 + vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb ;
437 *data = vga->map[2] + mapa_offset;
441 mapb_offset = (vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb << 1)
442 + vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb ;
443 *data = vga->map[2] + mapb_offset;
446 PrintError(VM_NONE, VCORE_NONE, "vga: unknown char_map given to find_text_font_start\n");
452 static int extended_fontset(struct vga_internal *vga)
454 if (vga->vga_sequencer.vga_mem_mode.extended_memory &&
455 ! ( (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb
456 == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb) &&
457 (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb
458 == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb))) {
466 static int blinking(struct vga_internal *vga)
468 return vga->vga_attribute_controller.vga_attribute_mode_control.enable_blink;
472 static void find_graphics_data_starting_offset(struct vga_internal *vga, uint32_t *offset)
475 *offset = vga->vga_crt_controller.vga_start_address_high;
477 *offset += vga->vga_crt_controller.vga_start_address_low;
481 static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode)
483 if (vga->vga_graphics_controller.vga_graphics_mode.c256) {
486 if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) {
495 static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
497 uint32_t vert_lsb, vert_msb;
499 *width = ((vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
500 - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew);
502 *width *= (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
504 vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
505 vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
506 + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
508 *height = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
510 // At this point we have the resolution in dot clocks across and scanlines top-to-bottom
511 // This is usually the resolution in pixels, but it can be monkeyed with
512 // at least in the following ways
514 // vga sequencer dot clock divide by two
515 if (vga->vga_sequencer.vga_clocking_mode.dot_clock) {
520 // crt_controller.max_row_scan.double_scan => each row twice for 200=>400
521 if (vga->vga_crt_controller.vga_max_row_scan.double_scan) {
525 // crt_controller.crt_mode_control.count_by_two => pixels twice as wide as normal
526 if (vga->vga_crt_controller.vga_crt_mode_control.count_by_two) {
530 // crt_controller.crt_mode_control.horizontal_retrace_select => pixels twice as tall as normal
531 if (vga->vga_crt_controller.vga_crt_mode_control.horizontal_retrace_select) {
538 static void find_graphics_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y)
545 static void dac_lookup_24bit_color(struct vga_internal *vga,
551 // use internal or external palette?
553 vga_palette_reg *r = &(vga->vga_dac.vga_dac_palette[entry]);
555 // converting from 6 bits to 8 bits so << 2
556 *red = (*r & 0x3f) << 2;
557 *green = ((*r >> 8) & 0x3f) << 2;
558 *blue = ((*r >> 16) & 0x3f) << 2;
564 Colors work like this:
566 4 bit modes: index is to the internal palette on the attribute controller
567 that supplies 6 bits, but we need 8 to index the dac
568 2 more (the msbs) are supplied from the color select register
569 we can optionally overwrite bits 5 and 4 from the color
570 select register as well, depending on a selection bit
571 in the mode control register. The result of all this is
572 8 bit index for the dac
574 8 bit modes: the attribute controller passes the index straight through
578 The DAC translates from the 8 bit index into 6 bits per color channel
579 (18 bit color). We mulitply by 4 to get 24 bit color.
582 static void find_24bit_color(struct vga_internal *vga,
588 uint8_t di; // ultimate dac index
590 if (vga->vga_attribute_controller.vga_attribute_mode_control.pixel_width) {
591 // 8 bit mode does right to the DAC
594 struct vga_internal_palette_reg pr = vga->vga_attribute_controller.vga_internal_palette[val%16];
595 di = pr.palette_data;
597 // Fix bits 5-4 if needed
598 if (vga->vga_attribute_controller.vga_attribute_mode_control.p54_select) {
599 di &= ~0x30; // clear 5-4
600 di |= vga->vga_attribute_controller.vga_color_select.sc4 << 4;
601 di |= vga->vga_attribute_controller.vga_color_select.sc5 << 5;
604 // We must always produce bits 6 and 7
605 di &= ~0xc0; // clear 7-6
606 di |= vga->vga_attribute_controller.vga_color_select.sc6 << 6;
607 di |= vga->vga_attribute_controller.vga_color_select.sc7 << 7;
610 dac_lookup_24bit_color(vga,di,red,green,blue);
613 static void render_graphics(struct vga_internal *vga, void *fb)
616 struct v3_frame_buffer_spec *spec = &(vga->target_spec);
618 uint32_t gw, gh; // graphics w/h
619 uint32_t fw, fh; // fb w/h
620 uint32_t rgw, rgh; // region we can actually show on the frame buffer
623 uint32_t fx, fy; // pixel position within the frame buffer
625 uint32_t offset; // offset into the maps
627 uint8_t p; // pixel in the current map byte (0..7)
629 uint8_t r,g,b; // looked up colors for entry
631 void *pixel; // current pixel in the fb
632 uint8_t *red; // and the channels in the pixel
636 uint8_t db[4]; // 4 bytes read at a time
637 uint8_t pb[8]; // 8 pixels assembled at a time
639 shift_mode_t sm; // shift mode
641 uint32_t cur_x, cur_y;
644 find_graphics_res(vga,&gw,&gh);
646 find_shift_mode(vga,&sm);
648 find_graphics_cursor_pos(vga,&cur_x,&cur_y);
650 find_graphics_data_starting_offset(vga,&offset);
656 PrintDebug(VM_NONE, VCORE_NONE, "vga: attempting graphics render (%s): graphics_res=(%u,%u), fb_res=(%u,%u), "
657 "fb=0x%p offset=0x%x\n",
658 sm == PLANAR_SHIFT ? "planar shift" :
659 sm == PACKED_SHIFT ? "packed shift" :
660 sm == C256_SHIFT ? "color256 shift" : "UNKNOWN",
661 gw,gh,fw,fh,fb,offset);
663 // First we need to clip to what we can actually show
664 rgw = gw < fw ? gw : fw;
665 rgh = gh < fh ? gh : fh;
668 PrintError(VM_NONE, VCORE_NONE, "vga: warning: graphics width is not a multiple of 8\n");
673 // Now we scan across by row
674 for (fy=0;fy<gh;fy++) {
677 fx += (sm==C256_SHIFT ? 4 : 8) , offset++ ) {
679 // if any of these pixels are in the rendger region
680 if (fy < rgh && fx < rgw) {
681 // assemble all 4 or 8 pixels
683 // fetch the data bytes
685 db[m]=*((uint8_t*)(vga->map[m]+offset));
693 (( db[0] >> 7) & 0x1) |
694 (( db[1] >> 6) & 0x2) |
695 (( db[2] >> 5) & 0x4) |
696 (( db[3] >> 4) & 0x8) ;
705 // first 4 pixels use planes 0 and 2
708 ((db[2] >> 4) & 0xc) |
709 ((db[0] >> 6) & 0x3) ;
715 // next 4 pixels use planes 1 and 3
718 ((db[3] >> 4) & 0xc) |
719 ((db[1] >> 6) & 0x3) ;
726 // this one is either very bizarre or as simple as this
734 for (p=0;p< (sm==C256_SHIFT ? 4 : 8);p++) {
737 find_24bit_color(vga,pb[p],&r,&g,&b);
739 // find its position in the framebuffer;
740 pixel = fb + (((fx + p) + (fy*spec->width)) * spec->bytes_per_pixel);
741 red = pixel + spec->red_offset;
742 green = pixel + spec->green_offset;
743 blue = pixel + spec->blue_offset;
754 PrintDebug(VM_NONE, VCORE_NONE, "vga: render done\n");
758 static void render_text_cursor(struct vga_internal *vga, void *fb)
766 // A variant of this function could render to
767 // a text console interface as well
769 static void render_text(struct vga_internal *vga, void *fb)
771 // line graphics enable bit means to dupe column 8 to 9 when
772 // in 9 dot wide mode
773 // otherwise 9th dot is background
775 struct v3_frame_buffer_spec *spec = &(vga->target_spec);
777 uint32_t gw, gh; // graphics w/h
778 uint32_t tw, th; // text w/h
779 uint32_t rtw, rth; // rendered text w/h
780 uint32_t cw, ch; // char font w/h including 8/9
781 uint32_t fw, fh; // fb w/h
783 uint32_t px, py; // cursor position
785 uint32_t x, y, l, p; // text location, line and pixel within the char
786 uint32_t fx, fy; // pixel position within the frame buffer
789 uint8_t *text; // points to current char
790 uint8_t *attr; // and its matching attribute
791 uint8_t *curs; // to where the cursor is
792 uint8_t *font; // to where the current font is
794 uint8_t fg_entry; // foreground color entry
795 uint8_t bg_entry; // background color entry
796 uint8_t fgr,fgg,fgb; // looked up foreground colors
797 uint8_t bgr,bgg,bgb; // looked up bg colors
799 uint8_t ct, ca; // the current char and attribute
800 struct vga_attribute_byte a; // decoded attribute
802 void *pixel; // current pixel in the fb
803 uint8_t *red; // and the channels in the pixel
809 find_graphics_res(vga,&gw,&gh);
810 find_text_res(vga,&tw,&th);
811 find_text_char_dim(vga,&cw,&ch);
815 find_text_cursor_pos(vga,&px,&py,(void**)&curs);
816 find_text_data_start(vga,(void**)&text);
817 find_text_attr_start(vga,(void**)&attr);
819 find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr
821 PrintDebug(VM_NONE, VCORE_NONE, "vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), "
822 "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p"
823 "graphics extension=%u, extended_fontset=%d, blinking=%d\n",
824 gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb,
825 vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code,
826 extended_fontset(vga), blinking(vga));
830 // First we need to clip to what we can actually show
831 rtw = tw < fw/cw ? tw : fw/cw;
832 rth = th < fh/ch ? th : fh/ch;
834 PrintDebug(VM_NONE, VCORE_NONE, "\n");
836 // Now let's scan by char across the whole thing
838 for (x=0;x<tw;x++, text++, attr++) {
839 if (x < rtw && y < rth) {
840 // grab the character and attribute for the position
845 PrintDebug(VM_NONE, VCORE_NONE, "%c",ct);
847 // find the character's font bitmap (one byte per row)
848 find_text_font_start(vga,(void**)&font,
849 extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
851 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
853 // Now let's find out what colors we will be using
856 if (!extended_fontset(vga)) {
857 fg_entry = a.foreground_intensity_or_font_select << 3;
863 find_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
865 if (!blinking(vga)) {
866 bg_entry = a.blinking_or_bg_intensity << 3;
872 find_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
874 // Draw the character
875 for (l=0; l<ch; l++, font++) {
876 uint8_t frow = *font; // this is the row of of the font map
880 // a char can be 9 bits wide, but the font map
881 // is only 8 bits wide, which means we need to know where to
884 // We get it from the font map if
885 // its line line graphics mode and its a graphics char
886 // otherwise it's the background color
887 if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
888 && ct>=0xc0 && ct<=0xdf ) {
894 fbit= (frow >> (7-p) ) & 0x1;
897 // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
898 // For now, we will draw it as black/white
900 // find its position in the framebuffer;
903 pixel = fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
904 red = pixel + spec->red_offset;
905 green = pixel + spec->green_offset;
906 blue = pixel + spec->blue_offset;
908 // Are we on the cursor?
909 // if so, let's negate this pixel to invert the cell
913 // update the framebuffer
927 PrintDebug(VM_NONE, VCORE_NONE, "\n");
936 static void render_test(struct vga_internal *vga, void *fb)
938 struct v3_frame_buffer_spec *s;
940 s=&(vga->target_spec);
942 if (fb && s->height>=480 && s->width>=640 ) {
943 uint8_t color = (uint8_t)(vga->updates_since_render);
947 for (y=0;y<480;y++) {
948 for (x=0;x<640;x++) {
949 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
950 uint8_t *red = pixel + s->red_offset;
951 uint8_t *green = pixel + s->green_offset;
952 uint8_t *blue = pixel + s->blue_offset;
958 } else if (y<(480/2)) {
962 } else if (y<(3*(480/4))) {
967 *red=*green=*blue=color+x;
974 static void render_black(struct vga_internal *vga, void *fb)
976 struct v3_frame_buffer_spec *s;
978 s=&(vga->target_spec);
980 memset(fb,0,s->height*s->width*s->bytes_per_pixel);
983 static void render_maps(struct vga_internal *vga, void *fb)
986 struct v3_frame_buffer_spec *s;
989 s=&(vga->target_spec);
991 if (fb && s->height>=768 && s->width>=1024 ) {
992 // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
999 for (y=480+32;y<768;y++) {
1000 for (x=m*256;x<(m+1)*256;x++,b++) {
1001 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
1002 uint8_t *red = pixel + s->red_offset;
1003 uint8_t *green = pixel + s->green_offset;
1004 uint8_t *blue = pixel + s->blue_offset;
1006 *red=*green=*blue=*b;
1013 static int render_core(struct vga_internal *vga)
1017 PrintDebug(VM_NONE, VCORE_NONE, "vga: render on update %u\n",vga->updates_since_render);
1019 fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
1021 if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
1022 if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) {
1023 render_graphics(vga,fb);
1025 render_text(vga,fb);
1026 render_text_cursor(vga,fb);
1029 render_black(vga,fb);
1032 if (0) { render_test(vga,fb); }
1034 // always render maps for now
1035 render_maps(vga,fb);
1037 v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
1039 vga->updates_since_render=0;
1046 static int render(struct vga_internal *vga)
1049 vga->updates_since_render++;
1052 if (vga->host_cons) {
1055 if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING)
1057 (vga->updates_since_render > vga->render_model.updates_before_render)) {
1058 PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to periodic\n");
1063 if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING)
1065 (v3_graphics_console_inform_update(vga->host_cons) > 0) ) {
1067 PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to advisory\n");
1072 // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function
1075 return render_core(vga);
1085 static int render_callback(v3_graphics_console_t cons,
1088 struct vga_internal *vga = (struct vga_internal *) priv;
1090 PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to callback\n");
1092 return render_core(vga);
1095 static int update_callback(v3_graphics_console_t cons,
1098 struct vga_internal *vga = (struct vga_internal *) priv;
1100 return vga->updates_since_render>0;
1105 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
1107 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
1127 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
1129 uint64_t mem_start, mem_end;
1132 mem_start=mem_end=0;
1134 get_mem_region(vga, &mem_start, &mem_end);
1136 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1138 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1139 // NOT odd/even mode
1140 return (guest_addr-mem_start) % size;
1143 return ((guest_addr-mem_start) >> 1 ) % size;
1150 // Determines which maps should be enabled for this single byte write
1151 // and what the increment (actually 1/increment for the copy loop
1153 // memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
1155 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
1157 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
1159 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1160 // NOT odd/even mode
1164 if (guest_addr & 0x1) {
1165 return mm & 0xa; // 0x1010
1167 return mm & 0x5; // 0x0101
1172 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
1174 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1175 // NOT odd/even mode
1178 return !(new_guest_addr & 0x1);
1184 static int vga_write(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;
1193 PrintDebug(core->vm_info, core, "vga: memory write: guest_addr=0x%p len=%u write_mode=%d first_byte=0x%x\n",
1194 (void*)guest_addr, length, vga->vga_graphics_controller.vga_graphics_mode.write_mode, *(uint8_t*)src);
1196 if (vga->passthrough) {
1197 PrintDebug(core->vm_info, core, "vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
1198 memcpy(V3_VAddr((void*)guest_addr),src,length);
1203 PrintDebug(core->vm_info, core, "vga: data written was 0x");
1204 for (i=0;i<length;i++) {
1205 uint8_t c= ((char*)src)[i];
1206 PrintDebug(core->vm_info, core, "%.2x", c);
1208 PrintDebug(core->vm_info, core, " \"");
1209 for (i=0;i<length;i++) {
1210 char c= ((char*)src)[i];
1211 PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1213 PrintDebug(core->vm_info, core, "\"\n");
1216 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
1219 // probably could just reduce this to the datapath itself instead
1220 // of following the programmer's perspective...
1222 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1226 00b -- Write Mode 0: In this mode, the host data is first rotated
1227 as per the Rotate Count field, then the Enable Set/Reset mechanism
1228 selects data from this or the Set/Reset field. Then the selected
1229 Logical Operation is performed on the resulting data and the data
1230 in the latch register. Then the Bit Mask field is used to select
1231 which bits come from the resulting data and which come
1232 from the latch register. Finally, only the bit planes enabled by
1233 the Memory Plane Write Enable field are written to memory.
1241 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1242 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1244 offset = find_offset_write(vga, guest_addr);
1247 PrintDebug(core->vm_info, core, "vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1250 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1252 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1253 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1254 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1255 uint8_t mm = find_map_write(vga,guest_addr+i);
1258 PrintDebug(core->vm_info, core, "vga: write i=%u, mm=0x%x, bm=0x%x sr=0x%x esr=0x%x offset=0x%x\n",i,(unsigned int)mm,(unsigned int)bm, (unsigned int)sr, (unsigned int)esr,(unsigned int)offset);
1261 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) {
1262 vga_map map = vga->map[mapnum];
1263 uint8_t data = ((uint8_t *)src)[i];
1264 uint8_t latchval = vga->latch[mapnum];
1267 PrintDebug(core->vm_info, core, "vga: raw data=0x%x\n",data);
1269 // rotate data right
1271 data = (data>>ror) | (data<<(8-ror));
1275 PrintDebug(core->vm_info, core, "vga: data after ror=0x%x\n",data);
1277 // use SR bit if ESR is on for this map
1279 data = (sr&0x1) * -1;
1284 PrintDebug(core->vm_info, core, "vga: data after esrr=0x%x\n",data);
1303 PrintDebug(core->vm_info, core, "vga: data after func=0x%x\n",data);
1306 // mux between the data byte and the latch byte on
1308 data = (bm & data) | ((~bm) & latchval);
1312 PrintDebug(core->vm_info, core, "vga: data after bm mux=0x%x\n",data);
1317 // write to this map
1319 PrintDebug(core->vm_info, core, "vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
1334 01b -- Write Mode 1: In this mode, data is transferred directly
1335 from the 32 bit latch register to display memory, affected only by
1336 the Memory Plane Write Enable field. The host data is not used in this mode.
1341 uint64_t offset = find_offset_write(vga,guest_addr);
1344 PrintDebug(core->vm_info, core, "vga: mode 1 write, offset=0x%llx\n", offset);
1347 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1350 uint8_t mm = find_map_write(vga,guest_addr+i);
1352 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1353 vga_map map = vga->map[mapnum];
1354 uint8_t latchval = vga->latch[mapnum];
1358 // write to this map
1359 map[offset] = latchval;
1370 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
1371 are replicated across all 8 bits of their respective planes.
1372 Then the selected Logical Operation is performed on the resulting
1373 data and the data in the latch register. Then the Bit Mask field is used to
1374 select which bits come from the resulting data and which come from
1375 the latch register. Finally, only the bit planes enabled by the
1376 Memory Plane Write Enable field are written to memory.
1382 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1384 offset = find_offset_write(vga, guest_addr);
1387 PrintDebug(core->vm_info, core, "vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1390 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1392 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1393 uint8_t mm = find_map_write(vga,guest_addr+i);
1395 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1396 vga_map map = vga->map[mapnum];
1397 uint8_t data = ((uint8_t *)src)[i];
1398 uint8_t latchval = vga->latch[mapnum];
1400 // expand relevant bit to 8 bit
1401 // it's basically esr=1, sr=bit from mode 0 write
1402 data = ((data>>mapnum)&0x1) * -1;
1419 // mux between latch and alu output
1420 data = (bm & data) | ((~bm) & latchval);
1424 // write to this map
1435 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
1436 as if the Enable Set/Reset field were set to 1111b. Then the host data is
1437 first rotated as per the Rotate Count field, then logical ANDed with the
1438 value of the Bit Mask field. The resulting value is used on the data
1439 obtained from the Set/Reset field in the same way that the Bit Mask field
1440 would ordinarily be used. to select which bits come from the expansion
1441 of the Set/Reset field and which come from the latch register. Finally,
1442 only the bit planes enabled by the Memory Plane Write Enable field
1443 are written to memory.
1450 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1452 offset = find_offset_write(vga, guest_addr);
1454 PrintDebug(core->vm_info, core, "vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1456 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1458 uint8_t data = ((uint8_t *)src)[i];
1461 data = (data>>ror) | (data<<(8-ror));
1464 // Note here that the bitmask is the register AND the data
1465 // the data written by the system is used for no other purpose
1466 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1468 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1470 uint8_t mm = find_map_write(vga,guest_addr+i);
1472 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, mm>>=1) {
1473 vga_map map = vga->map[mapnum];
1474 uint8_t latchval = vga->latch[mapnum];
1476 // expand SR bit - that's the data we're going to use
1477 data = (sr&0x1) * -1;
1479 // mux between latch and alu output
1480 data = (bm & data) | ((~bm) & latchval);
1484 // write to this map
1495 // There is no default
1505 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1507 uint64_t mem_start, mem_end;
1510 mem_start=mem_end=0;
1512 get_mem_region(vga, &mem_start, &mem_end);
1514 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1516 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1517 // odd/even mode takes priority
1518 return ((guest_addr-mem_start) >> 1 ) % size;
1521 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1522 // otherwise chain4 if it's on
1523 return ((guest_addr - mem_start) >> 2) % size;
1526 // and what you would expect if neither are on
1527 return (guest_addr-mem_start) % size;
1530 // Given this address
1531 // which specific map should we write into?
1532 // Note that unlike with find_map_write, here we are looking
1533 // for a single map number, not a bit vector of maps to be selected
1534 static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr)
1536 uint64_t mem_start, mem_end;
1538 mem_start=mem_end=0;
1540 get_mem_region(vga, &mem_start, &mem_end);
1542 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1544 // last bit tells us map 0 or 1
1545 return (guest_addr-mem_start) & 0x1;
1548 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1549 // otherwise chain4 if it's on
1551 return (guest_addr - mem_start) & 0x3;
1554 // and what you would expect if neither are on
1555 // note that it's not the same as a write!
1556 return vga->vga_graphics_controller.vga_read_map_select.map_select;
1559 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1562 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1564 return !(new_guest_addr & 0x1);
1567 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1568 return !(new_guest_addr & 0x3);
1574 static int vga_read(struct guest_info * core,
1580 struct vm_device *dev = (struct vm_device *)priv_data;
1581 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1584 PrintDebug(core->vm_info, core, "vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length,
1585 vga->vga_graphics_controller.vga_graphics_mode.read_mode);
1590 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1592 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
1594 /* 0 - a byte from ONE of the 4 planes is returned;
1595 which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
1596 OR by odd/even chaining OR by chain4 chaining
1602 offset = find_offset_read(vga,guest_addr);
1605 PrintDebug(core->vm_info, core, "vga: mode 0 read, offset=0x%llx\n",offset);
1607 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1609 mapnum = find_map_read(vga,guest_addr+i);
1611 // the data returned
1612 ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1614 // need to load all latches even though we are
1615 // returning data from only the selected map
1616 for (mapnum=0;mapnum<4;mapnum++) {
1617 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1625 /* 1 - Compare video memory and reference color
1626 (in Color Compare, except those not set in Color Don't Care),
1627 each bit in returned result is one comparison between the reference color
1629 Ref color is *4* bits, and thus a one byte read returns a comparison
1636 offset = find_offset_read(vga,guest_addr);
1639 PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx\n",offset);
1642 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1644 uint8_t mapcalc=0xff;
1646 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1647 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1649 for (mapnum=0;mapnum<4;mapnum++, cc>>=1, dc>>=1) {
1650 if (dc&0x1) { // dc is active low; 1=we do care
1651 mapcalc &= (cc * -1) & *(vga->map[mapnum]+offset);
1654 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1656 // write back the comparison result (for 8 pixels)
1657 ((uint8_t *)dst)[i]=mapcalc;
1663 // there is no default
1666 if (vga->passthrough) {
1667 PrintDebug(core->vm_info, core, "vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1668 memcpy(dst,V3_VAddr((void*)guest_addr),length);
1674 PrintDebug(core->vm_info, core, "vga: data read is 0x");
1675 for (i=0;i<length;i++) {
1676 uint8_t c= ((char*)dst)[i];
1677 PrintDebug(core->vm_info, core, "%.2x", c);
1679 PrintDebug(core->vm_info, core, " \"");
1680 for (i=0;i<length;i++) {
1681 char c= ((char*)dst)[i];
1682 PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1684 PrintDebug(core->vm_info, core, "\"\n");
1695 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
1696 if (((len)<(min)) || ((len)>(max))) { \
1697 PrintError(core->vm_info, core, "vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
1701 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1704 *(uint8_t *)dest = v3_inb(port);
1707 *(uint16_t *)dest = v3_inw(port);
1710 *(uint32_t *)dest = v3_indw(port);
1713 PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io in size %u\n",length);
1719 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1722 v3_outb(port, *(uint8_t *)src);
1725 v3_outw(port, *(uint16_t *)src);
1728 v3_outdw(port, *(uint32_t *)src);
1731 PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io out size %u\n",length);
1736 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
1737 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1739 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
1740 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1742 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
1743 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1745 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1746 do { if ((vga)->passthrough) { if ((inter)!=(pass)) { PrintError(core->vm_info, core, "vga: passthrough error: passthrough value read is 0x%x, but internal value read is 0x%x\n",(pass),(inter)); } } } while (0)
1748 static int misc_out_read(struct guest_info *core,
1754 struct vga_internal *vga = (struct vga_internal *) priv_data;
1756 PrintDebug(core->vm_info, core, "vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1758 ERR_WRONG_SIZE("read","misc out",len,1,1);
1760 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1762 PASSTHROUGH_IO_IN(vga,port,dest,len);
1764 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1769 static int misc_out_write(struct guest_info *core,
1775 struct vga_internal *vga = (struct vga_internal *) priv_data;
1777 PrintDebug(core->vm_info, core, "vga: misc out write data=0x%x\n", *((uint8_t*)src));
1779 ERR_WRONG_SIZE("write","misc out",len,1,1);
1781 PASSTHROUGH_IO_OUT(vga,port,src,len);
1783 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
1792 static int input_stat0_read(struct guest_info *core,
1798 struct vga_internal *vga = (struct vga_internal *) priv_data;
1800 PrintDebug(core->vm_info, core, "vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1802 ERR_WRONG_SIZE("read","input stat0",len,1,1);
1804 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1806 PASSTHROUGH_IO_IN(vga,port,dest,len);
1808 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1814 static int input_stat1_read(struct guest_info *core,
1820 struct vga_internal *vga = (struct vga_internal *) priv_data;
1822 PrintDebug(core->vm_info, core, "vga: input stat0 (%s) read data=0x%x\n",
1823 port==0x3ba ? "mono" : "color",
1824 vga->vga_misc.vga_input_stat1.val);
1826 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1829 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1831 // Stunningly, reading stat1 is also a way to reset
1832 // the state of attribute controller address/data flipflop
1833 // That is some mighty fine crack the designers were smoking.
1835 vga->vga_attribute_controller.state=ATTR_ADDR;
1837 PASSTHROUGH_IO_IN(vga,port,dest,len);
1839 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1845 static int feature_control_read(struct guest_info *core,
1851 struct vga_internal *vga = (struct vga_internal *) priv_data;
1853 PrintDebug(core->vm_info, core, "vga: feature control read data=0x%x\n",
1854 vga->vga_misc.vga_feature_control.val);
1856 ERR_WRONG_SIZE("read","feature control",len,1,1);
1859 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1861 PASSTHROUGH_IO_IN(vga,port,dest,len);
1863 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1868 static int feature_control_write(struct guest_info *core,
1874 struct vga_internal *vga = (struct vga_internal *) priv_data;
1876 PrintDebug(core->vm_info, core, "vga: feature control (%s) write data=0x%x\n",
1877 port==0x3ba ? "mono" : "color",
1880 ERR_WRONG_SIZE("write","feature control",len,1,1);
1882 PASSTHROUGH_IO_OUT(vga,port,src,len);
1884 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1892 static int video_subsys_enable_read(struct guest_info *core,
1898 struct vga_internal *vga = (struct vga_internal *) priv_data;
1900 PrintDebug(core->vm_info, core, "vga: video subsys enable read data=0x%x\n",
1901 vga->vga_misc.vga_video_subsys_enable.val);
1903 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1905 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1907 PASSTHROUGH_IO_IN(vga,port,dest,len);
1909 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1914 static int video_subsys_enable_write(struct guest_info *core,
1920 struct vga_internal *vga = (struct vga_internal *) priv_data;
1922 PrintDebug(core->vm_info, core, "vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1924 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1926 PASSTHROUGH_IO_OUT(vga,port,src,len);
1928 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1935 static int sequencer_address_read(struct guest_info *core,
1941 struct vga_internal *vga = (struct vga_internal *) priv_data;
1943 PrintDebug(core->vm_info, core, "vga: sequencer address read data=0x%x\n",
1944 vga->vga_sequencer.vga_sequencer_addr.val);
1946 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1948 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1950 PASSTHROUGH_IO_IN(vga,port,dest,len);
1952 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1957 static int sequencer_data_write(struct guest_info *core,
1963 struct vga_internal *vga = (struct vga_internal *) priv_data;
1967 data=*((uint8_t*)src);
1968 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1970 PrintDebug(core->vm_info, core, "vga: sequencer write data (index=%d) with 0x%x\n",
1973 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1975 PASSTHROUGH_IO_OUT(vga,port,src,len);
1978 if (index>=VGA_SEQUENCER_NUM) {
1979 PrintError(core->vm_info, core, "vga: sequencer data write is for invalid index %d, ignoring\n",index);
1981 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1989 static int sequencer_address_write(struct guest_info *core,
1995 struct vga_internal *vga = (struct vga_internal *) priv_data;
1998 new_addr=*((uint8_t*)src);
2000 PrintDebug(core->vm_info, core, "vga: sequencer address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2002 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
2004 PASSTHROUGH_IO_OUT(vga,port,src,len);
2006 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
2009 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2010 // second byte is the data
2011 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
2012 PrintError(core->vm_info, core, "vga: write of data failed\n");
2020 static int sequencer_data_read(struct guest_info *core,
2026 struct vga_internal *vga = (struct vga_internal *) priv_data;
2030 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
2032 if (index>=VGA_SEQUENCER_NUM) {
2034 PrintError(core->vm_info, core, "vga: sequencer data read at invalid index %d, returning zero\n",index);
2036 data=vga->vga_sequencer.vga_sequencer_regs[index];
2039 PrintDebug(core->vm_info, core, "vga: sequencer data read data (index=%d) = 0x%x\n",
2042 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2044 *((uint8_t*)dest) = data;
2046 PASSTHROUGH_IO_IN(vga,port,dest,len);
2048 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2057 static int crt_controller_address_read(struct guest_info *core,
2063 struct vga_internal *vga = (struct vga_internal *) priv_data;
2065 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address read data=0x%x\n",
2066 port==0x3b4 ? "mono" : "color",
2067 vga->vga_crt_controller.vga_crt_addr.val);
2069 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2071 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2073 PASSTHROUGH_IO_IN(vga,port,dest,len);
2075 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2080 static int crt_controller_data_write(struct guest_info *core,
2086 struct vga_internal *vga = (struct vga_internal *) priv_data;
2090 data=*((uint8_t*)src);
2092 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2094 PrintDebug(core->vm_info, core, "vga: crt controller (%s) write data (index=%d) with 0x%x\n",
2095 port==0x3b5 ? "mono" : "color",
2098 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2100 PASSTHROUGH_IO_OUT(vga,port,src,len);
2102 if (index>=VGA_CRT_CONTROLLER_NUM) {
2103 PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
2105 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2113 static int crt_controller_address_write(struct guest_info *core,
2119 struct vga_internal *vga = (struct vga_internal *) priv_data;
2122 new_addr=*((uint8_t*)src);
2124 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address write data=0x%x len=%u\n",
2125 port==0x3b4 ? "mono" : "color",
2126 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2128 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2130 PASSTHROUGH_IO_OUT(vga,port,src,len);
2132 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
2135 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2136 // second byte is the data
2137 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
2138 PrintError(core->vm_info, core, "vga: write of data failed\n");
2146 static int crt_controller_data_read(struct guest_info *core,
2152 struct vga_internal *vga = (struct vga_internal *) priv_data;
2156 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2158 if (index>=VGA_CRT_CONTROLLER_NUM) {
2160 PrintError(core->vm_info, core, "vga: crt controller data read for illegal index %d, returning zero\n",index);
2162 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2165 PrintDebug(core->vm_info, core, "vga: crt controller data (index=%d) = 0x%x\n",index,data);
2167 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2169 *((uint8_t*)dest) = data;
2171 PASSTHROUGH_IO_IN(vga,port,dest,len);
2173 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2180 static int graphics_controller_address_read(struct guest_info *core,
2186 struct vga_internal *vga = (struct vga_internal *) priv_data;
2188 PrintDebug(core->vm_info, core, "vga: graphics controller address read data=0x%x\n",
2189 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2191 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2193 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2195 PASSTHROUGH_IO_IN(vga,port,dest,len);
2197 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2202 static int graphics_controller_data_write(struct guest_info *core,
2208 struct vga_internal *vga = (struct vga_internal *) priv_data;
2212 data=*((uint8_t*)src);
2213 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2216 PrintDebug(core->vm_info, core, "vga: graphics_controller write data (index=%d) with 0x%x\n",
2219 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2221 PASSTHROUGH_IO_OUT(vga,port,src,len);
2223 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2224 PrintError(core->vm_info, core, "vga: graphics controller write for illegal index %d ignored\n",index);
2226 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2234 static int graphics_controller_address_write(struct guest_info *core,
2240 struct vga_internal *vga = (struct vga_internal *) priv_data;
2243 new_addr=*((uint8_t*)src);
2245 PrintDebug(core->vm_info, core, "vga: graphics controller address write data=0x%x len=%u\n",
2246 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2248 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2250 PASSTHROUGH_IO_OUT(vga,port,src,len);
2252 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
2255 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2256 // second byte is the data
2257 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
2258 PrintError(core->vm_info, core, "vga: write of data failed\n");
2266 static int graphics_controller_data_read(struct guest_info *core,
2272 struct vga_internal *vga = (struct vga_internal *) priv_data;
2276 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2279 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2281 PrintError(core->vm_info, core, "vga: graphics controller data read from illegal index %d, returning zero\n",index);
2283 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2286 PrintDebug(core->vm_info, core, "vga: graphics controller data read data (index=%d) = 0x%x\n",
2289 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2291 *((uint8_t*)dest) = data;
2293 PASSTHROUGH_IO_IN(vga,port,dest,len);
2295 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2303 /* Note that these guys have a bizarre protocol*/
2305 static int attribute_controller_address_read(struct guest_info *core,
2311 struct vga_internal *vga = (struct vga_internal *) priv_data;
2313 PrintDebug(core->vm_info, core, "vga: attribute controller address read data=0x%x\n",
2314 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2316 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
2318 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2320 PASSTHROUGH_IO_IN(vga,port,dest,len);
2322 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2324 // Reading the attribute controller does not change the state
2329 static int attribute_controller_address_and_data_write(struct guest_info *core,
2335 struct vga_internal *vga = (struct vga_internal *) priv_data;
2338 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
2339 uint8_t new_addr = *((uint8_t*)src);
2340 // We are to treat this as an address write, and flip state
2341 // to expect data ON THIS SAME PORT
2342 PrintDebug(core->vm_info, core, "vga: attribute controller address write data=0x%x\n", new_addr);
2344 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2346 PASSTHROUGH_IO_OUT(vga,port,src,len);
2348 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
2350 vga->vga_attribute_controller.state=ATTR_DATA;
2353 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
2355 uint8_t data = *((uint8_t*)src);
2356 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2358 PrintDebug(core->vm_info, core, "vga: attribute controller data write index %d with data=0x%x\n", index,data);
2360 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2362 PASSTHROUGH_IO_OUT(vga,port,src,len);
2364 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2365 PrintError(core->vm_info, core, "vga: attribute controller write to illegal index %d ignored\n",index);
2367 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2370 vga->vga_attribute_controller.state=ATTR_ADDR;
2379 static int attribute_controller_data_read(struct guest_info *core,
2385 struct vga_internal *vga = (struct vga_internal *) priv_data;
2389 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2391 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2393 PrintError(core->vm_info, core, "vga: attribute controller read of illegal index %d, returning zero\n",index);
2395 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2398 PrintDebug(core->vm_info, core, "vga: attribute controller data read data (index=%d) = 0x%x\n",
2401 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2403 *((uint8_t*)dest) = data;
2405 PASSTHROUGH_IO_IN(vga,port,dest,len);
2407 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2414 Note that these guys also have a strange protocol
2415 since they need to squeeze 18 bits of data through
2418 static int dac_write_address_read(struct guest_info *core,
2424 struct vga_internal *vga = (struct vga_internal *) priv_data;
2426 PrintDebug(core->vm_info, core, "vga: dac write address read data=0x%x\n",
2427 vga->vga_dac.vga_dac_write_addr);
2429 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2432 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2434 PASSTHROUGH_IO_IN(vga,port,dest,len);
2436 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2438 // This read does not reset the state machine
2443 static int dac_write_address_write(struct guest_info *core,
2449 struct vga_internal *vga = (struct vga_internal *) priv_data;
2452 new_addr=*((uint8_t*)src);
2454 PrintDebug(core->vm_info, core, "vga: dac write address write data=0x%x\n", new_addr);
2456 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2458 PASSTHROUGH_IO_OUT(vga,port,src,len);
2460 // cannot be out of bounds since there are 256 regs
2462 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2464 // Now we also need to reset the state machine
2466 vga->vga_dac.state=DAC_WRITE;
2467 vga->vga_dac.channel=RED;
2473 static int dac_read_address_read(struct guest_info *core,
2479 struct vga_internal *vga = (struct vga_internal *) priv_data;
2481 PrintDebug(core->vm_info, core, "vga: dac read address read data=0x%x\n",
2482 vga->vga_dac.vga_dac_read_addr);
2484 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2486 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2488 PASSTHROUGH_IO_IN(vga,port,dest,len);
2490 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2492 // This read does not reset the state machine
2497 static int dac_read_address_write(struct guest_info *core,
2503 struct vga_internal *vga = (struct vga_internal *) priv_data;
2506 new_addr=*((uint8_t*)src);
2508 PrintDebug(core->vm_info, core, "vga: dac read address write data=0x%x\n", new_addr);
2510 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2512 PASSTHROUGH_IO_OUT(vga,port,src,len);
2514 // cannot be out of bounds since there are 256 regs
2516 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2518 // Now we also need to reset the state machine
2520 vga->vga_dac.state=DAC_READ;
2521 vga->vga_dac.channel=RED;
2527 static int dac_data_read(struct guest_info *core,
2533 struct vga_internal *vga = (struct vga_internal *) priv_data;
2538 if (vga->vga_dac.state!=DAC_READ) {
2539 PrintError(core->vm_info, core, "vga: dac data read while in other state\n");
2540 // results undefined, so we continue
2543 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2545 curreg = vga->vga_dac.vga_dac_read_addr;
2546 curchannel = vga->vga_dac.channel;
2547 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2549 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] = 0x%x\n",
2551 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2552 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2555 *((uint8_t*)dest) = data;
2557 PASSTHROUGH_IO_IN(vga,port,dest,len);
2559 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2561 curchannel = (curchannel+1)%3;
2562 vga->vga_dac.channel=curchannel;
2563 if (curchannel==0) {
2564 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2566 vga->vga_dac.vga_dac_read_addr = curreg;
2567 vga->vga_dac.state=DAC_READ;
2574 static int dac_data_write(struct guest_info *core,
2580 struct vga_internal *vga = (struct vga_internal *) priv_data;
2584 vga_palette_reg data32;
2585 vga_palette_reg mask32;
2587 if (vga->vga_dac.state!=DAC_WRITE) {
2588 PrintError(core->vm_info, core, "vga: dac data write while in other state\n");
2589 // results undefined, so we continue
2592 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2594 PASSTHROUGH_IO_OUT(vga,port,src,len);
2596 curreg = vga->vga_dac.vga_dac_write_addr;
2597 curchannel = vga->vga_dac.channel;
2598 data = *((uint8_t *)src);
2600 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] write with 0x%x\n",
2602 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2603 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2606 data32 = data & 0x3f ;
2607 data32 <<= curchannel*8;
2608 mask32 = ~(0xff << (curchannel * 8));
2610 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2611 vga->vga_dac.vga_dac_palette[curreg] |= data32;
2613 curchannel = (curchannel+1)%3;
2614 vga->vga_dac.channel=curchannel;
2615 if (curchannel==0) {
2616 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2618 vga->vga_dac.vga_dac_write_addr = curreg;
2619 vga->vga_dac.state=DAC_WRITE;
2628 static int dac_pixel_mask_read(struct guest_info *core,
2634 struct vga_internal *vga = (struct vga_internal *) priv_data;
2636 PrintDebug(core->vm_info, core, "vga: dac pixel mask read data=0x%x\n",
2637 vga->vga_dac.vga_pixel_mask);
2639 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2641 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2643 PASSTHROUGH_IO_IN(vga,port,dest,len);
2645 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2650 static int dac_pixel_mask_write(struct guest_info *core,
2656 struct vga_internal *vga = (struct vga_internal *) priv_data;
2659 new_data=*((uint8_t*)src);
2661 PrintDebug(core->vm_info, core, "vga: dac pixel mask write data=0x%x\n", new_data);
2663 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2665 PASSTHROUGH_IO_OUT(vga,port,src,len);
2667 vga->vga_dac.vga_pixel_mask = new_data;
2672 static int init_vga(struct vga_internal *vga)
2674 // TODO: startup spec of register contents, if any
2675 vga->vga_misc.vga_input_stat1.val = 0x1; // display enable, not in retrace
2680 static int free_vga(struct vga_internal *vga)
2684 struct vm_device *dev = vga->dev;
2686 // Framebuffer deletion is user's responsibility
2688 // if (vga->mem_store) {
2689 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2690 // vga->mem_store=0;
2693 for (i=0;i<MAP_NUM;i++) {
2695 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2700 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2704 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2705 // The following also covers VGA_INPUT_STAT0_READ
2706 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2707 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2708 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2709 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2710 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2711 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2713 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2715 /* Sequencer registers */
2716 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2717 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2719 /* CRT controller registers */
2720 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2721 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2722 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2723 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2725 /* graphics controller registers */
2726 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2727 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2729 /* attribute controller registers */
2730 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2731 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2733 /* video DAC palette registers */
2734 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2735 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2736 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2737 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2740 if (vga->host_cons) {
2741 v3_graphics_console_close(vga->host_cons);
2749 static struct v3_device_ops dev_ops = {
2750 .free = (int (*)(void *))free_vga,
2754 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2755 struct vga_internal *vga;
2759 char * dev_id = v3_cfg_val(cfg, "ID");
2760 char * passthrough = v3_cfg_val(cfg, "passthrough");
2761 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2763 PrintDebug(vm, VCORE_NONE, "vga: init_device\n");
2765 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2768 PrintError(vm, VCORE_NONE, "vga: cannot allocate\n");
2772 memset(vga, 0, sizeof(struct vga_internal));
2774 vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2775 vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2777 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2778 PrintDebug(vm, VCORE_NONE, "vga: enabling passthrough\n");
2779 vga->passthrough=true;
2780 vga->skip_next_passthrough_out=false;
2784 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2785 struct v3_frame_buffer_spec req;
2787 PrintDebug(vm, VCORE_NONE, "vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2789 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2790 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2792 req.height=VGA_MAXY;
2794 req.bytes_per_pixel=4;
2795 req.bits_per_channel=8;
2801 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2803 if (!vga->host_cons) {
2804 PrintError(vm, VCORE_NONE, "vga: unable to open host OS's graphics console\n");
2809 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2810 PrintDebug(vm, VCORE_NONE, "vga: warning: target spec differs from requested spec\n");
2811 PrintDebug(vm, VCORE_NONE, "vga: request: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", req.width, req.height, req.bytes_per_pixel, req.bits_per_channel, req.red_offset, req.green_offset, req.blue_offset);
2812 PrintDebug(vm, VCORE_NONE, "vga: response: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", vga->target_spec.width, vga->target_spec.height, vga->target_spec.bytes_per_pixel, vga->target_spec.bits_per_channel, vga->target_spec.red_offset, vga->target_spec.green_offset, vga->target_spec.blue_offset);
2816 if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) {
2817 V3_Print(vm, VCORE_NONE, "vga: enabling console-driven rendering\n");
2818 if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) {
2819 PrintError(vm, VCORE_NONE, "vga: cannot enable console-driven rendering\n");
2825 V3_Print(vm, VCORE_NONE, "vga: enabling console inquiry for updates\n");
2826 if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) {
2827 PrintError(vm, VCORE_NONE, "vga: cannot enable console inquiry for updates\n");
2833 if (!vga->passthrough && !vga->host_cons) {
2834 V3_Print(vm, VCORE_NONE, "vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2838 // No memory store is allocated since we will use a full memory hook
2839 // The VGA maps can be read as well as written
2840 // Reads also affect writes, since they are how you fill the latches
2842 // Now allocate the maps
2843 for (i=0;i<MAP_NUM;i++) {
2846 temp = (void*)V3_AllocShadowSafePages(vm,MAP_SIZE/4096);
2848 PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
2853 vga->map[i] = (vga_map) V3_VAddr(temp);
2855 memset(vga->map[i],0,MAP_SIZE);
2858 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2861 PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
2868 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2869 MEM_REGION_START, MEM_REGION_END,
2873 PrintError(vm, VCORE_NONE, "vga: memory book failed\n");
2874 v3_remove_device(dev);
2880 /* Miscelaneous registers */
2881 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2882 // The following also covers VGA_INPUT_STAT0_READ
2883 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2884 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2885 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2886 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2887 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2888 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2890 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2892 /* Sequencer registers */
2893 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2894 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2896 /* CRT controller registers */
2897 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2898 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2899 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2900 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2902 /* graphics controller registers */
2903 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2904 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2906 /* attribute controller registers */
2907 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2908 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2910 /* video DAC palette registers */
2911 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2912 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2913 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2914 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2917 PrintError(vm, VCORE_NONE, "vga: Error allocating VGA I/O ports\n");
2918 v3_remove_device(dev);
2924 PrintDebug(vm, VCORE_NONE, "vga: successfully added and initialized.\n");
2930 device_register("VGA", vga_init);