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 #define MEM_REGION_START 0xa0000
30 #define MEM_REGION_END 0xc0000
31 #define MEM_REGION_NUM_PAGES (((MEM_REGION_END)-(MEM_REGION_START))/4096)
33 #define MAP_SIZE 65536
36 #define UPDATES_PER_RENDER 100
38 typedef uint8_t *vga_map; // points to MAP_SIZE data
44 #define VGA_MISC_OUT_READ 0x3cc
45 #define VGA_MISC_OUT_WRITE 0x3c2
47 #define VGA_INPUT_STAT0_READ 0x3c2
49 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
50 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
52 #define VGA_FEATURE_CONTROL_READ 0x3ca
53 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
54 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
56 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
58 #define VGA_SEQUENCER_ADDRESS 0x3c4
59 #define VGA_SEQUENCER_DATA 0x3c5
60 #define VGA_SEQUENCER_NUM 5
63 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
64 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
65 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
66 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
67 #define VGA_CRT_CONTROLLER_NUM 25
70 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
71 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
72 #define VGA_GRAPHICS_CONTROLLER_NUM 9
74 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
75 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
76 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
78 #define VGA_DAC_WRITE_ADDR 0x3c8
79 #define VGA_DAC_READ_ADDR 0x3c7
80 #define VGA_DAC_DATA 0x3c9
81 #define VGA_DAC_PIXEL_MASK 0x3c6
83 #define VGA_DAC_NUM_ENTRIES 256
85 struct vga_misc_regs {
86 /* Read: 0x3cc; Write: 0x3c2 */
87 struct vga_misc_out_reg vga_misc_out;
89 struct vga_input_stat0_reg vga_input_stat0;
90 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
91 struct vga_input_stat1_reg vga_input_stat1;
92 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
93 struct vga_feature_control_reg vga_feature_control;
94 /* Read: 0x3c3; Write: 0x3c3 */
95 struct vga_video_subsys_enable_reg vga_video_subsys_enable;
96 } __attribute__((packed));
98 struct vga_sequencer_regs {
99 /* Address register is 0x3c4, data register is 0x3c5 */
101 struct vga_sequencer_addr_reg vga_sequencer_addr;
103 /* these can be accessed via the index, offset on start
104 or via the specific regs. For this reason, it is essential
105 that this is all packed and that the order does not change */
107 uint8_t vga_sequencer_regs[0];
110 struct vga_reset_reg vga_reset;
112 struct vga_clocking_mode_reg vga_clocking_mode;
114 struct vga_map_mask_reg vga_map_mask;
116 struct vga_char_map_select_reg vga_char_map_select;
118 struct vga_mem_mode_reg vga_mem_mode;
119 } __attribute__((packed));
121 struct vga_crt_controller_regs {
122 /* Address Register is 0x3b4 or 0x3d4 */
123 /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
124 struct vga_crt_addr_reg vga_crt_addr;
126 /* these can be accessed via the index, offset on start
127 or via the specific regs. For this reason, it is essential
128 that this is all packed and that the order does not change */
130 uint8_t vga_crt_controller_regs[0];
133 vga_horizontal_total_reg vga_horizontal_total;
135 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
137 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
139 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
141 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
143 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
145 vga_vertical_total_reg vga_vertical_total;
147 struct vga_overflow_reg vga_overflow;
149 struct vga_preset_row_scan_reg vga_preset_row_scan;
151 struct vga_max_row_scan_reg vga_row_scan;
153 struct vga_cursor_start_reg vga_cursor_start;
155 struct vga_cursor_end_reg vga_cursor_end;
157 vga_start_address_high_reg vga_start_address_high;
159 vga_start_address_low_reg vga_start_address_low;
161 vga_cursor_location_high_reg vga_cursor_location_high;
163 vga_cursor_location_low_reg vga_cursor_location_low;
165 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
167 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
169 vga_vertical_display_enable_end_reg vga_vertical_display_enable;
171 vga_offset_reg vga_offset;
173 struct vga_underline_location_reg vga_underline_location;
175 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
177 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
179 struct vga_crt_mode_control_reg vga_crt_mode_control;
181 vga_line_compare_reg vga_line_compare;
182 } __attribute__((packed));
184 struct vga_graphics_controller_regs {
185 /* Address: 0x3ce Data: 0x3cf */
188 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
190 /* these can be accessed via the index, offset on start
191 or via the specific regs. For this reason, it is essential
192 that this is all packed and that the order does not change */
194 uint8_t vga_graphics_controller_regs[0];
197 struct vga_set_reset_reg vga_set_reset;
199 struct vga_enable_set_reset_reg vga_enable_set_reset;
201 struct vga_color_compare_reg vga_color_compare;
203 struct vga_data_rotate_reg vga_data_rotate;
205 struct vga_read_map_select_reg vga_read_map_select;
207 struct vga_graphics_mode_reg vga_graphics_mode;
209 struct vga_misc_reg vga_misc;
211 struct vga_color_dont_care_reg vga_color_dont_care;
213 vga_bit_mask_reg vga_bit_mask;
214 } __attribute__((packed));
217 struct vga_attribute_contoller_regs {
219 Address AND WRITE: 0x3c0
222 The write protocol is to write the index to 0x3c0 followed by
223 the data. The read protocol is to write the index to 0x3c0
224 and then read from 0x3c1
226 IMPORTANT: write address, write data flips state back to write address
227 write address, read data DOES NOT
229 To reset to write address state, read input status register 1
231 enum { ATTR_ADDR, ATTR_DATA } state; //state of the flip flop
234 struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
238 /* these can be accessed via the index, offset on start
239 or via the specific regs. For this reason, it is essential
240 that this is all packed and that the order does not change */
242 uint8_t vga_attribute_controller_regs[0];
245 vga_internal_palette_regs vga_internal_palette;
247 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
249 vga_overscan_color_reg vga_overscan_color;
251 struct vga_color_plane_enable_reg vga_color_plane_enable;
253 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
255 struct vga_color_select_reg vga_color_select;
256 } __attribute__((packed));
258 struct vga_dac_regs {
259 enum {DAC_READ=0, DAC_WRITE} state;
260 enum {RED=0,GREEN,BLUE} channel;
261 vga_dac_pixel_mask_reg vga_pixel_mask;
262 vga_dac_write_addr_reg vga_dac_write_addr;
263 vga_dac_read_addr_reg vga_dac_read_addr;
264 // the dac_data register is used only to access the registers
265 // and thus has no representation here
266 vga_palette_reg vga_dac_palette[VGA_DAC_NUM_ENTRIES];
267 } __attribute__((packed));
270 struct vga_internal {
271 struct vm_device *dev;
274 bool skip_next_passthrough_out; // for word access
276 struct v3_frame_buffer_spec target_spec;
277 v3_graphics_console_t host_cons;
279 uint32_t updates_since_render;
281 struct frame_buf *framebuf; // we render to this
283 // void *mem_store; // This is the region where the memory hooks will go
285 vga_map map[MAP_NUM]; // the maps that the host writes to
287 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
289 /* Range of I/O ports here for backward compat with MDA and CGA */
290 struct vga_misc_regs vga_misc;
292 /* Address Register is 0x3b4 or 0x3d4 */
293 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
294 struct vga_crt_controller_regs vga_crt_controller;
296 /* Address register is 0x3c4, data register is 0x3c5 */
297 struct vga_sequencer_regs vga_sequencer;
299 /* Address: 0x3ce Data: 0x3cf */
300 struct vga_graphics_controller_regs vga_graphics_controller;
303 Address AND WRITE: 0x3c0
307 struct vga_attribute_contoller_regs vga_attribute_controller;
310 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
311 address for writes: 0x3c8 ("")
313 pixel mask: 0x3c6 - do not write (init to 0xff)
315 struct vga_dac_regs vga_dac;
320 static int render(struct vga_internal *vga)
322 vga->updates_since_render++;
324 if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) {
325 // Draw some crap for testing for now
328 struct v3_frame_buffer_spec *s;
330 fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
332 s=&(vga->target_spec);
334 if (0 && fb && s->height>=480 && s->width>=640 ) {
335 uint8_t color = (uint8_t)(vga->updates_since_render);
339 for (y=0;y<480;y++) {
340 for (x=0;x<640;x++) {
341 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
342 uint8_t *red = pixel + s->red_offset;
343 uint8_t *green = pixel + s->green_offset;
344 uint8_t *blue = pixel + s->blue_offset;
350 } else if (y<(480/2)) {
354 } else if (y<(3*(480/4))) {
359 *red=*green=*blue=color+x;
365 if (1 && fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) {
366 // we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
373 for (y=480+32;y<768;y++) {
374 for (x=m*256;x<(m+1)*256;x++,b++) {
375 void *pixel = fb + ((x + (y*s->width)) * s->bytes_per_pixel);
376 uint8_t *red = pixel + s->red_offset;
377 uint8_t *green = pixel + s->green_offset;
378 uint8_t *blue = pixel + s->blue_offset;
380 *red=*green=*blue=*b;
385 v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
392 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
394 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
414 static uint64_t find_offset(struct vga_internal *vga, addr_t guest_addr)
416 uint64_t mem_start, mem_end;
420 get_mem_region(vga, &mem_start, &mem_end);
422 return (guest_addr-mem_start) % (mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
429 static int vga_write(struct guest_info * core,
435 struct vm_device *dev = (struct vm_device *)priv_data;
436 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
438 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
440 if (vga->passthrough) {
441 PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
442 memcpy(V3_VAddr((void*)guest_addr),src,length);
447 PrintDebug("vga: data written was 0x");
448 for (i=0;i<length;i++) {
449 uint8_t c= ((char*)src)[i];
450 PrintDebug("%.2x", c);
453 for (i=0;i<length;i++) {
454 char c= ((char*)src)[i];
455 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
460 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
462 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
466 00b -- Write Mode 0: In this mode, the host data is first rotated
467 as per the Rotate Count field, then the Enable Set/Reset mechanism
468 selects data from this or the Set/Reset field. Then the selected
469 Logical Operation is performed on the resulting data and the data
470 in the latch register. Then the Bit Mask field is used to select
471 which bits come from the resulting data and which come
472 from the latch register. Finally, only the bit planes enabled by
473 the Memory Plane Write Enable field are written to memory.
481 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
482 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
484 offset = find_offset(vga, guest_addr);
486 PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
488 for (i=0;i<length;i++,offset++) {
490 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
491 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
492 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
493 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
495 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
496 vga_map map = vga->map[mapnum];
497 uint8_t data = ((uint8_t *)src)[i];
498 uint8_t latchval = vga->latch[mapnum];
501 data = (data>>ror) | data<<(8-ror);
503 // use SR bit if ESR is on for this map
505 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
523 // mux between latch and alu output
525 // use alu output, which is in data
534 //PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
548 01b -- Write Mode 1: In this mode, data is transferred directly
549 from the 32 bit latch register to display memory, affected only by
550 the Memory Plane Write Enable field. The host data is not used in this mode.
555 uint64_t offset = find_offset(vga,guest_addr);
557 PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
559 for (i=0;i<length;i++,offset++) {
562 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
564 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
565 vga_map map = vga->map[mapnum];
566 uint8_t latchval = vga->latch[mapnum];
571 map[offset] = latchval;
582 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
583 are replicated across all 8 bits of their respective planes.
584 Then the selected Logical Operation is performed on the resulting
585 data and the data in the latch register. Then the Bit Mask field is used to
586 select which bits come from the resulting data and which come from
587 the latch register. Finally, only the bit planes enabled by the
588 Memory Plane Write Enable field are written to memory.
594 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
596 offset = find_offset(vga, guest_addr);
598 PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
600 for (i=0;i<length;i++,offset++) {
602 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
603 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
605 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
606 vga_map map = vga->map[mapnum];
607 uint8_t data = ((uint8_t *)src)[i];
608 uint8_t latchval = vga->latch[mapnum];
610 // expand relevant bit to 8 bit
611 // it's basically esr=1, sr=bit from write
612 data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7);
629 // mux between latch and alu output
631 // use alu output, which is in data
650 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
651 as if the Enable Set/Reset field were set to 1111b. Then the host data is
652 first rotated as per the Rotate Count field, then logical ANDed with the
653 value of the Bit Mask field. The resulting value is used on the data
654 obtained from the Set/Reset field in the same way that the Bit Mask field
655 would ordinarily be used. to select which bits come from the expansion
656 of the Set/Reset field and which come from the latch register. Finally,
657 only the bit planes enabled by the Memory Plane Write Enable field
658 are written to memory.
665 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
667 offset = find_offset(vga, guest_addr);
669 PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
671 for (i=0;i<length;i++,offset++) {
673 uint8_t data = ((uint8_t *)src)[i];
675 data = (data>>ror) | data<<(8-ror);
677 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
678 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
679 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
681 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
682 vga_map map = vga->map[mapnum];
683 uint8_t latchval = vga->latch[mapnum];
685 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
688 // mux between latch and alu output
690 // use alu output, which is in data
709 // There is no default
719 up to 256K mapped through a window of 32 to 128K
721 most cards support linear mode as well
723 Need to implement readability too
725 Write extended memory bit to enable all 256K:
727 Sequencer Memory Mode Register (Index 04h) . extended memory
729 Must enable writes before effects happen:
731 Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
733 Choose which addresses are supported for CPU writes:
735 Miscellaneous Graphics Register (Index 06h).memory map select
737 00b -- A0000h-BFFFFh (128K region)
738 01b -- A0000h-AFFFFh (64K region)
739 10b -- B0000h-B7FFFh (32K region)
740 11b -- B8000h-BFFFFh (32K region)
742 There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
744 Chain 4: This mode is used for MCGA emulation in the 320x200 256-color mode. The address is mapped to memory MOD 4 (shifted right 2 places.)
746 Memory model: 64K 32 bit locations; divided into 4 64K bit planes
752 Assume linear framebuffer, starting at address buf:
758 static int vga_read(struct guest_info * core,
764 struct vm_device *dev = (struct vm_device *)priv_data;
765 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
768 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
774 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
776 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
778 /* 0 - a byte from ONE of the 4 planes is returned;
779 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
783 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
784 offset = find_offset(vga,guest_addr);
787 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
790 memcpy(dst,(vga->map[mapnum])+offset,length);
792 // load the latches with the last item read
793 for (mapnum=0;mapnum<4;mapnum++) {
794 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
801 /* 1 - Compare video memory and reference color
802 (in Color Compare, except those not set in Color Don't Care),
803 each bit in returned result is one comparison between the reference color
805 Ref color is *4* bits, and thus a one byte read returns a comparison
811 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
812 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
819 offset = find_offset(vga,guest_addr);
821 for (i=0;i<length;i++,offset++) {
824 for (mapnum=0;mapnum<4;mapnum++) {
825 map = vga->map[mapnum];
826 if ( (dc>>mapnum)&0x1 ) { // don't care
830 bits = (map[offset]&0xf) == cc;
833 bits |= (((map[offset]>>4))&0xf) == cc;
835 // not clear whether it is 0..k or k..0
841 // load the latches with the last item read
842 for (mapnum=0;mapnum<4;mapnum++) {
843 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
848 // there is no default
851 if (vga->passthrough) {
852 PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
853 memcpy(dst,V3_VAddr((void*)guest_addr),length);
859 PrintDebug("vga: data read is 0x");
860 for (i=0;i<length;i++) {
861 uint8_t c= ((char*)dst)[i];
862 PrintDebug("%.2x", c);
865 for (i=0;i<length;i++) {
866 char c= ((char*)dst)[i];
867 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || (c==' ') ? c : '.');
880 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
881 if (((len)<(min)) || ((len)>(max))) { \
882 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
886 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
889 *(uint8_t *)dest = v3_inb(port);
892 *(uint16_t *)dest = v3_inw(port);
895 *(uint32_t *)dest = v3_indw(port);
898 PrintError("vga: unsupported passthrough io in size %u\n",length);
904 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
907 v3_outb(port, *(uint8_t *)src);
910 v3_outw(port, *(uint16_t *)src);
913 v3_outdw(port, *(uint32_t *)src);
916 PrintError("vga: unsupported passthrough io out size %u\n",length);
921 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
922 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
924 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
925 do { if ((vga)->passthrough && (!(vga)->skip_next_passthrough_out)) { passthrough_io_out(port,src,len); } (vga)->skip_next_passthrough_out=false; } while (0)
927 #define PASSTHROUGH_IO_SKIP_NEXT_OUT(vga) \
928 do { if ((vga)->passthrough) { (vga)->skip_next_passthrough_out=true; } } while (0)
930 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
931 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)
933 static int misc_out_read(struct guest_info *core,
939 struct vga_internal *vga = (struct vga_internal *) priv_data;
941 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
943 ERR_WRONG_SIZE("read","misc out",len,1,1);
945 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
947 PASSTHROUGH_IO_IN(vga,port,dest,len);
949 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
954 static int misc_out_write(struct guest_info *core,
960 struct vga_internal *vga = (struct vga_internal *) priv_data;
962 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
964 ERR_WRONG_SIZE("write","misc out",len,1,1);
966 PASSTHROUGH_IO_OUT(vga,port,src,len);
968 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
977 static int input_stat0_read(struct guest_info *core,
983 struct vga_internal *vga = (struct vga_internal *) priv_data;
985 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
987 ERR_WRONG_SIZE("read","input stat0",len,1,1);
989 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
991 PASSTHROUGH_IO_IN(vga,port,dest,len);
993 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
999 static int input_stat1_read(struct guest_info *core,
1005 struct vga_internal *vga = (struct vga_internal *) priv_data;
1007 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
1008 port==0x3ba ? "mono" : "color",
1009 vga->vga_misc.vga_input_stat1.val);
1011 ERR_WRONG_SIZE("read","input stat1",len,1,1);
1014 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
1016 // Stunningly, reading stat1 is also a way to reset
1017 // the state of attribute controller address/data flipflop
1018 // That is some mighty fine crack the designers were smoking.
1020 vga->vga_attribute_controller.state=ATTR_ADDR;
1022 PASSTHROUGH_IO_IN(vga,port,dest,len);
1024 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
1030 static int feature_control_read(struct guest_info *core,
1036 struct vga_internal *vga = (struct vga_internal *) priv_data;
1038 PrintDebug("vga: feature control read data=0x%x\n",
1039 vga->vga_misc.vga_feature_control.val);
1041 ERR_WRONG_SIZE("read","feature control",len,1,1);
1044 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
1046 PASSTHROUGH_IO_IN(vga,port,dest,len);
1048 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
1053 static int feature_control_write(struct guest_info *core,
1059 struct vga_internal *vga = (struct vga_internal *) priv_data;
1061 PrintDebug("vga: feature control (%s) write data=0x%x\n",
1062 port==0x3ba ? "mono" : "color",
1065 ERR_WRONG_SIZE("write","feature control",len,1,1);
1067 PASSTHROUGH_IO_OUT(vga,port,src,len);
1069 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1077 static int video_subsys_enable_read(struct guest_info *core,
1083 struct vga_internal *vga = (struct vga_internal *) priv_data;
1085 PrintDebug("vga: video subsys enable read data=0x%x\n",
1086 vga->vga_misc.vga_video_subsys_enable.val);
1088 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1090 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1092 PASSTHROUGH_IO_IN(vga,port,dest,len);
1094 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1099 static int video_subsys_enable_write(struct guest_info *core,
1105 struct vga_internal *vga = (struct vga_internal *) priv_data;
1107 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1109 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1111 PASSTHROUGH_IO_OUT(vga,port,src,len);
1113 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1120 static int sequencer_address_read(struct guest_info *core,
1126 struct vga_internal *vga = (struct vga_internal *) priv_data;
1128 PrintDebug("vga: sequencer address read data=0x%x\n",
1129 vga->vga_sequencer.vga_sequencer_addr.val);
1131 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1133 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1135 PASSTHROUGH_IO_IN(vga,port,dest,len);
1137 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1142 static int sequencer_data_write(struct guest_info *core,
1148 struct vga_internal *vga = (struct vga_internal *) priv_data;
1152 data=*((uint8_t*)src);
1153 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1155 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1158 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1160 PASSTHROUGH_IO_OUT(vga,port,src,len);
1163 if (index>=VGA_SEQUENCER_NUM) {
1164 PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index);
1166 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1174 static int sequencer_address_write(struct guest_info *core,
1180 struct vga_internal *vga = (struct vga_internal *) priv_data;
1183 new_addr=*((uint8_t*)src);
1185 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);
1187 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1189 PASSTHROUGH_IO_OUT(vga,port,src,len);
1191 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
1194 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1195 // second byte is the data
1196 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
1197 PrintError("vga: write of data failed\n");
1205 static int sequencer_data_read(struct guest_info *core,
1211 struct vga_internal *vga = (struct vga_internal *) priv_data;
1215 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1217 if (index>=VGA_SEQUENCER_NUM) {
1219 PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index);
1221 data=vga->vga_sequencer.vga_sequencer_regs[index];
1224 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
1227 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
1229 *((uint8_t*)dest) = data;
1231 PASSTHROUGH_IO_IN(vga,port,dest,len);
1233 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1242 static int crt_controller_address_read(struct guest_info *core,
1248 struct vga_internal *vga = (struct vga_internal *) priv_data;
1250 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
1251 port==0x3b4 ? "mono" : "color",
1252 vga->vga_crt_controller.vga_crt_addr.val);
1254 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
1256 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
1258 PASSTHROUGH_IO_IN(vga,port,dest,len);
1260 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
1265 static int crt_controller_data_write(struct guest_info *core,
1271 struct vga_internal *vga = (struct vga_internal *) priv_data;
1275 data=*((uint8_t*)src);
1277 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1279 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
1280 port==0x3b5 ? "mono" : "color",
1283 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
1285 PASSTHROUGH_IO_OUT(vga,port,src,len);
1287 if (index>=VGA_CRT_CONTROLLER_NUM) {
1288 PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index);
1290 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
1298 static int crt_controller_address_write(struct guest_info *core,
1304 struct vga_internal *vga = (struct vga_internal *) priv_data;
1307 new_addr=*((uint8_t*)src);
1309 PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n",
1310 port==0x3b4 ? "mono" : "color",
1311 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1313 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
1315 PASSTHROUGH_IO_OUT(vga,port,src,len);
1317 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
1320 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1321 // second byte is the data
1322 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
1323 PrintError("vga: write of data failed\n");
1331 static int crt_controller_data_read(struct guest_info *core,
1337 struct vga_internal *vga = (struct vga_internal *) priv_data;
1341 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1343 if (index>=VGA_CRT_CONTROLLER_NUM) {
1345 PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index);
1347 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
1350 PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data);
1352 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
1354 *((uint8_t*)dest) = data;
1356 PASSTHROUGH_IO_IN(vga,port,dest,len);
1358 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
1365 static int graphics_controller_address_read(struct guest_info *core,
1371 struct vga_internal *vga = (struct vga_internal *) priv_data;
1373 PrintDebug("vga: graphics controller address read data=0x%x\n",
1374 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
1376 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
1378 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
1380 PASSTHROUGH_IO_IN(vga,port,dest,len);
1382 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
1387 static int graphics_controller_data_write(struct guest_info *core,
1393 struct vga_internal *vga = (struct vga_internal *) priv_data;
1397 data=*((uint8_t*)src);
1398 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1401 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
1404 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
1406 PASSTHROUGH_IO_OUT(vga,port,src,len);
1408 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
1409 PrintError("vga: graphics controller write for illegal index %d ignored\n",index);
1411 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
1419 static int graphics_controller_address_write(struct guest_info *core,
1425 struct vga_internal *vga = (struct vga_internal *) priv_data;
1428 new_addr=*((uint8_t*)src);
1430 PrintDebug("vga: graphics controller address write data=0x%x len=%u\n",
1431 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1433 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
1435 PASSTHROUGH_IO_OUT(vga,port,src,len);
1437 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
1440 PASSTHROUGH_IO_SKIP_NEXT_OUT(vga);
1441 // second byte is the data
1442 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
1443 PrintError("vga: write of data failed\n");
1451 static int graphics_controller_data_read(struct guest_info *core,
1457 struct vga_internal *vga = (struct vga_internal *) priv_data;
1461 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1464 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
1466 PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index);
1468 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
1471 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
1474 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
1476 *((uint8_t*)dest) = data;
1478 PASSTHROUGH_IO_IN(vga,port,dest,len);
1480 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1488 /* Note that these guys have a bizarre protocol*/
1490 static int attribute_controller_address_read(struct guest_info *core,
1496 struct vga_internal *vga = (struct vga_internal *) priv_data;
1498 PrintDebug("vga: attribute controller address read data=0x%x\n",
1499 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
1501 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
1503 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
1505 PASSTHROUGH_IO_IN(vga,port,dest,len);
1507 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
1509 // Reading the attribute controller does not change the state
1514 static int attribute_controller_address_and_data_write(struct guest_info *core,
1520 struct vga_internal *vga = (struct vga_internal *) priv_data;
1523 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
1524 uint8_t new_addr = *((uint8_t*)src);
1525 // We are to treat this as an address write, and flip state
1526 // to expect data ON THIS SAME PORT
1527 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
1529 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
1531 PASSTHROUGH_IO_OUT(vga,port,src,len);
1533 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
1535 vga->vga_attribute_controller.state=ATTR_DATA;
1538 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
1540 uint8_t data = *((uint8_t*)src);
1541 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1543 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
1545 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
1547 PASSTHROUGH_IO_OUT(vga,port,src,len);
1549 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
1550 PrintError("vga: attribute controller write to illegal index %d ignored\n",index);
1552 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
1555 vga->vga_attribute_controller.state=ATTR_ADDR;
1564 static int attribute_controller_data_read(struct guest_info *core,
1570 struct vga_internal *vga = (struct vga_internal *) priv_data;
1574 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1576 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
1578 PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index);
1580 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
1583 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
1586 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
1588 *((uint8_t*)dest) = data;
1590 PASSTHROUGH_IO_IN(vga,port,dest,len);
1592 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1599 Note that these guys also have a strange protocol
1600 since they need to squeeze 18 bits of data through
1603 static int dac_write_address_read(struct guest_info *core,
1609 struct vga_internal *vga = (struct vga_internal *) priv_data;
1611 PrintDebug("vga: dac write address read data=0x%x\n",
1612 vga->vga_dac.vga_dac_write_addr);
1614 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
1617 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
1619 PASSTHROUGH_IO_IN(vga,port,dest,len);
1621 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
1623 // This read does not reset the state machine
1628 static int dac_write_address_write(struct guest_info *core,
1634 struct vga_internal *vga = (struct vga_internal *) priv_data;
1637 new_addr=*((uint8_t*)src);
1639 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
1641 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
1643 PASSTHROUGH_IO_OUT(vga,port,src,len);
1645 // cannot be out of bounds since there are 256 regs
1647 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
1649 // Now we also need to reset the state machine
1651 vga->vga_dac.state=DAC_WRITE;
1652 vga->vga_dac.channel=RED;
1658 static int dac_read_address_read(struct guest_info *core,
1664 struct vga_internal *vga = (struct vga_internal *) priv_data;
1666 PrintDebug("vga: dac read address read data=0x%x\n",
1667 vga->vga_dac.vga_dac_read_addr);
1669 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
1671 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
1673 PASSTHROUGH_IO_IN(vga,port,dest,len);
1675 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
1677 // This read does not reset the state machine
1682 static int dac_read_address_write(struct guest_info *core,
1688 struct vga_internal *vga = (struct vga_internal *) priv_data;
1691 new_addr=*((uint8_t*)src);
1693 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
1695 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
1697 PASSTHROUGH_IO_OUT(vga,port,src,len);
1699 // cannot be out of bounds since there are 256 regs
1701 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
1703 // Now we also need to reset the state machine
1705 vga->vga_dac.state=DAC_READ;
1706 vga->vga_dac.channel=RED;
1712 static int dac_data_read(struct guest_info *core,
1718 struct vga_internal *vga = (struct vga_internal *) priv_data;
1723 if (vga->vga_dac.state!=DAC_READ) {
1724 PrintError("vga: dac data read while in other state\n");
1725 // results undefined, so we continue
1728 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
1730 curreg = vga->vga_dac.vga_dac_read_addr;
1731 curchannel = vga->vga_dac.channel;
1732 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
1734 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
1736 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1737 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1740 *((uint8_t*)dest) = data;
1742 PASSTHROUGH_IO_IN(vga,port,dest,len);
1744 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1746 curchannel = (curchannel+1)%3;
1747 vga->vga_dac.channel=curchannel;
1748 if (curchannel==0) {
1749 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1751 vga->vga_dac.vga_dac_read_addr = curreg;
1752 vga->vga_dac.state=DAC_READ;
1759 static int dac_data_write(struct guest_info *core,
1765 struct vga_internal *vga = (struct vga_internal *) priv_data;
1769 vga_palette_reg data32;
1770 vga_palette_reg mask32;
1772 if (vga->vga_dac.state!=DAC_WRITE) {
1773 PrintError("vga: dac data write while in other state\n");
1774 // results undefined, so we continue
1777 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
1779 PASSTHROUGH_IO_OUT(vga,port,src,len);
1781 curreg = vga->vga_dac.vga_dac_write_addr;
1782 curchannel = vga->vga_dac.channel;
1783 data = *((uint8_t *)src);
1785 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
1787 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1788 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1791 data32 = data & 0x3f ;
1792 data32 <<= curchannel*8;
1793 mask32 = ~(0xff << (curchannel * 8));
1795 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
1796 vga->vga_dac.vga_dac_palette[curreg] |= data32;
1798 curchannel = (curchannel+1)%3;
1799 vga->vga_dac.channel=curchannel;
1800 if (curchannel==0) {
1801 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1803 vga->vga_dac.vga_dac_write_addr = curreg;
1804 vga->vga_dac.state=DAC_WRITE;
1813 static int dac_pixel_mask_read(struct guest_info *core,
1819 struct vga_internal *vga = (struct vga_internal *) priv_data;
1821 PrintDebug("vga: dac pixel mask read data=0x%x\n",
1822 vga->vga_dac.vga_pixel_mask);
1824 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
1826 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
1828 PASSTHROUGH_IO_IN(vga,port,dest,len);
1830 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
1835 static int dac_pixel_mask_write(struct guest_info *core,
1841 struct vga_internal *vga = (struct vga_internal *) priv_data;
1844 new_data=*((uint8_t*)src);
1846 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
1848 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
1850 PASSTHROUGH_IO_OUT(vga,port,src,len);
1852 vga->vga_dac.vga_pixel_mask = new_data;
1857 static int init_vga(struct vga_internal *vga)
1859 // TODO: startup spec of register contents, if any
1860 PrintError("vga: init_vga is UNIMPLEMTED\n");
1864 static int free_vga(struct vga_internal *vga)
1868 struct vm_device *dev = vga->dev;
1870 // Framebuffer deletion is user's responsibility
1872 // if (vga->mem_store) {
1873 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
1874 // vga->mem_store=0;
1877 for (i=0;i<MAP_NUM;i++) {
1879 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
1884 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
1888 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
1889 // The following also covers VGA_INPUT_STAT0_READ
1890 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
1891 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1892 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
1893 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1894 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
1895 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
1897 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
1899 /* Sequencer registers */
1900 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
1901 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
1903 /* CRT controller registers */
1904 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
1905 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
1906 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
1907 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
1909 /* graphics controller registers */
1910 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
1911 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
1913 /* attribute controller registers */
1914 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
1915 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
1917 /* video DAC palette registers */
1918 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
1919 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
1920 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
1921 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
1924 if (vga->host_cons) {
1925 v3_graphics_console_close(vga->host_cons);
1933 static struct v3_device_ops dev_ops = {
1934 .free = (int (*)(void *))free_vga,
1938 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1939 struct vga_internal *vga;
1943 char * dev_id = v3_cfg_val(cfg, "ID");
1944 char * passthrough = v3_cfg_val(cfg, "passthrough");
1945 char * hostframebuf = v3_cfg_val(cfg, "hostframebuf");
1947 PrintDebug("vga: init_device\n");
1949 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
1952 PrintError("vga: cannot allocate\n");
1956 memset(vga, 0, sizeof(struct vga_internal));
1958 if (passthrough && strcasecmp(passthrough,"enable")==0) {
1959 PrintDebug("vga: enabling passthrough\n");
1960 vga->passthrough=true;
1961 vga->skip_next_passthrough_out=false;
1965 if (hostframebuf && strcasecmp(hostframebuf,"enable")==0) {
1966 struct v3_frame_buffer_spec req;
1968 PrintDebug("vga: enabling host frame buffer console (GRAPHICS_CONSOLE)\n");
1970 memset(&req,0,sizeof(struct v3_frame_buffer_spec));
1971 memset(&(vga->target_spec),0,sizeof(struct v3_frame_buffer_spec));
1973 req.height=VGA_MAXY;
1975 req.bytes_per_pixel=4;
1976 req.bits_per_channel=8;
1982 vga->host_cons = v3_graphics_console_open(vm,&req,&(vga->target_spec));
1984 if (!vga->host_cons) {
1985 PrintError("vga: unable to open host OS's graphics console\n");
1990 if (memcmp(&req,&(vga->target_spec),sizeof(req))) {
1991 PrintDebug("vga: warning: target spec differs from requested spec\n");
1992 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);
1993 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);
1998 if (!vga->passthrough && !vga->host_cons) {
1999 V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n");
2003 // No memory store is allocated since we will use a full memory hook
2004 // The VGA maps can be read as well as written
2005 // Reads also affect writes, since they are how you fill the latches
2007 // Now allocate the maps
2008 for (i=0;i<MAP_NUM;i++) {
2009 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
2010 if (!(vga->map[i])) {
2011 PrintError("vga: cannot allocate maps\n");
2015 memset(vga->map[i],0,MAP_SIZE);
2018 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
2021 PrintError("Could not attach device %s\n", dev_id);
2028 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
2029 MEM_REGION_START, MEM_REGION_END,
2033 PrintError("vga: memory book failed\n");
2034 v3_remove_device(dev);
2040 /* Miscelaneous registers */
2041 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
2042 // The following also covers VGA_INPUT_STAT0_READ
2043 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
2044 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
2045 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
2046 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
2047 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
2048 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
2050 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
2052 /* Sequencer registers */
2053 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
2054 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
2056 /* CRT controller registers */
2057 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
2058 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
2059 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
2060 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
2062 /* graphics controller registers */
2063 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
2064 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
2066 /* attribute controller registers */
2067 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
2068 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
2070 /* video DAC palette registers */
2071 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
2072 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
2073 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
2074 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
2077 PrintError("vga: Error allocating VGA I/O ports\n");
2078 v3_remove_device(dev);
2084 PrintDebug("vga: successfully added and initialized.\n");
2090 device_register("VGA", vga_init);