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 typedef uint8_t *vga_map; // points to MAP_SIZE data
42 uint32_t bitsperpixel;
51 struct fb *palacios_linux_fb_hack_pointer;
56 #define VGA_MISC_OUT_READ 0x3cc
57 #define VGA_MISC_OUT_WRITE 0x3c2
59 #define VGA_INPUT_STAT0_READ 0x3c2
61 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
62 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
64 #define VGA_FEATURE_CONTROL_READ 0x3ca
65 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
66 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
68 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
70 #define VGA_SEQUENCER_ADDRESS 0x3c4
71 #define VGA_SEQUENCER_DATA 0x3c5
72 #define VGA_SEQUENCER_NUM 5
75 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
76 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
77 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
78 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
79 #define VGA_CRT_CONTROLLER_NUM 25
82 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
83 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
84 #define VGA_GRAPHICS_CONTROLLER_NUM 9
86 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
87 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
88 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
90 #define VGA_DAC_WRITE_ADDR 0x3c8
91 #define VGA_DAC_READ_ADDR 0x3c7
92 #define VGA_DAC_DATA 0x3c9
93 #define VGA_DAC_PIXEL_MASK 0x3c6
95 #define VGA_DAC_NUM_ENTRIES 256
97 struct vga_misc_regs {
98 /* Read: 0x3cc; Write: 0x3c2 */
99 struct vga_misc_out_reg vga_misc_out;
101 struct vga_input_stat0_reg vga_input_stat0;
102 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
103 struct vga_input_stat1_reg vga_input_stat1;
104 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
105 struct vga_feature_control_reg vga_feature_control;
106 /* Read: 0x3c3; Write: 0x3c3 */
107 struct vga_video_subsys_enable_reg vga_video_subsys_enable;
108 } __attribute__((packed));
110 struct vga_sequencer_regs {
111 /* Address register is 0x3c4, data register is 0x3c5 */
113 struct vga_sequencer_addr_reg vga_sequencer_addr;
115 /* these can be accessed via the index, offset on start
116 or via the specific regs. For this reason, it is essential
117 that this is all packed and that the order does not change */
119 uint8_t vga_sequencer_regs[0];
122 struct vga_reset_reg vga_reset;
124 struct vga_clocking_mode_reg vga_clocking_mode;
126 struct vga_map_mask_reg vga_map_mask;
128 struct vga_char_map_select_reg vga_char_map_select;
130 struct vga_mem_mode_reg vga_mem_mode;
131 } __attribute__((packed));
133 struct vga_crt_controller_regs {
134 /* Address Register is 0x3b4 or 0x3d4 */
135 /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
136 struct vga_crt_addr_reg vga_crt_addr;
138 /* these can be accessed via the index, offset on start
139 or via the specific regs. For this reason, it is essential
140 that this is all packed and that the order does not change */
142 uint8_t vga_crt_controller_regs[0];
145 vga_horizontal_total_reg vga_horizontal_total;
147 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
149 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
151 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
153 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
155 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
157 vga_vertical_total_reg vga_vertical_total;
159 struct vga_overflow_reg vga_overflow;
161 struct vga_preset_row_scan_reg vga_preset_row_scan;
163 struct vga_max_row_scan_reg vga_row_scan;
165 struct vga_cursor_start_reg vga_cursor_start;
167 struct vga_cursor_end_reg vga_cursor_end;
169 vga_start_address_high_reg vga_start_address_high;
171 vga_start_address_low_reg vga_start_address_low;
173 vga_cursor_location_high_reg vga_cursor_location_high;
175 vga_cursor_location_low_reg vga_cursor_location_low;
177 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
179 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
181 vga_vertical_display_enable_end_reg vga_vertical_display_enable;
183 vga_offset_reg vga_offset;
185 struct vga_underline_location_reg vga_underline_location;
187 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
189 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
191 struct vga_crt_mode_control_reg vga_crt_mode_control;
193 vga_line_compare_reg vga_line_compare;
194 } __attribute__((packed));
196 struct vga_graphics_controller_regs {
197 /* Address: 0x3ce Data: 0x3cf */
200 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
202 /* these can be accessed via the index, offset on start
203 or via the specific regs. For this reason, it is essential
204 that this is all packed and that the order does not change */
206 uint8_t vga_graphics_controller_regs[0];
209 struct vga_set_reset_reg vga_set_reset;
211 struct vga_enable_set_reset_reg vga_enable_set_reset;
213 struct vga_color_compare_reg vga_color_compare;
215 struct vga_data_rotate_reg vga_data_rotate;
217 struct vga_read_map_select_reg vga_read_map_select;
219 struct vga_graphics_mode_reg vga_graphics_mode;
221 struct vga_misc_reg vga_misc;
223 struct vga_color_dont_care_reg vga_color_dont_care;
225 vga_bit_mask_reg vga_bit_mask;
226 } __attribute__((packed));
229 struct vga_attribute_contoller_regs {
231 Address AND WRITE: 0x3c0
234 The write protocol is to write the index to 0x3c0 followed by
235 the data. The read protocol is to write the index to 0x3c0
236 and then read from 0x3c1
238 IMPORTANT: write address, write data flips state back to write address
239 write address, read data DOES NOT
241 To reset to write address state, read input status register 1
243 enum { ATTR_ADDR, ATTR_DATA } state; //state of the flip flop
246 struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
250 /* these can be accessed via the index, offset on start
251 or via the specific regs. For this reason, it is essential
252 that this is all packed and that the order does not change */
254 uint8_t vga_attribute_controller_regs[0];
257 vga_internal_palette_regs vga_internal_palette;
259 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
261 vga_overscan_color_reg vga_overscan_color;
263 struct vga_color_plane_enable_reg vga_color_plane_enable;
265 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
267 struct vga_color_select_reg vga_color_select;
268 } __attribute__((packed));
270 struct vga_dac_regs {
271 enum {DAC_READ=0, DAC_WRITE} state;
272 enum {RED=0,GREEN,BLUE} channel;
273 vga_dac_pixel_mask_reg vga_pixel_mask;
274 vga_dac_write_addr_reg vga_dac_write_addr;
275 vga_dac_read_addr_reg vga_dac_read_addr;
276 // the dac_data register is used only to access the registers
277 // and thus has no representation here
278 vga_palette_reg vga_dac_palette[VGA_DAC_NUM_ENTRIES];
279 } __attribute__((packed));
282 struct vga_internal {
283 struct vm_device *dev;
287 struct frame_buf *framebuf; // we render to this
289 // void *mem_store; // This is the region where the memory hooks will go
291 vga_map map[MAP_NUM]; // the maps that the host writes to
293 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
295 /* Range of I/O ports here for backward compat with MDA and CGA */
296 struct vga_misc_regs vga_misc;
298 /* Address Register is 0x3b4 or 0x3d4 */
299 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
300 struct vga_crt_controller_regs vga_crt_controller;
302 /* Address register is 0x3c4, data register is 0x3c5 */
303 struct vga_sequencer_regs vga_sequencer;
305 /* Address: 0x3ce Data: 0x3cf */
306 struct vga_graphics_controller_regs vga_graphics_controller;
309 Address AND WRITE: 0x3c0
313 struct vga_attribute_contoller_regs vga_attribute_controller;
316 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
317 address for writes: 0x3c8 ("")
319 pixel mask: 0x3c6 - do not write (init to 0xff)
321 struct vga_dac_regs vga_dac;
325 static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
327 switch (vga->vga_graphics_controller.vga_misc.memory_map) {
347 static uint64_t find_offset(struct vga_internal *vga, addr_t guest_addr)
349 uint64_t mem_start, mem_end;
353 get_mem_region(vga, &mem_start, &mem_end);
355 return (guest_addr-mem_start) % (mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
362 static int vga_write(struct guest_info * core,
368 struct vm_device *dev = (struct vm_device *)priv_data;
369 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
371 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
373 if (vga->passthrough) {
374 memcpy(V3_VAddr((void*)guest_addr),src,length);
377 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
379 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
383 00b -- Write Mode 0: In this mode, the host data is first rotated
384 as per the Rotate Count field, then the Enable Set/Reset mechanism
385 selects data from this or the Set/Reset field. Then the selected
386 Logical Operation is performed on the resulting data and the data
387 in the latch register. Then the Bit Mask field is used to select
388 which bits come from the resulting data and which come
389 from the latch register. Finally, only the bit planes enabled by
390 the Memory Plane Write Enable field are written to memory.
398 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
399 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
401 offset = find_offset(vga, guest_addr);
403 PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
405 for (i=0;i<length;i++,offset++) {
407 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
408 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
409 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
410 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
412 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
413 vga_map map = vga->map[mapnum];
414 uint8_t data = ((uint8_t *)src)[i];
415 uint8_t latchval = vga->latch[mapnum];
418 data = (data>>ror) | data<<(8-ror);
420 // use SR bit if ESR is on for this map
422 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
440 // mux between latch and alu output
442 // use alu output, which is in data
451 PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
465 01b -- Write Mode 1: In this mode, data is transferred directly
466 from the 32 bit latch register to display memory, affected only by
467 the Memory Plane Write Enable field. The host data is not used in this mode.
472 uint64_t offset = find_offset(vga,guest_addr);
474 PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
476 for (i=0;i<length;i++,offset++) {
479 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
481 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
482 vga_map map = vga->map[mapnum];
483 uint8_t latchval = vga->latch[mapnum];
488 map[offset] = latchval;
499 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
500 are replicated across all 8 bits of their respective planes.
501 Then the selected Logical Operation is performed on the resulting
502 data and the data in the latch register. Then the Bit Mask field is used to
503 select which bits come from the resulting data and which come from
504 the latch register. Finally, only the bit planes enabled by the
505 Memory Plane Write Enable field are written to memory.
511 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
513 offset = find_offset(vga, guest_addr);
515 PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
517 for (i=0;i<length;i++,offset++) {
519 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
520 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
522 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
523 vga_map map = vga->map[mapnum];
524 uint8_t data = ((uint8_t *)src)[i];
525 uint8_t latchval = vga->latch[mapnum];
527 // expand relevant bit to 8 bit
528 // it's basically esr=1, sr=bit from write
529 data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7);
546 // mux between latch and alu output
548 // use alu output, which is in data
567 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
568 as if the Enable Set/Reset field were set to 1111b. Then the host data is
569 first rotated as per the Rotate Count field, then logical ANDed with the
570 value of the Bit Mask field. The resulting value is used on the data
571 obtained from the Set/Reset field in the same way that the Bit Mask field
572 would ordinarily be used. to select which bits come from the expansion
573 of the Set/Reset field and which come from the latch register. Finally,
574 only the bit planes enabled by the Memory Plane Write Enable field
575 are written to memory.
582 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
584 offset = find_offset(vga, guest_addr);
586 PrintDebug("vga: mode 3 write, offset=0x%llx, ror=%u\n", offset,ror);
588 for (i=0;i<length;i++,offset++) {
590 uint8_t data = ((uint8_t *)src)[i];
592 data = (data>>ror) | data<<(8-ror);
594 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
595 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
596 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
598 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
599 vga_map map = vga->map[mapnum];
600 uint8_t latchval = vga->latch[mapnum];
602 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
605 // mux between latch and alu output
607 // use alu output, which is in data
626 // There is no default
632 // PrintError("vga: vga_write UNIMPLEMENTED\n");
635 up to 256K mapped through a window of 128K
637 most cards support linear mode as well
639 Need to implement readability too
641 Write extended memory bit to enable all 256K:
643 Sequencer Memory Mode Register (Index 04h) . extended memory
645 Must enable writes before effects happen:
647 Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
649 Choose which addresses are supported for CPU writes:
651 Miscellaneous Graphics Register (Index 06h).memory map select
653 00b -- A0000h-BFFFFh (128K region)
654 01b -- A0000h-AFFFFh (64K region)
655 10b -- B0000h-B7FFFh (32K region)
656 11b -- B8000h-BFFFFh (32K region)
658 There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
660 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.)
662 Memory model: 64K 32 bit locations; divided into 4 64K bit planes
668 Assume linear framebuffer, starting at address buf:
674 static int vga_read(struct guest_info * core,
680 struct vm_device *dev = (struct vm_device *)priv_data;
681 struct vga_internal *vga = (struct vga_internal *) dev->private_data;
683 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
686 if (vga->passthrough) {
687 memcpy(dst,V3_VAddr((void*)guest_addr),length);
693 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
695 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
697 /* 0 - a byte from ONE of the 4 planes is returned;
698 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
702 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
703 offset = find_offset(vga,guest_addr);
706 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
709 memcpy(dst,(vga->map[mapnum])+offset,length);
711 // load the latches with the last item read
712 for (mapnum=0;mapnum<4;mapnum++) {
713 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
720 /* 1 - Compare video memory and reference color
721 (in Color Compare, except those not set in Color Don't Care),
722 each bit in returned result is one comparison between the reference color
724 Ref color is *4* bits, and thus a one byte read returns a comparison
730 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
731 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
738 offset = find_offset(vga,guest_addr);
740 for (i=0;i<length;i++,offset++) {
743 for (mapnum=0;mapnum<4;mapnum++) {
744 map = vga->map[mapnum];
745 if ( (dc>>mapnum)&0x1 ) { // don't care
749 bits = (map[offset]&0xf) == cc;
752 bits |= (((map[offset]>>4))&0xf) == cc;
754 // not clear whether it is 0..k or k..0
760 // load the latches with the last item read
761 for (mapnum=0;mapnum<4;mapnum++) {
762 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
767 // there is no default
776 static int render(struct vga_internal *vga)
778 PrintError("vga: render UNIMPLEMENTED\n");
780 if (!palacios_linux_fb_hack_pointer) {
790 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
791 if (((len)<(min)) || ((len)>(max))) { \
792 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
796 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
799 *(uint8_t *)dest = v3_inb(port);
802 *(uint16_t *)dest = v3_inw(port);
805 *(uint32_t *)dest = v3_indw(port);
808 PrintError("vga: unsupported passthrough io in size %u\n",length);
814 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
817 v3_outb(port, *(uint8_t *)src);
820 v3_outw(port, *(uint16_t *)src);
823 v3_outdw(port, *(uint32_t *)src);
826 PrintError("vga: unsupported passthrough io out size %u\n",length);
831 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
832 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
834 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
835 do { if ((vga)->passthrough) { passthrough_io_in(port,src,len); } } while (0)
839 static int misc_out_read(struct guest_info *core,
845 struct vga_internal *vga = (struct vga_internal *) priv_data;
847 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
849 ERR_WRONG_SIZE("read","misc out",len,1,1);
851 PASSTHROUGH_IO_IN(vga,port,dest,len);
853 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
858 static int misc_out_write(struct guest_info *core,
864 struct vga_internal *vga = (struct vga_internal *) priv_data;
866 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
868 ERR_WRONG_SIZE("write","misc out",len,1,1);
870 PASSTHROUGH_IO_OUT(vga,port,src,len);
872 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
881 static int input_stat0_read(struct guest_info *core,
887 struct vga_internal *vga = (struct vga_internal *) priv_data;
889 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
891 ERR_WRONG_SIZE("read","input stat0",len,1,1);
893 PASSTHROUGH_IO_IN(vga,port,dest,len);
895 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
901 static int input_stat1_read(struct guest_info *core,
907 struct vga_internal *vga = (struct vga_internal *) priv_data;
909 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
910 port==0x3ba ? "mono" : "color",
911 vga->vga_misc.vga_input_stat1.val);
913 ERR_WRONG_SIZE("read","input stat1",len,1,1);
915 PASSTHROUGH_IO_IN(vga,port,dest,len);
917 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
919 // Stunningly, reading stat1 is also a way to reset
920 // the state of attribute controller address/data flipflop
921 // That is some mighty fine crack the designers were smoking.
923 vga->vga_attribute_controller.state=ATTR_ADDR;
929 static int feature_control_read(struct guest_info *core,
935 struct vga_internal *vga = (struct vga_internal *) priv_data;
937 PrintDebug("vga: feature control read data=0x%x\n",
938 vga->vga_misc.vga_feature_control.val);
940 ERR_WRONG_SIZE("read","feature control",len,1,1);
942 PASSTHROUGH_IO_IN(vga,port,dest,len);
944 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
949 static int feature_control_write(struct guest_info *core,
955 struct vga_internal *vga = (struct vga_internal *) priv_data;
957 PrintDebug("vga: feature control (%s) write data=0x%x\n",
958 port==0x3ba ? "mono" : "color",
961 ERR_WRONG_SIZE("write","feature control",len,1,1);
963 PASSTHROUGH_IO_OUT(vga,port,src,len);
965 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
973 static int video_subsys_enable_read(struct guest_info *core,
979 struct vga_internal *vga = (struct vga_internal *) priv_data;
981 PrintDebug("vga: video subsys enable read data=0x%x\n",
982 vga->vga_misc.vga_video_subsys_enable.val);
984 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
986 PASSTHROUGH_IO_IN(vga,port,dest,len);
988 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
993 static int video_subsys_enable_write(struct guest_info *core,
999 struct vga_internal *vga = (struct vga_internal *) priv_data;
1001 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
1003 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
1005 PASSTHROUGH_IO_OUT(vga,port,src,len);
1007 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
1014 static int sequencer_address_read(struct guest_info *core,
1020 struct vga_internal *vga = (struct vga_internal *) priv_data;
1022 PrintDebug("vga: sequencer address read data=0x%x\n",
1023 vga->vga_sequencer.vga_sequencer_addr.val);
1025 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
1027 PASSTHROUGH_IO_IN(vga,port,dest,len);
1029 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
1034 static int sequencer_data_write(struct guest_info *core,
1040 struct vga_internal *vga = (struct vga_internal *) priv_data;
1044 data=*((uint8_t*)src);
1045 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1047 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1050 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1052 PASSTHROUGH_IO_OUT(vga,port,src,len);
1054 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1061 static int sequencer_address_write(struct guest_info *core,
1067 struct vga_internal *vga = (struct vga_internal *) priv_data;
1070 new_addr=*((uint8_t*)src);
1072 PrintDebug("vga: sequencer address write data=0x%x len=%u\n", new_addr,len);
1074 ERR_WRONG_SIZE("write","vga sequencer addr",len,1,2);
1076 PASSTHROUGH_IO_OUT(vga,port,src,1);
1078 if (new_addr>VGA_SEQUENCER_NUM) {
1079 PrintError("vga: ignoring change of sequencer address to %u (>%u)\n",
1080 new_addr, VGA_SEQUENCER_NUM);
1083 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
1085 // second byte is the data
1086 if (sequencer_data_write(core,port,src+1,1,vga)!=1) {
1087 PrintError("vga: write of data failed\n");
1097 static int sequencer_data_read(struct guest_info *core,
1103 struct vga_internal *vga = (struct vga_internal *) priv_data;
1107 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1108 data=vga->vga_sequencer.vga_sequencer_regs[index];
1110 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
1113 ERR_WRONG_SIZE("read","vga sequenver data",len,1,1);
1115 PASSTHROUGH_IO_IN(vga,port,dest,len);
1117 *((uint8_t*)dest) = data;
1126 static int crt_controller_address_read(struct guest_info *core,
1132 struct vga_internal *vga = (struct vga_internal *) priv_data;
1134 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
1135 port==0x3b4 ? "mono" : "color",
1136 vga->vga_crt_controller.vga_crt_addr.val);
1138 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
1140 PASSTHROUGH_IO_IN(vga,port,dest,len);
1142 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
1147 static int crt_controller_data_write(struct guest_info *core,
1153 struct vga_internal *vga = (struct vga_internal *) priv_data;
1157 data=*((uint8_t*)src);
1159 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1161 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
1162 port==0x3b5 ? "mono" : "color",
1165 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
1167 PASSTHROUGH_IO_OUT(vga,port,src,len);
1169 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
1176 static int crt_controller_address_write(struct guest_info *core,
1182 struct vga_internal *vga = (struct vga_internal *) priv_data;
1185 new_addr=*((uint8_t*)src);
1187 PrintDebug("vga: crt controller (%s) address write data=0x%x len=%u\n",
1188 port==0x3b4 ? "mono" : "color",
1191 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,2);
1193 PASSTHROUGH_IO_OUT(vga,port,src,1);
1195 if (new_addr>VGA_CRT_CONTROLLER_NUM) {
1196 PrintError("vga: ignoring change of crt controller address to %u (>%u)\n",
1197 new_addr, VGA_CRT_CONTROLLER_NUM);
1200 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
1202 // second byte is the data
1203 if (crt_controller_data_write(core,port,src+1,1,vga)!=1) {
1204 PrintError("vga: write of data failed\n");
1214 static int crt_controller_data_read(struct guest_info *core,
1220 struct vga_internal *vga = (struct vga_internal *) priv_data;
1224 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1225 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
1227 PrintDebug("vga: crt controller data (%s) read data (index=%d) = 0x%x\n",
1228 port==0x3b5 ? "mono" : "color",
1231 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
1233 PASSTHROUGH_IO_IN(vga,port,dest,len);
1235 *((uint8_t*)dest) = data;
1242 static int graphics_controller_address_read(struct guest_info *core,
1248 struct vga_internal *vga = (struct vga_internal *) priv_data;
1250 PrintDebug("vga: graphics controller address read data=0x%x\n",
1251 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
1253 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
1255 PASSTHROUGH_IO_IN(vga,port,dest,len);
1257 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
1262 static int graphics_controller_data_write(struct guest_info *core,
1268 struct vga_internal *vga = (struct vga_internal *) priv_data;
1272 data=*((uint8_t*)src);
1273 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1275 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
1278 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
1280 PASSTHROUGH_IO_OUT(vga,port,src,len);
1282 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
1289 static int graphics_controller_address_write(struct guest_info *core,
1295 struct vga_internal *vga = (struct vga_internal *) priv_data;
1298 new_addr=*((uint8_t*)src);
1300 PrintDebug("vga: graphics controller address write data=0x%x len=%u\n", new_addr,len);
1302 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,2);
1304 PASSTHROUGH_IO_OUT(vga,port,src,1);
1306 if (new_addr>VGA_GRAPHICS_CONTROLLER_NUM) {
1307 PrintError("vga: ignoring change of graphics controller address to %u (>%u)\n",
1308 new_addr, VGA_GRAPHICS_CONTROLLER_NUM);
1311 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
1313 // second byte is the data
1314 if (graphics_controller_data_write(core,port,src+1,1,vga)!=1) {
1315 PrintError("vga: write of data failed\n");
1323 static int graphics_controller_data_read(struct guest_info *core,
1329 struct vga_internal *vga = (struct vga_internal *) priv_data;
1333 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1334 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
1336 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
1339 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
1341 PASSTHROUGH_IO_IN(vga,port,dest,len);
1343 *((uint8_t*)dest) = data;
1351 /* Note that these guys have a bizarre protocol*/
1353 static int attribute_controller_address_read(struct guest_info *core,
1359 struct vga_internal *vga = (struct vga_internal *) priv_data;
1361 PrintDebug("vga: attribute controller address read data=0x%x\n",
1362 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
1364 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
1366 PASSTHROUGH_IO_IN(vga,port,dest,len);
1368 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
1370 // Reading the attribute controller does not change the state
1375 static int attribute_controller_address_and_data_write(struct guest_info *core,
1381 struct vga_internal *vga = (struct vga_internal *) priv_data;
1384 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
1385 uint8_t new_addr = *((uint8_t*)src);
1386 // We are to treat this as an address write, and flip state
1387 // to expect data ON THIS SAME PORT
1388 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
1390 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
1392 PASSTHROUGH_IO_OUT(vga,port,src,len);
1394 if (new_addr>VGA_ATTRIBUTE_CONTROLLER_NUM) {
1395 PrintError("vga: ignoring change of attribute controller address to %u (>%u)\n",
1396 new_addr, VGA_ATTRIBUTE_CONTROLLER_NUM);
1399 vga->vga_attribute_controller.vga_attribute_controller_addr.val = *((uint8_t*)src) ;
1401 vga->vga_attribute_controller.state=ATTR_DATA;
1404 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
1406 uint8_t data = *((uint8_t*)src);
1407 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1409 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
1411 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
1413 PASSTHROUGH_IO_OUT(vga,port,src,len);
1415 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
1417 vga->vga_attribute_controller.state=ATTR_ADDR;
1426 static int attribute_controller_data_read(struct guest_info *core,
1432 struct vga_internal *vga = (struct vga_internal *) priv_data;
1436 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1437 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
1439 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
1442 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
1444 PASSTHROUGH_IO_IN(vga,port,dest,len);
1446 *((uint8_t*)dest) = data;
1453 Note that these guys also have a strange protocol
1454 since they need to squeeze 18 bits of data through
1457 static int dac_write_address_read(struct guest_info *core,
1463 struct vga_internal *vga = (struct vga_internal *) priv_data;
1465 PrintDebug("vga: dac write address read data=0x%x\n",
1466 vga->vga_dac.vga_dac_write_addr);
1468 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
1470 PASSTHROUGH_IO_IN(vga,port,dest,len);
1472 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
1474 // This read does not reset the state machine
1479 static int dac_write_address_write(struct guest_info *core,
1485 struct vga_internal *vga = (struct vga_internal *) priv_data;
1488 new_addr=*((uint8_t*)src);
1490 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
1492 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
1494 PASSTHROUGH_IO_OUT(vga,port,src,len);
1496 // cannot be out of bounds since there are 256 regs
1498 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
1500 // Now we also need to reset the state machine
1502 vga->vga_dac.state=DAC_WRITE;
1503 vga->vga_dac.channel=RED;
1509 static int dac_read_address_read(struct guest_info *core,
1515 struct vga_internal *vga = (struct vga_internal *) priv_data;
1517 PrintDebug("vga: dac read address read data=0x%x\n",
1518 vga->vga_dac.vga_dac_read_addr);
1520 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
1522 PASSTHROUGH_IO_IN(vga,port,dest,len);
1524 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
1526 // This read does not reset the state machine
1531 static int dac_read_address_write(struct guest_info *core,
1537 struct vga_internal *vga = (struct vga_internal *) priv_data;
1540 new_addr=*((uint8_t*)src);
1542 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
1544 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
1546 PASSTHROUGH_IO_OUT(vga,port,src,len);
1548 // cannot be out of bounds since there are 256 regs
1550 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
1552 // Now we also need to reset the state machine
1554 vga->vga_dac.state=DAC_READ;
1555 vga->vga_dac.channel=RED;
1561 static int dac_data_read(struct guest_info *core,
1567 struct vga_internal *vga = (struct vga_internal *) priv_data;
1572 if (vga->vga_dac.state!=DAC_READ) {
1573 PrintError("vga: dac data read while in other state\n");
1574 // results undefined, so we continue
1577 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
1579 PASSTHROUGH_IO_IN(vga,port,dest,len);
1581 curreg = vga->vga_dac.vga_dac_read_addr;
1582 curchannel = vga->vga_dac.channel;
1583 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
1585 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
1587 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1588 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1591 *((uint8_t*)dest) = data;
1593 curchannel = (curchannel+1)%3;
1594 vga->vga_dac.channel=curchannel;
1595 if (curchannel==0) {
1596 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1598 vga->vga_dac.vga_dac_read_addr = curreg;
1599 vga->vga_dac.state=DAC_READ;
1606 static int dac_data_write(struct guest_info *core,
1612 struct vga_internal *vga = (struct vga_internal *) priv_data;
1616 vga_palette_reg data32;
1617 vga_palette_reg mask32;
1619 if (vga->vga_dac.state!=DAC_WRITE) {
1620 PrintError("vga: dac data write while in other state\n");
1621 // results undefined, so we continue
1624 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
1626 PASSTHROUGH_IO_OUT(vga,port,src,len);
1628 curreg = vga->vga_dac.vga_dac_write_addr;
1629 curchannel = vga->vga_dac.channel;
1630 data = *((uint8_t *)src);
1632 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
1634 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1635 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1638 data32 = data & 0x3f ;
1639 data32 <<= curchannel*8;
1640 mask32 = ~(0xff << (curchannel * 8));
1642 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
1643 vga->vga_dac.vga_dac_palette[curreg] |= data32;
1645 curchannel = (curchannel+1)%3;
1646 vga->vga_dac.channel=curchannel;
1647 if (curchannel==0) {
1648 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1650 vga->vga_dac.vga_dac_write_addr = curreg;
1651 vga->vga_dac.state=DAC_WRITE;
1660 static int dac_pixel_mask_read(struct guest_info *core,
1666 struct vga_internal *vga = (struct vga_internal *) priv_data;
1668 PrintDebug("vga: dac pixel mask read data=0x%x\n",
1669 vga->vga_dac.vga_pixel_mask);
1671 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
1673 PASSTHROUGH_IO_IN(vga,port,dest,len);
1675 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
1680 static int dac_pixel_mask_write(struct guest_info *core,
1686 struct vga_internal *vga = (struct vga_internal *) priv_data;
1689 new_data=*((uint8_t*)src);
1691 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
1693 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
1695 PASSTHROUGH_IO_OUT(vga,port,src,len);
1697 vga->vga_dac.vga_pixel_mask = new_data;
1702 static int init_vga(struct vga_internal *vga)
1704 // TODO: startup spec of register contents, if any
1705 PrintError("vga: init_vga is UNIMPLEMTED\n");
1709 static int free_vga(struct vga_internal *vga)
1713 struct vm_device *dev = vga->dev;
1715 // Framebuffer deletion is user's responsibility
1717 // if (vga->mem_store) {
1718 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
1719 // vga->mem_store=0;
1722 for (i=0;i<MAP_NUM;i++) {
1724 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
1729 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
1733 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
1734 // The following also covers VGA_INPUT_STAT0_READ
1735 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
1736 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1737 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
1738 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1739 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
1740 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
1742 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
1744 /* Sequencer registers */
1745 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
1746 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
1748 /* CRT controller registers */
1749 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
1750 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
1751 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
1752 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
1754 /* graphics controller registers */
1755 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
1756 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
1758 /* attribute controller registers */
1759 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
1760 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
1762 /* video DAC palette registers */
1763 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
1764 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
1765 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
1766 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
1774 static struct v3_device_ops dev_ops = {
1775 .free = (int (*)(void *))free_vga,
1779 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1780 struct vga_internal *vga;
1784 char * dev_id = v3_cfg_val(cfg, "ID");
1785 char * passthrough = v3_cfg_val(cfg, "passthrough");
1787 // DETERMINE THE FRAMEBUFFER AND SET IT EARLY
1788 // FRAMEBUFFER IS SUPPLIED BY THE BACKEND
1790 PrintDebug("vga: init_device\n");
1792 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
1795 PrintError("vga: cannot allocate\n");
1799 memset(vga, 0, sizeof(struct vga_internal));
1801 if (passthrough && strcasecmp(passthrough,"enable")==0) {
1802 PrintDebug("vga: enabling passthrough\n");
1803 vga->passthrough=true;
1806 // No memory store is allocated since we will use a full memory hook
1807 // The VGA maps can be read as well as written
1808 // Reads also affect writes, since they are how you fill the latches
1810 // Now allocate the maps
1811 for (i=0;i<MAP_NUM;i++) {
1812 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
1813 if (!(vga->map[i])) {
1814 PrintError("vga: cannot allocate maps\n");
1818 memset(vga->map[i],0,MAP_SIZE);
1821 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
1824 PrintError("Could not attach device %s\n", dev_id);
1831 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
1832 MEM_REGION_START, MEM_REGION_END,
1836 PrintError("vga: memory book failed\n");
1837 v3_remove_device(dev);
1843 /* Miscelaneous registers */
1844 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
1845 // The following also covers VGA_INPUT_STAT0_READ
1846 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
1847 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1848 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
1849 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1850 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
1851 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
1853 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
1855 /* Sequencer registers */
1856 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
1857 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
1859 /* CRT controller registers */
1860 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
1861 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
1862 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
1863 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
1865 /* graphics controller registers */
1866 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
1867 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
1869 /* attribute controller registers */
1870 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
1871 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
1873 /* video DAC palette registers */
1874 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
1875 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
1876 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
1877 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
1880 PrintError("vga: Error allocating VGA I/O ports\n");
1881 v3_remove_device(dev);
1887 PrintDebug("vga: successfully added and initialized, waiting for framebuffer attach\n");
1893 device_register("VGA", vga_init);