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
46 #define UPDATES_PER_RENDER 100
48 typedef uint8_t *vga_map; // points to MAP_SIZE data
54 #define VGA_MISC_OUT_READ 0x3cc
55 #define VGA_MISC_OUT_WRITE 0x3c2
57 #define VGA_INPUT_STAT0_READ 0x3c2
59 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
60 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
62 #define VGA_FEATURE_CONTROL_READ 0x3ca
63 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
64 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
66 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
68 #define VGA_SEQUENCER_ADDRESS 0x3c4
69 #define VGA_SEQUENCER_DATA 0x3c5
70 #define VGA_SEQUENCER_NUM 5
73 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
74 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
75 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
76 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
77 #define VGA_CRT_CONTROLLER_NUM 25
80 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
81 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
82 #define VGA_GRAPHICS_CONTROLLER_NUM 9
84 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
85 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
86 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
88 #define VGA_DAC_WRITE_ADDR 0x3c8
89 #define VGA_DAC_READ_ADDR 0x3c7
90 #define VGA_DAC_DATA 0x3c9
91 #define VGA_DAC_PIXEL_MASK 0x3c6
93 #define VGA_DAC_NUM_ENTRIES 256
96 #define VGA_FONT_WIDTH 8
97 #define VGA_MAX_FONT_HEIGHT 32
99 struct vga_misc_regs {
100 /* Read: 0x3cc; Write: 0x3c2 */
101 struct vga_misc_out_reg vga_misc_out;
103 struct vga_input_stat0_reg vga_input_stat0;
104 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
105 struct vga_input_stat1_reg vga_input_stat1;
106 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
107 struct vga_feature_control_reg vga_feature_control;
108 /* Read: 0x3c3; Write: 0x3c3 */
109 struct vga_video_subsys_enable_reg vga_video_subsys_enable;
110 } __attribute__((packed));
112 struct vga_sequencer_regs {
113 /* Address register is 0x3c4, data register is 0x3c5 */
115 struct vga_sequencer_addr_reg vga_sequencer_addr;
117 /* these can be accessed via the index, offset on start
118 or via the specific regs. For this reason, it is essential
119 that this is all packed and that the order does not change */
121 uint8_t vga_sequencer_regs[0];
124 struct vga_reset_reg vga_reset;
126 struct vga_clocking_mode_reg vga_clocking_mode;
128 struct vga_map_mask_reg vga_map_mask;
130 struct vga_char_map_select_reg vga_char_map_select;
132 struct vga_mem_mode_reg vga_mem_mode;
133 } __attribute__((packed));
135 struct vga_crt_controller_regs {
136 /* Address Register is 0x3b4 or 0x3d4 */
137 /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
138 struct vga_crt_addr_reg vga_crt_addr;
140 /* these can be accessed via the index, offset on start
141 or via the specific regs. For this reason, it is essential
142 that this is all packed and that the order does not change */
144 uint8_t vga_crt_controller_regs[0];
147 vga_horizontal_total_reg vga_horizontal_total;
149 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
151 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
153 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
155 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
157 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
159 vga_vertical_total_reg vga_vertical_total;
161 struct vga_overflow_reg vga_overflow;
163 struct vga_preset_row_scan_reg vga_preset_row_scan;
165 struct vga_max_row_scan_reg vga_max_row_scan;
167 struct vga_cursor_start_reg vga_cursor_start;
169 struct vga_cursor_end_reg vga_cursor_end;
171 vga_start_address_high_reg vga_start_address_high;
173 vga_start_address_low_reg vga_start_address_low;
175 vga_cursor_location_high_reg vga_cursor_location_high;
177 vga_cursor_location_low_reg vga_cursor_location_low;
179 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
181 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
183 vga_vertical_display_enable_end_reg vga_vertical_display_enable_end;
185 vga_offset_reg vga_offset;
187 struct vga_underline_location_reg vga_underline_location;
189 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
191 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
193 struct vga_crt_mode_control_reg vga_crt_mode_control;
195 vga_line_compare_reg vga_line_compare;
196 } __attribute__((packed));
198 struct vga_graphics_controller_regs {
199 /* Address: 0x3ce Data: 0x3cf */
202 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
204 /* these can be accessed via the index, offset on start
205 or via the specific regs. For this reason, it is essential
206 that this is all packed and that the order does not change */
208 uint8_t vga_graphics_controller_regs[0];
211 struct vga_set_reset_reg vga_set_reset;
213 struct vga_enable_set_reset_reg vga_enable_set_reset;
215 struct vga_color_compare_reg vga_color_compare;
217 struct vga_data_rotate_reg vga_data_rotate;
219 struct vga_read_map_select_reg vga_read_map_select;
221 struct vga_graphics_mode_reg vga_graphics_mode;
223 struct vga_misc_reg vga_misc;
225 struct vga_color_dont_care_reg vga_color_dont_care;
227 vga_bit_mask_reg vga_bit_mask;
228 } __attribute__((packed));
231 struct vga_attribute_contoller_regs {
233 Address AND WRITE: 0x3c0
236 The write protocol is to write the index to 0x3c0 followed by
237 the data. The read protocol is to write the index to 0x3c0
238 and then read from 0x3c1
240 IMPORTANT: write address, write data flips state back to write address
241 write address, read data DOES NOT
243 To reset to write address state, read input status register 1
245 enum { ATTR_ADDR, ATTR_DATA } state; //state of the flip flop
248 struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
252 /* these can be accessed via the index, offset on start
253 or via the specific regs. For this reason, it is essential
254 that this is all packed and that the order does not change */
256 uint8_t vga_attribute_controller_regs[0];
259 vga_internal_palette_regs vga_internal_palette;
261 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
263 vga_overscan_color_reg vga_overscan_color;
265 struct vga_color_plane_enable_reg vga_color_plane_enable;
267 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
269 struct vga_color_select_reg vga_color_select;
270 } __attribute__((packed));
272 struct vga_dac_regs {
273 enum {DAC_READ=0, DAC_WRITE} state;
274 enum {RED=0,GREEN,BLUE} channel;
275 vga_dac_pixel_mask_reg vga_pixel_mask;
276 vga_dac_write_addr_reg vga_dac_write_addr;
277 vga_dac_read_addr_reg vga_dac_read_addr;
278 // the dac_data register is used only to access the registers
279 // and thus has no representation here
280 vga_palette_reg vga_dac_palette[VGA_DAC_NUM_ENTRIES];
281 } __attribute__((packed));
284 struct vga_internal {
285 struct vm_device *dev;
288 bool skip_next_passthrough_out; // for word access
290 struct v3_frame_buffer_spec target_spec;
291 v3_graphics_console_t host_cons;
293 uint32_t updates_since_render;
295 struct frame_buf *framebuf; // we render to this
297 // void *mem_store; // This is the region where the memory hooks will go
299 vga_map map[MAP_NUM]; // the maps that the host writes to
301 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
303 /* Range of I/O ports here for backward compat with MDA and CGA */
304 struct vga_misc_regs vga_misc;
306 /* Address Register is 0x3b4 or 0x3d4 */
307 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
308 struct vga_crt_controller_regs vga_crt_controller;
310 /* Address register is 0x3c4, data register is 0x3c5 */
311 struct vga_sequencer_regs vga_sequencer;
313 /* Address: 0x3ce Data: 0x3cf */
314 struct vga_graphics_controller_regs vga_graphics_controller;
317 Address AND WRITE: 0x3c0
321 struct vga_attribute_contoller_regs vga_attribute_controller;
324 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
325 address for writes: 0x3c8 ("")
327 pixel mask: 0x3c6 - do not write (init to 0xff)
329 struct vga_dac_regs vga_dac;
333 typedef enum {PLANAR_SHIFT, PACKED_SHIFT, C256_SHIFT} shift_mode_t;
336 static void find_text_char_dim(struct vga_internal *vga, uint32_t *w, uint32_t *h)
338 *w = (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
340 *h = vga->vga_crt_controller.vga_max_row_scan.max_scan_line+1;
344 static void find_text_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
346 uint32_t vert_lsb, vert_msb;
350 *width = (vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
351 - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew;
353 vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
354 vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
355 + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
357 ph = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
359 find_text_char_dim(vga,&cw, &ch);
366 static void find_text_data_start(struct vga_internal *vga, void **data)
370 offset = vga->vga_crt_controller.vga_start_address_high;
372 offset += vga->vga_crt_controller.vga_start_address_low;
374 *data = vga->map[0]+offset;
379 static void find_text_attr_start(struct vga_internal *vga, void **data)
383 offset = vga->vga_crt_controller.vga_start_address_high;
385 offset += vga->vga_crt_controller.vga_start_address_low;
387 *data = vga->map[1]+offset;
391 static void find_text_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y, void **data)
398 find_text_res(vga,&w,&h);
400 find_text_data_start(vga,&buf);
402 offset = vga->vga_crt_controller.vga_cursor_location_high;
404 offset += vga->vga_crt_controller.vga_cursor_location_low;
406 *data = vga->map[0]+offset;
408 charsin = (uint32_t)(*data - buf);
416 static void find_text_font_start(struct vga_internal *vga, void **data, uint8_t char_map)
418 uint32_t mapa_offset, mapb_offset;
423 mapa_offset = (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb << 1)
424 + vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb ;
425 *data = vga->map[2] + mapa_offset;
429 mapb_offset = (vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb << 1)
430 + vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb ;
431 *data = vga->map[2] + mapb_offset;
434 PrintError("vga: unknown char_map given to find_text_font_start\n");
440 static int extended_fontset(struct vga_internal *vga)
442 if (vga->vga_sequencer.vga_mem_mode.extended_memory &&
443 ! ( (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_lsb
444 == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_lsb) &&
445 (vga->vga_sequencer.vga_char_map_select.char_map_a_sel_msb
446 == vga->vga_sequencer.vga_char_map_select.char_map_b_sel_msb))) {
454 static int blinking(struct vga_internal *vga)
456 return vga->vga_attribute_controller.vga_attribute_mode_control.enable_blink;
460 static void find_graphics_data_starting_offset(struct vga_internal *vga, uint32_t *offset)
463 *offset = vga->vga_crt_controller.vga_start_address_high;
465 *offset += vga->vga_crt_controller.vga_start_address_low;
469 static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode)
471 if (vga->vga_graphics_controller.vga_graphics_mode.c256) {
474 if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) {
483 static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
485 uint32_t vert_lsb, vert_msb;
487 *width = ((vga->vga_crt_controller.vga_horizontal_display_enable_end + 1)
488 - vga->vga_crt_controller.vga_end_horizontal_blanking.display_enable_skew);
490 *width *= (vga->vga_sequencer.vga_clocking_mode.dot8 ? 8 : 9);
492 vert_lsb = vga->vga_crt_controller.vga_vertical_display_enable_end; // 8 bits here
493 vert_msb = (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end9 << 1) // 2 bits here
494 + (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
496 *height = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
498 // At this point we have the resolution in dot clocks across and scanlines top-to-bottom
499 // This is usually the resolution in pixels, but it can be monkeyed with
500 // at least in the following ways
502 // vga sequencer dot clock divide by two
503 if (vga->vga_sequencer.vga_clocking_mode.dot_clock) {
508 // crt_controller.max_row_scan.double_scan => each row twice for 200=>400
509 if (vga->vga_crt_controller.vga_max_row_scan.double_scan) {
513 // crt_controller.crt_mode_control.count_by_two => pixels twice as wide as normal
514 if (vga->vga_crt_controller.vga_crt_mode_control.count_by_two) {
518 // crt_controller.crt_mode_control.horizontal_retrace_select => pixels twice as tall as normal
519 if (vga->vga_crt_controller.vga_crt_mode_control.horizontal_retrace_select) {
526 static void find_graphics_cursor_pos(struct vga_internal *vga, uint32_t *x, uint32_t *y)
533 static void dac_lookup_24bit_color(struct vga_internal *vga,
539 // use internal or external palette?
541 vga_palette_reg *r = &(vga->vga_dac.vga_dac_palette[entry]);
543 // converting from 6 bits to 8 bits so << 2
544 *red = (*r & 0x3f) << 2;
545 *green = ((*r >> 8) & 0x3f) << 2;
546 *blue = ((*r >> 16) & 0x3f) << 2;
552 Colors work like this:
554 4 bit modes: index is to the internal palette on the attribute controller
555 that supplies 6 bits, but we need 8 to index the dac
556 2 more (the msbs) are supplied from the color select register
557 we can optionally overwrite bits 5 and 4 from the color
558 select register as well, depending on a selection bit
559 in the mode control register. The result of all this is
560 8 bit index for the dac
562 8 bit modes: the attribute controller passes the index straight through
566 The DAC translates from the 8 bit index into 6 bits per color channel
567 (18 bit color). We mulitply by 4 to get 24 bit color.
570 static void find_24bit_color(struct vga_internal *vga,
576 uint8_t di; // ultimate dac index
578 if (vga->vga_attribute_controller.vga_attribute_mode_control.pixel_width) {
579 // 8 bit mode does right to the DAC
582 struct vga_internal_palette_reg pr = vga->vga_attribute_controller.vga_internal_palette[val%16];
583 di = pr.palette_data;
585 // Fix bits 5-4 if needed
586 if (vga->vga_attribute_controller.vga_attribute_mode_control.p54_select) {
587 di &= ~0x30; // clear 5-4
588 di |= vga->vga_attribute_controller.vga_color_select.sc4 << 4;
589 di |= vga->vga_attribute_controller.vga_color_select.sc5 << 5;
592 // We must always produce bits 6 and 7
593 di &= ~0xc0; // clear 7-6
594 di |= vga->vga_attribute_controller.vga_color_select.sc6 << 6;
595 di |= vga->vga_attribute_controller.vga_color_select.sc7 << 7;
598 dac_lookup_24bit_color(vga,di,red,green,blue);
601 static void render_graphics(struct vga_internal *vga, void *fb)
604 struct v3_frame_buffer_spec *spec = &(vga->target_spec);
606 uint32_t gw, gh; // graphics w/h
607 uint32_t fw, fh; // fb w/h
608 uint32_t rgw, rgh; // region we can actually show on the frame buffer
611 uint32_t fx, fy; // pixel position within the frame buffer
613 uint32_t offset; // offset into the maps
615 uint8_t p; // pixel in the current map byte (0..7)
617 uint8_t r,g,b; // looked up colors for entry
619 void *pixel; // current pixel in the fb
620 uint8_t *red; // and the channels in the pixel
624 uint8_t db[4]; // 4 bytes read at a time
625 uint8_t pb[8]; // 8 pixels assembled at a time
627 shift_mode_t sm; // shift mode
629 uint32_t cur_x, cur_y;
632 find_graphics_res(vga,&gw,&gh);
634 find_shift_mode(vga,&sm);
636 find_graphics_cursor_pos(vga,&cur_x,&cur_y);
638 find_graphics_data_starting_offset(vga,&offset);
644 PrintDebug("vga: attempting graphics render (%s): graphics_res=(%u,%u), fb_res=(%u,%u), "
645 "fb=0x%p offset=0x%x\n",
646 sm == PLANAR_SHIFT ? "planar shift" :
647 sm == PACKED_SHIFT ? "packed shift" :
648 sm == C256_SHIFT ? "color256 shift" : "UNKNOWN",
649 gw,gh,fw,fh,fb,offset);
651 // First we need to clip to what we can actually show
652 rgw = gw < fw ? gw : fw;
653 rgh = gh < fh ? gh : fh;
656 PrintError("vga: warning: graphics width is not a multiple of 8\n");
661 // Now we scan across by row
662 for (fy=0;fy<gh;fy++) {
665 fx += (sm==C256_SHIFT ? 4 : 8) , offset++ ) {
667 // if any of these pixels are in the rendger region
668 if (fy < rgh && fx < rgw) {
669 // assemble all 4 or 8 pixels
671 // fetch the data bytes
673 db[m]=*((uint8_t*)(vga->map[m]+offset));
681 (( db[0] >> 7) & 0x1) |
682 (( db[1] >> 6) & 0x2) |
683 (( db[2] >> 5) & 0x4) |
684 (( db[3] >> 4) & 0x8) ;
693 // first 4 pixels use planes 0 and 2
696 ((db[2] >> 4) & 0xc) |
697 ((db[0] >> 6) & 0x3) ;
703 // next 4 pixels use planes 1 and 3
706 ((db[3] >> 4) & 0xc) |
707 ((db[1] >> 6) & 0x3) ;
714 // this one is either very bizarre or as simple as this
722 for (p=0;p< (sm==C256_SHIFT ? 4 : 8);p++) {
725 find_24bit_color(vga,pb[p],&r,&g,&b);
727 // find its position in the framebuffer;
728 pixel = fb + (((fx + p) + (fy*spec->width)) * spec->bytes_per_pixel);
729 red = pixel + spec->red_offset;
730 green = pixel + spec->green_offset;
731 blue = pixel + spec->blue_offset;
742 PrintDebug("vga: render done\n");
746 static void render_text_cursor(struct vga_internal *vga, void *fb)
754 // A variant of this function could render to
755 // a text console interface as well
757 static void render_text(struct vga_internal *vga, void *fb)
759 // line graphics enable bit means to dupe column 8 to 9 when
760 // in 9 dot wide mode
761 // otherwise 9th dot is background
763 struct v3_frame_buffer_spec *spec = &(vga->target_spec);
765 uint32_t gw, gh; // graphics w/h
766 uint32_t tw, th; // text w/h
767 uint32_t rtw, rth; // rendered text w/h
768 uint32_t cw, ch; // char font w/h including 8/9
769 uint32_t fw, fh; // fb w/h
771 uint32_t px, py; // cursor position
773 uint32_t x, y, l, p; // text location, line and pixel within the char
774 uint32_t fx, fy; // pixel position within the frame buffer
777 uint8_t *text; // points to current char
778 uint8_t *attr; // and its matching attribute
779 uint8_t *curs; // to where the cursor is
780 uint8_t *font; // to where the current font is
782 uint8_t fg_entry; // foreground color entry
783 uint8_t bg_entry; // background color entry
784 uint8_t fgr,fgg,fgb; // looked up foreground colors
785 uint8_t bgr,bgg,bgb; // looked up bg colors
787 uint8_t ct, ca; // the current char and attribute
788 struct vga_attribute_byte a; // decoded attribute
790 void *pixel; // current pixel in the fb
791 uint8_t *red; // and the channels in the pixel
797 find_graphics_res(vga,&gw,&gh);
798 find_text_res(vga,&tw,&th);
799 find_text_char_dim(vga,&cw,&ch);
803 find_text_cursor_pos(vga,&px,&py,(void**)&curs);
804 find_text_data_start(vga,(void**)&text);
805 find_text_attr_start(vga,(void**)&attr);
807 find_text_font_start(vga,(void**)&font,0); // will need to switch this as we go since it is part of attr
809 PrintDebug("vga: attempting text render: graphics_res=(%u,%u), fb_res=(%u,%u), text_res=(%u,%u), "
810 "char_res=(%u,%u), cursor=(%u,%u) font=0x%p, text=0x%p, attr=0x%p, curs=0x%p, fb=0x%p"
811 "graphics extension=%u, extended_fontset=%d, blinking=%d\n",
812 gw,gh,fw,fh,tw,th,cw,ch,px,py,font,text,attr,curs,fb,
813 vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code,
814 extended_fontset(vga), blinking(vga));
818 // First we need to clip to what we can actually show
819 rtw = tw < fw/cw ? tw : fw/cw;
820 rth = th < fh/ch ? th : fh/ch;
824 // Now let's scan by char across the whole thing
826 for (x=0;x<tw;x++, text++, attr++) {
827 if (x < rtw && y < rth) {
828 // grab the character and attribute for the position
833 // find the character's font bitmap (one byte per row)
834 find_text_font_start(vga,(void**)&font,
835 extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
837 font += ct * ((VGA_MAX_FONT_HEIGHT * VGA_FONT_WIDTH)/8);
839 // Now let's find out what colors we will be using
842 if (!extended_fontset(vga)) {
843 fg_entry = a.foreground_intensity_or_font_select << 3;
849 find_24bit_color(vga,fg_entry,&fgr,&fgg,&fgb);
851 if (!blinking(vga)) {
852 bg_entry = a.blinking_or_bg_intensity << 3;
858 find_24bit_color(vga,bg_entry,&bgr,&bgg,&bgb);
860 // Draw the character
861 for (l=0; l<ch; l++, font++) {
862 uint8_t frow = *font; // this is the row of of the font map
866 // a char can be 9 bits wide, but the font map
867 // is only 8 bits wide, which means we need to know where to
870 // We get it from the font map if
871 // its line line graphics mode and its a graphics char
872 // otherwise it's the background color
873 if (vga->vga_attribute_controller.vga_attribute_mode_control.enable_line_graphics_char_code
874 && ct>=0xc0 && ct<=0xdf ) {
880 fbit= (frow >> (7-p) ) & 0x1;
883 // We are now at the pixel level, with fbit being the pixel we draw (color+attr or bg+attr)
884 // For now, we will draw it as black/white
886 // find its position in the framebuffer;
889 pixel = fb + ((fx + (fy*spec->width)) * spec->bytes_per_pixel);
890 red = pixel + spec->red_offset;
891 green = pixel + spec->green_offset;
892 blue = pixel + spec->blue_offset;
894 // Are we on the cursor?
895 // if so, let's negate this pixel to invert the cell
899 // update the framebuffer
922 static void render_test(struct vga_internal *vga, void *fb)
924 struct v3_frame_buffer_spec *s;
926 s=&(vga->target_spec);
928 if (fb && s->height>=480 && s->width>=640 ) {
929 uint8_t color = (uint8_t)(vga->updates_since_render);
933 for (y=0;y<480;y++) {
934 for (x=0;x<640;x++) {
935 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
936 uint8_t *red = pixel + s->red_offset;
937 uint8_t *green = pixel + s->green_offset;
938 uint8_t *blue = pixel + s->blue_offset;
944 } else if (y<(480/2)) {
948 } else if (y<(3*(480/4))) {
953 *red=*green=*blue=color+x;
960 static void render_black(struct vga_internal *vga, void *fb)
962 struct v3_frame_buffer_spec *s;
964 s=&(vga->target_spec);
966 memset(fb,0,s->height*s->width*s->bytes_per_pixel);
969 static void render_maps(struct vga_internal *vga, void *fb)
972 struct v3_frame_buffer_spec *s;
975 s=&(vga->target_spec);
977 if (fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) {
978 // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
985 for (y=480+32;y<768;y++) {
986 for (x=m*256;x<(m+1)*256;x++,b++) {
987 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
988 uint8_t *red = pixel + s->red_offset;
989 uint8_t *green = pixel + s->green_offset;
990 uint8_t *blue = pixel + s->blue_offset;
992 *red=*green=*blue=*b;
1000 static int render(struct vga_internal *vga)
1005 vga->updates_since_render++;
1007 if (vga->updates_since_render%100) {
1012 if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) {
1014 fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
1016 if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
1017 if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) {
1018 render_graphics(vga,fb);
1020 render_text(vga,fb);
1021 render_text_cursor(vga,fb);
1024 render_black(vga,fb);
1027 if (0) { render_test(vga,fb); }
1029 // always render maps for now
1030 render_maps(vga,fb);
1032 v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
1039 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
1041 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
1061 static uint64_t find_offset_write(struct vga_internal *vga, addr_t guest_addr)
1063 uint64_t mem_start, mem_end;
1066 mem_start=mem_end=0;
1068 get_mem_region(vga, &mem_start, &mem_end);
1070 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1072 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1073 return (guest_addr-mem_start) % size;
1076 return ((guest_addr-mem_start) >> 1 ) % size;
1083 // Determines which maps should be enabled for this single byte write
1084 // and what the increment (actually 1/increment for the copy loop
1086 // memory_mode.odd_even == 0 => even address = maps 0 and 2 enabled; 1,3 otherwise
1088 static uint8_t find_map_write(struct vga_internal *vga, addr_t guest_addr)
1090 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
1092 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1095 if (guest_addr & 0x1) {
1096 return mm & 0xa; // 0x1010
1098 return mm & 0x5; // 0x0101
1103 static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
1105 if (vga->vga_sequencer.vga_mem_mode.odd_even) {
1108 return !(new_guest_addr & 0x1);
1114 static int vga_write(struct guest_info * core,
1120 struct vm_device *dev = (struct vm_device *)priv_data;
1121 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1123 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1125 if (vga->passthrough) {
1126 PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
1127 memcpy(V3_VAddr((void*)guest_addr),src,length);
1132 PrintDebug("vga: data written was 0x");
1133 for (i=0;i<length;i++) {
1134 uint8_t c= ((char*)src)[i];
1135 PrintDebug("%.2x", c);
1138 for (i=0;i<length;i++) {
1139 char c= ((char*)src)[i];
1140 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1145 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
1148 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
1152 00b -- Write Mode 0: In this mode, the host data is first rotated
1153 as per the Rotate Count field, then the Enable Set/Reset mechanism
1154 selects data from this or the Set/Reset field. Then the selected
1155 Logical Operation is performed on the resulting data and the data
1156 in the latch register. Then the Bit Mask field is used to select
1157 which bits come from the resulting data and which come
1158 from the latch register. Finally, only the bit planes enabled by
1159 the Memory Plane Write Enable field are written to memory.
1167 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1168 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1170 offset = find_offset_write(vga, guest_addr);
1173 PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
1176 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1178 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1179 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
1180 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1181 uint8_t mm = find_map_write(vga,guest_addr+i);
1184 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);
1187 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) {
1188 vga_map map = vga->map[mapnum];
1189 uint8_t data = ((uint8_t *)src)[i];
1190 uint8_t latchval = vga->latch[mapnum];
1193 PrintDebug("vga: raw data=0x%x\n",data);
1195 // rotate data right
1197 data = (data>>ror) | (data<<(8-ror));
1201 PrintDebug("vga: data after ror=0x%x\n",data);
1203 // use SR bit if ESR is on for this map
1205 data = (sr&0x1) * -1;
1210 PrintDebug("vga: data after esrr=0x%x\n",data);
1229 PrintDebug("vga: data after func=0x%x\n",data);
1232 // mux between the data byte and the latch byte on
1234 data = (bm & data) | ((~bm) & latchval);
1238 PrintDebug("vga: data after bm mux=0x%x\n",data);
1243 // write to this map
1245 PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
1260 01b -- Write Mode 1: In this mode, data is transferred directly
1261 from the 32 bit latch register to display memory, affected only by
1262 the Memory Plane Write Enable field. The host data is not used in this mode.
1267 uint64_t offset = find_offset_write(vga,guest_addr);
1270 PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
1273 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1276 uint8_t mm = find_map_write(vga,guest_addr+i);
1278 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
1279 vga_map map = vga->map[mapnum];
1280 uint8_t latchval = vga->latch[mapnum];
1284 // write to this map
1285 map[offset] = latchval;
1296 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
1297 are replicated across all 8 bits of their respective planes.
1298 Then the selected Logical Operation is performed on the resulting
1299 data and the data in the latch register. Then the Bit Mask field is used to
1300 select which bits come from the resulting data and which come from
1301 the latch register. Finally, only the bit planes enabled by the
1302 Memory Plane Write Enable field are written to memory.
1308 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
1310 offset = find_offset_write(vga, guest_addr);
1313 PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
1316 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1318 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
1319 uint8_t mm = find_map_write(vga,guest_addr+i);
1321 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
1322 vga_map map = vga->map[mapnum];
1323 uint8_t data = ((uint8_t *)src)[i];
1324 uint8_t latchval = vga->latch[mapnum];
1326 // expand relevant bit to 8 bit
1327 // it's basically esr=1, sr=bit from mode 0 write
1328 data = ((data>>mapnum)&0x1) * -1;
1345 // mux between latch and alu output
1346 data = (bm & data) | ((~bm) & latchval);
1350 // write to this map
1361 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
1362 as if the Enable Set/Reset field were set to 1111b. Then the host data is
1363 first rotated as per the Rotate Count field, then logical ANDed with the
1364 value of the Bit Mask field. The resulting value is used on the data
1365 obtained from the Set/Reset field in the same way that the Bit Mask field
1366 would ordinarily be used. to select which bits come from the expansion
1367 of the Set/Reset field and which come from the latch register. Finally,
1368 only the bit planes enabled by the Memory Plane Write Enable field
1369 are written to memory.
1376 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
1378 offset = find_offset_write(vga, guest_addr);
1380 PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
1382 for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
1384 uint8_t data = ((uint8_t *)src)[i];
1387 data = (data>>ror) | (data<<(8-ror));
1390 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
1391 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
1392 uint8_t mm = find_map_write(vga,guest_addr+i);
1394 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
1395 vga_map map = vga->map[mapnum];
1396 uint8_t latchval = vga->latch[mapnum];
1399 data = (sr&0x1) * -1;
1401 // mux between latch and alu output
1402 data = (bm & data) | ((~bm) & latchval);
1406 // write to this map
1417 // There is no default
1427 static uint64_t find_offset_read(struct vga_internal *vga, addr_t guest_addr)
1429 uint64_t mem_start, mem_end;
1432 mem_start=mem_end=0;
1434 get_mem_region(vga, &mem_start, &mem_end);
1436 size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
1438 if (!vga->vga_sequencer.vga_mem_mode.chain4) {
1439 return (guest_addr-mem_start) % size;
1442 return ((guest_addr - mem_start) >> 2) % size;
1446 static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
1449 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1450 return !(new_guest_addr & 0x3);
1457 static int vga_read(struct guest_info * core,
1463 struct vm_device *dev = (struct vm_device *)priv_data;
1464 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
1467 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
1472 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
1474 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
1476 /* 0 - a byte from ONE of the 4 planes is returned;
1477 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
1482 if (vga->vga_sequencer.vga_mem_mode.chain4) {
1484 offset = find_offset_read(vga,guest_addr);
1485 // address bytes select the map
1486 for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
1487 mapnum = (guest_addr+i) % 4;
1489 PrintDebug("vga: mode 0 read, chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
1491 ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
1493 // presumably all the latches are to be reloaded, not just the selected one?
1494 for (mapnum=0;mapnum<4;mapnum++) {
1495 vga->latch[mapnum] = *(vga->map[mapnum]+offset);
1499 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
1500 offset = find_offset_read(vga,guest_addr);
1502 if (offset>=65536) {
1503 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
1507 PrintDebug("vga: mode 0 read, not-chain4, offset=0x%llx, mapnum=%u\n",offset,mapnum);
1510 memcpy(dst,(vga->map[mapnum])+offset,length);
1512 // load the latches with the last item read
1513 for (mapnum=0;mapnum<4;mapnum++) {
1514 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1521 /* 1 - Compare video memory and reference color
1522 (in Color Compare, except those not set in Color Don't Care),
1523 each bit in returned result is one comparison between the reference color
1525 Ref color is *4* bits, and thus a one byte read returns a comparison
1531 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
1532 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
1539 offset = find_offset_read(vga,guest_addr);
1542 PrintDebug("vga: mode 1 read, offset=0x%llx, cc=0x%x, dc-0x%x\n",offset,cc,dc);
1546 for (i=0;i<length;i++,offset++) {
1549 for (mapnum=0;mapnum<4;mapnum++) {
1550 map = vga->map[mapnum];
1551 if ( (dc>>mapnum)&0x1 ) { // don't care
1555 bits = (map[offset]&0xf) == cc;
1558 bits |= (((map[offset]>>4))&0xf) == cc;
1560 // not clear whether it is 0..k or k..0
1566 // load the latches with the last item read
1567 for (mapnum=0;mapnum<4;mapnum++) {
1568 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
1573 // there is no default
1576 if (vga->passthrough) {
1577 PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
1578 memcpy(dst,V3_VAddr((void*)guest_addr),length);
1584 PrintDebug("vga: data read is 0x");
1585 for (i=0;i<length;i++) {
1586 uint8_t c= ((char*)dst)[i];
1587 PrintDebug("%.2x", c);
1590 for (i=0;i<length;i++) {
1591 char c= ((char*)dst)[i];
1592 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
1605 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
1606 if (((len)<(min)) || ((len)>(max))) { \
1607 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
1611 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
1614 *(uint8_t *)dest = v3_inb(port);
1617 *(uint16_t *)dest = v3_inw(port);
1620 *(uint32_t *)dest = v3_indw(port);
1623 PrintError("vga: unsupported passthrough io in size %u\n",length);
1629 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
1632 v3_outb(port, *(uint8_t *)src);
1635 v3_outw(port, *(uint16_t *)src);
1638 v3_outdw(port, *(uint32_t *)src);
1641 PrintError("vga: unsupported passthrough io out size %u\n",length);
1646 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
1647 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
1649 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
1650 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
1652 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
1653 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
1655 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
1656 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)
1658 static int misc_out_read(struct guest_info *core,
1664 struct vga_internal *vga = (struct vga_internal *) priv_data;
1666 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
1668 ERR_WRONG_SIZE("read","misc out",len,1,1);
1670 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
1672 PASSTHROUGH_IO_IN(vga,port,dest,len);
1674 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
1679 static int misc_out_write(struct guest_info *core,
1685 struct vga_internal *vga = (struct vga_internal *) priv_data;
1687 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
1689 ERR_WRONG_SIZE("write","misc out",len,1,1);
1691 PASSTHROUGH_IO_OUT(vga,port,src,len);
1693 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
1702 static int input_stat0_read(struct guest_info *core,
1708 struct vga_internal *vga = (struct vga_internal *) priv_data;
1710 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
1712 ERR_WRONG_SIZE("read","input stat0",len,1,1);
1714 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
1716 PASSTHROUGH_IO_IN(vga,port,dest,len);
1718 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
1724 static int input_stat1_read(struct guest_info *core,
1730 struct vga_internal *vga = (struct vga_internal *) priv_data;
1732 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
1733 port==0x3ba ? "mono" : "color",
1734 vga->vga_misc.vga_input_stat1.val);
1736 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1739 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1741 // Stunningly, reading stat1 is also a way to reset
1742 // the state of attribute controller address/data flipflop
1743 // That is some mighty fine crack the designers were smoking.
1745 vga->vga_attribute_controller.state=ATTR_ADDR;
1747 PASSTHROUGH_IO_IN(vga,port,dest,len);
1749 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1755 static int feature_control_read(struct guest_info *core,
1761 struct vga_internal *vga = (struct vga_internal *) priv_data;
1763 PrintDebug("vga: feature control read data=0x%x\n",
1764 vga->vga_misc.vga_feature_control.val);
1766 ERR_WRONG_SIZE("read","feature control",len,1,1);
1769 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1771 PASSTHROUGH_IO_IN(vga,port,dest,len);
1773 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1778 static int feature_control_write(struct guest_info *core,
1784 struct vga_internal *vga = (struct vga_internal *) priv_data;
1786 PrintDebug("vga: feature control (%s) write data=0x%x\n",
1787 port==0x3ba ? "mono" : "color",
1790 ERR_WRONG_SIZE("write","feature control",len,1,1);
1792 PASSTHROUGH_IO_OUT(vga,port,src,len);
1794 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1802 static int video_subsys_enable_read(struct guest_info *core,
1808 struct vga_internal *vga = (struct vga_internal *) priv_data;
1810 PrintDebug("vga: video subsys enable read data=0x%x\n",
1811 vga->vga_misc.vga_video_subsys_enable.val);
1813 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1815 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1817 PASSTHROUGH_IO_IN(vga,port,dest,len);
1819 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1824 static int video_subsys_enable_write(struct guest_info *core,
1830 struct vga_internal *vga = (struct vga_internal *) priv_data;
1832 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1834 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1836 PASSTHROUGH_IO_OUT(vga,port,src,len);
1838 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1845 static int sequencer_address_read(struct guest_info *core,
1851 struct vga_internal *vga = (struct vga_internal *) priv_data;
1853 PrintDebug("vga: sequencer address read data=0x%x\n",
1854 vga->vga_sequencer.vga_sequencer_addr.val);
1856 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1858 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1860 PASSTHROUGH_IO_IN(vga,port,dest,len);
1862 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1867 static int sequencer_data_write(struct guest_info *core,
1873 struct vga_internal *vga = (struct vga_internal *) priv_data;
1877 data=*((uint8_t*)src);
1878 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1880 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1883 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1885 PASSTHROUGH_IO_OUT(vga,port,src,len);
1888 if (index>=VGA_SEQUENCER_NUM) {
1889 PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index);
1891 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1899 static int sequencer_address_write(struct guest_info *core,
1905 struct vga_internal *vga = (struct vga_internal *) priv_data;
1908 new_addr=*((uint8_t*)src);
1910 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);
1912 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1914 PASSTHROUGH_IO_OUT(vga,port,src,len);
1916 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
1919 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1920 // second byte is the data
1921 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
1922 PrintError("vga: write of data failed\n");
1930 static int sequencer_data_read(struct guest_info *core,
1936 struct vga_internal *vga = (struct vga_internal *) priv_data;
1940 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1942 if (index>=VGA_SEQUENCER_NUM) {
1944 PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index);
1946 data=vga->vga_sequencer.vga_sequencer_regs[index];
1949 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
1952 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
1954 *((uint8_t*)dest) = data;
1956 PASSTHROUGH_IO_IN(vga,port,dest,len);
1958 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1967 static int crt_controller_address_read(struct guest_info *core,
1973 struct vga_internal *vga = (struct vga_internal *) priv_data;
1975 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
1976 port==0x3b4 ? "mono" : "color",
1977 vga->vga_crt_controller.vga_crt_addr.val);
1979 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
1981 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
1983 PASSTHROUGH_IO_IN(vga,port,dest,len);
1985 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
1990 static int crt_controller_data_write(struct guest_info *core,
1996 struct vga_internal *vga = (struct vga_internal *) priv_data;
2000 data=*((uint8_t*)src);
2002 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2004 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
2005 port==0x3b5 ? "mono" : "color",
2008 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
2010 PASSTHROUGH_IO_OUT(vga,port,src,len);
2012 if (index>=VGA_CRT_CONTROLLER_NUM) {
2013 PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index);
2015 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
2023 static int crt_controller_address_write(struct guest_info *core,
2029 struct vga_internal *vga = (struct vga_internal *) priv_data;
2032 new_addr=*((uint8_t*)src);
2034 PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n",
2035 port==0x3b4 ? "mono" : "color",
2036 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2038 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
2040 PASSTHROUGH_IO_OUT(vga,port,src,len);
2042 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
2045 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2046 // second byte is the data
2047 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
2048 PrintError("vga: write of data failed\n");
2056 static int crt_controller_data_read(struct guest_info *core,
2062 struct vga_internal *vga = (struct vga_internal *) priv_data;
2066 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
2068 if (index>=VGA_CRT_CONTROLLER_NUM) {
2070 PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index);
2072 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
2075 PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data);
2077 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
2079 *((uint8_t*)dest) = data;
2081 PASSTHROUGH_IO_IN(vga,port,dest,len);
2083 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
2090 static int graphics_controller_address_read(struct guest_info *core,
2096 struct vga_internal *vga = (struct vga_internal *) priv_data;
2098 PrintDebug("vga: graphics controller address read data=0x%x\n",
2099 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
2101 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
2103 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
2105 PASSTHROUGH_IO_IN(vga,port,dest,len);
2107 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
2112 static int graphics_controller_data_write(struct guest_info *core,
2118 struct vga_internal *vga = (struct vga_internal *) priv_data;
2122 data=*((uint8_t*)src);
2123 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2126 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
2129 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
2131 PASSTHROUGH_IO_OUT(vga,port,src,len);
2133 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2134 PrintError("vga: graphics controller write for illegal index %d ignored\n",index);
2136 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
2144 static int graphics_controller_address_write(struct guest_info *core,
2150 struct vga_internal *vga = (struct vga_internal *) priv_data;
2153 new_addr=*((uint8_t*)src);
2155 PrintDebug("vga: graphics controller address write data=0x%x len=%u\n",
2156 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
2158 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
2160 PASSTHROUGH_IO_OUT(vga,port,src,len);
2162 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
2165 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
2166 // second byte is the data
2167 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
2168 PrintError("vga: write of data failed\n");
2176 static int graphics_controller_data_read(struct guest_info *core,
2182 struct vga_internal *vga = (struct vga_internal *) priv_data;
2186 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
2189 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
2191 PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index);
2193 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
2196 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
2199 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
2201 *((uint8_t*)dest) = data;
2203 PASSTHROUGH_IO_IN(vga,port,dest,len);
2205 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2213 /* Note that these guys have a bizarre protocol*/
2215 static int attribute_controller_address_read(struct guest_info *core,
2221 struct vga_internal *vga = (struct vga_internal *) priv_data;
2223 PrintDebug("vga: attribute controller address read data=0x%x\n",
2224 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
2226 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
2228 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
2230 PASSTHROUGH_IO_IN(vga,port,dest,len);
2232 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
2234 // Reading the attribute controller does not change the state
2239 static int attribute_controller_address_and_data_write(struct guest_info *core,
2245 struct vga_internal *vga = (struct vga_internal *) priv_data;
2248 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
2249 uint8_t new_addr = *((uint8_t*)src);
2250 // We are to treat this as an address write, and flip state
2251 // to expect data ON THIS SAME PORT
2252 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
2254 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
2256 PASSTHROUGH_IO_OUT(vga,port,src,len);
2258 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
2260 vga->vga_attribute_controller.state=ATTR_DATA;
2263 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
2265 uint8_t data = *((uint8_t*)src);
2266 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2268 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
2270 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
2272 PASSTHROUGH_IO_OUT(vga,port,src,len);
2274 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2275 PrintError("vga: attribute controller write to illegal index %d ignored\n",index);
2277 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
2280 vga->vga_attribute_controller.state=ATTR_ADDR;
2289 static int attribute_controller_data_read(struct guest_info *core,
2295 struct vga_internal *vga = (struct vga_internal *) priv_data;
2299 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
2301 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
2303 PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index);
2305 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
2308 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
2311 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
2313 *((uint8_t*)dest) = data;
2315 PASSTHROUGH_IO_IN(vga,port,dest,len);
2317 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2324 Note that these guys also have a strange protocol
2325 since they need to squeeze 18 bits of data through
2328 static int dac_write_address_read(struct guest_info *core,
2334 struct vga_internal *vga = (struct vga_internal *) priv_data;
2336 PrintDebug("vga: dac write address read data=0x%x\n",
2337 vga->vga_dac.vga_dac_write_addr);
2339 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
2342 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
2344 PASSTHROUGH_IO_IN(vga,port,dest,len);
2346 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
2348 // This read does not reset the state machine
2353 static int dac_write_address_write(struct guest_info *core,
2359 struct vga_internal *vga = (struct vga_internal *) priv_data;
2362 new_addr=*((uint8_t*)src);
2364 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
2366 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
2368 PASSTHROUGH_IO_OUT(vga,port,src,len);
2370 // cannot be out of bounds since there are 256 regs
2372 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
2374 // Now we also need to reset the state machine
2376 vga->vga_dac.state=DAC_WRITE;
2377 vga->vga_dac.channel=RED;
2383 static int dac_read_address_read(struct guest_info *core,
2389 struct vga_internal *vga = (struct vga_internal *) priv_data;
2391 PrintDebug("vga: dac read address read data=0x%x\n",
2392 vga->vga_dac.vga_dac_read_addr);
2394 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
2396 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
2398 PASSTHROUGH_IO_IN(vga,port,dest,len);
2400 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
2402 // This read does not reset the state machine
2407 static int dac_read_address_write(struct guest_info *core,
2413 struct vga_internal *vga = (struct vga_internal *) priv_data;
2416 new_addr=*((uint8_t*)src);
2418 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
2420 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
2422 PASSTHROUGH_IO_OUT(vga,port,src,len);
2424 // cannot be out of bounds since there are 256 regs
2426 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
2428 // Now we also need to reset the state machine
2430 vga->vga_dac.state=DAC_READ;
2431 vga->vga_dac.channel=RED;
2437 static int dac_data_read(struct guest_info *core,
2443 struct vga_internal *vga = (struct vga_internal *) priv_data;
2448 if (vga->vga_dac.state!=DAC_READ) {
2449 PrintError("vga: dac data read while in other state\n");
2450 // results undefined, so we continue
2453 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
2455 curreg = vga->vga_dac.vga_dac_read_addr;
2456 curchannel = vga->vga_dac.channel;
2457 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
2459 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
2461 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2462 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2465 *((uint8_t*)dest) = data;
2467 PASSTHROUGH_IO_IN(vga,port,dest,len);
2469 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
2471 curchannel = (curchannel+1)%3;
2472 vga->vga_dac.channel=curchannel;
2473 if (curchannel==0) {
2474 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2476 vga->vga_dac.vga_dac_read_addr = curreg;
2477 vga->vga_dac.state=DAC_READ;
2484 static int dac_data_write(struct guest_info *core,
2490 struct vga_internal *vga = (struct vga_internal *) priv_data;
2494 vga_palette_reg data32;
2495 vga_palette_reg mask32;
2497 if (vga->vga_dac.state!=DAC_WRITE) {
2498 PrintError("vga: dac data write while in other state\n");
2499 // results undefined, so we continue
2502 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
2504 PASSTHROUGH_IO_OUT(vga,port,src,len);
2506 curreg = vga->vga_dac.vga_dac_write_addr;
2507 curchannel = vga->vga_dac.channel;
2508 data = *((uint8_t *)src);
2510 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
2512 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
2513 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
2516 data32 = data & 0x3f ;
2517 data32 <<= curchannel*8;
2518 mask32 = ~(0xff << (curchannel * 8));
2520 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
2521 vga->vga_dac.vga_dac_palette[curreg] |= data32;
2523 curchannel = (curchannel+1)%3;
2524 vga->vga_dac.channel=curchannel;
2525 if (curchannel==0) {
2526 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
2528 vga->vga_dac.vga_dac_write_addr = curreg;
2529 vga->vga_dac.state=DAC_WRITE;
2538 static int dac_pixel_mask_read(struct guest_info *core,
2544 struct vga_internal *vga = (struct vga_internal *) priv_data;
2546 PrintDebug("vga: dac pixel mask read data=0x%x\n",
2547 vga->vga_dac.vga_pixel_mask);
2549 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
2551 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
2553 PASSTHROUGH_IO_IN(vga,port,dest,len);
2555 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
2560 static int dac_pixel_mask_write(struct guest_info *core,
2566 struct vga_internal *vga = (struct vga_internal *) priv_data;
2569 new_data=*((uint8_t*)src);
2571 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
2573 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
2575 PASSTHROUGH_IO_OUT(vga,port,src,len);
2577 vga->vga_dac.vga_pixel_mask = new_data;
2582 static int init_vga(struct vga_internal *vga)
2584 // TODO: startup spec of register contents, if any
2585 PrintError("vga: init_vga is UNIMPLEMTED\n");
2589 static int free_vga(struct vga_internal *vga)
2593 struct vm_device *dev = vga->dev;
2595 // Framebuffer deletion is user's responsibility
2597 // if (vga->mem_store) {
2598 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
2599 // vga->mem_store=0;
2602 for (i=0;i<MAP_NUM;i++) {
2604 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
2609 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
2613 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
2614 // The following also covers VGA_INPUT_STAT0_READ
2615 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
2616 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2617 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
2618 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2619 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
2620 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
2622 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
2624 /* Sequencer registers */
2625 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
2626 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
2628 /* CRT controller registers */
2629 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
2630 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
2631 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
2632 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
2634 /* graphics controller registers */
2635 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
2636 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
2638 /* attribute controller registers */
2639 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
2640 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
2642 /* video DAC palette registers */
2643 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
2644 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
2645 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
2646 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
2649 if (vga->host_cons) {
2650 v3_graphics_console_close(vga->host_cons);
2658 static struct v3_device_ops dev_ops = {
2659 .free = (int (*)(void *))free_vga,
2663 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2664 struct vga_internal *vga;
2668 char * dev_id = v3_cfg_val(cfg, "ID");
2669 char * passthrough = v3_cfg_val(cfg, "passthrough");
2670 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
2672 PrintDebug("vga: init_device\n");
2674 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
2677 PrintError("vga: cannot allocate\n");
2681 memset(vga, 0, sizeof(struct vga_internal));
2683 if (passthrough && strcasecmp(passthrough,"enable")==0) {
2684 PrintDebug("vga: enabling passthrough\n");
2685 vga->passthrough=true;
2686 vga->skip_next_passthrough_out=false;
2690 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
2691 struct v3_frame_buffer_spec req;
2693 PrintDebug("vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
2695 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
2696 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
2698 req.height=VGA_MAXY;
2700 req.bytes_per_pixel=4;
2701 req.bits_per_channel=8;
2707 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
2709 if (!vga->host_cons) {
2710 PrintError("vga: unable to open host OS's graphics console\n");
2715 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
2716 PrintDebug("vga: warning: target spec differs from requested spec\n");
2717 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);
2718 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);
2723 if (!vga->passthrough && !vga->host_cons) {
2724 V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2728 // No memory store is allocated since we will use a full memory hook
2729 // The VGA maps can be read as well as written
2730 // Reads also affect writes, since they are how you fill the latches
2732 // Now allocate the maps
2733 for (i=0;i<MAP_NUM;i++) {
2734 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
2735 if (!(vga->map[i])) {
2736 PrintError("vga: cannot allocate maps\n");
2740 memset(vga->map[i],0,MAP_SIZE);
2743 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2746 PrintError("Could not attach device %s\n", dev_id);
2753 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2754 MEM_REGION_START, MEM_REGION_END,
2758 PrintError("vga: memory book failed\n");
2759 v3_remove_device(dev);
2765 /* Miscelaneous registers */
2766 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2767 // The following also covers VGA_INPUT_STAT0_READ
2768 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2769 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2770 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2771 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2772 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2773 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2775 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2777 /* Sequencer registers */
2778 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2779 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2781 /* CRT controller registers */
2782 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2783 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2784 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2785 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2787 /* graphics controller registers */
2788 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2789 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2791 /* attribute controller registers */
2792 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2793 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2795 /* video DAC palette registers */
2796 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2797 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2798 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2799 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2802 PrintError("vga: Error allocating VGA I/O ports\n");
2803 v3_remove_device(dev);
2809 PrintDebug("vga: successfully added and initialized.\n");
2815 device_register("VGA", vga_init);