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>
28 #define MEM_REGION_START 0xa0000
29 #define MEM_REGION_END 0xc0000
30 #define MEM_REGION_NUM_PAGES (((MEM_REGION_END)-(MEM_REGION_START))/4096)
32 #define MAP_SIZE 65536
35 #define UPDATES_PER_RENDER 100
37 typedef uint8_t *vga_map; // points to MAP_SIZE data
44 uint32_t bitsperpixel;
53 struct fb *palacios_linux_fb_hack_pointer;
58 #define VGA_MISC_OUT_READ 0x3cc
59 #define VGA_MISC_OUT_WRITE 0x3c2
61 #define VGA_INPUT_STAT0_READ 0x3c2
63 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
64 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
66 #define VGA_FEATURE_CONTROL_READ 0x3ca
67 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
68 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
70 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
72 #define VGA_SEQUENCER_ADDRESS 0x3c4
73 #define VGA_SEQUENCER_DATA 0x3c5
74 #define VGA_SEQUENCER_NUM 5
77 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
78 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
79 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
80 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
81 #define VGA_CRT_CONTROLLER_NUM 25
84 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
85 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
86 #define VGA_GRAPHICS_CONTROLLER_NUM 9
88 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
89 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
90 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
92 #define VGA_DAC_WRITE_ADDR 0x3c8
93 #define VGA_DAC_READ_ADDR 0x3c7
94 #define VGA_DAC_DATA 0x3c9
95 #define VGA_DAC_PIXEL_MASK 0x3c6
97 #define VGA_DAC_NUM_ENTRIES 256
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_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;
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;
289 uint32_t updates_since_render;
291 struct frame_buf *framebuf; // we render to this
293 // void *mem_store; // This is the region where the memory hooks will go
295 vga_map map[MAP_NUM]; // the maps that the host writes to
297 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
299 /* Range of I/O ports here for backward compat with MDA and CGA */
300 struct vga_misc_regs vga_misc;
302 /* Address Register is 0x3b4 or 0x3d4 */
303 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
304 struct vga_crt_controller_regs vga_crt_controller;
306 /* Address register is 0x3c4, data register is 0x3c5 */
307 struct vga_sequencer_regs vga_sequencer;
309 /* Address: 0x3ce Data: 0x3cf */
310 struct vga_graphics_controller_regs vga_graphics_controller;
313 Address AND WRITE: 0x3c0
317 struct vga_attribute_contoller_regs vga_attribute_controller;
320 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
321 address for writes: 0x3c8 ("")
323 pixel mask: 0x3c6 - do not write (init to 0xff)
325 struct vga_dac_regs vga_dac;
330 static int render(struct vga_internal *vga)
332 vga->updates_since_render++;
334 if (vga->updates_since_render<UPDATES_PER_RENDER) {
338 // PrintError("vga: render UNIMPLEMENTED\n");
340 vga->updates_since_render=0;
342 if (!palacios_linux_fb_hack_pointer) {
353 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
355 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
375 static uint64_t find_offset(struct vga_internal *vga, addr_t guest_addr)
377 uint64_t mem_start, mem_end;
381 get_mem_region(vga, &mem_start, &mem_end);
383 return (guest_addr-mem_start) % (mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
390 static int vga_write(struct guest_info * core,
397 struct vm_device *dev = (struct vm_device *)priv_data;
398 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
400 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
402 if (vga->passthrough) {
403 PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
404 memcpy(V3_VAddr((void*)guest_addr),src,length);
407 PrintDebug("vga: data written was \"");
408 for (i=0;i<length;i++) {
409 char c= ((char*)src)[i];
410 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ? c : '.');
414 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
416 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
420 00b -- Write Mode 0: In this mode, the host data is first rotated
421 as per the Rotate Count field, then the Enable Set/Reset mechanism
422 selects data from this or the Set/Reset field. Then the selected
423 Logical Operation is performed on the resulting data and the data
424 in the latch register. Then the Bit Mask field is used to select
425 which bits come from the resulting data and which come
426 from the latch register. Finally, only the bit planes enabled by
427 the Memory Plane Write Enable field are written to memory.
435 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
436 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
438 offset = find_offset(vga, guest_addr);
440 PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
442 for (i=0;i<length;i++,offset++) {
444 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
445 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
446 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
447 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
449 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
450 vga_map map = vga->map[mapnum];
451 uint8_t data = ((uint8_t *)src)[i];
452 uint8_t latchval = vga->latch[mapnum];
455 data = (data>>ror) | data<<(8-ror);
457 // use SR bit if ESR is on for this map
459 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
477 // mux between latch and alu output
479 // use alu output, which is in data
488 //PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
502 01b -- Write Mode 1: In this mode, data is transferred directly
503 from the 32 bit latch register to display memory, affected only by
504 the Memory Plane Write Enable field. The host data is not used in this mode.
509 uint64_t offset = find_offset(vga,guest_addr);
511 PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
513 for (i=0;i<length;i++,offset++) {
516 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
518 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
519 vga_map map = vga->map[mapnum];
520 uint8_t latchval = vga->latch[mapnum];
525 map[offset] = latchval;
536 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
537 are replicated across all 8 bits of their respective planes.
538 Then the selected Logical Operation is performed on the resulting
539 data and the data in the latch register. Then the Bit Mask field is used to
540 select which bits come from the resulting data and which come from
541 the latch register. Finally, only the bit planes enabled by the
542 Memory Plane Write Enable field are written to memory.
548 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
550 offset = find_offset(vga, guest_addr);
552 PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
554 for (i=0;i<length;i++,offset++) {
556 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
557 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
559 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
560 vga_map map = vga->map[mapnum];
561 uint8_t data = ((uint8_t *)src)[i];
562 uint8_t latchval = vga->latch[mapnum];
564 // expand relevant bit to 8 bit
565 // it's basically esr=1, sr=bit from write
566 data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7);
583 // mux between latch and alu output
585 // use alu output, which is in data
604 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
605 as if the Enable Set/Reset field were set to 1111b. Then the host data is
606 first rotated as per the Rotate Count field, then logical ANDed with the
607 value of the Bit Mask field. The resulting value is used on the data
608 obtained from the Set/Reset field in the same way that the Bit Mask field
609 would ordinarily be used. to select which bits come from the expansion
610 of the Set/Reset field and which come from the latch register. Finally,
611 only the bit planes enabled by the Memory Plane Write Enable field
612 are written to memory.
619 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
621 offset = find_offset(vga, guest_addr);
623 PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
625 for (i=0;i<length;i++,offset++) {
627 uint8_t data = ((uint8_t *)src)[i];
629 data = (data>>ror) | data<<(8-ror);
631 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
632 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
633 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
635 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
636 vga_map map = vga->map[mapnum];
637 uint8_t latchval = vga->latch[mapnum];
639 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
642 // mux between latch and alu output
644 // use alu output, which is in data
663 // There is no default
673 up to 256K mapped through a window of 32 to 128K
675 most cards support linear mode as well
677 Need to implement readability too
679 Write extended memory bit to enable all 256K:
681 Sequencer Memory Mode Register (Index 04h) . extended memory
683 Must enable writes before effects happen:
685 Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
687 Choose which addresses are supported for CPU writes:
689 Miscellaneous Graphics Register (Index 06h).memory map select
691 00b -- A0000h-BFFFFh (128K region)
692 01b -- A0000h-AFFFFh (64K region)
693 10b -- B0000h-B7FFFh (32K region)
694 11b -- B8000h-BFFFFh (32K region)
696 There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
698 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.)
700 Memory model: 64K 32 bit locations; divided into 4 64K bit planes
706 Assume linear framebuffer, starting at address buf:
712 static int vga_read(struct guest_info * core,
719 struct vm_device *dev = (struct vm_device *)priv_data;
720 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
723 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
729 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
731 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
733 /* 0 - a byte from ONE of the 4 planes is returned;
734 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
738 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
739 offset = find_offset(vga,guest_addr);
742 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
745 memcpy(dst,(vga->map[mapnum])+offset,length);
747 // load the latches with the last item read
748 for (mapnum=0;mapnum<4;mapnum++) {
749 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
756 /* 1 - Compare video memory and reference color
757 (in Color Compare, except those not set in Color Don't Care),
758 each bit in returned result is one comparison between the reference color
760 Ref color is *4* bits, and thus a one byte read returns a comparison
766 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
767 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
774 offset = find_offset(vga,guest_addr);
776 for (i=0;i<length;i++,offset++) {
779 for (mapnum=0;mapnum<4;mapnum++) {
780 map = vga->map[mapnum];
781 if ( (dc>>mapnum)&0x1 ) { // don't care
785 bits = (map[offset]&0xf) == cc;
788 bits |= (((map[offset]>>4))&0xf) == cc;
790 // not clear whether it is 0..k or k..0
796 // load the latches with the last item read
797 for (mapnum=0;mapnum<4;mapnum++) {
798 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
803 // there is no default
806 if (vga->passthrough) {
807 PrintDebug("vga: passthrough read from 0x%p\n",V3_VAddr((void*)guest_addr));
808 memcpy(dst,V3_VAddr((void*)guest_addr),length);
812 PrintDebug("vga: data read is \"");
813 for (i=0;i<length;i++) {
814 char c= ((char*)dst)[i];
815 PrintDebug("%c", (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') ? c : '.');
827 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
828 if (((len)<(min)) || ((len)>(max))) { \
829 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
833 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
836 *(uint8_t *)dest = v3_inb(port);
839 *(uint16_t *)dest = v3_inw(port);
842 *(uint32_t *)dest = v3_indw(port);
845 PrintError("vga: unsupported passthrough io in size %u\n",length);
851 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
854 v3_outb(port, *(uint8_t *)src);
857 v3_outw(port, *(uint16_t *)src);
860 v3_outdw(port, *(uint32_t *)src);
863 PrintError("vga: unsupported passthrough io out size %u\n",length);
868 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
869 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
871 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
872 do { if ((vga)->passthrough) { passthrough_io_out(port,src,len); } } while (0)
874 #define PASSTHROUGH_READ_CHECK(vga,inter,pass) \
875 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)
877 static int misc_out_read(struct guest_info *core,
883 struct vga_internal *vga = (struct vga_internal *) priv_data;
885 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
887 ERR_WRONG_SIZE("read","misc out",len,1,1);
889 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
891 PASSTHROUGH_IO_IN(vga,port,dest,len);
893 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_misc_out.val,*((uint8_t*)dest));
898 static int misc_out_write(struct guest_info *core,
904 struct vga_internal *vga = (struct vga_internal *) priv_data;
906 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
908 ERR_WRONG_SIZE("write","misc out",len,1,1);
910 PASSTHROUGH_IO_OUT(vga,port,src,len);
912 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
921 static int input_stat0_read(struct guest_info *core,
927 struct vga_internal *vga = (struct vga_internal *) priv_data;
929 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
931 ERR_WRONG_SIZE("read","input stat0",len,1,1);
933 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
935 PASSTHROUGH_IO_IN(vga,port,dest,len);
937 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat0.val,*(uint8_t*)dest);
943 static int input_stat1_read(struct guest_info *core,
949 struct vga_internal *vga = (struct vga_internal *) priv_data;
951 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
952 port==0x3ba ? "mono" : "color",
953 vga->vga_misc.vga_input_stat1.val);
955 ERR_WRONG_SIZE("read","input stat1",len,1,1);
958 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
960 // Stunningly, reading stat1 is also a way to reset
961 // the state of attribute controller address/data flipflop
962 // That is some mighty fine crack the designers were smoking.
964 vga->vga_attribute_controller.state=ATTR_ADDR;
966 PASSTHROUGH_IO_IN(vga,port,dest,len);
968 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_input_stat1.val,*(uint8_t*)dest);
974 static int feature_control_read(struct guest_info *core,
980 struct vga_internal *vga = (struct vga_internal *) priv_data;
982 PrintDebug("vga: feature control read data=0x%x\n",
983 vga->vga_misc.vga_feature_control.val);
985 ERR_WRONG_SIZE("read","feature control",len,1,1);
988 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
990 PASSTHROUGH_IO_IN(vga,port,dest,len);
992 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_feature_control.val,*(uint8_t*)dest);
997 static int feature_control_write(struct guest_info *core,
1003 struct vga_internal *vga = (struct vga_internal *) priv_data;
1005 PrintDebug("vga: feature control (%s) write data=0x%x\n",
1006 port==0x3ba ? "mono" : "color",
1009 ERR_WRONG_SIZE("write","feature control",len,1,1);
1011 PASSTHROUGH_IO_OUT(vga,port,src,len);
1013 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
1021 static int video_subsys_enable_read(struct guest_info *core,
1027 struct vga_internal *vga = (struct vga_internal *) priv_data;
1029 PrintDebug("vga: video subsys enable read data=0x%x\n",
1030 vga->vga_misc.vga_video_subsys_enable.val);
1032 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
1034 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
1036 PASSTHROUGH_IO_IN(vga,port,dest,len);
1038 PASSTHROUGH_READ_CHECK(vga,vga->vga_misc.vga_video_subsys_enable.val,*(uint8_t*)dest);
1043 static int video_subsys_enable_write(struct guest_info *core,
1049 struct vga_internal *vga = (struct vga_internal *) priv_data;
1051 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1053 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1055 PASSTHROUGH_IO_OUT(vga,port,src,len);
1057 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1064 static int sequencer_address_read(struct guest_info *core,
1070 struct vga_internal *vga = (struct vga_internal *) priv_data;
1072 PrintDebug("vga: sequencer address read data=0x%x\n",
1073 vga->vga_sequencer.vga_sequencer_addr.val);
1075 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1077 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1079 PASSTHROUGH_IO_IN(vga,port,dest,len);
1081 PASSTHROUGH_READ_CHECK(vga,vga->vga_sequencer.vga_sequencer_addr.val,*(uint8_t*)dest);
1086 static int sequencer_data_write(struct guest_info *core,
1092 struct vga_internal *vga = (struct vga_internal *) priv_data;
1096 data=*((uint8_t*)src);
1097 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1099 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1102 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1104 PASSTHROUGH_IO_OUT(vga,port,src,len);
1107 if (index>=VGA_SEQUENCER_NUM) {
1108 PrintError("vga: sequencer data write is for invalid index %d, ignoring\n",index);
1110 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1118 static int sequencer_address_write(struct guest_info *core,
1124 struct vga_internal *vga = (struct vga_internal *) priv_data;
1127 new_addr=*((uint8_t*)src);
1129 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);
1131 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1133 PASSTHROUGH_IO_OUT(vga,port,src,1);
1135 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
1138 // second byte is the data
1139 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
1140 PrintError("vga: write of data failed\n");
1148 static int sequencer_data_read(struct guest_info *core,
1154 struct vga_internal *vga = (struct vga_internal *) priv_data;
1158 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1160 if (index>=VGA_SEQUENCER_NUM) {
1162 PrintError("vga: sequencer data read at invalid index %d, returning zero\n",index);
1164 data=vga->vga_sequencer.vga_sequencer_regs[index];
1167 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
1170 ERR_WRONG_SIZE("read","vga sequencer data",len,1,1);
1172 *((uint8_t*)dest) = data;
1174 PASSTHROUGH_IO_IN(vga,port,dest,len);
1176 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1185 static int crt_controller_address_read(struct guest_info *core,
1191 struct vga_internal *vga = (struct vga_internal *) priv_data;
1193 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
1194 port==0x3b4 ? "mono" : "color",
1195 vga->vga_crt_controller.vga_crt_addr.val);
1197 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
1199 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
1201 PASSTHROUGH_IO_IN(vga,port,dest,len);
1203 PASSTHROUGH_READ_CHECK(vga,vga->vga_crt_controller.vga_crt_addr.val,*(uint8_t*)dest);
1208 static int crt_controller_data_write(struct guest_info *core,
1214 struct vga_internal *vga = (struct vga_internal *) priv_data;
1218 data=*((uint8_t*)src);
1220 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1222 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
1223 port==0x3b5 ? "mono" : "color",
1226 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
1228 PASSTHROUGH_IO_OUT(vga,port,src,len);
1230 if (index>=VGA_CRT_CONTROLLER_NUM) {
1231 PrintError("vga; crt controller write is for illegal index %d, ignoring\n",index);
1233 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
1241 static int crt_controller_address_write(struct guest_info *core,
1247 struct vga_internal *vga = (struct vga_internal *) priv_data;
1250 new_addr=*((uint8_t*)src);
1252 PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n",
1253 port==0x3b4 ? "mono" : "color",
1254 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1256 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
1258 PASSTHROUGH_IO_OUT(vga,port,src,1);
1260 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
1263 // second byte is the data
1264 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
1265 PrintError("vga: write of data failed\n");
1273 static int crt_controller_data_read(struct guest_info *core,
1279 struct vga_internal *vga = (struct vga_internal *) priv_data;
1283 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1285 if (index>=VGA_CRT_CONTROLLER_NUM) {
1287 PrintError("vga: crt controller data read for illegal index %d, returning zero\n",index);
1289 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
1292 PrintDebug("vga: crt controller data (index=%d) = 0x%x\n",index,data);
1294 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
1296 *((uint8_t*)dest) = data;
1298 PASSTHROUGH_IO_IN(vga,port,dest,len);
1300 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t *)dest);
1307 static int graphics_controller_address_read(struct guest_info *core,
1313 struct vga_internal *vga = (struct vga_internal *) priv_data;
1315 PrintDebug("vga: graphics controller address read data=0x%x\n",
1316 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
1318 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
1320 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
1322 PASSTHROUGH_IO_IN(vga,port,dest,len);
1324 PASSTHROUGH_READ_CHECK(vga,vga->vga_graphics_controller.vga_graphics_ctrl_addr.val,*(uint8_t*)dest);
1329 static int graphics_controller_data_write(struct guest_info *core,
1335 struct vga_internal *vga = (struct vga_internal *) priv_data;
1339 data=*((uint8_t*)src);
1340 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1343 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
1346 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
1348 PASSTHROUGH_IO_OUT(vga,port,src,len);
1350 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
1351 PrintError("vga: graphics controller write for illegal index %d ignored\n",index);
1353 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
1361 static int graphics_controller_address_write(struct guest_info *core,
1367 struct vga_internal *vga = (struct vga_internal *) priv_data;
1370 new_addr=*((uint8_t*)src);
1372 PrintDebug("vga: graphics controller address write data=0x%x len=%u\n",
1373 len==1 ? *((uint8_t*)src) : len==2 ? *((uint16_t*)src) : *((uint32_t*)src), len);
1375 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
1377 PASSTHROUGH_IO_OUT(vga,port,src,1);
1379 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
1382 // second byte is the data
1383 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
1384 PrintError("vga: write of data failed\n");
1392 static int graphics_controller_data_read(struct guest_info *core,
1398 struct vga_internal *vga = (struct vga_internal *) priv_data;
1402 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1405 if (index>=VGA_GRAPHICS_CONTROLLER_NUM) {
1407 PrintError("vga: graphics controller data read from illegal index %d, returning zero\n",index);
1409 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
1412 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
1415 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
1417 *((uint8_t*)dest) = data;
1419 PASSTHROUGH_IO_IN(vga,port,dest,len);
1421 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1429 /* Note that these guys have a bizarre protocol*/
1431 static int attribute_controller_address_read(struct guest_info *core,
1437 struct vga_internal *vga = (struct vga_internal *) priv_data;
1439 PrintDebug("vga: attribute controller address read data=0x%x\n",
1440 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
1442 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
1444 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
1446 PASSTHROUGH_IO_IN(vga,port,dest,len);
1448 PASSTHROUGH_READ_CHECK(vga,vga->vga_attribute_controller.vga_attribute_controller_addr.val,*(uint8_t*)dest);
1450 // Reading the attribute controller does not change the state
1455 static int attribute_controller_address_and_data_write(struct guest_info *core,
1461 struct vga_internal *vga = (struct vga_internal *) priv_data;
1464 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
1465 uint8_t new_addr = *((uint8_t*)src);
1466 // We are to treat this as an address write, and flip state
1467 // to expect data ON THIS SAME PORT
1468 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
1470 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
1472 PASSTHROUGH_IO_OUT(vga,port,src,len);
1474 vga->vga_attribute_controller.vga_attribute_controller_addr.val = new_addr;
1476 vga->vga_attribute_controller.state=ATTR_DATA;
1479 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
1481 uint8_t data = *((uint8_t*)src);
1482 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1484 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
1486 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
1488 PASSTHROUGH_IO_OUT(vga,port,src,len);
1490 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
1491 PrintError("vga: attribute controller write to illegal index %d ignored\n",index);
1493 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
1496 vga->vga_attribute_controller.state=ATTR_ADDR;
1505 static int attribute_controller_data_read(struct guest_info *core,
1511 struct vga_internal *vga = (struct vga_internal *) priv_data;
1515 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1517 if (index>=VGA_ATTRIBUTE_CONTROLLER_NUM) {
1519 PrintError("vga: attribute controller read of illegal index %d, returning zero\n",index);
1521 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
1524 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
1527 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
1529 *((uint8_t*)dest) = data;
1531 PASSTHROUGH_IO_IN(vga,port,dest,len);
1533 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1540 Note that these guys also have a strange protocol
1541 since they need to squeeze 18 bits of data through
1544 static int dac_write_address_read(struct guest_info *core,
1550 struct vga_internal *vga = (struct vga_internal *) priv_data;
1552 PrintDebug("vga: dac write address read data=0x%x\n",
1553 vga->vga_dac.vga_dac_write_addr);
1555 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
1558 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
1560 PASSTHROUGH_IO_IN(vga,port,dest,len);
1562 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_write_addr,*(uint8_t*)dest);
1564 // This read does not reset the state machine
1569 static int dac_write_address_write(struct guest_info *core,
1575 struct vga_internal *vga = (struct vga_internal *) priv_data;
1578 new_addr=*((uint8_t*)src);
1580 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
1582 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
1584 PASSTHROUGH_IO_OUT(vga,port,src,len);
1586 // cannot be out of bounds since there are 256 regs
1588 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
1590 // Now we also need to reset the state machine
1592 vga->vga_dac.state=DAC_WRITE;
1593 vga->vga_dac.channel=RED;
1599 static int dac_read_address_read(struct guest_info *core,
1605 struct vga_internal *vga = (struct vga_internal *) priv_data;
1607 PrintDebug("vga: dac read address read data=0x%x\n",
1608 vga->vga_dac.vga_dac_read_addr);
1610 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
1612 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
1614 PASSTHROUGH_IO_IN(vga,port,dest,len);
1616 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_dac_read_addr,*(uint8_t*)dest);
1618 // This read does not reset the state machine
1623 static int dac_read_address_write(struct guest_info *core,
1629 struct vga_internal *vga = (struct vga_internal *) priv_data;
1632 new_addr=*((uint8_t*)src);
1634 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
1636 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
1638 PASSTHROUGH_IO_OUT(vga,port,src,len);
1640 // cannot be out of bounds since there are 256 regs
1642 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
1644 // Now we also need to reset the state machine
1646 vga->vga_dac.state=DAC_READ;
1647 vga->vga_dac.channel=RED;
1653 static int dac_data_read(struct guest_info *core,
1659 struct vga_internal *vga = (struct vga_internal *) priv_data;
1664 if (vga->vga_dac.state!=DAC_READ) {
1665 PrintError("vga: dac data read while in other state\n");
1666 // results undefined, so we continue
1669 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
1671 curreg = vga->vga_dac.vga_dac_read_addr;
1672 curchannel = vga->vga_dac.channel;
1673 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
1675 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
1677 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1678 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1681 *((uint8_t*)dest) = data;
1683 PASSTHROUGH_IO_IN(vga,port,dest,len);
1685 PASSTHROUGH_READ_CHECK(vga,data,*(uint8_t*)dest);
1687 curchannel = (curchannel+1)%3;
1688 vga->vga_dac.channel=curchannel;
1689 if (curchannel==0) {
1690 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1692 vga->vga_dac.vga_dac_read_addr = curreg;
1693 vga->vga_dac.state=DAC_READ;
1700 static int dac_data_write(struct guest_info *core,
1706 struct vga_internal *vga = (struct vga_internal *) priv_data;
1710 vga_palette_reg data32;
1711 vga_palette_reg mask32;
1713 if (vga->vga_dac.state!=DAC_WRITE) {
1714 PrintError("vga: dac data write while in other state\n");
1715 // results undefined, so we continue
1718 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
1720 PASSTHROUGH_IO_OUT(vga,port,src,len);
1722 curreg = vga->vga_dac.vga_dac_write_addr;
1723 curchannel = vga->vga_dac.channel;
1724 data = *((uint8_t *)src);
1726 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
1728 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1729 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1732 data32 = data & 0x3f ;
1733 data32 <<= curchannel*8;
1734 mask32 = ~(0xff << (curchannel * 8));
1736 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
1737 vga->vga_dac.vga_dac_palette[curreg] |= data32;
1739 curchannel = (curchannel+1)%3;
1740 vga->vga_dac.channel=curchannel;
1741 if (curchannel==0) {
1742 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1744 vga->vga_dac.vga_dac_write_addr = curreg;
1745 vga->vga_dac.state=DAC_WRITE;
1754 static int dac_pixel_mask_read(struct guest_info *core,
1760 struct vga_internal *vga = (struct vga_internal *) priv_data;
1762 PrintDebug("vga: dac pixel mask read data=0x%x\n",
1763 vga->vga_dac.vga_pixel_mask);
1765 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
1767 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
1769 PASSTHROUGH_IO_IN(vga,port,dest,len);
1771 PASSTHROUGH_READ_CHECK(vga,vga->vga_dac.vga_pixel_mask,*(uint8_t*)dest);
1776 static int dac_pixel_mask_write(struct guest_info *core,
1782 struct vga_internal *vga = (struct vga_internal *) priv_data;
1785 new_data=*((uint8_t*)src);
1787 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
1789 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
1791 PASSTHROUGH_IO_OUT(vga,port,src,len);
1793 vga->vga_dac.vga_pixel_mask = new_data;
1798 static int init_vga(struct vga_internal *vga)
1800 // TODO: startup spec of register contents, if any
1801 PrintError("vga: init_vga is UNIMPLEMTED\n");
1805 static int free_vga(struct vga_internal *vga)
1809 struct vm_device *dev = vga->dev;
1811 // Framebuffer deletion is user's responsibility
1813 // if (vga->mem_store) {
1814 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
1815 // vga->mem_store=0;
1818 for (i=0;i<MAP_NUM;i++) {
1820 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
1825 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
1829 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
1830 // The following also covers VGA_INPUT_STAT0_READ
1831 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
1832 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1833 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
1834 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1835 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
1836 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
1838 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
1840 /* Sequencer registers */
1841 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
1842 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
1844 /* CRT controller registers */
1845 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
1846 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
1847 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
1848 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
1850 /* graphics controller registers */
1851 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
1852 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
1854 /* attribute controller registers */
1855 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
1856 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
1858 /* video DAC palette registers */
1859 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
1860 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
1861 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
1862 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
1870 static struct v3_device_ops dev_ops = {
1871 .free = (int (*)(void *))free_vga,
1875 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1876 struct vga_internal *vga;
1880 char * dev_id = v3_cfg_val(cfg, "ID");
1881 char * passthrough = v3_cfg_val(cfg, "passthrough");
1883 // DETERMINE THE FRAMEBUFFER AND SET IT EARLY
1884 // FRAMEBUFFER IS SUPPLIED BY THE BACKEND
1886 PrintDebug("vga: init_device\n");
1888 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
1891 PrintError("vga: cannot allocate\n");
1895 memset(vga, 0, sizeof(struct vga_internal));
1897 if (passthrough && strcasecmp(passthrough,"enable")==0) {
1898 PrintDebug("vga: enabling passthrough\n");
1899 vga->passthrough=true;
1902 // No memory store is allocated since we will use a full memory hook
1903 // The VGA maps can be read as well as written
1904 // Reads also affect writes, since they are how you fill the latches
1906 // Now allocate the maps
1907 for (i=0;i<MAP_NUM;i++) {
1908 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
1909 if (!(vga->map[i])) {
1910 PrintError("vga: cannot allocate maps\n");
1914 memset(vga->map[i],0,MAP_SIZE);
1917 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
1920 PrintError("Could not attach device %s\n", dev_id);
1927 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
1928 MEM_REGION_START, MEM_REGION_END,
1932 PrintError("vga: memory book failed\n");
1933 v3_remove_device(dev);
1939 /* Miscelaneous registers */
1940 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
1941 // The following also covers VGA_INPUT_STAT0_READ
1942 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
1943 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1944 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
1945 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1946 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
1947 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
1949 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
1951 /* Sequencer registers */
1952 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
1953 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
1955 /* CRT controller registers */
1956 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
1957 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
1958 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
1959 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
1961 /* graphics controller registers */
1962 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
1963 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
1965 /* attribute controller registers */
1966 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
1967 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
1969 /* video DAC palette registers */
1970 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
1971 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
1972 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
1973 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
1976 PrintError("vga: Error allocating VGA I/O ports\n");
1977 v3_remove_device(dev);
1983 PrintDebug("vga: successfully added and initialized, waiting for framebuffer attach\n");
1989 device_register("VGA", vga_init);