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\n",(void*)guest_addr, length,
1194 vga->vga_graphics_controller.vga_graphics_mode.write_mode);
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 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1223 00b -- Write Mode 0: In this mode, the host data is first rotated
1224 as per the Rotate Count field, then the Enable Set/Reset mechanism
1225 selects data from this or the Set/Reset field. Then the selected
1226 Logical Operation is performed on the resulting data and the data
1227 in the latch register. Then the Bit Mask field is used to select
1228 which bits come from the resulting data and which come
1229 from the latch register. Finally, only the bit planes enabled by
1230 the Memory Plane Write Enable field are written to memory.
1238 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1239 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1241 offset = find_offset_write(vga, guest_addr);
1244 PrintDebug(core->vm_info, core, "vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1247 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1249 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1250 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1251 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1252 uint8_t mm = find_map_write(vga,guest_addr+i);
1255 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);
1258 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) {
1259 vga_map map = vga->map[mapnum];
1260 uint8_t data = ((uint8_t *)src)[i];
1261 uint8_t latchval = vga->latch[mapnum];
1264 PrintDebug(core->vm_info, core, "vga: raw data=0x%x\n",data);
1266 // rotate data right
1268 data = (data>>ror) | (data<<(8-ror));
1272 PrintDebug(core->vm_info, core, "vga: data after ror=0x%x\n",data);
1274 // use SR bit if ESR is on for this map
1276 data = (sr&0x1) * -1;
1281 PrintDebug(core->vm_info, core, "vga: data after esrr=0x%x\n",data);
1300 PrintDebug(core->vm_info, core, "vga: data after func=0x%x\n",data);
1303 // mux between the data byte and the latch byte on
1305 data = (bm & data) | ((~bm) & latchval);
1309 PrintDebug(core->vm_info, core, "vga: data after bm mux=0x%x\n",data);
1314 // write to this map
1316 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]));
1331 01b -- Write Mode 1: In this mode, data is transferred directly
1332 from the 32 bit latch register to display memory, affected only by
1333 the Memory Plane Write Enable field. The host data is not used in this mode.
1338 uint64_t offset = find_offset_write(vga,guest_addr);
1341 PrintDebug(core->vm_info, core, "vga: mode 1 write, offset=0x%llx\n", offset);
1344 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1347 uint8_t mm = find_map_write(vga,guest_addr+i);
1349 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1350 vga_map map = vga->map[mapnum];
1351 uint8_t latchval = vga->latch[mapnum];
1355 // write to this map
1356 map[offset] = latchval;
1367 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
1368 are replicated across all 8 bits of their respective planes.
1369 Then the selected Logical Operation is performed on the resulting
1370 data and the data in the latch register. Then the Bit Mask field is used to
1371 select which bits come from the resulting data and which come from
1372 the latch register. Finally, only the bit planes enabled by the
1373 Memory Plane Write Enable field are written to memory.
1379 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1381 offset = find_offset_write(vga, guest_addr);
1384 PrintDebug(core->vm_info, core, "vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1387 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1389 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1390 uint8_t mm = find_map_write(vga,guest_addr+i);
1392 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
1393 vga_map map = vga->map[mapnum];
1394 uint8_t data = ((uint8_t *)src)[i];
1395 uint8_t latchval = vga->latch[mapnum];
1397 // expand relevant bit to 8 bit
1398 // it's basically esr=1, sr=bit from mode 0 write
1399 data = ((data>>mapnum)&0x1) * -1;
1416 // mux between latch and alu output
1417 data = (bm & data) | ((~bm) & latchval);
1421 // write to this map
1432 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
1433 as if the Enable Set/Reset field were set to 1111b. Then the host data is
1434 first rotated as per the Rotate Count field, then logical ANDed with the
1435 value of the Bit Mask field. The resulting value is used on the data
1436 obtained from the Set/Reset field in the same way that the Bit Mask field
1437 would ordinarily be used. to select which bits come from the expansion
1438 of the Set/Reset field and which come from the latch register. Finally,
1439 only the bit planes enabled by the Memory Plane Write Enable field
1440 are written to memory.
1447 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1449 offset = find_offset_write(vga, guest_addr);
1451 PrintDebug(core->vm_info, core, "vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1453 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1455 uint8_t data = ((uint8_t *)src)[i];
1458 data = (data>>ror) | (data<<(8-ror));
1461 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1462 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1463 uint8_t mm = find_map_write(vga,guest_addr+i);
1465 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
1466 vga_map map = vga->map[mapnum];
1467 uint8_t latchval = vga->latch[mapnum];
1470 data = (sr&0x1) * -1;
1472 // mux between latch and alu output
1473 data = (bm & data) | ((~bm) & latchval);
1477 // write to this map
1488 // There is no default
1498 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1500 uint64_t mem_start, mem_end;
1503 mem_start=mem_end=0;
1505 get_mem_region(vga, &mem_start, &mem_end);
1507 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1509 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1510 // odd/even mode takes priority
1511 return ((guest_addr-mem_start) >> 1 ) % size;
1514 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1515 // otherwise chain4 if it's on
1516 return ((guest_addr - mem_start) >> 2) % size;
1519 // and what you would expect if neither are on
1520 return (guest_addr-mem_start) % size;
1523 // Given this address
1524 // which specific map should we write into?
1525 // Note that unlike with find_map_write, here we are looking
1526 // for a single map number, not a bit vector of maps to be selected
1527 static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr)
1529 uint64_t mem_start, mem_end;
1531 mem_start=mem_end=0;
1533 get_mem_region(vga, &mem_start, &mem_end);
1535 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1537 // last bit tells us map 0 or 1
1538 return (guest_addr-mem_start) & 0x1;
1541 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1542 // otherwise chain4 if it's on
1544 return (guest_addr - mem_start) & 0x3;
1547 // and what you would expect if neither are on
1548 // note that it's not the same as a write!
1549 return vga->vga_graphics_controller.vga_read_map_select.map_select;
1552 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1555 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1557 return !(new_guest_addr & 0x1);
1560 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1561 return !(new_guest_addr & 0x3);
1567 static int vga_read(struct guest_info * core,
1573 struct vm_device *dev = (struct vm_device *)priv_data;
1574 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1577 PrintDebug(core->vm_info, core, "vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length,
1578 vga->vga_graphics_controller.vga_graphics_mode.read_mode);
1583 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1585 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
1587 /* 0 - a byte from ONE of the 4 planes is returned;
1588 which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
1589 OR by odd/even chaining OR by chain4 chaining
1595 offset = find_offset_read(vga,guest_addr);
1598 PrintDebug(core->vm_info, core, "vga: mode 0 read, offset=0x%llx\n",offset);
1600 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1602 mapnum = find_map_read(vga,guest_addr+i);
1604 ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1606 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1615 /* 1 - Compare video memory and reference color
1616 (in Color Compare, except those not set in Color Don't Care),
1617 each bit in returned result is one comparison between the reference color
1619 Ref color is *4* bits, and thus a one byte read returns a comparison
1625 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1626 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1633 offset = find_offset_read(vga,guest_addr);
1636 PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx, cc=0x%x, dc-0x%x\n",offset,cc,dc);
1640 for (i=0;i<length;i++,offset++) {
1643 for (mapnum=0;mapnum<4;mapnum++) {
1644 map = vga->map[mapnum];
1645 if ( (dc>>mapnum)&0x1 ) { // don't care
1649 bits = (map[offset]&0xf) == cc;
1652 bits |= (((map[offset]>>4))&0xf) == cc;
1654 // not clear whether it is 0..k or k..0
1660 // load the latches with the last item read
1661 for (mapnum=0;mapnum<4;mapnum++) {
1662 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1667 // there is no default
1670 if (vga->passthrough) {
1671 PrintDebug(core->vm_info, core, "vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1672 memcpy(dst,V3_VAddr((void*)guest_addr),length);
1678 PrintDebug(core->vm_info, core, "vga: data read is 0x");
1679 for (i=0;i<length;i++) {
1680 uint8_t c= ((char*)dst)[i];
1681 PrintDebug(core->vm_info, core, "%.2x", c);
1683 PrintDebug(core->vm_info, core, " \"");
1684 for (i=0;i<length;i++) {
1685 char c= ((char*)dst)[i];
1686 PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1688 PrintDebug(core->vm_info, core, "\"\n");
1699 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
1700 if (((len)<(min)) || ((len)>(max))) { \
1701 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)); \
1705 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1708 *(uint8_t *)dest = v3_inb(port);
1711 *(uint16_t *)dest = v3_inw(port);
1714 *(uint32_t *)dest = v3_indw(port);
1717 PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io in size %u\n",length);
1723 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1726 v3_outb(port, *(uint8_t *)src);
1729 v3_outw(port, *(uint16_t *)src);
1732 v3_outdw(port, *(uint32_t *)src);
1735 PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io out size %u\n",length);
1740 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
1741 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1743 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
1744 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1746 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
1747 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1749 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1750 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)
1752 static int misc_out_read(struct guest_info *core,
1758 struct vga_internal *vga = (struct vga_internal *) priv_data;
1760 PrintDebug(core->vm_info, core, "vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1762 ERR_WRONG_SIZE("read","misc out",len,1,1);
1764 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1766 PASSTHROUGH_IO_IN(vga,port,dest,len);
1768 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1773 static int misc_out_write(struct guest_info *core,
1779 struct vga_internal *vga = (struct vga_internal *) priv_data;
1781 PrintDebug(core->vm_info, core, "vga: misc out write data=0x%x\n", *((uint8_t*)src));
1783 ERR_WRONG_SIZE("write","misc out",len,1,1);
1785 PASSTHROUGH_IO_OUT(vga,port,src,len);
1787 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
1796 static int input_stat0_read(struct guest_info *core,
1802 struct vga_internal *vga = (struct vga_internal *) priv_data;
1804 PrintDebug(core->vm_info, core, "vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1806 ERR_WRONG_SIZE("read","input stat0",len,1,1);
1808 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1810 PASSTHROUGH_IO_IN(vga,port,dest,len);
1812 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1818 static int input_stat1_read(struct guest_info *core,
1824 struct vga_internal *vga = (struct vga_internal *) priv_data;
1826 PrintDebug(core->vm_info, core, "vga: input stat0 (%s) read data=0x%x\n",
1827 port==0x3ba ? "mono" : "color",
1828 vga->vga_misc.vga_input_stat1.val);
1830 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1833 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1835 // Stunningly, reading stat1 is also a way to reset
1836 // the state of attribute controller address/data flipflop
1837 // That is some mighty fine crack the designers were smoking.
1839 vga->vga_attribute_controller.state=ATTR_ADDR;
1841 PASSTHROUGH_IO_IN(vga,port,dest,len);
1843 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1849 static int feature_control_read(struct guest_info *core,
1855 struct vga_internal *vga = (struct vga_internal *) priv_data;
1857 PrintDebug(core->vm_info, core, "vga: feature control read data=0x%x\n",
1858 vga->vga_misc.vga_feature_control.val);
1860 ERR_WRONG_SIZE("read","feature control",len,1,1);
1863 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1865 PASSTHROUGH_IO_IN(vga,port,dest,len);
1867 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1872 static int feature_control_write(struct guest_info *core,
1878 struct vga_internal *vga = (struct vga_internal *) priv_data;
1880 PrintDebug(core->vm_info, core, "vga: feature control (%s) write data=0x%x\n",
1881 port==0x3ba ? "mono" : "color",
1884 ERR_WRONG_SIZE("write","feature control",len,1,1);
1886 PASSTHROUGH_IO_OUT(vga,port,src,len);
1888 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1896 static int video_subsys_enable_read(struct guest_info *core,
1902 struct vga_internal *vga = (struct vga_internal *) priv_data;
1904 PrintDebug(core->vm_info, core, "vga: video subsys enable read data=0x%x\n",
1905 vga->vga_misc.vga_video_subsys_enable.val);
1907 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1909 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1911 PASSTHROUGH_IO_IN(vga,port,dest,len);
1913 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1918 static int video_subsys_enable_write(struct guest_info *core,
1924 struct vga_internal *vga = (struct vga_internal *) priv_data;
1926 PrintDebug(core->vm_info, core, "vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1928 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1930 PASSTHROUGH_IO_OUT(vga,port,src,len);
1932 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1939 static int sequencer_address_read(struct guest_info *core,
1945 struct vga_internal *vga = (struct vga_internal *) priv_data;
1947 PrintDebug(core->vm_info, core, "vga: sequencer address read data=0x%x\n",
1948 vga->vga_sequencer.vga_sequencer_addr.val);
1950 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1952 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1954 PASSTHROUGH_IO_IN(vga,port,dest,len);
1956 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1961 static int sequencer_data_write(struct guest_info *core,
1967 struct vga_internal *vga = (struct vga_internal *) priv_data;
1971 data=*((uint8_t*)src);
1972 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1974 PrintDebug(core->vm_info, core, "vga: sequencer write data (index=%d) with 0x%x\n",
1977 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1979 PASSTHROUGH_IO_OUT(vga,port,src,len);
1982 if (index>=VGA_SEQUENCER_NUM) {
1983 PrintError(core->vm_info, core, "vga: sequencer data write is for invalid index %d, ignoring\n",index);
1985 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1993 static int sequencer_address_write(struct guest_info *core,
1999 struct vga_internal *vga = (struct vga_internal *) priv_data;
2002 new_addr=*((uint8_t*)src);
2004 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);
2006 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
2008 PASSTHROUGH_IO_OUT(vga,port,src,len);
2010 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
2013 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2014 // second byte is the data
2015 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
2016 PrintError(core->vm_info, core, "vga: write of data failed\n");
2024 static int sequencer_data_read(struct guest_info *core,
2030 struct vga_internal *vga = (struct vga_internal *) priv_data;
2034 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
2036 if (index>=VGA_SEQUENCER_NUM) {
2038 PrintError(core->vm_info, core, "vga: sequencer data read at invalid index %d, returning zero\n",index);
2040 data=vga->vga_sequencer.vga_sequencer_regs[index];
2043 PrintDebug(core->vm_info, core, "vga: sequencer data read data (index=%d) = 0x%x\n",
2046 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2048 *((uint8_t*)dest) = data;
2050 PASSTHROUGH_IO_IN(vga,port,dest,len);
2052 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2061 static int crt_controller_address_read(struct guest_info *core,
2067 struct vga_internal *vga = (struct vga_internal *) priv_data;
2069 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address read data=0x%x\n",
2070 port==0x3b4 ? "mono" : "color",
2071 vga->vga_crt_controller.vga_crt_addr.val);
2073 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2075 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2077 PASSTHROUGH_IO_IN(vga,port,dest,len);
2079 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2084 static int crt_controller_data_write(struct guest_info *core,
2090 struct vga_internal *vga = (struct vga_internal *) priv_data;
2094 data=*((uint8_t*)src);
2096 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2098 PrintDebug(core->vm_info, core, "vga: crt controller (%s) write data (index=%d) with 0x%x\n",
2099 port==0x3b5 ? "mono" : "color",
2102 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2104 PASSTHROUGH_IO_OUT(vga,port,src,len);
2106 if (index>=VGA_CRT_CONTROLLER_NUM) {
2107 PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
2109 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2117 static int crt_controller_address_write(struct guest_info *core,
2123 struct vga_internal *vga = (struct vga_internal *) priv_data;
2126 new_addr=*((uint8_t*)src);
2128 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address write data=0x%x len=%u\n",
2129 port==0x3b4 ? "mono" : "color",
2130 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2132 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2134 PASSTHROUGH_IO_OUT(vga,port,src,len);
2136 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
2139 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2140 // second byte is the data
2141 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
2142 PrintError(core->vm_info, core, "vga: write of data failed\n");
2150 static int crt_controller_data_read(struct guest_info *core,
2156 struct vga_internal *vga = (struct vga_internal *) priv_data;
2160 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2162 if (index>=VGA_CRT_CONTROLLER_NUM) {
2164 PrintError(core->vm_info, core, "vga: crt controller data read for illegal index %d, returning zero\n",index);
2166 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2169 PrintDebug(core->vm_info, core, "vga: crt controller data (index=%d) = 0x%x\n",index,data);
2171 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2173 *((uint8_t*)dest) = data;
2175 PASSTHROUGH_IO_IN(vga,port,dest,len);
2177 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2184 static int graphics_controller_address_read(struct guest_info *core,
2190 struct vga_internal *vga = (struct vga_internal *) priv_data;
2192 PrintDebug(core->vm_info, core, "vga: graphics controller address read data=0x%x\n",
2193 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2195 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2197 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2199 PASSTHROUGH_IO_IN(vga,port,dest,len);
2201 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2206 static int graphics_controller_data_write(struct guest_info *core,
2212 struct vga_internal *vga = (struct vga_internal *) priv_data;
2216 data=*((uint8_t*)src);
2217 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2220 PrintDebug(core->vm_info, core, "vga: graphics_controller write data (index=%d) with 0x%x\n",
2223 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2225 PASSTHROUGH_IO_OUT(vga,port,src,len);
2227 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2228 PrintError(core->vm_info, core, "vga: graphics controller write for illegal index %d ignored\n",index);
2230 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2238 static int graphics_controller_address_write(struct guest_info *core,
2244 struct vga_internal *vga = (struct vga_internal *) priv_data;
2247 new_addr=*((uint8_t*)src);
2249 PrintDebug(core->vm_info, core, "vga: graphics controller address write data=0x%x len=%u\n",
2250 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2252 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2254 PASSTHROUGH_IO_OUT(vga,port,src,len);
2256 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
2259 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2260 // second byte is the data
2261 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
2262 PrintError(core->vm_info, core, "vga: write of data failed\n");
2270 static int graphics_controller_data_read(struct guest_info *core,
2276 struct vga_internal *vga = (struct vga_internal *) priv_data;
2280 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2283 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2285 PrintError(core->vm_info, core, "vga: graphics controller data read from illegal index %d, returning zero\n",index);
2287 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2290 PrintDebug(core->vm_info, core, "vga: graphics controller data read data (index=%d) = 0x%x\n",
2293 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2295 *((uint8_t*)dest) = data;
2297 PASSTHROUGH_IO_IN(vga,port,dest,len);
2299 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2307 /* Note that these guys have a bizarre protocol*/
2309 static int attribute_controller_address_read(struct guest_info *core,
2315 struct vga_internal *vga = (struct vga_internal *) priv_data;
2317 PrintDebug(core->vm_info, core, "vga: attribute controller address read data=0x%x\n",
2318 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2320 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
2322 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2324 PASSTHROUGH_IO_IN(vga,port,dest,len);
2326 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2328 // Reading the attribute controller does not change the state
2333 static int attribute_controller_address_and_data_write(struct guest_info *core,
2339 struct vga_internal *vga = (struct vga_internal *) priv_data;
2342 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
2343 uint8_t new_addr = *((uint8_t*)src);
2344 // We are to treat this as an address write, and flip state
2345 // to expect data ON THIS SAME PORT
2346 PrintDebug(core->vm_info, core, "vga: attribute controller address write data=0x%x\n", new_addr);
2348 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2350 PASSTHROUGH_IO_OUT(vga,port,src,len);
2352 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
2354 vga->vga_attribute_controller.state=ATTR_DATA;
2357 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
2359 uint8_t data = *((uint8_t*)src);
2360 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2362 PrintDebug(core->vm_info, core, "vga: attribute controller data write index %d with data=0x%x\n", index,data);
2364 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2366 PASSTHROUGH_IO_OUT(vga,port,src,len);
2368 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2369 PrintError(core->vm_info, core, "vga: attribute controller write to illegal index %d ignored\n",index);
2371 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2374 vga->vga_attribute_controller.state=ATTR_ADDR;
2383 static int attribute_controller_data_read(struct guest_info *core,
2389 struct vga_internal *vga = (struct vga_internal *) priv_data;
2393 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2395 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2397 PrintError(core->vm_info, core, "vga: attribute controller read of illegal index %d, returning zero\n",index);
2399 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2402 PrintDebug(core->vm_info, core, "vga: attribute controller data read data (index=%d) = 0x%x\n",
2405 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2407 *((uint8_t*)dest) = data;
2409 PASSTHROUGH_IO_IN(vga,port,dest,len);
2411 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2418 Note that these guys also have a strange protocol
2419 since they need to squeeze 18 bits of data through
2422 static int dac_write_address_read(struct guest_info *core,
2428 struct vga_internal *vga = (struct vga_internal *) priv_data;
2430 PrintDebug(core->vm_info, core, "vga: dac write address read data=0x%x\n",
2431 vga->vga_dac.vga_dac_write_addr);
2433 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2436 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2438 PASSTHROUGH_IO_IN(vga,port,dest,len);
2440 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2442 // This read does not reset the state machine
2447 static int dac_write_address_write(struct guest_info *core,
2453 struct vga_internal *vga = (struct vga_internal *) priv_data;
2456 new_addr=*((uint8_t*)src);
2458 PrintDebug(core->vm_info, core, "vga: dac write address write data=0x%x\n", new_addr);
2460 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2462 PASSTHROUGH_IO_OUT(vga,port,src,len);
2464 // cannot be out of bounds since there are 256 regs
2466 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2468 // Now we also need to reset the state machine
2470 vga->vga_dac.state=DAC_WRITE;
2471 vga->vga_dac.channel=RED;
2477 static int dac_read_address_read(struct guest_info *core,
2483 struct vga_internal *vga = (struct vga_internal *) priv_data;
2485 PrintDebug(core->vm_info, core, "vga: dac read address read data=0x%x\n",
2486 vga->vga_dac.vga_dac_read_addr);
2488 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2490 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2492 PASSTHROUGH_IO_IN(vga,port,dest,len);
2494 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2496 // This read does not reset the state machine
2501 static int dac_read_address_write(struct guest_info *core,
2507 struct vga_internal *vga = (struct vga_internal *) priv_data;
2510 new_addr=*((uint8_t*)src);
2512 PrintDebug(core->vm_info, core, "vga: dac read address write data=0x%x\n", new_addr);
2514 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2516 PASSTHROUGH_IO_OUT(vga,port,src,len);
2518 // cannot be out of bounds since there are 256 regs
2520 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2522 // Now we also need to reset the state machine
2524 vga->vga_dac.state=DAC_READ;
2525 vga->vga_dac.channel=RED;
2531 static int dac_data_read(struct guest_info *core,
2537 struct vga_internal *vga = (struct vga_internal *) priv_data;
2542 if (vga->vga_dac.state!=DAC_READ) {
2543 PrintError(core->vm_info, core, "vga: dac data read while in other state\n");
2544 // results undefined, so we continue
2547 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2549 curreg = vga->vga_dac.vga_dac_read_addr;
2550 curchannel = vga->vga_dac.channel;
2551 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2553 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] = 0x%x\n",
2555 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2556 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2559 *((uint8_t*)dest) = data;
2561 PASSTHROUGH_IO_IN(vga,port,dest,len);
2563 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2565 curchannel = (curchannel+1)%3;
2566 vga->vga_dac.channel=curchannel;
2567 if (curchannel==0) {
2568 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2570 vga->vga_dac.vga_dac_read_addr = curreg;
2571 vga->vga_dac.state=DAC_READ;
2578 static int dac_data_write(struct guest_info *core,
2584 struct vga_internal *vga = (struct vga_internal *) priv_data;
2588 vga_palette_reg data32;
2589 vga_palette_reg mask32;
2591 if (vga->vga_dac.state!=DAC_WRITE) {
2592 PrintError(core->vm_info, core, "vga: dac data write while in other state\n");
2593 // results undefined, so we continue
2596 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2598 PASSTHROUGH_IO_OUT(vga,port,src,len);
2600 curreg = vga->vga_dac.vga_dac_write_addr;
2601 curchannel = vga->vga_dac.channel;
2602 data = *((uint8_t *)src);
2604 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] write with 0x%x\n",
2606 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2607 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2610 data32 = data & 0x3f ;
2611 data32 <<= curchannel*8;
2612 mask32 = ~(0xff << (curchannel * 8));
2614 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2615 vga->vga_dac.vga_dac_palette[curreg] |= data32;
2617 curchannel = (curchannel+1)%3;
2618 vga->vga_dac.channel=curchannel;
2619 if (curchannel==0) {
2620 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2622 vga->vga_dac.vga_dac_write_addr = curreg;
2623 vga->vga_dac.state=DAC_WRITE;
2632 static int dac_pixel_mask_read(struct guest_info *core,
2638 struct vga_internal *vga = (struct vga_internal *) priv_data;
2640 PrintDebug(core->vm_info, core, "vga: dac pixel mask read data=0x%x\n",
2641 vga->vga_dac.vga_pixel_mask);
2643 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2645 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2647 PASSTHROUGH_IO_IN(vga,port,dest,len);
2649 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2654 static int dac_pixel_mask_write(struct guest_info *core,
2660 struct vga_internal *vga = (struct vga_internal *) priv_data;
2663 new_data=*((uint8_t*)src);
2665 PrintDebug(core->vm_info, core, "vga: dac pixel mask write data=0x%x\n", new_data);
2667 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2669 PASSTHROUGH_IO_OUT(vga,port,src,len);
2671 vga->vga_dac.vga_pixel_mask = new_data;
2676 static int init_vga(struct vga_internal *vga)
2678 // TODO: startup spec of register contents, if any
2679 vga->vga_misc.vga_input_stat1.val = 0x1; // display enable, not in retrace
2684 static int free_vga(struct vga_internal *vga)
2688 struct vm_device *dev = vga->dev;
2690 // Framebuffer deletion is user's responsibility
2692 // if (vga->mem_store) {
2693 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2694 // vga->mem_store=0;
2697 for (i=0;i<MAP_NUM;i++) {
2699 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2704 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2708 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2709 // The following also covers VGA_INPUT_STAT0_READ
2710 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2711 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2712 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2713 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2714 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2715 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2717 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2719 /* Sequencer registers */
2720 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2721 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2723 /* CRT controller registers */
2724 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2725 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2726 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2727 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2729 /* graphics controller registers */
2730 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2731 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2733 /* attribute controller registers */
2734 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2735 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2737 /* video DAC palette registers */
2738 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2739 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2740 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2741 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2744 if (vga->host_cons) {
2745 v3_graphics_console_close(vga->host_cons);
2753 static struct v3_device_ops dev_ops = {
2754 .free = (int (*)(void *))free_vga,
2758 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2759 struct vga_internal *vga;
2763 char * dev_id = v3_cfg_val(cfg, "ID");
2764 char * passthrough = v3_cfg_val(cfg, "passthrough");
2765 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2767 PrintDebug(vm, VCORE_NONE, "vga: init_device\n");
2769 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2772 PrintError(vm, VCORE_NONE, "vga: cannot allocate\n");
2776 memset(vga, 0, sizeof(struct vga_internal));
2778 vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2779 vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2781 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2782 PrintDebug(vm, VCORE_NONE, "vga: enabling passthrough\n");
2783 vga->passthrough=true;
2784 vga->skip_next_passthrough_out=false;
2788 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2789 struct v3_frame_buffer_spec req;
2791 PrintDebug(vm, VCORE_NONE, "vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2793 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2794 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2796 req.height=VGA_MAXY;
2798 req.bytes_per_pixel=4;
2799 req.bits_per_channel=8;
2805 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2807 if (!vga->host_cons) {
2808 PrintError(vm, VCORE_NONE, "vga: unable to open host OS's graphics console\n");
2813 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2814 PrintDebug(vm, VCORE_NONE, "vga: warning: target spec differs from requested spec\n");
2815 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);
2816 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);
2820 if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) {
2821 V3_Print(vm, VCORE_NONE, "vga: enabling console-driven rendering\n");
2822 if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) {
2823 PrintError(vm, VCORE_NONE, "vga: cannot enable console-driven rendering\n");
2829 V3_Print(vm, VCORE_NONE, "vga: enabling console inquiry for updates\n");
2830 if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) {
2831 PrintError(vm, VCORE_NONE, "vga: cannot enable console inquiry for updates\n");
2837 if (!vga->passthrough && !vga->host_cons) {
2838 V3_Print(vm, VCORE_NONE, "vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2842 // No memory store is allocated since we will use a full memory hook
2843 // The VGA maps can be read as well as written
2844 // Reads also affect writes, since they are how you fill the latches
2846 // Now allocate the maps
2847 for (i=0;i<MAP_NUM;i++) {
2850 temp = (void*)V3_AllocPages(MAP_SIZE/4096);
2852 PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
2857 vga->map[i] = (vga_map) V3_VAddr(temp);
2859 memset(vga->map[i],0,MAP_SIZE);
2862 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2865 PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
2872 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2873 MEM_REGION_START, MEM_REGION_END,
2877 PrintError(vm, VCORE_NONE, "vga: memory book failed\n");
2878 v3_remove_device(dev);
2884 /* Miscelaneous registers */
2885 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2886 // The following also covers VGA_INPUT_STAT0_READ
2887 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2888 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2889 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2890 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2891 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2892 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2894 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2896 /* Sequencer registers */
2897 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2898 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2900 /* CRT controller registers */
2901 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2902 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2903 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2904 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2906 /* graphics controller registers */
2907 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2908 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2910 /* attribute controller registers */
2911 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2912 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2914 /* video DAC palette registers */
2915 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2916 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2917 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2918 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2921 PrintError(vm, VCORE_NONE, "vga: Error allocating VGA I/O ports\n");
2922 v3_remove_device(dev);
2928 PrintDebug(vm, VCORE_NONE, "vga: successfully added and initialized.\n");
2934 device_register("VGA", vga_init);