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("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("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("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("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("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;
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 // find the character's font bitmap (one byte per row)
846 find_text_font_start(vga,(void**)&font,
847 extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
849 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
851 // Now let's find out what colors we will be using
854 if (!extended_fontset(vga)) {
855 fg_entry = a.foreground_intensity_or_font_select << 3;
861 find_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
863 if (!blinking(vga)) {
864 bg_entry = a.blinking_or_bg_intensity << 3;
870 find_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
872 // Draw the character
873 for (l=0; l<ch; l++, font++) {
874 uint8_t frow = *font; // this is the row of of the font map
878 // a char can be 9 bits wide, but the font map
879 // is only 8 bits wide, which means we need to know where to
882 // We get it from the font map if
883 // its line line graphics mode and its a graphics char
884 // otherwise it's the background color
885 if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
886 && ct>=0xc0 && ct<=0xdf ) {
892 fbit= (frow >> (7-p) ) & 0x1;
895 // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
896 // For now, we will draw it as black/white
898 // find its position in the framebuffer;
901 pixel = fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
902 red = pixel + spec->red_offset;
903 green = pixel + spec->green_offset;
904 blue = pixel + spec->blue_offset;
906 // Are we on the cursor?
907 // if so, let's negate this pixel to invert the cell
911 // update the framebuffer
934 static void render_test(struct vga_internal *vga, void *fb)
936 struct v3_frame_buffer_spec *s;
938 s=&(vga->target_spec);
940 if (fb && s->height>=480 && s->width>=640 ) {
941 uint8_t color = (uint8_t)(vga->updates_since_render);
945 for (y=0;y<480;y++) {
946 for (x=0;x<640;x++) {
947 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
948 uint8_t *red = pixel + s->red_offset;
949 uint8_t *green = pixel + s->green_offset;
950 uint8_t *blue = pixel + s->blue_offset;
956 } else if (y<(480/2)) {
960 } else if (y<(3*(480/4))) {
965 *red=*green=*blue=color+x;
972 static void render_black(struct vga_internal *vga, void *fb)
974 struct v3_frame_buffer_spec *s;
976 s=&(vga->target_spec);
978 memset(fb,0,s->height*s->width*s->bytes_per_pixel);
981 static void render_maps(struct vga_internal *vga, void *fb)
984 struct v3_frame_buffer_spec *s;
987 s=&(vga->target_spec);
989 if (fb && s->height>=768 && s->width>=1024 ) {
990 // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
997 for (y=480+32;y<768;y++) {
998 for (x=m*256;x<(m+1)*256;x++,b++) {
999 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
1000 uint8_t *red = pixel + s->red_offset;
1001 uint8_t *green = pixel + s->green_offset;
1002 uint8_t *blue = pixel + s->blue_offset;
1004 *red=*green=*blue=*b;
1011 static int render_core(struct vga_internal *vga)
1015 PrintDebug("vga: render on update %u\n",vga->updates_since_render);
1017 fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
1019 if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
1020 if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) {
1021 render_graphics(vga,fb);
1023 render_text(vga,fb);
1024 render_text_cursor(vga,fb);
1027 render_black(vga,fb);
1030 if (0) { render_test(vga,fb); }
1032 // always render maps for now
1033 render_maps(vga,fb);
1035 v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
1037 vga->updates_since_render=0;
1044 static int render(struct vga_internal *vga)
1047 vga->updates_since_render++;
1050 if (vga->host_cons) {
1053 if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING)
1055 (vga->updates_since_render > vga->render_model.updates_before_render)) {
1056 PrintDebug("vga: render due to periodic\n");
1061 if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING)
1063 (v3_graphics_console_inform_update(vga->host_cons) > 0) ) {
1065 PrintDebug("vga: render due to advisory\n");
1070 // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function
1073 return render_core(vga);
1083 static int render_callback(v3_graphics_console_t cons,
1086 struct vga_internal *vga = (struct vga_internal *) priv;
1088 PrintDebug("vga: render due to callback\n");
1090 return render_core(vga);
1093 static int update_callback(v3_graphics_console_t cons,
1096 struct vga_internal *vga = (struct vga_internal *) priv;
1098 return vga->updates_since_render>0;
1103 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
1105 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
1125 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
1127 uint64_t mem_start, mem_end;
1130 mem_start=mem_end=0;
1132 get_mem_region(vga, &mem_start, &mem_end);
1134 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1136 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1137 return (guest_addr-mem_start) % size;
1140 return ((guest_addr-mem_start) >> 1 ) % size;
1147 // Determines which maps should be enabled for this single byte write
1148 // and what the increment (actually 1/increment for the copy loop
1150 // memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
1152 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
1154 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
1156 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1159 if (guest_addr & 0x1) {
1160 return mm & 0xa; // 0x1010
1162 return mm & 0x5; // 0x0101
1167 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
1169 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1172 return !(new_guest_addr & 0x1);
1178 static int vga_write(struct guest_info * core,
1184 struct vm_device *dev = (struct vm_device *)priv_data;
1185 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1187 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1189 if (vga->passthrough) {
1190 PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
1191 memcpy(V3_VAddr((void*)guest_addr),src,length);
1196 PrintDebug("vga: data written was 0x");
1197 for (i=0;i<length;i++) {
1198 uint8_t c= ((char*)src)[i];
1199 PrintDebug("%.2x", c);
1202 for (i=0;i<length;i++) {
1203 char c= ((char*)src)[i];
1204 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1209 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
1212 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1216 00b -- Write Mode 0: In this mode, the host data is first rotated
1217 as per the Rotate Count field, then the Enable Set/Reset mechanism
1218 selects data from this or the Set/Reset field. Then the selected
1219 Logical Operation is performed on the resulting data and the data
1220 in the latch register. Then the Bit Mask field is used to select
1221 which bits come from the resulting data and which come
1222 from the latch register. Finally, only the bit planes enabled by
1223 the Memory Plane Write Enable field are written to memory.
1231 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1232 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1234 offset = find_offset_write(vga, guest_addr);
1237 PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1240 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1242 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1243 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1244 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1245 uint8_t mm = find_map_write(vga,guest_addr+i);
1248 PrintDebug("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);
1251 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) {
1252 vga_map map = vga->map[mapnum];
1253 uint8_t data = ((uint8_t *)src)[i];
1254 uint8_t latchval = vga->latch[mapnum];
1257 PrintDebug("vga: raw data=0x%x\n",data);
1259 // rotate data right
1261 data = (data>>ror) | (data<<(8-ror));
1265 PrintDebug("vga: data after ror=0x%x\n",data);
1267 // use SR bit if ESR is on for this map
1269 data = (sr&0x1) * -1;
1274 PrintDebug("vga: data after esrr=0x%x\n",data);
1293 PrintDebug("vga: data after func=0x%x\n",data);
1296 // mux between the data byte and the latch byte on
1298 data = (bm & data) | ((~bm) & latchval);
1302 PrintDebug("vga: data after bm mux=0x%x\n",data);
1307 // write to this map
1309 PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
1324 01b -- Write Mode 1: In this mode, data is transferred directly
1325 from the 32 bit latch register to display memory, affected only by
1326 the Memory Plane Write Enable field. The host data is not used in this mode.
1331 uint64_t offset = find_offset_write(vga,guest_addr);
1334 PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
1337 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1340 uint8_t mm = find_map_write(vga,guest_addr+i);
1342 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1343 vga_map map = vga->map[mapnum];
1344 uint8_t latchval = vga->latch[mapnum];
1348 // write to this map
1349 map[offset] = latchval;
1360 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
1361 are replicated across all 8 bits of their respective planes.
1362 Then the selected Logical Operation is performed on the resulting
1363 data and the data in the latch register. Then the Bit Mask field is used to
1364 select which bits come from the resulting data and which come from
1365 the latch register. Finally, only the bit planes enabled by the
1366 Memory Plane Write Enable field are written to memory.
1372 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1374 offset = find_offset_write(vga, guest_addr);
1377 PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1380 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1382 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1383 uint8_t mm = find_map_write(vga,guest_addr+i);
1385 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
1386 vga_map map = vga->map[mapnum];
1387 uint8_t data = ((uint8_t *)src)[i];
1388 uint8_t latchval = vga->latch[mapnum];
1390 // expand relevant bit to 8 bit
1391 // it's basically esr=1, sr=bit from mode 0 write
1392 data = ((data>>mapnum)&0x1) * -1;
1409 // mux between latch and alu output
1410 data = (bm & data) | ((~bm) & latchval);
1414 // write to this map
1425 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
1426 as if the Enable Set/Reset field were set to 1111b. Then the host data is
1427 first rotated as per the Rotate Count field, then logical ANDed with the
1428 value of the Bit Mask field. The resulting value is used on the data
1429 obtained from the Set/Reset field in the same way that the Bit Mask field
1430 would ordinarily be used. to select which bits come from the expansion
1431 of the Set/Reset field and which come from the latch register. Finally,
1432 only the bit planes enabled by the Memory Plane Write Enable field
1433 are written to memory.
1440 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1442 offset = find_offset_write(vga, guest_addr);
1444 PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1446 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1448 uint8_t data = ((uint8_t *)src)[i];
1451 data = (data>>ror) | (data<<(8-ror));
1454 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1455 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1456 uint8_t mm = find_map_write(vga,guest_addr+i);
1458 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
1459 vga_map map = vga->map[mapnum];
1460 uint8_t latchval = vga->latch[mapnum];
1463 data = (sr&0x1) * -1;
1465 // mux between latch and alu output
1466 data = (bm & data) | ((~bm) & latchval);
1470 // write to this map
1481 // There is no default
1491 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1493 uint64_t mem_start, mem_end;
1496 mem_start=mem_end=0;
1498 get_mem_region(vga, &mem_start, &mem_end);
1500 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1502 if (!vga->vga_sequencer.vga_mem_mode.chain4) {
1503 return (guest_addr-mem_start) % size;
1506 return ((guest_addr - mem_start) >> 2) % size;
1510 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1513 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1514 return !(new_guest_addr & 0x3);
1521 static int vga_read(struct guest_info * core,
1527 struct vm_device *dev = (struct vm_device *)priv_data;
1528 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1531 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1536 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1538 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
1540 /* 0 - a byte from ONE of the 4 planes is returned;
1541 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
1546 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1548 offset = find_offset_read(vga,guest_addr);
1549 // address bytes select the map
1550 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1551 mapnum = (guest_addr+i) % 4;
1553 PrintDebug("vga: mode 0 read, chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
1555 ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1557 // presumably all the latches are to be reloaded, not just the selected one?
1558 for (mapnum=0;mapnum<4;mapnum++) {
1559 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1563 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
1564 offset = find_offset_read(vga,guest_addr);
1566 if (offset>=65536) {
1567 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
1571 PrintDebug("vga: mode 0 read, not-chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
1574 memcpy(dst,(vga->map[mapnum])+offset,length);
1576 // load the latches with the last item read
1577 for (mapnum=0;mapnum<4;mapnum++) {
1578 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1585 /* 1 - Compare video memory and reference color
1586 (in Color Compare, except those not set in Color Don't Care),
1587 each bit in returned result is one comparison between the reference color
1589 Ref color is *4* bits, and thus a one byte read returns a comparison
1595 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1596 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1603 offset = find_offset_read(vga,guest_addr);
1606 PrintDebug("vga: mode 1 read, offset=0x%llx, cc=0x%x, dc-0x%x\n",offset,cc,dc);
1610 for (i=0;i<length;i++,offset++) {
1613 for (mapnum=0;mapnum<4;mapnum++) {
1614 map = vga->map[mapnum];
1615 if ( (dc>>mapnum)&0x1 ) { // don't care
1619 bits = (map[offset]&0xf) == cc;
1622 bits |= (((map[offset]>>4))&0xf) == cc;
1624 // not clear whether it is 0..k or k..0
1630 // load the latches with the last item read
1631 for (mapnum=0;mapnum<4;mapnum++) {
1632 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1637 // there is no default
1640 if (vga->passthrough) {
1641 PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1642 memcpy(dst,V3_VAddr((void*)guest_addr),length);
1648 PrintDebug("vga: data read is 0x");
1649 for (i=0;i<length;i++) {
1650 uint8_t c= ((char*)dst)[i];
1651 PrintDebug("%.2x", c);
1654 for (i=0;i<length;i++) {
1655 char c= ((char*)dst)[i];
1656 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1669 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
1670 if (((len)<(min)) || ((len)>(max))) { \
1671 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
1675 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1678 *(uint8_t *)dest = v3_inb(port);
1681 *(uint16_t *)dest = v3_inw(port);
1684 *(uint32_t *)dest = v3_indw(port);
1687 PrintError("vga: unsupported passthrough io in size %u\n",length);
1693 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1696 v3_outb(port, *(uint8_t *)src);
1699 v3_outw(port, *(uint16_t *)src);
1702 v3_outdw(port, *(uint32_t *)src);
1705 PrintError("vga: unsupported passthrough io out size %u\n",length);
1710 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
1711 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1713 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
1714 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1716 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
1717 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1719 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1720 do { if ((vga)->passthrough) { if ((inter)!=(pass)) { PrintError("vga: passthrough error: passthrough value read is 0x%x, but internal value read is 0x%x\n",(pass),(inter)); } } } while (0)
1722 static int misc_out_read(struct guest_info *core,
1728 struct vga_internal *vga = (struct vga_internal *) priv_data;
1730 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1732 ERR_WRONG_SIZE("read","misc out",len,1,1);
1734 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1736 PASSTHROUGH_IO_IN(vga,port,dest,len);
1738 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1743 static int misc_out_write(struct guest_info *core,
1749 struct vga_internal *vga = (struct vga_internal *) priv_data;
1751 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
1753 ERR_WRONG_SIZE("write","misc out",len,1,1);
1755 PASSTHROUGH_IO_OUT(vga,port,src,len);
1757 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
1766 static int input_stat0_read(struct guest_info *core,
1772 struct vga_internal *vga = (struct vga_internal *) priv_data;
1774 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1776 ERR_WRONG_SIZE("read","input stat0",len,1,1);
1778 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1780 PASSTHROUGH_IO_IN(vga,port,dest,len);
1782 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1788 static int input_stat1_read(struct guest_info *core,
1794 struct vga_internal *vga = (struct vga_internal *) priv_data;
1796 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
1797 port==0x3ba ? "mono" : "color",
1798 vga->vga_misc.vga_input_stat1.val);
1800 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1803 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1805 // Stunningly, reading stat1 is also a way to reset
1806 // the state of attribute controller address/data flipflop
1807 // That is some mighty fine crack the designers were smoking.
1809 vga->vga_attribute_controller.state=ATTR_ADDR;
1811 PASSTHROUGH_IO_IN(vga,port,dest,len);
1813 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1819 static int feature_control_read(struct guest_info *core,
1825 struct vga_internal *vga = (struct vga_internal *) priv_data;
1827 PrintDebug("vga: feature control read data=0x%x\n",
1828 vga->vga_misc.vga_feature_control.val);
1830 ERR_WRONG_SIZE("read","feature control",len,1,1);
1833 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1835 PASSTHROUGH_IO_IN(vga,port,dest,len);
1837 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1842 static int feature_control_write(struct guest_info *core,
1848 struct vga_internal *vga = (struct vga_internal *) priv_data;
1850 PrintDebug("vga: feature control (%s) write data=0x%x\n",
1851 port==0x3ba ? "mono" : "color",
1854 ERR_WRONG_SIZE("write","feature control",len,1,1);
1856 PASSTHROUGH_IO_OUT(vga,port,src,len);
1858 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1866 static int video_subsys_enable_read(struct guest_info *core,
1872 struct vga_internal *vga = (struct vga_internal *) priv_data;
1874 PrintDebug("vga: video subsys enable read data=0x%x\n",
1875 vga->vga_misc.vga_video_subsys_enable.val);
1877 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1879 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1881 PASSTHROUGH_IO_IN(vga,port,dest,len);
1883 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1888 static int video_subsys_enable_write(struct guest_info *core,
1894 struct vga_internal *vga = (struct vga_internal *) priv_data;
1896 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1898 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1900 PASSTHROUGH_IO_OUT(vga,port,src,len);
1902 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1909 static int sequencer_address_read(struct guest_info *core,
1915 struct vga_internal *vga = (struct vga_internal *) priv_data;
1917 PrintDebug("vga: sequencer address read data=0x%x\n",
1918 vga->vga_sequencer.vga_sequencer_addr.val);
1920 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1922 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1924 PASSTHROUGH_IO_IN(vga,port,dest,len);
1926 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1931 static int sequencer_data_write(struct guest_info *core,
1937 struct vga_internal *vga = (struct vga_internal *) priv_data;
1941 data=*((uint8_t*)src);
1942 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1944 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1947 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1949 PASSTHROUGH_IO_OUT(vga,port,src,len);
1952 if (index>=VGA_SEQUENCER_NUM) {
1953 PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index);
1955 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1963 static int sequencer_address_write(struct guest_info *core,
1969 struct vga_internal *vga = (struct vga_internal *) priv_data;
1972 new_addr=*((uint8_t*)src);
1974 PrintDebug("vga: sequencer address write data=0x%x len=%u\n", len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1976 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1978 PASSTHROUGH_IO_OUT(vga,port,src,len);
1980 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
1983 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1984 // second byte is the data
1985 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
1986 PrintError("vga: write of data failed\n");
1994 static int sequencer_data_read(struct guest_info *core,
2000 struct vga_internal *vga = (struct vga_internal *) priv_data;
2004 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
2006 if (index>=VGA_SEQUENCER_NUM) {
2008 PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index);
2010 data=vga->vga_sequencer.vga_sequencer_regs[index];
2013 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
2016 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
2018 *((uint8_t*)dest) = data;
2020 PASSTHROUGH_IO_IN(vga,port,dest,len);
2022 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2031 static int crt_controller_address_read(struct guest_info *core,
2037 struct vga_internal *vga = (struct vga_internal *) priv_data;
2039 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
2040 port==0x3b4 ? "mono" : "color",
2041 vga->vga_crt_controller.vga_crt_addr.val);
2043 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
2045 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
2047 PASSTHROUGH_IO_IN(vga,port,dest,len);
2049 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
2054 static int crt_controller_data_write(struct guest_info *core,
2060 struct vga_internal *vga = (struct vga_internal *) priv_data;
2064 data=*((uint8_t*)src);
2066 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2068 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
2069 port==0x3b5 ? "mono" : "color",
2072 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2074 PASSTHROUGH_IO_OUT(vga,port,src,len);
2076 if (index>=VGA_CRT_CONTROLLER_NUM) {
2077 PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index);
2079 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2087 static int crt_controller_address_write(struct guest_info *core,
2093 struct vga_internal *vga = (struct vga_internal *) priv_data;
2096 new_addr=*((uint8_t*)src);
2098 PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n",
2099 port==0x3b4 ? "mono" : "color",
2100 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2102 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2104 PASSTHROUGH_IO_OUT(vga,port,src,len);
2106 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
2109 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2110 // second byte is the data
2111 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
2112 PrintError("vga: write of data failed\n");
2120 static int crt_controller_data_read(struct guest_info *core,
2126 struct vga_internal *vga = (struct vga_internal *) priv_data;
2130 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2132 if (index>=VGA_CRT_CONTROLLER_NUM) {
2134 PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index);
2136 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2139 PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data);
2141 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2143 *((uint8_t*)dest) = data;
2145 PASSTHROUGH_IO_IN(vga,port,dest,len);
2147 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2154 static int graphics_controller_address_read(struct guest_info *core,
2160 struct vga_internal *vga = (struct vga_internal *) priv_data;
2162 PrintDebug("vga: graphics controller address read data=0x%x\n",
2163 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2165 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2167 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2169 PASSTHROUGH_IO_IN(vga,port,dest,len);
2171 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2176 static int graphics_controller_data_write(struct guest_info *core,
2182 struct vga_internal *vga = (struct vga_internal *) priv_data;
2186 data=*((uint8_t*)src);
2187 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2190 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
2193 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2195 PASSTHROUGH_IO_OUT(vga,port,src,len);
2197 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2198 PrintError("vga: graphics controller write for illegal index %d ignored\n",index);
2200 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2208 static int graphics_controller_address_write(struct guest_info *core,
2214 struct vga_internal *vga = (struct vga_internal *) priv_data;
2217 new_addr=*((uint8_t*)src);
2219 PrintDebug("vga: graphics controller address write data=0x%x len=%u\n",
2220 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2222 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2224 PASSTHROUGH_IO_OUT(vga,port,src,len);
2226 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
2229 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2230 // second byte is the data
2231 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
2232 PrintError("vga: write of data failed\n");
2240 static int graphics_controller_data_read(struct guest_info *core,
2246 struct vga_internal *vga = (struct vga_internal *) priv_data;
2250 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2253 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2255 PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index);
2257 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2260 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
2263 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2265 *((uint8_t*)dest) = data;
2267 PASSTHROUGH_IO_IN(vga,port,dest,len);
2269 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2277 /* Note that these guys have a bizarre protocol*/
2279 static int attribute_controller_address_read(struct guest_info *core,
2285 struct vga_internal *vga = (struct vga_internal *) priv_data;
2287 PrintDebug("vga: attribute controller address read data=0x%x\n",
2288 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2290 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
2292 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2294 PASSTHROUGH_IO_IN(vga,port,dest,len);
2296 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2298 // Reading the attribute controller does not change the state
2303 static int attribute_controller_address_and_data_write(struct guest_info *core,
2309 struct vga_internal *vga = (struct vga_internal *) priv_data;
2312 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
2313 uint8_t new_addr = *((uint8_t*)src);
2314 // We are to treat this as an address write, and flip state
2315 // to expect data ON THIS SAME PORT
2316 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
2318 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2320 PASSTHROUGH_IO_OUT(vga,port,src,len);
2322 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
2324 vga->vga_attribute_controller.state=ATTR_DATA;
2327 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
2329 uint8_t data = *((uint8_t*)src);
2330 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2332 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
2334 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2336 PASSTHROUGH_IO_OUT(vga,port,src,len);
2338 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2339 PrintError("vga: attribute controller write to illegal index %d ignored\n",index);
2341 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2344 vga->vga_attribute_controller.state=ATTR_ADDR;
2353 static int attribute_controller_data_read(struct guest_info *core,
2359 struct vga_internal *vga = (struct vga_internal *) priv_data;
2363 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2365 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2367 PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index);
2369 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2372 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
2375 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2377 *((uint8_t*)dest) = data;
2379 PASSTHROUGH_IO_IN(vga,port,dest,len);
2381 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2388 Note that these guys also have a strange protocol
2389 since they need to squeeze 18 bits of data through
2392 static int dac_write_address_read(struct guest_info *core,
2398 struct vga_internal *vga = (struct vga_internal *) priv_data;
2400 PrintDebug("vga: dac write address read data=0x%x\n",
2401 vga->vga_dac.vga_dac_write_addr);
2403 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2406 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2408 PASSTHROUGH_IO_IN(vga,port,dest,len);
2410 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2412 // This read does not reset the state machine
2417 static int dac_write_address_write(struct guest_info *core,
2423 struct vga_internal *vga = (struct vga_internal *) priv_data;
2426 new_addr=*((uint8_t*)src);
2428 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
2430 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2432 PASSTHROUGH_IO_OUT(vga,port,src,len);
2434 // cannot be out of bounds since there are 256 regs
2436 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2438 // Now we also need to reset the state machine
2440 vga->vga_dac.state=DAC_WRITE;
2441 vga->vga_dac.channel=RED;
2447 static int dac_read_address_read(struct guest_info *core,
2453 struct vga_internal *vga = (struct vga_internal *) priv_data;
2455 PrintDebug("vga: dac read address read data=0x%x\n",
2456 vga->vga_dac.vga_dac_read_addr);
2458 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2460 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2462 PASSTHROUGH_IO_IN(vga,port,dest,len);
2464 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2466 // This read does not reset the state machine
2471 static int dac_read_address_write(struct guest_info *core,
2477 struct vga_internal *vga = (struct vga_internal *) priv_data;
2480 new_addr=*((uint8_t*)src);
2482 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
2484 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2486 PASSTHROUGH_IO_OUT(vga,port,src,len);
2488 // cannot be out of bounds since there are 256 regs
2490 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2492 // Now we also need to reset the state machine
2494 vga->vga_dac.state=DAC_READ;
2495 vga->vga_dac.channel=RED;
2501 static int dac_data_read(struct guest_info *core,
2507 struct vga_internal *vga = (struct vga_internal *) priv_data;
2512 if (vga->vga_dac.state!=DAC_READ) {
2513 PrintError("vga: dac data read while in other state\n");
2514 // results undefined, so we continue
2517 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2519 curreg = vga->vga_dac.vga_dac_read_addr;
2520 curchannel = vga->vga_dac.channel;
2521 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2523 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
2525 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2526 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2529 *((uint8_t*)dest) = data;
2531 PASSTHROUGH_IO_IN(vga,port,dest,len);
2533 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2535 curchannel = (curchannel+1)%3;
2536 vga->vga_dac.channel=curchannel;
2537 if (curchannel==0) {
2538 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2540 vga->vga_dac.vga_dac_read_addr = curreg;
2541 vga->vga_dac.state=DAC_READ;
2548 static int dac_data_write(struct guest_info *core,
2554 struct vga_internal *vga = (struct vga_internal *) priv_data;
2558 vga_palette_reg data32;
2559 vga_palette_reg mask32;
2561 if (vga->vga_dac.state!=DAC_WRITE) {
2562 PrintError("vga: dac data write while in other state\n");
2563 // results undefined, so we continue
2566 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2568 PASSTHROUGH_IO_OUT(vga,port,src,len);
2570 curreg = vga->vga_dac.vga_dac_write_addr;
2571 curchannel = vga->vga_dac.channel;
2572 data = *((uint8_t *)src);
2574 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
2576 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2577 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2580 data32 = data & 0x3f ;
2581 data32 <<= curchannel*8;
2582 mask32 = ~(0xff << (curchannel * 8));
2584 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2585 vga->vga_dac.vga_dac_palette[curreg] |= data32;
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_write_addr = curreg;
2593 vga->vga_dac.state=DAC_WRITE;
2602 static int dac_pixel_mask_read(struct guest_info *core,
2608 struct vga_internal *vga = (struct vga_internal *) priv_data;
2610 PrintDebug("vga: dac pixel mask read data=0x%x\n",
2611 vga->vga_dac.vga_pixel_mask);
2613 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2615 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2617 PASSTHROUGH_IO_IN(vga,port,dest,len);
2619 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2624 static int dac_pixel_mask_write(struct guest_info *core,
2630 struct vga_internal *vga = (struct vga_internal *) priv_data;
2633 new_data=*((uint8_t*)src);
2635 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
2637 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2639 PASSTHROUGH_IO_OUT(vga,port,src,len);
2641 vga->vga_dac.vga_pixel_mask = new_data;
2646 static int init_vga(struct vga_internal *vga)
2648 // TODO: startup spec of register contents, if any
2649 PrintError("vga: init_vga is UNIMPLEMTED\n");
2653 static int free_vga(struct vga_internal *vga)
2657 struct vm_device *dev = vga->dev;
2659 // Framebuffer deletion is user's responsibility
2661 // if (vga->mem_store) {
2662 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2663 // vga->mem_store=0;
2666 for (i=0;i<MAP_NUM;i++) {
2668 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2673 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2677 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2678 // The following also covers VGA_INPUT_STAT0_READ
2679 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2680 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2681 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2682 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2683 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2684 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2686 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2688 /* Sequencer registers */
2689 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2690 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2692 /* CRT controller registers */
2693 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2694 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2695 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2696 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2698 /* graphics controller registers */
2699 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2700 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2702 /* attribute controller registers */
2703 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2704 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2706 /* video DAC palette registers */
2707 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2708 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2709 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2710 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2713 if (vga->host_cons) {
2714 v3_graphics_console_close(vga->host_cons);
2722 static struct v3_device_ops dev_ops = {
2723 .free = (int (*)(void *))free_vga,
2727 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2728 struct vga_internal *vga;
2732 char * dev_id = v3_cfg_val(cfg, "ID");
2733 char * passthrough = v3_cfg_val(cfg, "passthrough");
2734 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2736 PrintDebug("vga: init_device\n");
2738 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2741 PrintError("vga: cannot allocate\n");
2745 memset(vga, 0, sizeof(struct vga_internal));
2747 vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
2748 vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
2750 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2751 PrintDebug("vga: enabling passthrough\n");
2752 vga->passthrough=true;
2753 vga->skip_next_passthrough_out=false;
2757 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2758 struct v3_frame_buffer_spec req;
2760 PrintDebug("vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2762 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2763 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2765 req.height=VGA_MAXY;
2767 req.bytes_per_pixel=4;
2768 req.bits_per_channel=8;
2774 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2776 if (!vga->host_cons) {
2777 PrintError("vga: unable to open host OS's graphics console\n");
2782 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2783 PrintDebug("vga: warning: target spec differs from requested spec\n");
2784 PrintDebug("vga: request: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", req.width, req.height, req.bytes_per_pixel, req.bits_per_channel, req.red_offset, req.green_offset, req.blue_offset);
2785 PrintDebug("vga: response: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", vga->target_spec.width, vga->target_spec.height, vga->target_spec.bytes_per_pixel, vga->target_spec.bits_per_channel, vga->target_spec.red_offset, vga->target_spec.green_offset, vga->target_spec.blue_offset);
2789 if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) {
2790 V3_Print("vga: enabling console-driven rendering\n");
2791 if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) {
2792 PrintError("vga: cannot enable console-driven rendering\n");
2798 V3_Print("vga: enabling console inquiry for updates\n");
2799 if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) {
2800 PrintError("vga: cannot enable console inquiry for updates\n");
2806 if (!vga->passthrough && !vga->host_cons) {
2807 V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2811 // No memory store is allocated since we will use a full memory hook
2812 // The VGA maps can be read as well as written
2813 // Reads also affect writes, since they are how you fill the latches
2815 // Now allocate the maps
2816 for (i=0;i<MAP_NUM;i++) {
2817 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
2818 if (!(vga->map[i])) {
2819 PrintError("vga: cannot allocate maps\n");
2823 memset(vga->map[i],0,MAP_SIZE);
2826 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2829 PrintError("Could not attach device %s\n", dev_id);
2836 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2837 MEM_REGION_START, MEM_REGION_END,
2841 PrintError("vga: memory book failed\n");
2842 v3_remove_device(dev);
2848 /* Miscelaneous registers */
2849 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2850 // The following also covers VGA_INPUT_STAT0_READ
2851 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2852 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2853 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2854 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2855 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2856 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2858 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2860 /* Sequencer registers */
2861 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2862 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2864 /* CRT controller registers */
2865 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2866 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2867 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2868 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2870 /* graphics controller registers */
2871 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2872 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2874 /* attribute controller registers */
2875 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2876 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2878 /* video DAC palette registers */
2879 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2880 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2881 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2882 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2885 PrintError("vga: Error allocating VGA I/O ports\n");
2886 v3_remove_device(dev);
2892 PrintDebug("vga: successfully added and initialized.\n");
2898 device_register("VGA", vga_init);