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_dev_mgr.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_types.h>
26 #define MAP_SIZE 65536
29 typedef uint8_t vga_map[MAP_SIZE];
32 struct vga_misc_regs {
33 /* Read: 0x3cc; Write: 0x3c2 */
34 struct vga_misc_out_reg vga_misc_out;
36 struct vga_input_stat0_reg vga_input_stat0;
37 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
38 struct vga_input_stat1_reg vga_input_stat1;
39 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
40 struct vga_feature_control_reg vga_feature_control;
41 /* Read: 0x3c3; Write: 0x3c3 */
42 struct vga_video_subsys_enable_reg vga_video_subsys_enable;
43 } __attribute__((packed));
45 struct vga_sequencer_regs {
46 /* Address register is 0x3c4, data register is 0x3c5 */
48 struct vga_sequencer_addr_reg vga_sequencer_addr;
50 /* these can be accessed via the index, offset on start
51 or via the specific regs. For this reason, it is essential
52 that this is all packed and that the order does not change */
54 uint8_t vga_sequencer_regs[0];
57 struct vga_reset_reg vga_reset;
59 struct vga_clocking_mode_reg vga_clocking_mode;
61 struct vga_map_mask_reg vga_map_mask;
63 struct vga_char_map_select_reg vga_char_map_select;
65 struct vga_mem_mode_reg vga_mem_mode;
66 } __attribute__((packed));
68 struct vga_crt_controller_regs {
69 /* Address Register is 0x3b4 or 0x3d4 */
70 /* Data register is 0x3b5 or 0x3d5 based on mono versus color */
71 struct vga_crt_addr_reg cga_crt_addr;
73 /* these can be accessed via the index, offset on start
74 or via the specific regs. For this reason, it is essential
75 that this is all packed and that the order does not change */
77 uint8_t vga_crt_controller_regs[0];
80 vga_horizontal_total_reg vga_horizontal_total;
82 vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
84 vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
86 struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
88 vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
90 struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
92 vga_vertical_total_reg vga_vertical_total;
94 struct vga_overflow_reg vga_overflow;
96 struct vga_preset_row_scan_reg vga_preset_row_scan;
98 struct vga_max_row_scan_reg vga_row_scan;
100 struct vga_cursor_start_reg vga_cursor_start;
102 struct vga_cursor_end_reg vga_cursor_end;
104 vga_start_address_high_reg vga_start_address_high;
106 vga_start_address_low_reg vga_start_address_low;
108 vga_cursor_location_high_reg vga_cursor_location_high;
110 vga_cursor_location_low_reg vga_cursor_location_low;
112 vga_vertical_retrace_start_reg vga_vertical_retrace_start;
114 struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
116 vga_vertical_display_enable_end_reg vga_vertical_display_enable;
118 vga_offset_reg vga_offset;
120 struct vga_underline_location_reg vga_underline_location;
122 vga_start_vertical_blanking_reg vga_start_vertical_blanking;
124 vga_end_vertical_blanking_reg vga_end_vertical_blanking;
126 struct vga_crt_mode_control_reg vga_crt_mode_control;
128 vga_line_compare_reg vga_line_compare;
129 } __attribute__((packed));
131 struct vga_graphics_controller_regs {
132 /* Address: 0x3ce Data: 0x3cf */
135 struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
137 /* these can be accessed via the index, offset on start
138 or via the specific regs. For this reason, it is essential
139 that this is all packed and that the order does not change */
141 uint8_t vga_graphics_controller_regs[0];
144 struct vga_set_reset_reg vga_set_reset;
146 struct vga_enable_set_reset_reg vga_enable_set_reset;
148 struct vga_color_compare_reg vga_color_compare;
150 struct vga_data_rotate_reg vga_data_rotate;
152 struct vga_read_map_select_reg vga_read_map_select;
154 struct vga_graphics_mode_reg vga_graphics_mode;
156 struct vga_misc_reg vga_misc;
158 struct vga_color_dont_care__reg vga_color_dont_care;
160 vga_bit_mask_reg vga_bit_mask;
161 } __attribute__((packed));
164 struct vga_attribute_contoller_regs {
166 Address AND WRITE: 0x3c0
169 The write protocol is to write the index to 0x3c0 followed by
170 the data. The read protocol is to write the index to 0x3c0
171 and then read from 0x3c1
173 IMPORTANT: write address, write data flips state back to write address
174 write address, read data DOES NOT
176 To reset to write address state, read input status register 1
180 struct vga_attribute_controller_address_reg vga_attribute_controller_address;
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_attribute_controller_regs[0];
191 vga_internal_palette_regs vga_internal_palette;
193 struct vga_attribute_mode_control_reg vga_attribute_mode_control;
195 vga_overscan_color_reg vga_overscan_color;
197 struct vga_color_plane_enable_reg vga_color_plane_enable;
199 struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
201 struct vga_color_select_reg vga_color_select;
202 } __attribute__((packed));
204 struct vga_internal {
205 struct frame_buf *framebuf; // we render to this
207 vga_map map[MAP_NUM];
209 /* Range of I/O ports here for backward compat with MDA and CGA */
210 struct vga_misc_regs vga_misc;
212 /* Address Register is 0x3b4 or 0x3d4 */
213 /* Data register is 0x3b5 or 0x3d5 based on MDA/CGA/VGA (backward compat) */
214 struct vga_crt_controller_regs vga_crt_controller;
216 /* Address register is 0x3c4, data register is 0x3c5 */
217 struct vga_sequencer_regs vga_sequencer;
219 /* Address: 0x3ce Data: 0x3cf */
220 struct vga_graphics_controller_regs vga_graphics_contoller;
223 Address AND WRITE: 0x3c0
227 struct vga_attribute_contoller_regs vga_attribute_controller;
233 up to 256K mapped through a window of 128K
235 most cards support linear mode as well
237 Need to implement readability too
239 Write extended memory bit to enable all 256K:
241 Sequencer Memory Mode Register (Index 04h) . extended memory
243 Must enable writes before effects happen:
245 Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
247 Choose which addresses are supported for CPU writes:
249 Miscellaneous Graphics Register (Index 06h).memory map select
251 00b -- A0000h-BFFFFh (128K region)
252 01b -- A0000h-AFFFFh (64K region)
253 10b -- B0000h-B7FFFh (32K region)
254 11b -- B8000h-BFFFFh (32K region)
256 There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
258 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.)
260 Memory model: 64K 32 bit locations; divided into 4 64K bit planes
262 Reading, 2 modes, set via Graphics Mode Register (index 05h).Read Mode:
263 0 - a byte from ONE of the 4 planes is returned; which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
264 1 - Compare video memory and reference color (in Color Compare, except those not set in Color Don't Care), each bit in returned result is one comparison between the reference color, and is set to one if true (plane by plane, I assume)
266 Write Modes - set via Graphics Mode Register (Index 05h).writemode
268 00b -- Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
270 01b -- Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode.
272 10b -- Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
274 11b -- Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
276 five stages of a write:
278 write(void *adx, uint8_t x) // or 4 byte?!
282 switch (Write Mode) {
285 x = ROR(x,Rotate Count)
287 // 2. Clone from Host Data or Set/Reset Reg
289 if (Enable Set/Reset[i]) {
290 rx[i]=Set/Reset (expanded to 8 bits)
296 // 3. Logical Operator
298 rx[i] = rx[i] LOP LATCH_REG[i]
299 // LOP = NOP, AND, OR, XOR
304 rx[i] = BITWISE_MUX(rx[i], LATCH_REG[i], Bit Mask Reg);
307 // 5. Selective Write
309 if (Map Mask Reg.Memory Plane Write Enable[i])
310 BUF[TRANSLATE(adx,i)] = rx[i];
315 // 4. Select latch register directly
317 rx[i] = LATCH_REG[i];
319 // 5. Selective Write
321 if (Map Mask Reg.Memory Plane Write Enable[i])
322 BUF[TRANSLATE(adx,i)] = rx[i];
330 Assume linear framebuffer, starting at address buf: