Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


VGA: added internal state structure and comments on operation
[palacios.git] / palacios / src / devices / vga.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2011, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Peter Dinda <pdinda@northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_dev_mgr.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_types.h>
23
24 #include "vga_regs.h"
25
26 #define MAP_SIZE 65536
27 #define MAP_NUM  4
28
29 typedef uint8_t vga_map[MAP_SIZE];
30
31
32 struct vga_misc_regs {
33     /* Read: 0x3cc; Write: 0x3c2 */
34     struct vga_misc_out_reg        vga_misc_out;
35     /* Read: 0x3c2 */
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));
44
45 struct vga_sequencer_regs {
46     /*   Address register is 0x3c4, data register is 0x3c5 */
47     /* 0x3c4 */
48     struct vga_sequencer_addr_reg vga_sequencer_addr;
49
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 */
53     
54     uint8_t  vga_sequencer_regs[0];
55
56     /* Index 0 */
57     struct vga_reset_reg   vga_reset;
58     /* Index 1 */
59     struct vga_clocking_mode_reg vga_clocking_mode;
60     /* Index 2 */
61     struct vga_map_mask_reg vga_map_mask;
62     /* Index 3 */
63     struct vga_char_map_select_reg vga_char_map_select;
64     /* Index 4 */
65     struct vga_mem_mode_reg  vga_mem_mode;
66 } __attribute__((packed));
67
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;
72
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 */
76     
77     uint8_t  vga_crt_controller_regs[0];
78
79     /* index 0 */
80     vga_horizontal_total_reg vga_horizontal_total;
81     /* index 1 */
82     vga_horizontal_display_enable_end_reg vga_horizontal_display_enable_end;
83     /* index 2 */
84     vga_start_horizontal_blanking_reg vga_start_horizontal_blanking;
85     /* index 3 */
86     struct vga_end_horizontal_blanking_reg vga_end_horizontal_blanking;
87     /* index 4 */
88     vga_start_horizontal_retrace_pulse_reg vga_start_horizontal_retrace_pulse;
89     /* index 5 */
90     struct vga_end_horizontal_retrace_reg vga_end_horizontal_retrace;
91     /* index 6 */
92     vga_vertical_total_reg vga_vertical_total;
93     /* index 7 */
94     struct vga_overflow_reg vga_overflow;
95     /* index 8 */
96     struct vga_preset_row_scan_reg vga_preset_row_scan;
97     /* index 9 */
98     struct vga_max_row_scan_reg vga_row_scan;
99     /* index 10 */
100     struct vga_cursor_start_reg vga_cursor_start;
101     /* index 11 */
102     struct vga_cursor_end_reg vga_cursor_end;
103     /* index 12 */
104     vga_start_address_high_reg vga_start_address_high;
105     /* index 13 */
106     vga_start_address_low_reg vga_start_address_low;
107     /* index 14 */
108     vga_cursor_location_high_reg vga_cursor_location_high;
109     /* index 15 */
110     vga_cursor_location_low_reg vga_cursor_location_low;
111     /* index 16 */
112     vga_vertical_retrace_start_reg vga_vertical_retrace_start;
113     /* index 17 */
114     struct vga_vertical_retrace_end_reg vga_vertical_retrace_end;
115     /* index 18 */
116     vga_vertical_display_enable_end_reg vga_vertical_display_enable;
117     /* index 19 */
118     vga_offset_reg vga_offset;
119     /* index 20 */
120     struct vga_underline_location_reg vga_underline_location;
121     /* index 21 */
122     vga_start_vertical_blanking_reg vga_start_vertical_blanking;
123     /* index 22 */
124     vga_end_vertical_blanking_reg vga_end_vertical_blanking;
125     /* index 23 */
126     struct vga_crt_mode_control_reg vga_crt_mode_control;
127     /* index 24 */
128     vga_line_compare_reg vga_line_compare;
129 } __attribute__((packed));
130
131 struct vga_graphics_controller_regs {
132     /*   Address: 0x3ce    Data: 0x3cf */
133
134     /* 0x3ce */
135     struct vga_graphics_ctrl_addr_reg vga_graphics_ctrl_addr;
136
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 */
140     
141     uint8_t  vga_graphics_controller_regs[0];
142
143     /* Index 0 */
144     struct vga_set_reset_reg vga_set_reset;
145     /* Index 1 */
146     struct vga_enable_set_reset_reg vga_enable_set_reset;
147     /* Index 2 */
148     struct vga_color_compare_reg vga_color_compare;
149     /* Index 3 */
150     struct vga_data_rotate_reg vga_data_rotate;
151     /* Index 4 */
152     struct vga_read_map_select_reg vga_read_map_select;
153     /* Index 5 */
154     struct vga_graphics_mode_reg vga_graphics_mode;
155     /* Index 6 */
156     struct vga_misc_reg vga_misc;
157     /* Index 7 */
158     struct vga_color_dont_care__reg vga_color_dont_care;
159     /* Index 8 */
160     vga_bit_mask_reg vga_bit_mask;
161 } __attribute__((packed));
162
163
164 struct vga_attribute_contoller_regs {
165     /*
166       Address AND WRITE: 0x3c0
167       Read: 0x3c1
168
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
172   
173       IMPORTANT: write address, write data flips state back to write address
174       write address, read data DOES NOT
175
176       To reset to write address state, read input status register 1
177 */
178
179     /* 0x3c0 */
180     struct vga_attribute_controller_address_reg vga_attribute_controller_address;
181
182
183     
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 */
187     
188     uint8_t  vga_attribute_controller_regs[0];
189
190     /* Indices 0..15 */
191     vga_internal_palette_regs   vga_internal_palette;
192     /* Index 16 */
193     struct vga_attribute_mode_control_reg vga_attribute_mode_control;
194     /* Index 17 */
195     vga_overscan_color_reg vga_overscan_color;
196     /* Index 18 */
197     struct vga_color_plane_enable_reg vga_color_plane_enable;
198     /* Index 19 */
199     struct vga_horizontal_pixel_pan_reg vga_horizontal_pixel_pan;
200     /* Index 20 */
201     struct vga_color_select_reg vga_color_select;
202 } __attribute__((packed));
203
204 struct vga_internal {
205     struct frame_buf *framebuf; // we render to this
206     
207     vga_map  map[MAP_NUM];
208
209     /* Range of I/O ports here for backward compat with MDA and CGA */
210     struct vga_misc_regs  vga_misc;
211
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;
215
216     /*   Address register is 0x3c4, data register is 0x3c5 */
217     struct vga_sequencer_regs vga_sequencer;
218
219     /*   Address: 0x3ce    Data: 0x3cf */
220     struct vga_graphics_controller_regs vga_graphics_contoller;
221
222     /*
223       Address AND WRITE: 0x3c0
224       Read: 0x3c1
225       Flip-Flop
226     */
227     struct vga_attribute_contoller_regs vga_attribute_controller;
228
229 };
230
231
232 /*
233 up to 256K mapped through a window of 128K
234
235 most cards support linear mode as well
236
237 Need to implement readability too
238
239 Write extended memory bit to enable all 256K: 
240
241    Sequencer Memory Mode Register (Index 04h) . extended memory
242
243 Must enable writes before effects happen:
244   
245   Miscellaneous Output Register (Read at 3CCh, Write at 3C2h).ram enable
246
247 Choose which addresses are supported for CPU writes:
248
249 Miscellaneous Graphics Register (Index 06h).memory map select
250  
251 00b -- A0000h-BFFFFh (128K region)
252 01b -- A0000h-AFFFFh (64K region)
253 10b -- B0000h-B7FFFh (32K region)
254 11b -- B8000h-BFFFFh (32K region)
255
256 There are three addressing modes: Chain 4, Odd/Even mode, and normal mode:
257
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.)
259
260 Memory model: 64K 32 bit locations; divided into 4 64K bit planes
261
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)
265
266 Write Modes - set via Graphics Mode Register (Index 05h).writemode
267
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.
269
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.
271
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.
273
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.
275
276 five stages of a write:
277
278 write(void *adx, uint8_t x)  // or 4 byte?!
279   
280 uint8_t rx[4];
281
282 switch (Write Mode) { 
283 case 0:
284 // 1. Rotate
285    x = ROR(x,Rotate Count)
286
287 // 2. Clone from Host Data or Set/Reset Reg
288    for (i=0;i<4;i++) { 
289       if (Enable Set/Reset[i]) {
290           rx[i]=Set/Reset (expanded to 8 bits)
291        } else { 
292           rx[i]=x;
293        }
294    }    
295
296 // 3. Logical Operator 
297    for (i=0;i<4;i++) {
298       rx[i] = rx[i] LOP LATCH_REG[i]
299 //    LOP = NOP, AND, OR, XOR
300    }
301
302 // 4. Select
303    for (i=0;i<4;i++) { 
304       rx[i] = BITWISE_MUX(rx[i], LATCH_REG[i], Bit Mask Reg);
305    }
306
307 // 5. Selective Write
308    for (i=0;i<4;i++) { 
309      if (Map Mask Reg.Memory Plane Write Enable[i])
310       BUF[TRANSLATE(adx,i)] = rx[i];
311    }
312 break;
313
314 case 1:
315 // 4. Select latch register directly
316    for (i=0;i<4;i++) { 
317       rx[i] = LATCH_REG[i];
318    }
319 // 5. Selective Write
320    for (i=0;i<4;i++) { 
321      if (Map Mask Reg.Memory Plane Write Enable[i])
322       BUF[TRANSLATE(adx,i)] = rx[i];
323    }
324
325
326
327    
328
329
330 Assume linear framebuffer, starting at address buf:
331
332 */