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) ;
714 // next 4 pixels use planes 1 and 3
717 ((db[3] >> 4) & 0xc) |
718 ((db[1] >> 6) & 0x3) ;
725 // this one is either very bizarre or as simple as this
733 for (p=0;p< (sm==C256_SHIFT ? 4 : 8);p++) {
736 find_24bit_color(vga,pb[p],&r,&g,&b);
738 // find its position in the framebuffer;
739 pixel = fb + (((fx + p) + (fy*spec->width)) * spec->bytes_per_pixel);
740 red = pixel + spec->red_offset;
741 green = pixel + spec->green_offset;
742 blue = pixel + spec->blue_offset;
753 PrintDebug(VM_NONE, VCORE_NONE, "vga: render done\n");
757 static void render_text_cursor(struct vga_internal *vga, void *fb)
765 // A variant of this function could render to
766 // a text console interface as well
768 static void render_text(struct vga_internal *vga, void *fb)
770 // line graphics enable bit means to dupe column 8 to 9 when
771 // in 9 dot wide mode
772 // otherwise 9th dot is background
774 struct v3_frame_buffer_spec *spec = &(vga->target_spec);
776 uint32_t gw, gh; // graphics w/h
777 uint32_t tw, th; // text w/h
778 uint32_t rtw, rth; // rendered text w/h
779 uint32_t cw, ch; // char font w/h including 8/9
780 uint32_t fw, fh; // fb w/h
782 uint32_t px, py; // cursor position
784 uint32_t x, y, l, p; // text location, line and pixel within the char
785 uint32_t fx, fy; // pixel position within the frame buffer
788 uint8_t *text; // points to current char
789 uint8_t *attr; // and its matching attribute
790 uint8_t *curs; // to where the cursor is
791 uint8_t *font; // to where the current font is
793 uint8_t fg_entry; // foreground color entry
794 uint8_t bg_entry; // background color entry
795 uint8_t fgr,fgg,fgb; // looked up foreground colors
796 uint8_t bgr,bgg,bgb; // looked up bg colors
798 uint8_t ct, ca; // the current char and attribute
799 struct vga_attribute_byte a; // decoded attribute
801 void *pixel; // current pixel in the fb
802 uint8_t *red; // and the channels in the pixel
808 find_graphics_res(vga,&gw,&gh);
809 find_text_res(vga,&tw,&th);
810 find_text_char_dim(vga,&cw,&ch);
814 find_text_cursor_pos(vga,&px,&py,(void**)&curs);
815 find_text_data_start(vga,(void**)&text);
816 find_text_attr_start(vga,(void**)&attr);
818 find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr
820 PrintDebug(VM_NONE, VCORE_NONE, "vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), "
821 "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p"
822 "graphics extension=%u, extended_fontset=%d, blinking=%d\n",
823 gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb,
824 vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code,
825 extended_fontset(vga), blinking(vga));
829 // First we need to clip to what we can actually show
830 rtw = tw < fw/cw ? tw : fw/cw;
831 rth = th < fh/ch ? th : fh/ch;
833 PrintDebug(VM_NONE, VCORE_NONE, "\n");
835 // Now let's scan by char across the whole thing
837 for (x=0;x<tw;x++, text++, attr++) {
838 if (x < rtw && y < rth) {
839 // grab the character and attribute for the position
844 PrintDebug(VM_NONE, VCORE_NONE, "%c",ct);
846 // find the character's font bitmap (one byte per row)
847 find_text_font_start(vga,(void**)&font,
848 extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
850 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
852 // Now let's find out what colors we will be using
855 if (!extended_fontset(vga)) {
856 fg_entry = a.foreground_intensity_or_font_select << 3;
862 find_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
864 if (!blinking(vga)) {
865 bg_entry = a.blinking_or_bg_intensity << 3;
871 find_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
873 // Draw the character
874 for (l=0; l<ch; l++, font++) {
875 uint8_t frow = *font; // this is the row of of the font map
879 // a char can be 9 bits wide, but the font map
880 // is only 8 bits wide, which means we need to know where to
883 // We get it from the font map if
884 // its line line graphics mode and its a graphics char
885 // otherwise it's the background color
886 if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
887 && ct>=0xc0 && ct<=0xdf ) {
893 fbit= (frow >> (7-p) ) & 0x1;
896 // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
897 // For now, we will draw it as black/white
899 // find its position in the framebuffer;
902 pixel = fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
903 red = pixel + spec->red_offset;
904 green = pixel + spec->green_offset;
905 blue = pixel + spec->blue_offset;
907 // Are we on the cursor?
908 // if so, let's negate this pixel to invert the cell
912 // update the framebuffer
926 PrintDebug(VM_NONE, VCORE_NONE, "\n");
935 static void render_test(struct vga_internal *vga, void *fb)
937 struct v3_frame_buffer_spec *s;
939 s=&(vga->target_spec);
941 if (fb && s->height>=480 && s->width>=640 ) {
942 uint8_t color = (uint8_t)(vga->updates_since_render);
946 for (y=0;y<480;y++) {
947 for (x=0;x<640;x++) {
948 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
949 uint8_t *red = pixel + s->red_offset;
950 uint8_t *green = pixel + s->green_offset;
951 uint8_t *blue = pixel + s->blue_offset;
957 } else if (y<(480/2)) {
961 } else if (y<(3*(480/4))) {
966 *red=*green=*blue=color+x;
973 static void render_black(struct vga_internal *vga, void *fb)
975 struct v3_frame_buffer_spec *s;
977 s=&(vga->target_spec);
979 memset(fb,0,s->height*s->width*s->bytes_per_pixel);
982 static void render_maps(struct vga_internal *vga, void *fb)
985 struct v3_frame_buffer_spec *s;
988 s=&(vga->target_spec);
990 if (fb && s->height>=768 && s->width>=1024 ) {
991 // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
998 for (y=480+32;y<768;y++) {
999 for (x=m*256;x<(m+1)*256;x++,b++) {
1000 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
1001 uint8_t *red = pixel + s->red_offset;
1002 uint8_t *green = pixel + s->green_offset;
1003 uint8_t *blue = pixel + s->blue_offset;
1005 *red=*green=*blue=*b;
1012 static int render_core(struct vga_internal *vga)
1016 PrintDebug(VM_NONE, VCORE_NONE, "vga: render on update %u\n",vga->updates_since_render);
1018 fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
1020 if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
1021 if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) {
1022 render_graphics(vga,fb);
1024 render_text(vga,fb);
1025 render_text_cursor(vga,fb);
1028 render_black(vga,fb);
1031 if (0) { render_test(vga,fb); }
1033 // always render maps for now
1034 render_maps(vga,fb);
1036 v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
1038 vga->updates_since_render=0;
1045 static int render(struct vga_internal *vga)
1048 vga->updates_since_render++;
1051 if (vga->host_cons) {
1054 if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING)
1056 (vga->updates_since_render > vga->render_model.updates_before_render)) {
1057 PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to periodic\n");
1062 if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING)
1064 (v3_graphics_console_inform_update(vga->host_cons) > 0) ) {
1066 PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to advisory\n");
1071 // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function
1074 return render_core(vga);
1084 static int render_callback(v3_graphics_console_t cons,
1087 struct vga_internal *vga = (struct vga_internal *) priv;
1089 PrintDebug(VM_NONE, VCORE_NONE, "vga: render due to callback\n");
1091 return render_core(vga);
1094 static int update_callback(v3_graphics_console_t cons,
1097 struct vga_internal *vga = (struct vga_internal *) priv;
1099 return vga->updates_since_render>0;
1104 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
1106 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
1126 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
1128 uint64_t mem_start, mem_end;
1131 mem_start=mem_end=0;
1133 get_mem_region(vga, &mem_start, &mem_end);
1135 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1137 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1138 // NOT odd/even mode
1139 return (guest_addr-mem_start) % size;
1142 return ((guest_addr-mem_start) >> 1 ) % size;
1149 // Determines which maps should be enabled for this single byte write
1150 // and what the increment (actually 1/increment for the copy loop
1152 // memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
1154 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
1156 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
1158 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1159 // NOT odd/even mode
1163 if (guest_addr & 0x1) {
1164 return mm & 0xa; // 0x1010
1166 return mm & 0x5; // 0x0101
1171 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
1173 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1174 // NOT odd/even mode
1177 return !(new_guest_addr & 0x1);
1183 static int vga_write(struct guest_info * core,
1189 struct vm_device *dev = (struct vm_device *)priv_data;
1190 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1192 PrintDebug(core->vm_info, core, "vga: memory write: guest_addr=0x%p len=%u write_mode=%d first_byte=0x%x\n",
1193 (void*)guest_addr, length, vga->vga_graphics_controller.vga_graphics_mode.write_mode, *(uint8_t*)src);
1195 if (vga->passthrough) {
1196 PrintDebug(core->vm_info, core, "vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
1197 memcpy(V3_VAddr((void*)guest_addr),src,length);
1202 PrintDebug(core->vm_info, core, "vga: data written was 0x");
1203 for (i=0;i<length;i++) {
1204 uint8_t c= ((char*)src)[i];
1205 PrintDebug(core->vm_info, core, "%.2x", c);
1207 PrintDebug(core->vm_info, core, " \"");
1208 for (i=0;i<length;i++) {
1209 char c= ((char*)src)[i];
1210 PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1212 PrintDebug(core->vm_info, core, "\"\n");
1215 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
1218 // probably could just reduce this to the datapath itself instead
1219 // of following the programmer's perspective...
1221 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1225 00b -- Write Mode 0: In this mode, the host data is first rotated
1226 as per the Rotate Count field, then the Enable Set/Reset mechanism
1227 selects data from this or the Set/Reset field. Then the selected
1228 Logical Operation is performed on the resulting data and the data
1229 in the latch register. Then the Bit Mask field is used to select
1230 which bits come from the resulting data and which come
1231 from the latch register. Finally, only the bit planes enabled by
1232 the Memory Plane Write Enable field are written to memory.
1240 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1241 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1243 offset = find_offset_write(vga, guest_addr);
1246 PrintDebug(core->vm_info, core, "vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1249 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1251 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1252 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1253 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1254 uint8_t mm = find_map_write(vga,guest_addr+i);
1257 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);
1260 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) {
1261 vga_map map = vga->map[mapnum];
1262 uint8_t data = ((uint8_t *)src)[i];
1263 uint8_t latchval = vga->latch[mapnum];
1266 PrintDebug(core->vm_info, core, "vga: raw data=0x%x\n",data);
1268 // rotate data right
1270 data = (data>>ror) | (data<<(8-ror));
1274 PrintDebug(core->vm_info, core, "vga: data after ror=0x%x\n",data);
1276 // use SR bit if ESR is on for this map
1278 data = (sr&0x1) * -1;
1283 PrintDebug(core->vm_info, core, "vga: data after esrr=0x%x\n",data);
1302 PrintDebug(core->vm_info, core, "vga: data after func=0x%x\n",data);
1305 // mux between the data byte and the latch byte on
1307 data = (bm & data) | ((~bm) & latchval);
1311 PrintDebug(core->vm_info, core, "vga: data after bm mux=0x%x\n",data);
1316 // write to this map
1318 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]));
1333 01b -- Write Mode 1: In this mode, data is transferred directly
1334 from the 32 bit latch register to display memory, affected only by
1335 the Memory Plane Write Enable field. The host data is not used in this mode.
1340 uint64_t offset = find_offset_write(vga,guest_addr);
1343 PrintDebug(core->vm_info, core, "vga: mode 1 write, offset=0x%llx\n", offset);
1346 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1349 uint8_t mm = find_map_write(vga,guest_addr+i);
1351 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1352 vga_map map = vga->map[mapnum];
1353 uint8_t latchval = vga->latch[mapnum];
1357 // write to this map
1358 map[offset] = latchval;
1369 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
1370 are replicated across all 8 bits of their respective planes.
1371 Then the selected Logical Operation is performed on the resulting
1372 data and the data in the latch register. Then the Bit Mask field is used to
1373 select which bits come from the resulting data and which come from
1374 the latch register. Finally, only the bit planes enabled by the
1375 Memory Plane Write Enable field are written to memory.
1381 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1383 offset = find_offset_write(vga, guest_addr);
1386 PrintDebug(core->vm_info, core, "vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1389 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1391 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1392 uint8_t mm = find_map_write(vga,guest_addr+i);
1394 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1395 vga_map map = vga->map[mapnum];
1396 uint8_t data = ((uint8_t *)src)[i];
1397 uint8_t latchval = vga->latch[mapnum];
1399 // expand relevant bit to 8 bit
1400 // it's basically esr=1, sr=bit from mode 0 write
1401 data = ((data>>mapnum)&0x1) * -1;
1418 // mux between latch and alu output
1419 data = (bm & data) | ((~bm) & latchval);
1423 // write to this map
1434 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
1435 as if the Enable Set/Reset field were set to 1111b. Then the host data is
1436 first rotated as per the Rotate Count field, then logical ANDed with the
1437 value of the Bit Mask field. The resulting value is used on the data
1438 obtained from the Set/Reset field in the same way that the Bit Mask field
1439 would ordinarily be used. to select which bits come from the expansion
1440 of the Set/Reset field and which come from the latch register. Finally,
1441 only the bit planes enabled by the Memory Plane Write Enable field
1442 are written to memory.
1449 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1451 offset = find_offset_write(vga, guest_addr);
1453 PrintDebug(core->vm_info, core, "vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1455 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1457 uint8_t data = ((uint8_t *)src)[i];
1460 data = (data>>ror) | (data<<(8-ror));
1463 // Note here that the bitmask is the register AND the data
1464 // the data written by the system is used for no other purpose
1465 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1467 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1469 uint8_t mm = find_map_write(vga,guest_addr+i);
1471 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, mm>>=1) {
1472 vga_map map = vga->map[mapnum];
1473 uint8_t latchval = vga->latch[mapnum];
1475 // expand SR bit - that's the data we're going to use
1476 data = (sr&0x1) * -1;
1478 // mux between latch and alu output
1479 data = (bm & data) | ((~bm) & latchval);
1483 // write to this map
1494 // There is no default
1504 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1506 uint64_t mem_start, mem_end;
1509 mem_start=mem_end=0;
1511 get_mem_region(vga, &mem_start, &mem_end);
1513 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1515 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1516 // odd/even mode takes priority
1517 return ((guest_addr-mem_start) >> 1 ) % size;
1520 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1521 // otherwise chain4 if it's on
1522 return ((guest_addr - mem_start) >> 2) % size;
1525 // and what you would expect if neither are on
1526 return (guest_addr-mem_start) % size;
1529 // Given this address
1530 // which specific map should we write into?
1531 // Note that unlike with find_map_write, here we are looking
1532 // for a single map number, not a bit vector of maps to be selected
1533 static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr)
1535 uint64_t mem_start, mem_end;
1537 mem_start=mem_end=0;
1539 get_mem_region(vga, &mem_start, &mem_end);
1541 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1543 // last bit tells us map 0 or 1
1544 return (guest_addr-mem_start) & 0x1;
1547 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1548 // otherwise chain4 if it's on
1550 return (guest_addr - mem_start) & 0x3;
1553 // and what you would expect if neither are on
1554 // note that it's not the same as a write!
1555 return vga->vga_graphics_controller.vga_read_map_select.map_select;
1558 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1561 if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
1563 return !(new_guest_addr & 0x1);
1566 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1567 return !(new_guest_addr & 0x3);
1573 static int vga_read(struct guest_info * core,
1579 struct vm_device *dev = (struct vm_device *)priv_data;
1580 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1583 PrintDebug(core->vm_info, core, "vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length,
1584 vga->vga_graphics_controller.vga_graphics_mode.read_mode);
1589 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1591 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
1593 /* 0 - a byte from ONE of the 4 planes is returned;
1594 which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
1595 OR by odd/even chaining OR by chain4 chaining
1601 offset = find_offset_read(vga,guest_addr);
1604 PrintDebug(core->vm_info, core, "vga: mode 0 read, offset=0x%llx\n",offset);
1606 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1608 mapnum = find_map_read(vga,guest_addr+i);
1610 // the data returned
1611 ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1613 // need to load all latches even though we are
1614 // returning data from only the selected map
1615 for (mapnum=0;mapnum<4;mapnum++) {
1616 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1624 /* 1 - Compare video memory and reference color
1625 (in Color Compare, except those not set in Color Don't Care),
1626 each bit in returned result is one comparison between the reference color
1628 Ref color is *4* bits, and thus a one byte read returns a comparison
1635 offset = find_offset_read(vga,guest_addr);
1638 PrintDebug(core->vm_info, core, "vga: mode 1 read, offset=0x%llx\n",offset);
1641 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1643 uint8_t mapcalc=0xff;
1645 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1646 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1648 for (mapnum=0;mapnum<4;mapnum++, cc>>=1, dc>>=1) {
1649 if (dc&0x1) { // dc is active low; 1=we do care
1650 mapcalc &= (cc * -1) & *(vga->map[mapnum]+offset);
1653 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1655 // write back the comparison result (for 8 pixels)
1656 ((uint8_t *)dst)[i]=mapcalc;
1662 // there is no default
1665 if (vga->passthrough) {
1666 PrintDebug(core->vm_info, core, "vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1667 memcpy(dst,V3_VAddr((void*)guest_addr),length);
1673 PrintDebug(core->vm_info, core, "vga: data read is 0x");
1674 for (i=0;i<length;i++) {
1675 uint8_t c= ((char*)dst)[i];
1676 PrintDebug(core->vm_info, core, "%.2x", c);
1678 PrintDebug(core->vm_info, core, " \"");
1679 for (i=0;i<length;i++) {
1680 char c= ((char*)dst)[i];
1681 PrintDebug(core->vm_info, core, "%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1683 PrintDebug(core->vm_info, core, "\"\n");
1694 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
1695 if (((len)<(min)) || ((len)>(max))) { \
1696 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)); \
1700 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1703 *(uint8_t *)dest = v3_inb(port);
1706 *(uint16_t *)dest = v3_inw(port);
1709 *(uint32_t *)dest = v3_indw(port);
1712 PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io in size %u\n",length);
1718 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1721 v3_outb(port, *(uint8_t *)src);
1724 v3_outw(port, *(uint16_t *)src);
1727 v3_outdw(port, *(uint32_t *)src);
1730 PrintError(VM_NONE, VCORE_NONE, "vga: unsupported passthrough io out size %u\n",length);
1735 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
1736 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1738 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
1739 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1741 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
1742 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1744 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1745 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)
1747 static int misc_out_read(struct guest_info *core,
1753 struct vga_internal *vga = (struct vga_internal *) priv_data;
1755 PrintDebug(core->vm_info, core, "vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1757 ERR_WRONG_SIZE("read","misc out",len,1,1);
1759 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1761 PASSTHROUGH_IO_IN(vga,port,dest,len);
1763 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1768 static int misc_out_write(struct guest_info *core,
1774 struct vga_internal *vga = (struct vga_internal *) priv_data;
1776 PrintDebug(core->vm_info, core, "vga: misc out write data=0x%x\n", *((uint8_t*)src));
1778 ERR_WRONG_SIZE("write","misc out",len,1,1);
1780 PASSTHROUGH_IO_OUT(vga,port,src,len);
1782 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
1791 static int input_stat0_read(struct guest_info *core,
1797 struct vga_internal *vga = (struct vga_internal *) priv_data;
1799 PrintDebug(core->vm_info, core, "vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1801 ERR_WRONG_SIZE("read","input stat0",len,1,1);
1803 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1805 PASSTHROUGH_IO_IN(vga,port,dest,len);
1807 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1813 static int input_stat1_read(struct guest_info *core,
1819 struct vga_internal *vga = (struct vga_internal *) priv_data;
1821 PrintDebug(core->vm_info, core, "vga: input stat0 (%s) read data=0x%x\n",
1822 port==0x3ba ? "mono" : "color",
1823 vga->vga_misc.vga_input_stat1.val);
1825 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1828 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1830 // Pretend that horizontal and vertical blanking
1832 if (!vga->vga_misc.vga_input_stat1.disp_en) {
1834 // if not blanking, start horizontal blanking
1835 vga->vga_misc.vga_input_stat1.disp_en = 1;
1836 vga->vga_misc.vga_input_stat1.vert_retrace = 0;
1840 if (!vga->vga_misc.vga_input_stat1.vert_retrace) {
1841 // if not vertical blanking, then now vertical blanking
1842 vga->vga_misc.vga_input_stat1.disp_en = 1;
1843 vga->vga_misc.vga_input_stat1.vert_retrace = 1;
1845 // if vertical blanking, now not blanking
1846 vga->vga_misc.vga_input_stat1.disp_en = 0;
1847 vga->vga_misc.vga_input_stat1.vert_retrace = 0;
1852 // Stunningly, reading stat1 is also a way to reset
1853 // the state of attribute controller address/data flipflop
1854 // That is some mighty fine crack the designers were smoking.
1856 vga->vga_attribute_controller.state=ATTR_ADDR;
1858 PASSTHROUGH_IO_IN(vga,port,dest,len);
1860 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1866 static int feature_control_read(struct guest_info *core,
1872 struct vga_internal *vga = (struct vga_internal *) priv_data;
1874 PrintDebug(core->vm_info, core, "vga: feature control read data=0x%x\n",
1875 vga->vga_misc.vga_feature_control.val);
1877 ERR_WRONG_SIZE("read","feature control",len,1,1);
1880 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1882 PASSTHROUGH_IO_IN(vga,port,dest,len);
1884 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1889 static int feature_control_write(struct guest_info *core,
1895 struct vga_internal *vga = (struct vga_internal *) priv_data;
1897 PrintDebug(core->vm_info, core, "vga: feature control (%s) write data=0x%x\n",
1898 port==0x3ba ? "mono" : "color",
1901 ERR_WRONG_SIZE("write","feature control",len,1,1);
1903 PASSTHROUGH_IO_OUT(vga,port,src,len);
1905 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1913 static int video_subsys_enable_read(struct guest_info *core,
1919 struct vga_internal *vga = (struct vga_internal *) priv_data;
1921 PrintDebug(core->vm_info, core, "vga: video subsys enable read data=0x%x\n",
1922 vga->vga_misc.vga_video_subsys_enable.val);
1924 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1926 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1928 PASSTHROUGH_IO_IN(vga,port,dest,len);
1930 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1935 static int video_subsys_enable_write(struct guest_info *core,
1941 struct vga_internal *vga = (struct vga_internal *) priv_data;
1943 PrintDebug(core->vm_info, core, "vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1945 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1947 PASSTHROUGH_IO_OUT(vga,port,src,len);
1949 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1956 static int sequencer_address_read(struct guest_info *core,
1962 struct vga_internal *vga = (struct vga_internal *) priv_data;
1964 PrintDebug(core->vm_info, core, "vga: sequencer address read data=0x%x\n",
1965 vga->vga_sequencer.vga_sequencer_addr.val);
1967 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1969 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1971 PASSTHROUGH_IO_IN(vga,port,dest,len);
1973 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1978 static int sequencer_data_write(struct guest_info *core,
1984 struct vga_internal *vga = (struct vga_internal *) priv_data;
1988 data=*((uint8_t*)src);
1989 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1991 PrintDebug(core->vm_info, core, "vga: sequencer write data (index=%d) with 0x%x\n",
1994 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1996 PASSTHROUGH_IO_OUT(vga,port,src,len);
1999 if (index>=VGA_SEQUENCER_NUM) {
2000 PrintError(core->vm_info, core, "vga: sequencer data write is for invalid index %d, ignoring\n",index);
2002 vga->vga_sequencer.vga_sequencer_regs[index] = data;
2010 static int sequencer_address_write(struct guest_info *core,
2016 struct vga_internal *vga = (struct vga_internal *) priv_data;
2019 new_addr=*((uint8_t*)src);
2021 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);
2023 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
2025 PASSTHROUGH_IO_OUT(vga,port,src,len);
2027 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
2030 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2031 // second byte is the data
2032 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
2033 PrintError(core->vm_info, core, "vga: write of data failed\n");
2041 static int sequencer_data_read(struct guest_info *core,
2047 struct vga_internal *vga = (struct vga_internal *) priv_data;
2051 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
2053 if (index>=VGA_SEQUENCER_NUM) {
2055 PrintError(core->vm_info, core, "vga: sequencer data read at invalid index %d, returning zero\n",index);
2057 data=vga->vga_sequencer.vga_sequencer_regs[index];
2060 PrintDebug(core->vm_info, core, "vga: sequencer data read data (index=%d) = 0x%x\n",
2063 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2065 *((uint8_t*)dest) = data;
2067 PASSTHROUGH_IO_IN(vga,port,dest,len);
2069 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2078 static int crt_controller_address_read(struct guest_info *core,
2084 struct vga_internal *vga = (struct vga_internal *) priv_data;
2086 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address read data=0x%x\n",
2087 port==0x3b4 ? "mono" : "color",
2088 vga->vga_crt_controller.vga_crt_addr.val);
2090 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2092 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2094 PASSTHROUGH_IO_IN(vga,port,dest,len);
2096 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2101 static int crt_controller_data_write(struct guest_info *core,
2107 struct vga_internal *vga = (struct vga_internal *) priv_data;
2111 data=*((uint8_t*)src);
2113 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2115 PrintDebug(core->vm_info, core, "vga: crt controller (%s) write data (index=%d) with 0x%x\n",
2116 port==0x3b5 ? "mono" : "color",
2119 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2121 PASSTHROUGH_IO_OUT(vga,port,src,len);
2123 if (index>=VGA_CRT_CONTROLLER_NUM) {
2124 PrintError(core->vm_info, core, "vga; crt controller write is for illegal index %d, ignoring\n",index);
2126 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2128 if (vga->vga_crt_controller.vga_vertical_retrace_end.enable_vertical_interrupt) {
2129 PrintError(core->vm_info, core, "vga: vertical_retrace_interrupt_enabled is unsupported -- no interrupts will occur!\n");
2139 static int crt_controller_address_write(struct guest_info *core,
2145 struct vga_internal *vga = (struct vga_internal *) priv_data;
2148 new_addr=*((uint8_t*)src);
2150 PrintDebug(core->vm_info, core, "vga: crt controller (%s) address write data=0x%x len=%u\n",
2151 port==0x3b4 ? "mono" : "color",
2152 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2154 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2156 PASSTHROUGH_IO_OUT(vga,port,src,len);
2158 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
2161 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2162 // second byte is the data
2163 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
2164 PrintError(core->vm_info, core, "vga: write of data failed\n");
2172 static int crt_controller_data_read(struct guest_info *core,
2178 struct vga_internal *vga = (struct vga_internal *) priv_data;
2182 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2184 if (index>=VGA_CRT_CONTROLLER_NUM) {
2186 PrintError(core->vm_info, core, "vga: crt controller data read for illegal index %d, returning zero\n",index);
2188 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2191 PrintDebug(core->vm_info, core, "vga: crt controller data (index=%d) = 0x%x\n",index,data);
2193 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2195 *((uint8_t*)dest) = data;
2197 PASSTHROUGH_IO_IN(vga,port,dest,len);
2199 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2206 static int graphics_controller_address_read(struct guest_info *core,
2212 struct vga_internal *vga = (struct vga_internal *) priv_data;
2214 PrintDebug(core->vm_info, core, "vga: graphics controller address read data=0x%x\n",
2215 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2217 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2219 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2221 PASSTHROUGH_IO_IN(vga,port,dest,len);
2223 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2228 static int graphics_controller_data_write(struct guest_info *core,
2234 struct vga_internal *vga = (struct vga_internal *) priv_data;
2238 data=*((uint8_t*)src);
2239 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2242 PrintDebug(core->vm_info, core, "vga: graphics_controller write data (index=%d) with 0x%x\n",
2245 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2247 PASSTHROUGH_IO_OUT(vga,port,src,len);
2249 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2250 PrintError(core->vm_info, core, "vga: graphics controller write for illegal index %d ignored\n",index);
2252 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2260 static int graphics_controller_address_write(struct guest_info *core,
2266 struct vga_internal *vga = (struct vga_internal *) priv_data;
2269 new_addr=*((uint8_t*)src);
2271 PrintDebug(core->vm_info, core, "vga: graphics controller address write data=0x%x len=%u\n",
2272 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2274 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2276 PASSTHROUGH_IO_OUT(vga,port,src,len);
2278 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
2281 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2282 // second byte is the data
2283 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
2284 PrintError(core->vm_info, core, "vga: write of data failed\n");
2292 static int graphics_controller_data_read(struct guest_info *core,
2298 struct vga_internal *vga = (struct vga_internal *) priv_data;
2302 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2305 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2307 PrintError(core->vm_info, core, "vga: graphics controller data read from illegal index %d, returning zero\n",index);
2309 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2312 PrintDebug(core->vm_info, core, "vga: graphics controller data read data (index=%d) = 0x%x\n",
2315 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2317 *((uint8_t*)dest) = data;
2319 PASSTHROUGH_IO_IN(vga,port,dest,len);
2321 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2329 /* Note that these guys have a bizarre protocol*/
2331 static int attribute_controller_address_read(struct guest_info *core,
2337 struct vga_internal *vga = (struct vga_internal *) priv_data;
2339 PrintDebug(core->vm_info, core, "vga: attribute controller address read data=0x%x\n",
2340 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2342 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
2344 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2346 PASSTHROUGH_IO_IN(vga,port,dest,len);
2348 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2350 // Reading the attribute controller does not change the state
2355 static int attribute_controller_address_and_data_write(struct guest_info *core,
2361 struct vga_internal *vga = (struct vga_internal *) priv_data;
2364 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
2365 uint8_t new_addr = *((uint8_t*)src);
2366 // We are to treat this as an address write, and flip state
2367 // to expect data ON THIS SAME PORT
2368 PrintDebug(core->vm_info, core, "vga: attribute controller address write data=0x%x\n", new_addr);
2370 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2372 PASSTHROUGH_IO_OUT(vga,port,src,len);
2374 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
2376 vga->vga_attribute_controller.state=ATTR_DATA;
2379 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
2381 uint8_t data = *((uint8_t*)src);
2382 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2384 PrintDebug(core->vm_info, core, "vga: attribute controller data write index %d with data=0x%x\n", index,data);
2386 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2388 PASSTHROUGH_IO_OUT(vga,port,src,len);
2390 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2391 PrintError(core->vm_info, core, "vga: attribute controller write to illegal index %d ignored\n",index);
2393 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2396 vga->vga_attribute_controller.state=ATTR_ADDR;
2405 static int attribute_controller_data_read(struct guest_info *core,
2411 struct vga_internal *vga = (struct vga_internal *) priv_data;
2415 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2417 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2419 PrintError(core->vm_info, core, "vga: attribute controller read of illegal index %d, returning zero\n",index);
2421 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2424 PrintDebug(core->vm_info, core, "vga: attribute controller data read data (index=%d) = 0x%x\n",
2427 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2429 *((uint8_t*)dest) = data;
2431 PASSTHROUGH_IO_IN(vga,port,dest,len);
2433 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2440 Note that these guys also have a strange protocol
2441 since they need to squeeze 18 bits of data through
2444 static int dac_write_address_read(struct guest_info *core,
2450 struct vga_internal *vga = (struct vga_internal *) priv_data;
2452 PrintDebug(core->vm_info, core, "vga: dac write address read data=0x%x\n",
2453 vga->vga_dac.vga_dac_write_addr);
2455 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2458 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2460 PASSTHROUGH_IO_IN(vga,port,dest,len);
2462 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2464 // This read does not reset the state machine
2469 static int dac_write_address_write(struct guest_info *core,
2475 struct vga_internal *vga = (struct vga_internal *) priv_data;
2478 new_addr=*((uint8_t*)src);
2480 PrintDebug(core->vm_info, core, "vga: dac write address write data=0x%x\n", new_addr);
2482 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2484 PASSTHROUGH_IO_OUT(vga,port,src,len);
2486 // cannot be out of bounds since there are 256 regs
2488 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2490 // Now we also need to reset the state machine
2492 vga->vga_dac.state=DAC_WRITE;
2493 vga->vga_dac.channel=RED;
2499 static int dac_read_address_read(struct guest_info *core,
2505 struct vga_internal *vga = (struct vga_internal *) priv_data;
2507 PrintDebug(core->vm_info, core, "vga: dac read address read data=0x%x\n",
2508 vga->vga_dac.vga_dac_read_addr);
2510 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2512 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2514 PASSTHROUGH_IO_IN(vga,port,dest,len);
2516 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2518 // This read does not reset the state machine
2523 static int dac_read_address_write(struct guest_info *core,
2529 struct vga_internal *vga = (struct vga_internal *) priv_data;
2532 new_addr=*((uint8_t*)src);
2534 PrintDebug(core->vm_info, core, "vga: dac read address write data=0x%x\n", new_addr);
2536 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2538 PASSTHROUGH_IO_OUT(vga,port,src,len);
2540 // cannot be out of bounds since there are 256 regs
2542 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2544 // Now we also need to reset the state machine
2546 vga->vga_dac.state=DAC_READ;
2547 vga->vga_dac.channel=RED;
2553 static int dac_data_read(struct guest_info *core,
2559 struct vga_internal *vga = (struct vga_internal *) priv_data;
2564 if (vga->vga_dac.state!=DAC_READ) {
2565 PrintError(core->vm_info, core, "vga: dac data read while in other state\n");
2566 // results undefined, so we continue
2569 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2571 curreg = vga->vga_dac.vga_dac_read_addr;
2572 curchannel = vga->vga_dac.channel;
2573 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2575 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] = 0x%x\n",
2577 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2578 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2581 *((uint8_t*)dest) = data;
2583 PASSTHROUGH_IO_IN(vga,port,dest,len);
2585 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2587 curchannel = (curchannel+1)%3;
2588 vga->vga_dac.channel=curchannel;
2589 if (curchannel==0) {
2590 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2592 vga->vga_dac.vga_dac_read_addr = curreg;
2593 vga->vga_dac.state=DAC_READ;
2600 static int dac_data_write(struct guest_info *core,
2606 struct vga_internal *vga = (struct vga_internal *) priv_data;
2610 vga_palette_reg data32;
2611 vga_palette_reg mask32;
2613 if (vga->vga_dac.state!=DAC_WRITE) {
2614 PrintError(core->vm_info, core, "vga: dac data write while in other state\n");
2615 // results undefined, so we continue
2618 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2620 PASSTHROUGH_IO_OUT(vga,port,src,len);
2622 curreg = vga->vga_dac.vga_dac_write_addr;
2623 curchannel = vga->vga_dac.channel;
2624 data = *((uint8_t *)src);
2626 PrintDebug(core->vm_info, core, "vga: dac reg %u [%s] write with 0x%x\n",
2628 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2629 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2632 data32 = data & 0x3f ;
2633 data32 <<= curchannel*8;
2634 mask32 = ~(0xff << (curchannel * 8));
2636 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2637 vga->vga_dac.vga_dac_palette[curreg] |= data32;
2639 curchannel = (curchannel+1)%3;
2640 vga->vga_dac.channel=curchannel;
2641 if (curchannel==0) {
2642 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2644 vga->vga_dac.vga_dac_write_addr = curreg;
2645 vga->vga_dac.state=DAC_WRITE;
2654 static int dac_pixel_mask_read(struct guest_info *core,
2660 struct vga_internal *vga = (struct vga_internal *) priv_data;
2662 PrintDebug(core->vm_info, core, "vga: dac pixel mask read data=0x%x\n",
2663 vga->vga_dac.vga_pixel_mask);
2665 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2667 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2669 PASSTHROUGH_IO_IN(vga,port,dest,len);
2671 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2676 static int dac_pixel_mask_write(struct guest_info *core,
2682 struct vga_internal *vga = (struct vga_internal *) priv_data;
2685 new_data=*((uint8_t*)src);
2687 PrintDebug(core->vm_info, core, "vga: dac pixel mask write data=0x%x\n", new_data);
2689 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2691 PASSTHROUGH_IO_OUT(vga,port,src,len);
2693 vga->vga_dac.vga_pixel_mask = new_data;
2698 static int init_vga(struct vga_internal *vga)
2700 // TODO: startup spec of register contents, if any
2701 vga->vga_misc.vga_input_stat1.val = 0x1; // display enable, not in retrace
2706 static int free_vga(struct vga_internal *vga)
2710 struct vm_device *dev = vga->dev;
2712 // Framebuffer deletion is user's responsibility
2714 // if (vga->mem_store) {
2715 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2716 // vga->mem_store=0;
2719 for (i=0;i<MAP_NUM;i++) {
2721 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2726 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2730 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2731 // The following also covers VGA_INPUT_STAT0_READ
2732 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2733 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2734 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2735 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2736 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2737 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2739 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2741 /* Sequencer registers */
2742 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2743 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2745 /* CRT controller registers */
2746 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2747 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2748 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2749 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2751 /* graphics controller registers */
2752 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2753 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2755 /* attribute controller registers */
2756 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2757 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2759 /* video DAC palette registers */
2760 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2761 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2762 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2763 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2766 if (vga->host_cons) {
2767 v3_graphics_console_close(vga->host_cons);
2775 static struct v3_device_ops dev_ops = {
2776 .free = (int (*)(void *))free_vga,
2780 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2781 struct vga_internal *vga;
2785 char * dev_id = v3_cfg_val(cfg, "ID");
2786 char * passthrough = v3_cfg_val(cfg, "passthrough");
2787 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2789 PrintDebug(vm, VCORE_NONE, "vga: init_device\n");
2791 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2794 PrintError(vm, VCORE_NONE, "vga: cannot allocate\n");
2798 memset(vga, 0, sizeof(struct vga_internal));
2800 vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2801 vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2803 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2804 PrintDebug(vm, VCORE_NONE, "vga: enabling passthrough\n");
2805 vga->passthrough=true;
2806 vga->skip_next_passthrough_out=false;
2810 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2811 struct v3_frame_buffer_spec req;
2813 PrintDebug(vm, VCORE_NONE, "vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2815 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2816 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2818 req.height=VGA_MAXY;
2820 req.bytes_per_pixel=4;
2821 req.bits_per_channel=8;
2827 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2829 if (!vga->host_cons) {
2830 PrintError(vm, VCORE_NONE, "vga: unable to open host OS's graphics console\n");
2835 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2836 PrintDebug(vm, VCORE_NONE, "vga: warning: target spec differs from requested spec\n");
2837 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);
2838 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);
2842 if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) {
2843 V3_Print(vm, VCORE_NONE, "vga: enabling console-driven rendering\n");
2844 if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) {
2845 PrintError(vm, VCORE_NONE, "vga: cannot enable console-driven rendering\n");
2851 V3_Print(vm, VCORE_NONE, "vga: enabling console inquiry for updates\n");
2852 if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) {
2853 PrintError(vm, VCORE_NONE, "vga: cannot enable console inquiry for updates\n");
2859 if (!vga->passthrough && !vga->host_cons) {
2860 V3_Print(vm, VCORE_NONE, "vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2864 // No memory store is allocated since we will use a full memory hook
2865 // The VGA maps can be read as well as written
2866 // Reads also affect writes, since they are how you fill the latches
2868 // Now allocate the maps
2869 for (i=0;i<MAP_NUM;i++) {
2872 temp = (void*)V3_AllocPages(MAP_SIZE/4096);
2874 PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
2879 vga->map[i] = (vga_map) V3_VAddr(temp);
2881 memset(vga->map[i],0,MAP_SIZE);
2884 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2887 PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
2894 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2895 MEM_REGION_START, MEM_REGION_END,
2899 PrintError(vm, VCORE_NONE, "vga: memory book failed\n");
2900 v3_remove_device(dev);
2906 /* Miscelaneous registers */
2907 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2908 // The following also covers VGA_INPUT_STAT0_READ
2909 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2910 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2911 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2912 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2913 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2914 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2916 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2918 /* Sequencer registers */
2919 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2920 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2922 /* CRT controller registers */
2923 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2924 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2925 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2926 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2928 /* graphics controller registers */
2929 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2930 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2932 /* attribute controller registers */
2933 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2934 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2936 /* video DAC palette registers */
2937 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2938 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2939 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2940 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2943 PrintError(vm, VCORE_NONE, "vga: Error allocating VGA I/O ports\n");
2944 v3_remove_device(dev);
2950 PrintDebug(vm, VCORE_NONE, "vga: successfully added and initialized.\n");
2956 device_register("VGA", vga_init);