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
38 #define VGA_MISC_OUT_READ 0x3cc
39 #define VGA_MISC_OUT_WRITE 0x3c2
41 #define VGA_INPUT_STAT0_READ 0x3c2
43 #define VGA_INPUT_STAT1_READ_MONO 0x3ba
44 #define VGA_INPUT_STAT1_READ_COLOR 0x3da
46 #define VGA_FEATURE_CONTROL_READ 0x3ca
47 #define VGA_FEATURE_CONTROL_WRITE_MONO 0x3ba
48 #define VGA_FEATURE_CONTROL_WRITE_COLOR 0x3da
50 #define VGA_VIDEO_SUBSYS_ENABLE 0x3c3
52 #define VGA_SEQUENCER_ADDRESS 0x3c4
53 #define VGA_SEQUENCER_DATA 0x3c5
54 #define VGA_SEQUENCER_NUM 5
57 #define VGA_CRT_CONTROLLER_ADDRESS_MONO 0x3b4
58 #define VGA_CRT_CONTROLLER_ADDRESS_COLOR 0x3d4
59 #define VGA_CRT_CONTROLLER_DATA_MONO 0x3b5
60 #define VGA_CRT_CONTROLLER_DATA_COLOR 0x3d5
61 #define VGA_CRT_CONTROLLER_NUM 25
64 #define VGA_GRAPHICS_CONTROLLER_ADDRESS 0x3ce
65 #define VGA_GRAPHICS_CONTROLLER_DATA 0x3cf
66 #define VGA_GRAPHICS_CONTROLLER_NUM 9
68 #define VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE 0x3c0
69 #define VGA_ATTRIBUTE_CONTROLLER_READ 0x3c1
70 #define VGA_ATTRIBUTE_CONTROLLER_NUM 21
72 #define VGA_DAC_WRITE_ADDR 0x3c8
73 #define VGA_DAC_READ_ADDR 0x3c7
74 #define VGA_DAC_DATA 0x3c8
75 #define VGA_DAC_PIXEL_MASK 0x3c6
77 #define VGA_DAC_NUM_ENTRIES 256
79 struct vga_misc_regs {
80 /* Read: 0x3cc; Write: 0x3c2 */
81 struct vga_misc_out_reg vga_misc_out;
83 struct vga_input_stat0_reg vga_input_stat0;
84 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
85 struct vga_input_stat1_reg vga_input_stat1;
86 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
87 struct vga_feature_control_reg vga_feature_control;
88 /* Read: 0x3c3; Write: 0x3c3 */
89 struct vga_video_subsys_enable_reg vga_video_subsys_enable;
90 } __attribute__((packed));
92 struct vga_sequencer_regs {
93 /* Address register is 0x3c4, data register is 0x3c5 */
95 struct vga_sequencer_addr_reg vga_sequencer_addr;
97 /* these can be accessed via the index, offset on start
98 or via the specific regs. For this reason, it is essential
99 that this is all packed and that the order does not change */
101 uint8_t vga_sequencer_regs[0];
104 struct vga_reset_reg vga_reset;
106 struct vga_clocking_mode_reg vga_clocking_mode;
108 struct vga_map_mask_reg vga_map_mask;
110 struct vga_char_map_select_reg vga_char_map_select;
112 struct vga_mem_mode_reg vga_mem_mode;
113 } __attribute__((packed));
115 struct vga_crt_controller_regs {
116 /* Address Register is 0x3b4 or 0x3d4 */
117 /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
118 struct vga_crt_addr_reg vga_crt_addr;
120 /* these can be accessed via the index, offset on start
121 or via the specific regs. For this reason, it is essential
122 that this is all packed and that the order does not change */
124 uint8_t vga_crt_controller_regs[0];
127 vga_horizontal_total_reg vga_horizontal_total;
129 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
131 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
133 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
135 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
137 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
139 vga_vertical_total_reg vga_vertical_total;
141 struct vga_overflow_reg vga_overflow;
143 struct vga_preset_row_scan_reg vga_preset_row_scan;
145 struct vga_max_row_scan_reg vga_row_scan;
147 struct vga_cursor_start_reg vga_cursor_start;
149 struct vga_cursor_end_reg vga_cursor_end;
151 vga_start_address_high_reg vga_start_address_high;
153 vga_start_address_low_reg vga_start_address_low;
155 vga_cursor_location_high_reg vga_cursor_location_high;
157 vga_cursor_location_low_reg vga_cursor_location_low;
159 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
161 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
163 vga_vertical_display_enable_end_reg vga_vertical_display_enable;
165 vga_offset_reg vga_offset;
167 struct vga_underline_location_reg vga_underline_location;
169 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
171 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
173 struct vga_crt_mode_control_reg vga_crt_mode_control;
175 vga_line_compare_reg vga_line_compare;
176 } __attribute__((packed));
178 struct vga_graphics_controller_regs {
179 /* Address: 0x3ce Data: 0x3cf */
182 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
184 /* these can be accessed via the index, offset on start
185 or via the specific regs. For this reason, it is essential
186 that this is all packed and that the order does not change */
188 uint8_t vga_graphics_controller_regs[0];
191 struct vga_set_reset_reg vga_set_reset;
193 struct vga_enable_set_reset_reg vga_enable_set_reset;
195 struct vga_color_compare_reg vga_color_compare;
197 struct vga_data_rotate_reg vga_data_rotate;
199 struct vga_read_map_select_reg vga_read_map_select;
201 struct vga_graphics_mode_reg vga_graphics_mode;
203 struct vga_misc_reg vga_misc;
205 struct vga_color_dont_care_reg vga_color_dont_care;
207 vga_bit_mask_reg vga_bit_mask;
208 } __attribute__((packed));
211 struct vga_attribute_contoller_regs {
213 Address AND WRITE: 0x3c0
216 The write protocol is to write the index to 0x3c0 followed by
217 the data. The read protocol is to write the index to 0x3c0
218 and then read from 0x3c1
220 IMPORTANT: write address, write data flips state back to write address
221 write address, read data DOES NOT
223 To reset to write address state, read input status register 1
225 enum { ATTR_ADDR, ATTR_DATA } state; //state of the flip flop
228 struct vga_attribute_controller_address_reg vga_attribute_controller_addr;
232 /* these can be accessed via the index, offset on start
233 or via the specific regs. For this reason, it is essential
234 that this is all packed and that the order does not change */
236 uint8_t vga_attribute_controller_regs[0];
239 vga_internal_palette_regs vga_internal_palette;
241 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
243 vga_overscan_color_reg vga_overscan_color;
245 struct vga_color_plane_enable_reg vga_color_plane_enable;
247 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
249 struct vga_color_select_reg vga_color_select;
250 } __attribute__((packed));
252 struct vga_dac_regs {
253 enum {DAC_READ=0, DAC_WRITE} state;
254 enum {RED=0,GREEN,BLUE} channel;
255 vga_dac_pixel_mask_reg vga_pixel_mask;
256 vga_dac_write_addr_reg vga_dac_write_addr;
257 vga_dac_read_addr_reg vga_dac_read_addr;
258 // the dac_data register is used only to access the registers
259 // and thus has no representation here
260 vga_palette_reg vga_dac_palette[VGA_DAC_NUM_ENTRIES];
261 } __attribute__((packed));
264 struct vga_internal {
265 struct vm_device *dev;
269 struct frame_buf *framebuf; // we render to this
271 // void *mem_store; // This is the region where the memory hooks will go
273 vga_map map[MAP_NUM]; // the maps that the host writes to
275 uint8_t latch[MAP_NUM]; // written to in any read, used during writes
277 /* Range of I/O ports here for backward compat with MDA and CGA */
278 struct vga_misc_regs vga_misc;
280 /* Address Register is 0x3b4 or 0x3d4 */
281 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
282 struct vga_crt_controller_regs vga_crt_controller;
284 /* Address register is 0x3c4, data register is 0x3c5 */
285 struct vga_sequencer_regs vga_sequencer;
287 /* Address: 0x3ce Data: 0x3cf */
288 struct vga_graphics_controller_regs vga_graphics_controller;
291 Address AND WRITE: 0x3c0
295 struct vga_attribute_contoller_regs vga_attribute_controller;
298 address for reads: 0x3c7 (also resets state machine for access to 18 bit regs
299 address for writes: 0x3c8 ("")
301 pixel mask: 0x3c6 - do not write (init to 0xff)
303 struct vga_dac_regs vga_dac;
308 static int vga_write(struct guest_info * core,
314 struct vga_internal *vga = (struct vga_internal *) priv_data;
316 PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
318 if (vga->passthrough) {
319 memcpy(V3_VAddr((void*)guest_addr),src,length);
322 /* Write mode determine by Graphics Mode Register (Index 05h).writemode */
324 switch (vga->vga_graphics_controller.vga_graphics_mode.write_mode) {
328 00b -- Write Mode 0: In this mode, the host data is first rotated
329 as per the Rotate Count field, then the Enable Set/Reset mechanism
330 selects data from this or the Set/Reset field. Then the selected
331 Logical Operation is performed on the resulting data and the data
332 in the latch register. Then the Bit Mask field is used to select
333 which bits come from the resulting data and which come
334 from the latch register. Finally, only the bit planes enabled by
335 the Memory Plane Write Enable field are written to memory.
343 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
344 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
346 offset =(uint64_t) guest_addr - (uint64_t) MEM_REGION_START;
348 for (i=0;i<length;i++,offset++) {
350 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
351 uint8_t esr = vga->vga_graphics_controller.vga_enable_set_reset.val &0xf;
352 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
353 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
355 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
356 vga_map map = vga->map[mapnum];
357 uint8_t data = ((uint8_t *)src)[i];
358 uint8_t latchval = vga->latch[mapnum];
361 data = (data>>ror) | data<<(8-ror);
363 // use SR bit if ESR is on for this map
365 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
383 // mux between latch and alu output
385 // use alu output, which is in data
407 01b -- Write Mode 1: In this mode, data is transferred directly
408 from the 32 bit latch register to display memory, affected only by
409 the Memory Plane Write Enable field. The host data is not used in this mode.
414 uint64_t offset =(uint64_t) guest_addr - (uint64_t) MEM_REGION_START;
416 for (i=0;i<length;i++,offset++) {
419 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
421 for (mapnum=0;mapnum<4;mapnum++, mm>>=1) {
422 vga_map map = vga->map[mapnum];
423 uint8_t latchval = vga->latch[mapnum];
428 map[offset] = latchval;
439 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data
440 are replicated across all 8 bits of their respective planes.
441 Then the selected Logical Operation is performed on the resulting
442 data and the data in the latch register. Then the Bit Mask field is used to
443 select which bits come from the resulting data and which come from
444 the latch register. Finally, only the bit planes enabled by the
445 Memory Plane Write Enable field are written to memory.
451 uint8_t func = vga->vga_graphics_controller.vga_data_rotate.function;
453 offset =(uint64_t) guest_addr - (uint64_t) MEM_REGION_START;
455 for (i=0;i<length;i++,offset++) {
457 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
458 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
460 for (mapnum=0;mapnum<4;mapnum++, bm>>=1, mm>>=1) {
461 vga_map map = vga->map[mapnum];
462 uint8_t data = ((uint8_t *)src)[i];
463 uint8_t latchval = vga->latch[mapnum];
465 // expand relevant bit to 8 bit
466 // it's basically esr=1, sr=bit from write
467 data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7);
484 // mux between latch and alu output
486 // use alu output, which is in data
505 /* 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used
506 as if the Enable Set/Reset field were set to 1111b. Then the host data is
507 first rotated as per the Rotate Count field, then logical ANDed with the
508 value of the Bit Mask field. The resulting value is used on the data
509 obtained from the Set/Reset field in the same way that the Bit Mask field
510 would ordinarily be used. to select which bits come from the expansion
511 of the Set/Reset field and which come from the latch register. Finally,
512 only the bit planes enabled by the Memory Plane Write Enable field
513 are written to memory.
520 uint8_t ror = vga->vga_graphics_controller.vga_data_rotate.rotate_count;
522 offset =(uint64_t) guest_addr - (uint64_t) MEM_REGION_START;
524 for (i=0;i<length;i++,offset++) {
526 uint8_t data = ((uint8_t *)src)[i];
528 data = (data>>ror) | data<<(8-ror);
530 uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
531 uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
532 uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
534 for (mapnum=0;mapnum<4;mapnum++, sr>>=1, bm>>=1, mm>>=1) {
535 vga_map map = vga->map[mapnum];
536 uint8_t latchval = vga->latch[mapnum];
538 data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
541 // mux between latch and alu output
543 // use alu output, which is in data
562 // There is no default
568 // PrintError("vga: vga_write UNIMPLEMENTED\n");
571 up to 256K mapped through a window of 128K
573 most cards support linear mode as well
575 Need to implement readability too
577 Write extended memory bit to enable all 256K:
579 Sequencer Memory Mode Register (Index 04h) . extended memory
581 Must enable writes before effects happen:
583 Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
585 Choose which addresses are supported for CPU writes:
587 Miscellaneous Graphics Register (Index 06h).memory map select
589 00b -- A0000h-BFFFFh (128K region)
590 01b -- A0000h-AFFFFh (64K region)
591 10b -- B0000h-B7FFFh (32K region)
592 11b -- B8000h-BFFFFh (32K region)
594 There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
596 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.)
598 Memory model: 64K 32 bit locations; divided into 4 64K bit planes
604 Assume linear framebuffer, starting at address buf:
610 static int vga_read(struct guest_info * core,
617 struct vga_internal *vga = (struct vga_internal *) priv_data;
619 PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
621 if (vga->passthrough) {
622 memcpy(dst,V3_VAddr((void*)guest_addr),length);
626 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
628 switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
630 /* 0 - a byte from ONE of the 4 planes is returned;
631 which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
635 mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
636 offset =(uint64_t) guest_addr - (uint64_t) MEM_REGION_START;
639 PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
642 memcpy(dst,(vga->map[mapnum])+offset,length);
644 // load the latches with the last item read
645 for (mapnum=0;mapnum<4;mapnum++) {
646 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
653 /* 1 - Compare video memory and reference color
654 (in Color Compare, except those not set in Color Don't Care),
655 each bit in returned result is one comparison between the reference color
657 Ref color is *4* bits, and thus a one byte read returns a comparison
663 uint8_t cc=vga->vga_graphics_controller.vga_color_compare.val & 0xf ;
664 uint8_t dc=vga->vga_graphics_controller.vga_color_dont_care.val & 0xf;
671 offset =(uint64_t) guest_addr - (uint64_t) MEM_REGION_START;
673 for (i=0;i<length;i++,offset++) {
676 for (mapnum=0;mapnum<4;mapnum++) {
677 map = vga->map[mapnum];
678 if ( (dc>>mapnum)&0x1 ) { // don't care
682 bits = (map[offset]&0xf) == cc;
685 bits |= (((map[offset]>>4))&0xf) == cc;
687 // not clear whether it is 0..k or k..0
693 // load the latches with the last item read
694 for (mapnum=0;mapnum<4;mapnum++) {
695 vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
700 // there is no default
709 static int render(struct vga_internal *vga)
711 PrintError("vga: render UNIMPLEMENTED\n");
716 #define ERR_WRONG_SIZE(op,reg,len,min,max) \
717 if (((len)<(min)) || ((len)>(max))) { \
718 PrintError("vga: %s of %s wrong size (%d bytes, but only %d to %d allowed)\n",(op),(reg),(len),(min),(max)); \
722 static inline void passthrough_io_in(uint16_t port, void * dest, uint_t length) {
725 *(uint8_t *)dest = v3_inb(port);
728 *(uint16_t *)dest = v3_inw(port);
731 *(uint32_t *)dest = v3_indw(port);
734 PrintError("vga: unsupported passthrough io in size %u\n",length);
740 static inline void passthrough_io_out(uint16_t port, const void * src, uint_t length) {
743 v3_outb(port, *(uint8_t *)src);
746 v3_outw(port, *(uint16_t *)src);
749 v3_outdw(port, *(uint32_t *)src);
752 PrintError("vga: unsupported passthrough io out size %u\n",length);
757 #define PASSTHROUGH_IO_IN(vga,port,dest,len) \
758 do { if ((vga)->passthrough) { passthrough_io_in(port,dest,len); } } while (0)
760 #define PASSTHROUGH_IO_OUT(vga,port,src,len) \
761 do { if ((vga)->passthrough) { passthrough_io_in(port,src,len); } } while (0)
765 static int misc_out_read(struct guest_info *core,
771 struct vga_internal *vga = (struct vga_internal *) priv_data;
773 PrintDebug("vga: misc out read data=0x%x\n", vga->vga_misc.vga_misc_out.val);
775 ERR_WRONG_SIZE("read","misc out",len,1,1);
777 PASSTHROUGH_IO_IN(vga,port,dest,len);
779 *((uint8_t*)dest) = vga->vga_misc.vga_misc_out.val;
784 static int misc_out_write(struct guest_info *core,
790 struct vga_internal *vga = (struct vga_internal *) priv_data;
792 PrintDebug("vga: misc out write data=0x%x\n", *((uint8_t*)src));
794 ERR_WRONG_SIZE("write","misc out",len,1,1);
796 PASSTHROUGH_IO_OUT(vga,port,src,len);
798 vga->vga_misc.vga_misc_out.val = *((uint8_t*)src) ;
807 static int input_stat0_read(struct guest_info *core,
813 struct vga_internal *vga = (struct vga_internal *) priv_data;
815 PrintDebug("vga: input stat0 read data=0x%x\n", vga->vga_misc.vga_input_stat0.val);
817 ERR_WRONG_SIZE("read","input stat0",len,1,1);
819 PASSTHROUGH_IO_IN(vga,port,dest,len);
821 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat0.val;
827 static int input_stat1_read(struct guest_info *core,
833 struct vga_internal *vga = (struct vga_internal *) priv_data;
835 PrintDebug("vga: input stat0 (%s) read data=0x%x\n",
836 port==0x3ba ? "mono" : "color",
837 vga->vga_misc.vga_input_stat1.val);
839 ERR_WRONG_SIZE("read","input stat1",len,1,1);
841 PASSTHROUGH_IO_IN(vga,port,dest,len);
843 *((uint8_t*)dest) = vga->vga_misc.vga_input_stat1.val;
845 // Stunningly, reading stat1 is also a way to reset
846 // the state of attribute controller address/data flipflop
847 // That is some mighty fine crack the designers were smoking.
849 vga->vga_attribute_controller.state=ATTR_ADDR;
855 static int feature_control_read(struct guest_info *core,
861 struct vga_internal *vga = (struct vga_internal *) priv_data;
863 PrintDebug("vga: feature control read data=0x%x\n",
864 vga->vga_misc.vga_feature_control.val);
866 ERR_WRONG_SIZE("read","feature control",len,1,1);
868 PASSTHROUGH_IO_IN(vga,port,dest,len);
870 *((uint8_t*)dest) = vga->vga_misc.vga_feature_control.val;
875 static int feature_control_write(struct guest_info *core,
881 struct vga_internal *vga = (struct vga_internal *) priv_data;
883 PrintDebug("vga: feature control (%s) write data=0x%x\n",
884 port==0x3ba ? "mono" : "color",
887 ERR_WRONG_SIZE("write","feature control",len,1,1);
889 PASSTHROUGH_IO_OUT(vga,port,src,len);
891 vga->vga_misc.vga_feature_control.val = *((uint8_t*)src) ;
899 static int video_subsys_enable_read(struct guest_info *core,
905 struct vga_internal *vga = (struct vga_internal *) priv_data;
907 PrintDebug("vga: video subsys enable read data=0x%x\n",
908 vga->vga_misc.vga_video_subsys_enable.val);
910 ERR_WRONG_SIZE("read","video subsys enable",len,1,1);
912 PASSTHROUGH_IO_IN(vga,port,dest,len);
914 *((uint8_t*)dest) = vga->vga_misc.vga_video_subsys_enable.val;
919 static int video_subsys_enable_write(struct guest_info *core,
925 struct vga_internal *vga = (struct vga_internal *) priv_data;
927 PrintDebug("vga: video subsys enable write data=0x%x\n", *((uint8_t*)src));
929 ERR_WRONG_SIZE("write","video subsys enable",len,1,1);
931 PASSTHROUGH_IO_OUT(vga,port,src,len);
933 vga->vga_misc.vga_video_subsys_enable.val = *((uint8_t*)src) ;
940 static int sequencer_address_read(struct guest_info *core,
946 struct vga_internal *vga = (struct vga_internal *) priv_data;
948 PrintDebug("vga: sequencer address read data=0x%x\n",
949 vga->vga_sequencer.vga_sequencer_addr.val);
951 ERR_WRONG_SIZE("read","vga sequencer addr",len,1,1);
953 PASSTHROUGH_IO_IN(vga,port,dest,len);
955 *((uint8_t*)dest) = vga->vga_sequencer.vga_sequencer_addr.val;
960 static int sequencer_address_write(struct guest_info *core,
966 struct vga_internal *vga = (struct vga_internal *) priv_data;
969 new_addr=*((uint8_t*)src);
971 PrintDebug("vga: sequencer address write data=0x%x\n", new_addr);
973 ERR_WRONG_SIZE("write","vga sequenver addr",len,1,1);
975 PASSTHROUGH_IO_OUT(vga,port,src,len);
977 if (new_addr>VGA_SEQUENCER_NUM) {
978 PrintError("vga: ignoring change of sequencer address to %u (>%u)\n",
979 new_addr, VGA_SEQUENCER_NUM);
982 vga->vga_sequencer.vga_sequencer_addr.val = *((uint8_t*)src) ;
988 static int sequencer_data_read(struct guest_info *core,
994 struct vga_internal *vga = (struct vga_internal *) priv_data;
998 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
999 data=vga->vga_sequencer.vga_sequencer_regs[index];
1001 PrintDebug("vga: sequencer data read data (index=%d) = 0x%x\n",
1004 ERR_WRONG_SIZE("read","vga sequenver data",len,1,1);
1006 PASSTHROUGH_IO_IN(vga,port,dest,len);
1008 *((uint8_t*)dest) = data;
1013 static int sequencer_data_write(struct guest_info *core,
1019 struct vga_internal *vga = (struct vga_internal *) priv_data;
1023 data=*((uint8_t*)src);
1024 index=vga->vga_sequencer.vga_sequencer_addr.val; // should mask probably
1026 PrintDebug("vga: sequencer write data (index=%d) with 0x%x\n",
1029 ERR_WRONG_SIZE("write","vga sequencer data",len,1,1);
1031 PASSTHROUGH_IO_OUT(vga,port,src,len);
1033 vga->vga_sequencer.vga_sequencer_regs[index] = data;
1043 static int crt_controller_address_read(struct guest_info *core,
1049 struct vga_internal *vga = (struct vga_internal *) priv_data;
1051 PrintDebug("vga: crt controller (%s) address read data=0x%x\n",
1052 port==0x3b4 ? "mono" : "color",
1053 vga->vga_crt_controller.vga_crt_addr.val);
1055 ERR_WRONG_SIZE("read","vga crt controller addr",len,1,1);
1057 PASSTHROUGH_IO_IN(vga,port,dest,len);
1059 *((uint8_t*)dest) = vga->vga_crt_controller.vga_crt_addr.val;
1064 static int crt_controller_address_write(struct guest_info *core,
1070 struct vga_internal *vga = (struct vga_internal *) priv_data;
1073 new_addr=*((uint8_t*)src);
1075 PrintDebug("vga: crt controller (%s) address write data=0x%x\n",
1076 port==0x3b4 ? "mono" : "color",
1079 ERR_WRONG_SIZE("write","vga crt controller addr",len,1,1);
1081 PASSTHROUGH_IO_OUT(vga,port,src,len);
1083 if (new_addr>VGA_CRT_CONTROLLER_NUM) {
1084 PrintError("vga: ignoring change of crt controller address to %u (>%u)\n",
1085 new_addr, VGA_CRT_CONTROLLER_NUM);
1088 vga->vga_crt_controller.vga_crt_addr.val = *((uint8_t*)src) ;
1094 static int crt_controller_data_read(struct guest_info *core,
1100 struct vga_internal *vga = (struct vga_internal *) priv_data;
1104 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1105 data=vga->vga_crt_controller.vga_crt_controller_regs[index];
1107 PrintDebug("vga: crt controller data (%s) read data (index=%d) = 0x%x\n",
1108 port==0x3b5 ? "mono" : "color",
1111 ERR_WRONG_SIZE("read","vga crt controller data",len,1,1);
1113 PASSTHROUGH_IO_IN(vga,port,dest,len);
1115 *((uint8_t*)dest) = data;
1120 static int crt_controller_data_write(struct guest_info *core,
1126 struct vga_internal *vga = (struct vga_internal *) priv_data;
1130 data=*((uint8_t*)src);
1132 index=vga->vga_crt_controller.vga_crt_addr.val; // should mask probably
1134 PrintDebug("vga: crt controller (%s) write data (index=%d) with 0x%x\n",
1135 port==0x3b5 ? "mono" : "color",
1138 ERR_WRONG_SIZE("write","vga crt controller data",len,1,1);
1140 PASSTHROUGH_IO_OUT(vga,port,src,len);
1142 vga->vga_crt_controller.vga_crt_controller_regs[index] = data;
1150 static int graphics_controller_address_read(struct guest_info *core,
1156 struct vga_internal *vga = (struct vga_internal *) priv_data;
1158 PrintDebug("vga: graphics controller address read data=0x%x\n",
1159 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val);
1161 ERR_WRONG_SIZE("read","vga graphics controller addr",len,1,1);
1163 PASSTHROUGH_IO_IN(vga,port,dest,len);
1165 *((uint8_t*)dest) = vga->vga_graphics_controller.vga_graphics_ctrl_addr.val;
1170 static int graphics_controller_address_write(struct guest_info *core,
1176 struct vga_internal *vga = (struct vga_internal *) priv_data;
1179 new_addr=*((uint8_t*)src);
1181 PrintDebug("vga: graphics controller address write data=0x%x\n", new_addr);
1183 ERR_WRONG_SIZE("write","vga graphics controller addr",len,1,1);
1185 PASSTHROUGH_IO_OUT(vga,port,src,len);
1187 if (new_addr>VGA_GRAPHICS_CONTROLLER_NUM) {
1188 PrintError("vga: ignoring change of graphics controller address to %u (>%u)\n",
1189 new_addr, VGA_GRAPHICS_CONTROLLER_NUM);
1192 vga->vga_graphics_controller.vga_graphics_ctrl_addr.val = *((uint8_t*)src) ;
1198 static int graphics_controller_data_read(struct guest_info *core,
1204 struct vga_internal *vga = (struct vga_internal *) priv_data;
1208 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1209 data=vga->vga_graphics_controller.vga_graphics_controller_regs[index];
1211 PrintDebug("vga: graphics controller data read data (index=%d) = 0x%x\n",
1214 ERR_WRONG_SIZE("read","vga graphics controller data",len,1,1);
1216 PASSTHROUGH_IO_IN(vga,port,dest,len);
1218 *((uint8_t*)dest) = data;
1223 static int graphics_controller_data_write(struct guest_info *core,
1229 struct vga_internal *vga = (struct vga_internal *) priv_data;
1233 data=*((uint8_t*)src);
1234 index=vga->vga_graphics_controller.vga_graphics_ctrl_addr.val; // should mask probably
1236 PrintDebug("vga: graphics_controller write data (index=%d) with 0x%x\n",
1239 ERR_WRONG_SIZE("write","vga graphics controller data",len,1,1);
1241 PASSTHROUGH_IO_OUT(vga,port,src,len);
1243 vga->vga_graphics_controller.vga_graphics_controller_regs[index] = data;
1252 /* Note that these guys have a bizarre protocol*/
1254 static int attribute_controller_address_read(struct guest_info *core,
1260 struct vga_internal *vga = (struct vga_internal *) priv_data;
1262 PrintDebug("vga: attribute controller address read data=0x%x\n",
1263 vga->vga_attribute_controller.vga_attribute_controller_addr.val);
1265 ERR_WRONG_SIZE("read","vga attribute controller addr",len,1,1);
1267 PASSTHROUGH_IO_IN(vga,port,dest,len);
1269 *((uint8_t*)dest) = vga->vga_attribute_controller.vga_attribute_controller_addr.val;
1271 // Reading the attribute controller does not change the state
1276 static int attribute_controller_address_and_data_write(struct guest_info *core,
1282 struct vga_internal *vga = (struct vga_internal *) priv_data;
1285 if (vga->vga_attribute_controller.state==ATTR_ADDR) {
1286 uint8_t new_addr = *((uint8_t*)src);
1287 // We are to treat this as an address write, and flip state
1288 // to expect data ON THIS SAME PORT
1289 PrintDebug("vga: attribute controller address write data=0x%x\n", new_addr);
1291 ERR_WRONG_SIZE("write","vga attribute controller addr",len,1,1);
1293 PASSTHROUGH_IO_OUT(vga,port,src,len);
1295 if (new_addr>VGA_ATTRIBUTE_CONTROLLER_NUM) {
1296 PrintError("vga: ignoring change of attribute controller address to %u (>%u)\n",
1297 new_addr, VGA_ATTRIBUTE_CONTROLLER_NUM);
1300 vga->vga_attribute_controller.vga_attribute_controller_addr.val = *((uint8_t*)src) ;
1302 vga->vga_attribute_controller.state=ATTR_DATA;
1305 } else if (vga->vga_attribute_controller.state==ATTR_DATA) {
1307 uint8_t data = *((uint8_t*)src);
1308 uint8_t index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1310 PrintDebug("vga: attribute controller data write index %d with data=0x%x\n", index,data);
1312 ERR_WRONG_SIZE("write","vga attribute controller data",len,1,1);
1314 PASSTHROUGH_IO_OUT(vga,port,src,len);
1316 vga->vga_attribute_controller.vga_attribute_controller_regs[index] = data;
1318 vga->vga_attribute_controller.state=ATTR_ADDR;
1327 static int attribute_controller_data_read(struct guest_info *core,
1333 struct vga_internal *vga = (struct vga_internal *) priv_data;
1337 index=vga->vga_attribute_controller.vga_attribute_controller_addr.val; // should mask probably
1338 data=vga->vga_attribute_controller.vga_attribute_controller_regs[index];
1340 PrintDebug("vga: attribute controller data read data (index=%d) = 0x%x\n",
1343 ERR_WRONG_SIZE("read","vga attribute controller data",len,1,1);
1345 PASSTHROUGH_IO_IN(vga,port,dest,len);
1347 *((uint8_t*)dest) = data;
1354 Note that these guys also have a strange protocol
1355 since they need to squeeze 18 bits of data through
1358 static int dac_write_address_read(struct guest_info *core,
1364 struct vga_internal *vga = (struct vga_internal *) priv_data;
1366 PrintDebug("vga: dac write address read data=0x%x\n",
1367 vga->vga_dac.vga_dac_write_addr);
1369 ERR_WRONG_SIZE("read","vga dac write addr",len,1,1);
1371 PASSTHROUGH_IO_IN(vga,port,dest,len);
1373 *((uint8_t*)dest) = vga->vga_dac.vga_dac_write_addr;
1375 // This read does not reset the state machine
1380 static int dac_write_address_write(struct guest_info *core,
1386 struct vga_internal *vga = (struct vga_internal *) priv_data;
1389 new_addr=*((uint8_t*)src);
1391 PrintDebug("vga: dac write address write data=0x%x\n", new_addr);
1393 ERR_WRONG_SIZE("write","vga dac write addr",len,1,1);
1395 PASSTHROUGH_IO_OUT(vga,port,src,len);
1397 // cannot be out of bounds since there are 256 regs
1399 vga->vga_dac.vga_dac_write_addr = *((uint8_t*)src) ;
1401 // Now we also need to reset the state machine
1403 vga->vga_dac.state=DAC_WRITE;
1404 vga->vga_dac.channel=RED;
1410 static int dac_read_address_read(struct guest_info *core,
1416 struct vga_internal *vga = (struct vga_internal *) priv_data;
1418 PrintDebug("vga: dac read address read data=0x%x\n",
1419 vga->vga_dac.vga_dac_read_addr);
1421 ERR_WRONG_SIZE("read","vga dac read addr",len,1,1);
1423 PASSTHROUGH_IO_IN(vga,port,dest,len);
1425 *((uint8_t*)dest) = vga->vga_dac.vga_dac_read_addr;
1427 // This read does not reset the state machine
1432 static int dac_read_address_write(struct guest_info *core,
1438 struct vga_internal *vga = (struct vga_internal *) priv_data;
1441 new_addr=*((uint8_t*)src);
1443 PrintDebug("vga: dac read address write data=0x%x\n", new_addr);
1445 ERR_WRONG_SIZE("write","vga dac read addr",len,1,1);
1447 PASSTHROUGH_IO_OUT(vga,port,src,len);
1449 // cannot be out of bounds since there are 256 regs
1451 vga->vga_dac.vga_dac_read_addr = *((uint8_t*)src) ;
1453 // Now we also need to reset the state machine
1455 vga->vga_dac.state=DAC_READ;
1456 vga->vga_dac.channel=RED;
1462 static int dac_data_read(struct guest_info *core,
1468 struct vga_internal *vga = (struct vga_internal *) priv_data;
1473 if (vga->vga_dac.state!=DAC_READ) {
1474 PrintError("vga: dac data read while in other state\n");
1475 // results undefined, so we continue
1478 ERR_WRONG_SIZE("read","vga dac read data",len,1,1);
1480 PASSTHROUGH_IO_IN(vga,port,dest,len);
1482 curreg = vga->vga_dac.vga_dac_read_addr;
1483 curchannel = vga->vga_dac.channel;
1484 data = (vga->vga_dac.vga_dac_palette[curreg] >> curchannel*8) & 0x3f;
1486 PrintDebug("vga: dac reg %u [%s] = 0x%x\n",
1488 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1489 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1492 *((uint8_t*)dest) = data;
1494 curchannel = (curchannel+1)%3;
1495 vga->vga_dac.channel=curchannel;
1496 if (curchannel==0) {
1497 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1499 vga->vga_dac.vga_dac_read_addr = curreg;
1500 vga->vga_dac.state=DAC_READ;
1507 static int dac_data_write(struct guest_info *core,
1513 struct vga_internal *vga = (struct vga_internal *) priv_data;
1517 vga_palette_reg data32;
1518 vga_palette_reg mask32;
1520 if (vga->vga_dac.state!=DAC_WRITE) {
1521 PrintError("vga: dac data write while in other state\n");
1522 // results undefined, so we continue
1525 ERR_WRONG_SIZE("read","vga dac write data",len,1,1);
1527 PASSTHROUGH_IO_OUT(vga,port,src,len);
1529 curreg = vga->vga_dac.vga_dac_write_addr;
1530 curchannel = vga->vga_dac.channel;
1531 data = *((uint8_t *)src);
1533 PrintDebug("vga: dac reg %u [%s] write with 0x%x\n",
1535 curchannel == 0 ? "RED" : curchannel == 1 ? "GREEN"
1536 : curchannel==2 ? "BLUE" : "BAD CHANNEL",
1539 data32 = data & 0x3f ;
1540 data32 <<= curchannel*8;
1541 mask32 = ~(0xff << (curchannel * 8));
1543 vga->vga_dac.vga_dac_palette[curreg] &= mask32;
1544 vga->vga_dac.vga_dac_palette[curreg] |= data32;
1546 curchannel = (curchannel+1)%3;
1547 vga->vga_dac.channel=curchannel;
1548 if (curchannel==0) {
1549 curreg = (curreg + 1) % VGA_DAC_NUM_ENTRIES;
1551 vga->vga_dac.vga_dac_write_addr = curreg;
1552 vga->vga_dac.state=DAC_WRITE;
1561 static int dac_pixel_mask_read(struct guest_info *core,
1567 struct vga_internal *vga = (struct vga_internal *) priv_data;
1569 PrintDebug("vga: dac pixel mask read data=0x%x\n",
1570 vga->vga_dac.vga_pixel_mask);
1572 ERR_WRONG_SIZE("read","vga pixel mask",len,1,1);
1574 PASSTHROUGH_IO_IN(vga,port,dest,len);
1576 *((uint8_t*)dest) = vga->vga_dac.vga_pixel_mask;
1581 static int dac_pixel_mask_write(struct guest_info *core,
1587 struct vga_internal *vga = (struct vga_internal *) priv_data;
1590 new_data=*((uint8_t*)src);
1592 PrintDebug("vga: dac pixel mask write data=0x%x\n", new_data);
1594 ERR_WRONG_SIZE("write","pixel mask",len,1,1);
1596 PASSTHROUGH_IO_OUT(vga,port,src,len);
1598 vga->vga_dac.vga_pixel_mask = new_data;
1603 static int init_vga(struct vga_internal *vga)
1605 // TODO: startup spec of register contents, if any
1606 PrintError("vga: init_vga is UNIMPLEMTED\n");
1610 static int free_vga(struct vga_internal *vga)
1614 struct vm_device *dev = vga->dev;
1616 // Framebuffer deletion is user's responsibility
1618 // if (vga->mem_store) {
1619 // V3_FreePages(v3_hva_to_hpa(vga->mem_store),MEM_REGION_NUM_PAGES);
1620 // vga->mem_store=0;
1623 for (i=0;i<MAP_NUM;i++) {
1625 V3_FreePages(V3_PAddr(vga->map[i]),MAP_SIZE/4096);
1630 v3_unhook_mem(vga->dev->vm, V3_MEM_CORE_ANY, MEM_REGION_START);
1634 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_READ);
1635 // The following also covers VGA_INPUT_STAT0_READ
1636 ret |= v3_dev_unhook_io(dev, VGA_MISC_OUT_WRITE);
1637 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1638 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_MONO);
1639 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1640 ret |= v3_dev_unhook_io(dev, VGA_INPUT_STAT1_READ_COLOR);
1641 ret |= v3_dev_unhook_io(dev, VGA_FEATURE_CONTROL_READ);
1643 ret |= v3_dev_unhook_io(dev, VGA_VIDEO_SUBSYS_ENABLE);
1645 /* Sequencer registers */
1646 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_ADDRESS);
1647 ret |= v3_dev_unhook_io(dev, VGA_SEQUENCER_DATA);
1649 /* CRT controller registers */
1650 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO);
1651 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR);
1652 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO);
1653 ret |= v3_dev_unhook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR);
1655 /* graphics controller registers */
1656 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS);
1657 ret |= v3_dev_unhook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA);
1659 /* attribute controller registers */
1660 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE);
1661 ret |= v3_dev_unhook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ);
1663 /* video DAC palette registers */
1664 ret |= v3_dev_unhook_io(dev, VGA_DAC_WRITE_ADDR);
1665 ret |= v3_dev_unhook_io(dev, VGA_DAC_READ_ADDR);
1666 ret |= v3_dev_unhook_io(dev, VGA_DAC_DATA);
1667 ret |= v3_dev_unhook_io(dev, VGA_DAC_PIXEL_MASK);
1675 static struct v3_device_ops dev_ops = {
1676 .free = (int (*)(void *))free_vga,
1680 static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1681 struct vga_internal *vga;
1685 char * dev_id = v3_cfg_val(cfg, "ID");
1686 char * passthrough = v3_cfg_val(cfg, "passthrough");
1688 // DETERMINE THE FRAMEBUFFER AND SET IT EARLY
1689 // FRAMEBUFFER IS SUPPLIED BY THE BACKEND
1691 PrintDebug("vga: init_device\n");
1693 vga = (struct vga_internal *)V3_Malloc(sizeof(struct vga_internal));
1696 PrintError("vga: cannot allocate\n");
1700 memset(vga, 0, sizeof(struct vga_internal));
1702 if (passthrough && strcasecmp(passthrough,"enable")==0) {
1703 PrintDebug("vga: enabling passthrough\n");
1704 vga->passthrough=true;
1707 // No memory store is allocated since we will use a full memory hook
1708 // The VGA maps can be read as well as written
1710 // Now allocate the maps
1711 for (i=0;i<MAP_NUM;i++) {
1712 vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
1713 if (!(vga->map[i])) {
1716 memset(vga->map[i],0,MAP_SIZE);
1719 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vga);
1722 PrintError("Could not attach device %s\n", dev_id);
1729 if (v3_hook_full_mem(vm, V3_MEM_CORE_ANY,
1730 MEM_REGION_START, MEM_REGION_END,
1734 PrintError("vga: memory book failed\n");
1735 v3_remove_device(dev);
1741 /* Miscelaneous registers */
1742 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_READ, &misc_out_read, NULL);
1743 // The following also covers VGA_INPUT_STAT0_READ
1744 ret |= v3_dev_hook_io(dev, VGA_MISC_OUT_WRITE, &input_stat0_read, &misc_out_write);
1745 // The following also covers VGA_FEATURE_CTRL_WRITE_MONO
1746 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_MONO, &input_stat1_read, &feature_control_write);
1747 // The folowinn also covers VGA FEATURE_CONTROL_WRITE_COLOR
1748 ret |= v3_dev_hook_io(dev, VGA_INPUT_STAT1_READ_COLOR, &input_stat1_read, &feature_control_write);
1749 ret |= v3_dev_hook_io(dev, VGA_FEATURE_CONTROL_READ, &feature_control_read, NULL);
1751 ret |= v3_dev_hook_io(dev, VGA_VIDEO_SUBSYS_ENABLE, &video_subsys_enable_read, &video_subsys_enable_write);
1753 /* Sequencer registers */
1754 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_ADDRESS, &sequencer_address_read, &sequencer_address_write);
1755 ret |= v3_dev_hook_io(dev, VGA_SEQUENCER_DATA, &sequencer_data_read, &sequencer_data_write);
1757 /* CRT controller registers */
1758 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_MONO, &crt_controller_address_read,&crt_controller_address_write);
1759 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_ADDRESS_COLOR, &crt_controller_address_read,&crt_controller_address_write);
1760 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_MONO, &crt_controller_data_read,&crt_controller_data_write);
1761 ret |= v3_dev_hook_io(dev, VGA_CRT_CONTROLLER_DATA_COLOR, &crt_controller_data_read,&crt_controller_data_write);
1763 /* graphics controller registers */
1764 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_ADDRESS, &graphics_controller_address_read,&graphics_controller_address_write);
1765 ret |= v3_dev_hook_io(dev, VGA_GRAPHICS_CONTROLLER_DATA, &graphics_controller_data_read,&graphics_controller_data_write);
1767 /* attribute controller registers */
1768 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_ADDRESS_AND_WRITE, &attribute_controller_address_read,&attribute_controller_address_and_data_write);
1769 ret |= v3_dev_hook_io(dev, VGA_ATTRIBUTE_CONTROLLER_READ, &attribute_controller_data_read,NULL);
1771 /* video DAC palette registers */
1772 ret |= v3_dev_hook_io(dev, VGA_DAC_WRITE_ADDR, &dac_write_address_read,&dac_write_address_write);
1773 ret |= v3_dev_hook_io(dev, VGA_DAC_READ_ADDR, &dac_read_address_read,&dac_read_address_write);
1774 ret |= v3_dev_hook_io(dev, VGA_DAC_DATA, &dac_data_read, &dac_data_write);
1775 ret |= v3_dev_hook_io(dev, VGA_DAC_PIXEL_MASK, &dac_pixel_mask_read, &dac_pixel_mask_write);
1778 PrintError("vga: Error allocating VGA I/O ports\n");
1779 v3_remove_device(dev);
1785 PrintDebug("vga: successfully added and initialized, waiting for framebuffer attach\n");
1791 device_register("VGA", vga_init);