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 // Pretend that horizontal and vertical blanking
1833 if (!vga->vga_misc.vga_input_stat1.disp_en) {
1835 // if not blanking, start horizontal blanking
1836 vga->vga_misc.vga_input_stat1.disp_en = 1;
1837 vga->vga_misc.vga_input_stat1.vert_retrace = 0;
1841 if (!vga->vga_misc.vga_input_stat1.vert_retrace) {
1842 // if not vertical blanking, then now vertical blanking
1843 vga->vga_misc.vga_input_stat1.disp_en = 1;
1844 vga->vga_misc.vga_input_stat1.vert_retrace = 1;
1846 // if vertical blanking, now not blanking
1847 vga->vga_misc.vga_input_stat1.disp_en = 0;
1848 vga->vga_misc.vga_input_stat1.vert_retrace = 0;
1853 // Stunningly, reading stat1 is also a way to reset
1854 // the state of attribute controller address/data flipflop
1855 // That is some mighty fine crack the designers were smoking.
1857 vga->vga_attribute_controller.state=ATTR_ADDR;
1859 PASSTHROUGH_IO_IN(vga,port,dest,len);
1861 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1867 static int feature_control_read(struct guest_info *core,
1873 struct vga_internal *vga = (struct vga_internal *) priv_data;
1875 PrintDebug(core->vm_info, core, "vga: feature control read data=0x%x\n",
1876 vga->vga_misc.vga_feature_control.val);
1878 ERR_WRONG_SIZE("read","feature control",len,1,1);
1881 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1883 PASSTHROUGH_IO_IN(vga,port,dest,len);
1885 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1890 static int feature_control_write(struct guest_info *core,
1896 struct vga_internal *vga = (struct vga_internal *) priv_data;
1898 PrintDebug(core->vm_info, core, "vga: feature control (%s) write data=0x%x\n",
1899 port==0x3ba ? "mono" : "color",
1902 ERR_WRONG_SIZE("write","feature control",len,1,1);
1904 PASSTHROUGH_IO_OUT(vga,port,src,len);
1906 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1914 static int video_subsys_enable_read(struct guest_info *core,
1920 struct vga_internal *vga = (struct vga_internal *) priv_data;
1922 PrintDebug(core->vm_info, core, "vga: video subsys enable read data=0x%x\n",
1923 vga->vga_misc.vga_video_subsys_enable.val);
1925 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1927 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1929 PASSTHROUGH_IO_IN(vga,port,dest,len);
1931 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1936 static int video_subsys_enable_write(struct guest_info *core,
1942 struct vga_internal *vga = (struct vga_internal *) priv_data;
1944 PrintDebug(core->vm_info, core, "vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1946 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1948 PASSTHROUGH_IO_OUT(vga,port,src,len);
1950 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1957 static int sequencer_address_read(struct guest_info *core,
1963 struct vga_internal *vga = (struct vga_internal *) priv_data;
1965 PrintDebug(core->vm_info, core, "vga: sequencer address read data=0x%x\n",
1966 vga->vga_sequencer.vga_sequencer_addr.val);
1968 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1970 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1972 PASSTHROUGH_IO_IN(vga,port,dest,len);
1974 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1979 static int sequencer_data_write(struct guest_info *core,
1985 struct vga_internal *vga = (struct vga_internal *) priv_data;
1989 data=*((uint8_t*)src);
1990 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1992 PrintDebug(core->vm_info, core, "vga: sequencer write data (index=%d) with 0x%x\n",
1995 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1997 PASSTHROUGH_IO_OUT(vga,port,src,len);
2000 if (index>=VGA_SEQUENCER_NUM) {
2001 PrintError(core->vm_info, core, "vga: sequencer data write is for invalid index %d, ignoring\n",index);
2003 vga->vga_sequencer.vga_sequencer_regs[index] = data;
2011 static int sequencer_address_write(struct guest_info *core,
2017 struct vga_internal *vga = (struct vga_internal *) priv_data;
2020 new_addr=*((uint8_t*)src);
2022 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);
2024 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
2026 PASSTHROUGH_IO_OUT(vga,port,src,len);
2028 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
2031 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2032 // second byte is the data
2033 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
2034 PrintError(core->vm_info, core, "vga: write of data failed\n");
2042 static int sequencer_data_read(struct guest_info *core,
2048 struct vga_internal *vga = (struct vga_internal *) priv_data;
2052 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
2054 if (index>=VGA_SEQUENCER_NUM) {
2056 PrintError(core->vm_info, core, "vga: sequencer data read at invalid index %d, returning zero\n",index);
2058 data=vga->vga_sequencer.vga_sequencer_regs[index];
2061 PrintDebug(core->vm_info, core, "vga: sequencer data read data (index=%d) = 0x%x\n",
2064 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2066 *((uint8_t*)dest) = data;
2068 PASSTHROUGH_IO_IN(vga,port,dest,len);
2070 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2079 static int crt_controller_address_read(struct guest_info *core,
2085 struct vga_internal *vga = (struct vga_internal *) priv_data;
2087 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address read data=0x%x\n",
2088 port==0x3b4 ? "mono" : "color",
2089 vga->vga_crt_controller.vga_crt_addr.val);
2091 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2093 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2095 PASSTHROUGH_IO_IN(vga,port,dest,len);
2097 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2102 static int crt_controller_data_write(struct guest_info *core,
2108 struct vga_internal *vga = (struct vga_internal *) priv_data;
2112 data=*((uint8_t*)src);
2114 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2116 PrintDebug(core->vm_info, core, "vga: crt controller (%s) write data (index=%d) with 0x%x\n",
2117 port==0x3b5 ? "mono" : "color",
2120 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2122 PASSTHROUGH_IO_OUT(vga,port,src,len);
2124 if (index>=VGA_CRT_CONTROLLER_NUM) {
2125 PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
2127 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2129 if (vga->vga_crt_controller.vga_vertical_retrace_end.enable_vertical_interrupt) {
2130 PrintError(core->vm_info, core, "vga: vertical_retrace_interrupt_enabled is unsupported -- no interrupts will occur!\n");
2140 static int crt_controller_address_write(struct guest_info *core,
2146 struct vga_internal *vga = (struct vga_internal *) priv_data;
2149 new_addr=*((uint8_t*)src);
2151 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address write data=0x%x len=%u\n",
2152 port==0x3b4 ? "mono" : "color",
2153 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2155 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2157 PASSTHROUGH_IO_OUT(vga,port,src,len);
2159 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
2162 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2163 // second byte is the data
2164 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
2165 PrintError(core->vm_info, core, "vga: write of data failed\n");
2173 static int crt_controller_data_read(struct guest_info *core,
2179 struct vga_internal *vga = (struct vga_internal *) priv_data;
2183 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2185 if (index>=VGA_CRT_CONTROLLER_NUM) {
2187 PrintError(core->vm_info, core, "vga: crt controller data read for illegal index %d, returning zero\n",index);
2189 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2192 PrintDebug(core->vm_info, core, "vga: crt controller data (index=%d) = 0x%x\n",index,data);
2194 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2196 *((uint8_t*)dest) = data;
2198 PASSTHROUGH_IO_IN(vga,port,dest,len);
2200 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2207 static int graphics_controller_address_read(struct guest_info *core,
2213 struct vga_internal *vga = (struct vga_internal *) priv_data;
2215 PrintDebug(core->vm_info, core, "vga: graphics controller address read data=0x%x\n",
2216 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2218 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2220 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2222 PASSTHROUGH_IO_IN(vga,port,dest,len);
2224 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2229 static int graphics_controller_data_write(struct guest_info *core,
2235 struct vga_internal *vga = (struct vga_internal *) priv_data;
2239 data=*((uint8_t*)src);
2240 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2243 PrintDebug(core->vm_info, core, "vga: graphics_controller write data (index=%d) with 0x%x\n",
2246 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2248 PASSTHROUGH_IO_OUT(vga,port,src,len);
2250 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2251 PrintError(core->vm_info, core, "vga: graphics controller write for illegal index %d ignored\n",index);
2253 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2261 static int graphics_controller_address_write(struct guest_info *core,
2267 struct vga_internal *vga = (struct vga_internal *) priv_data;
2270 new_addr=*((uint8_t*)src);
2272 PrintDebug(core->vm_info, core, "vga: graphics controller address write data=0x%x len=%u\n",
2273 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2275 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2277 PASSTHROUGH_IO_OUT(vga,port,src,len);
2279 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
2282 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2283 // second byte is the data
2284 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
2285 PrintError(core->vm_info, core, "vga: write of data failed\n");
2293 static int graphics_controller_data_read(struct guest_info *core,
2299 struct vga_internal *vga = (struct vga_internal *) priv_data;
2303 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2306 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2308 PrintError(core->vm_info, core, "vga: graphics controller data read from illegal index %d, returning zero\n",index);
2310 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2313 PrintDebug(core->vm_info, core, "vga: graphics controller data read data (index=%d) = 0x%x\n",
2316 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2318 *((uint8_t*)dest) = data;
2320 PASSTHROUGH_IO_IN(vga,port,dest,len);
2322 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2330 /* Note that these guys have a bizarre protocol*/
2332 static int attribute_controller_address_read(struct guest_info *core,
2338 struct vga_internal *vga = (struct vga_internal *) priv_data;
2340 PrintDebug(core->vm_info, core, "vga: attribute controller address read data=0x%x\n",
2341 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2343 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
2345 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2347 PASSTHROUGH_IO_IN(vga,port,dest,len);
2349 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2351 // Reading the attribute controller does not change the state
2356 static int attribute_controller_address_and_data_write(struct guest_info *core,
2362 struct vga_internal *vga = (struct vga_internal *) priv_data;
2365 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
2366 uint8_t new_addr = *((uint8_t*)src);
2367 // We are to treat this as an address write, and flip state
2368 // to expect data ON THIS SAME PORT
2369 PrintDebug(core->vm_info, core, "vga: attribute controller address write data=0x%x\n", new_addr);
2371 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2373 PASSTHROUGH_IO_OUT(vga,port,src,len);
2375 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
2377 vga->vga_attribute_controller.state=ATTR_DATA;
2380 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
2382 uint8_t data = *((uint8_t*)src);
2383 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2385 PrintDebug(core->vm_info, core, "vga: attribute controller data write index %d with data=0x%x\n", index,data);
2387 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2389 PASSTHROUGH_IO_OUT(vga,port,src,len);
2391 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2392 PrintError(core->vm_info, core, "vga: attribute controller write to illegal index %d ignored\n",index);
2394 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2397 vga->vga_attribute_controller.state=ATTR_ADDR;
2406 static int attribute_controller_data_read(struct guest_info *core,
2412 struct vga_internal *vga = (struct vga_internal *) priv_data;
2416 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2418 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2420 PrintError(core->vm_info, core, "vga: attribute controller read of illegal index %d, returning zero\n",index);
2422 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2425 PrintDebug(core->vm_info, core, "vga: attribute controller data read data (index=%d) = 0x%x\n",
2428 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2430 *((uint8_t*)dest) = data;
2432 PASSTHROUGH_IO_IN(vga,port,dest,len);
2434 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2441 Note that these guys also have a strange protocol
2442 since they need to squeeze 18 bits of data through
2445 static int dac_write_address_read(struct guest_info *core,
2451 struct vga_internal *vga = (struct vga_internal *) priv_data;
2453 PrintDebug(core->vm_info, core, "vga: dac write address read data=0x%x\n",
2454 vga->vga_dac.vga_dac_write_addr);
2456 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2459 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2461 PASSTHROUGH_IO_IN(vga,port,dest,len);
2463 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2465 // This read does not reset the state machine
2470 static int dac_write_address_write(struct guest_info *core,
2476 struct vga_internal *vga = (struct vga_internal *) priv_data;
2479 new_addr=*((uint8_t*)src);
2481 PrintDebug(core->vm_info, core, "vga: dac write address write data=0x%x\n", new_addr);
2483 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2485 PASSTHROUGH_IO_OUT(vga,port,src,len);
2487 // cannot be out of bounds since there are 256 regs
2489 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2491 // Now we also need to reset the state machine
2493 vga->vga_dac.state=DAC_WRITE;
2494 vga->vga_dac.channel=RED;
2500 static int dac_read_address_read(struct guest_info *core,
2506 struct vga_internal *vga = (struct vga_internal *) priv_data;
2508 PrintDebug(core->vm_info, core, "vga: dac read address read data=0x%x\n",
2509 vga->vga_dac.vga_dac_read_addr);
2511 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2513 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2515 PASSTHROUGH_IO_IN(vga,port,dest,len);
2517 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2519 // This read does not reset the state machine
2524 static int dac_read_address_write(struct guest_info *core,
2530 struct vga_internal *vga = (struct vga_internal *) priv_data;
2533 new_addr=*((uint8_t*)src);
2535 PrintDebug(core->vm_info, core, "vga: dac read address write data=0x%x\n", new_addr);
2537 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2539 PASSTHROUGH_IO_OUT(vga,port,src,len);
2541 // cannot be out of bounds since there are 256 regs
2543 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2545 // Now we also need to reset the state machine
2547 vga->vga_dac.state=DAC_READ;
2548 vga->vga_dac.channel=RED;
2554 static int dac_data_read(struct guest_info *core,
2560 struct vga_internal *vga = (struct vga_internal *) priv_data;
2565 if (vga->vga_dac.state!=DAC_READ) {
2566 PrintError(core->vm_info, core, "vga: dac data read while in other state\n");
2567 // results undefined, so we continue
2570 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2572 curreg = vga->vga_dac.vga_dac_read_addr;
2573 curchannel = vga->vga_dac.channel;
2574 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2576 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] = 0x%x\n",
2578 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2579 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2582 *((uint8_t*)dest) = data;
2584 PASSTHROUGH_IO_IN(vga,port,dest,len);
2586 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2588 curchannel = (curchannel+1)%3;
2589 vga->vga_dac.channel=curchannel;
2590 if (curchannel==0) {
2591 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2593 vga->vga_dac.vga_dac_read_addr = curreg;
2594 vga->vga_dac.state=DAC_READ;
2601 static int dac_data_write(struct guest_info *core,
2607 struct vga_internal *vga = (struct vga_internal *) priv_data;
2611 vga_palette_reg data32;
2612 vga_palette_reg mask32;
2614 if (vga->vga_dac.state!=DAC_WRITE) {
2615 PrintError(core->vm_info, core, "vga: dac data write while in other state\n");
2616 // results undefined, so we continue
2619 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2621 PASSTHROUGH_IO_OUT(vga,port,src,len);
2623 curreg = vga->vga_dac.vga_dac_write_addr;
2624 curchannel = vga->vga_dac.channel;
2625 data = *((uint8_t *)src);
2627 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] write with 0x%x\n",
2629 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2630 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2633 data32 = data & 0x3f ;
2634 data32 <<= curchannel*8;
2635 mask32 = ~(0xff << (curchannel * 8));
2637 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2638 vga->vga_dac.vga_dac_palette[curreg] |= data32;
2640 curchannel = (curchannel+1)%3;
2641 vga->vga_dac.channel=curchannel;
2642 if (curchannel==0) {
2643 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2645 vga->vga_dac.vga_dac_write_addr = curreg;
2646 vga->vga_dac.state=DAC_WRITE;
2655 static int dac_pixel_mask_read(struct guest_info *core,
2661 struct vga_internal *vga = (struct vga_internal *) priv_data;
2663 PrintDebug(core->vm_info, core, "vga: dac pixel mask read data=0x%x\n",
2664 vga->vga_dac.vga_pixel_mask);
2666 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2668 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2670 PASSTHROUGH_IO_IN(vga,port,dest,len);
2672 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2677 static int dac_pixel_mask_write(struct guest_info *core,
2683 struct vga_internal *vga = (struct vga_internal *) priv_data;
2686 new_data=*((uint8_t*)src);
2688 PrintDebug(core->vm_info, core, "vga: dac pixel mask write data=0x%x\n", new_data);
2690 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2692 PASSTHROUGH_IO_OUT(vga,port,src,len);
2694 vga->vga_dac.vga_pixel_mask = new_data;
2699 static int init_vga(struct vga_internal *vga)
2701 // TODO: startup spec of register contents, if any
2702 vga->vga_misc.vga_input_stat1.val = 0x1; // display enable, not in retrace
2707 static int free_vga(struct vga_internal *vga)
2711 struct vm_device *dev = vga->dev;
2713 // Framebuffer deletion is user's responsibility
2715 // if (vga->mem_store) {
2716 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2717 // vga->mem_store=0;
2720 for (i=0;i<MAP_NUM;i++) {
2722 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2727 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2731 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2732 // The following also covers VGA_INPUT_STAT0_READ
2733 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2734 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2735 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2736 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2737 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2738 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2740 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2742 /* Sequencer registers */
2743 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2744 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2746 /* CRT controller registers */
2747 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2748 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2749 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2750 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2752 /* graphics controller registers */
2753 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2754 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2756 /* attribute controller registers */
2757 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2758 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2760 /* video DAC palette registers */
2761 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2762 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2763 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2764 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2767 if (vga->host_cons) {
2768 v3_graphics_console_close(vga->host_cons);
2776 static struct v3_device_ops dev_ops = {
2777 .free = (int (*)(void *))free_vga,
2781 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2782 struct vga_internal *vga;
2786 char * dev_id = v3_cfg_val(cfg, "ID");
2787 char * passthrough = v3_cfg_val(cfg, "passthrough");
2788 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2790 PrintDebug(vm, VCORE_NONE, "vga: init_device\n");
2792 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2795 PrintError(vm, VCORE_NONE, "vga: cannot allocate\n");
2799 memset(vga, 0, sizeof(struct vga_internal));
2801 vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2802 vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2804 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2805 PrintDebug(vm, VCORE_NONE, "vga: enabling passthrough\n");
2806 vga->passthrough=true;
2807 vga->skip_next_passthrough_out=false;
2811 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2812 struct v3_frame_buffer_spec req;
2814 PrintDebug(vm, VCORE_NONE, "vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2816 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2817 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2819 req.height=VGA_MAXY;
2821 req.bytes_per_pixel=4;
2822 req.bits_per_channel=8;
2828 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2830 if (!vga->host_cons) {
2831 PrintError(vm, VCORE_NONE, "vga: unable to open host OS's graphics console\n");
2836 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2837 PrintDebug(vm, VCORE_NONE, "vga: warning: target spec differs from requested spec\n");
2838 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);
2839 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);
2843 if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) {
2844 V3_Print(vm, VCORE_NONE, "vga: enabling console-driven rendering\n");
2845 if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) {
2846 PrintError(vm, VCORE_NONE, "vga: cannot enable console-driven rendering\n");
2852 V3_Print(vm, VCORE_NONE, "vga: enabling console inquiry for updates\n");
2853 if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) {
2854 PrintError(vm, VCORE_NONE, "vga: cannot enable console inquiry for updates\n");
2860 if (!vga->passthrough && !vga->host_cons) {
2861 V3_Print(vm, VCORE_NONE, "vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2865 // No memory store is allocated since we will use a full memory hook
2866 // The VGA maps can be read as well as written
2867 // Reads also affect writes, since they are how you fill the latches
2869 // Now allocate the maps
2870 for (i=0;i<MAP_NUM;i++) {
2873 temp = (void*)V3_AllocShadowSafePages(vm,MAP_SIZE/4096);
2875 PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
2880 vga->map[i] = (vga_map) V3_VAddr(temp);
2882 memset(vga->map[i],0,MAP_SIZE);
2885 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2888 PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
2895 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2896 MEM_REGION_START, MEM_REGION_END,
2900 PrintError(vm, VCORE_NONE, "vga: memory book failed\n");
2901 v3_remove_device(dev);
2907 /* Miscelaneous registers */
2908 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2909 // The following also covers VGA_INPUT_STAT0_READ
2910 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2911 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2912 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2913 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2914 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2915 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2917 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2919 /* Sequencer registers */
2920 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2921 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2923 /* CRT controller registers */
2924 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2925 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2926 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2927 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2929 /* graphics controller registers */
2930 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2931 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2933 /* attribute controller registers */
2934 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2935 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2937 /* video DAC palette registers */
2938 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2939 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2940 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2941 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2944 PrintError(vm, VCORE_NONE, "vga: Error allocating VGA I/O ports\n");
2945 v3_remove_device(dev);
2951 PrintDebug(vm, VCORE_NONE, "vga: successfully added and initialized.\n");
2957 device_register("VGA", vga_init);