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".
23 General Purpose Registers
25 These have well-known io ports for backward compatibility with
26 monochrome and cga controllers. Note that the ioports of
27 some of these vary depending on vga_misc_out_reg.io_addr_sel.
28 If this is zero, then they are mapped as expected for a mono card
29 If one, then as for a cga card
33 /* Read: 0x3cc; Write: 0x3c2 */
34 struct vga_misc_out_reg {
38 uint8_t io_addr_sel:1; // 0=>CRT at 0x3bx, input1 at 0x3ba (mono)
39 // 1=>CRT at 0x3dx, input1 at 0x3da (cga)
40 uint8_t en_ram:1; // allow FB writes
41 uint8_t clock_sel:2; // 00=>25.175/640 wide; 01=>28.322/720 wide
43 uint8_t horiz_sync_pol:1; // VH=01 => 400 lines; 10 => 350 lines
44 uint8_t vert_sync_pol:1; // VH=11 => 480 lines
46 } __attribute__((packed));
47 } __attribute__((packed));
48 } __attribute__((packed));
52 struct vga_input_stat0_reg {
57 uint8_t switch_sense:1; // type of display attached (mono/color)
59 uint8_t crt_inter:1; // vertical retrace interrupt pending;
60 } __attribute__((packed));
61 } __attribute__((packed));
62 } __attribute__((packed));
65 /* Read: 0x3?a 3ba for mono; 3da for cga set by misc.io_addr_sel */
66 struct vga_input_stat1_reg {
70 uint8_t disp_en:1; // in horizontal or vertical retrace (drawing)
72 uint8_t vert_retrace:1; // in vertical retrace interval
74 } __attribute__((packed));
75 } __attribute__((packed));
76 } __attribute__((packed));
79 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
80 struct vga_feature_control_reg {
84 uint8_t reserved:8; // per IBM spec
85 } __attribute__((packed));
86 } __attribute__((packed));
87 } __attribute__((packed));
89 /* Read: 0x3c3; Write: 0x3c3 */
90 struct vga_video_subsys_enable_reg {
94 uint8_t reserved:8; // per IBM spec
95 } __attribute__((packed));
96 } __attribute__((packed));
97 } __attribute__((packed));
102 These are all accessed via address and data registers.
104 Address register is 0x3c4, data register is 0x3c5
108 struct vga_sequencer_addr_reg {
112 uint8_t seq_address:3;
114 } __attribute__((packed));
115 } __attribute__((packed));
116 } __attribute__((packed))
120 struct vga_reset_reg {
124 uint8_t async_reset:1; // write zero to async clear and halt
125 uint8_t sync_reset:1; // write zero to sync clear and halt
128 } __attribute__((packed));
129 } __attribute__((packed));
130 } __attribute__((packed));
133 struct vga_clocking_mode_reg {
137 uint8_t dot8:1; // 0=>9 dot clocks per char clock; 1=>8
138 uint8_t reserved:1; // must be one
139 uint8_t shift_load:1; //
140 uint8_t dot_clock:1; // 0=> dc=master clock; 1=> dc=0.5*master
141 // e.g. 0 for 640 wide, 1 for 320 wide
142 uint8_t shift_4:1; // shift_4 shift_load Load video serializer
143 // 0 0 every char clock
146 uint8_t screen_off:1; // turn off display
148 } __attribute__((packed));
149 } __attribute__((packed));
150 } __attribute__((packed));
153 struct vga_map_mask_reg {
157 uint8_t map0_en:1; // enable map 0 (write to bank zero of mem)
158 uint8_t map1_en:1; // enable map 1
159 uint8_t map2_en:1; // enable map 2 All enabled=>chain4 mode
160 uint8_t map3_en:1; // enable map 3
162 } __attribute__((packed));
163 } __attribute__((packed));
164 } __attribute__((packed));
167 struct vga_char_map_select_reg {
171 uint8_t char_map_b_sel_lsb:2; // low 2 bits of char map b sel
172 uint8_t char_map_a_sel_lsb:2; // low 2 bits of char map a sel
173 uint8_t char_map_b_sel_msb:1; // high bit of char map b sel
174 uint8_t char_map_a_sel_msb:1; // high bit of char map a sel
177 For A: the map bits give the char sets at:
178 000 1st 8K of map (bank) 2
189 } __attribute__((packed));
190 } __attribute__((packed));
191 } __attribute__((packed));
194 struct vga_mem_mode_reg {
199 uint8_t extended_memory:1; // 1=>256K RAM, 0=>64K
201 // 0 => even addresses go to BOTH banks 0 and 2, odd 1 and 3
202 // or flip between 0/1 for CGA compat
203 // 1 => address bank sequentially, map mask selects bank
205 // 0 => map mask register used to select bank
206 // 1 => lower 2 bits of address used to select bank
208 } __attribute__((packed));
209 } __attribute__((packed));
210 } __attribute__((packed));
213 CRT Controller Registers
215 These registers control the rendering of the framebuffer (the maps)
216 to the monitor. This includes text/graphics mode, and which kind of mode
218 It's important to understand that while the vertical resolution works
219 as you would expect, using scan lines, the horizontal resolution is
220 in terms of characters (char clocks), EVEN IF YOU ARE IN A GRAPHICS MODE
222 Another important thing to understand is that the modes defined in he
223 VGA/VESA bios are just convenient names for particular settings of
224 the CRT controller registers. Other options are also possible.
226 Address register is 0x3d4 or 0x3b4 depending on misc.ioaddr_sel
227 Data register is 0x3d5 or 0x3b5 depending on misc.ioaddr_sel
228 b4/5 is for mono compatability
232 struct vga_crt_addr_reg {
236 uint8_t crt_address:5;
238 } __attribute__((packed));
239 } __attribute__((packed));
240 } __attribute__((packed))
245 // Total number of chars in horizontal interval, including retrace
246 typedef uint8_t vga_horizontal_total_reg;
249 // text: number of displayed characters minus 1 (columns-1)
250 // graphic: horizontal resolution is cols*#dotclocks_per_charclock
251 typedef uint8_t vga_horizontal_display_enable_end_reg;
254 // horizontal characer count at which blanking starts
255 typedef uint8_t vga_start_horizontal_blanking_reg;
258 struct vga_end_horizontal_blanking_reg {
262 uint8_t end_blanking:5; // when blanking ends, in char clocks
263 // top bit in horizontal retrace
264 uint8_t display_enable_skew:2; // skew in character clocks
265 uint8_t reserved:1; // must be 1
266 } __attribute__((packed));
267 } __attribute__((packed));
268 } __attribute__((packed))
272 // screen centering: char position where horizontal retrace is active
273 typedef uint8_t vga_start_horizontal_retrace_pulse_reg;
276 struct vga_end_horizontal_retrace_reg {
280 uint8_t end_horizontal_retrace:5;
281 // horizontal char count where retrace inactive
282 uint8_t horizontal_retrace_delay:2;
283 // skew of retace signal in char clocks
284 uint8_t end_horizontal_blanking5:1;
285 // top bit in horizontal blanking
286 } __attribute__((packed));
287 } __attribute__((packed));
288 } __attribute__((packed))
292 // lower 8 bits of total number of scan lines minus 2
293 // There are 10 bits total, 2 of which are on the overflow reg
294 typedef uint8_t vga_vertical_total_reg;
297 struct vga_overflow_reg {
301 uint8_t vertical_total8:1; // vert total, bit 8
302 uint8_t vertical_disp_enable_end8:1; // bit 8
303 uint8_t vertical_retrace_start8:1; // bit 8
304 uint8_t vertical_blanking_start8:1; //bit 8
305 uint8_t line_compare8:1; // bit 8;
306 uint8_t vertical_total9:1; // vert total, bit 9
307 uint8_t vertical_disp_enable_end9:1; // bit 9
308 uint8_t vertical_retrace_start9:1; // bit 9
309 } __attribute__((packed));
310 } __attribute__((packed));
311 } __attribute__((packed))
315 struct vga_preset_row_scan_reg {
319 uint8_t start_row_scan_count:5;
320 // what the row counter begins at?
321 uint8_t byte_panning:2;
324 } __attribute__((packed));
325 } __attribute__((packed));
326 } __attribute__((packed))
330 struct vga_max_row_scan_reg {
334 uint8_t max_scan_line:5;
335 // scan lines per character row minus 1
336 uint8_t start_vertical_blanking9:1;
337 // bit 9 of this field
338 uint8_t line_compare9:1;
339 // bit 9 of this field
340 uint8_t double_scan:1; // 1=> 200 scan lines double to 400
341 } __attribute__((packed));
342 } __attribute__((packed));
343 } __attribute__((packed))
347 struct vga_cursor_start_reg {
351 uint8_t row_scan_cursor_begin:5;
352 // row at which the cursor begins
353 uint8_t cursor_off:1;
354 // bit 9 of this field
356 } __attribute__((packed));
357 } __attribute__((packed));
358 } __attribute__((packed))
362 struct vga_cursor_end_reg {
366 uint8_t row_scan_cursor_end:5;
367 // row at which the cursor ends
368 uint8_t cursor_skew:2;
369 // skew in cursor clocks
371 } __attribute__((packed));
372 } __attribute__((packed));
373 } __attribute__((packed))
378 // starting address of regenerative buffer (?)
379 typedef uint8_t vga_start_address_high_reg;
381 // starting address of regenerative buffer (?)
382 typedef uint8_t vga_start_address_low_reg;
386 typedef uint8_t vga_cursor_location_high_reg;
389 typedef uint8_t vga_cursor_location_low_reg;
392 // vertical retrace start - low 8 bits, 9th is on overflow register
393 typedef uint8_t vga_vertical_retrace_start_reg;
397 struct vga_vertical_retrace_end_reg {
401 uint8_t vertical_retrace_end:4;
402 uint8_t clear_vertical_interrupt:1; // 0 to clear interrupt
403 uint8_t enable_vertical_interrupt:1; // IRQ2 on vert retrace
404 uint8_t select_5_refresh_cycles:1; // Slower displays
405 uint8_t protect_regs:1; // 1=> indices 0..7 disabled
406 } __attribute__((packed));
407 } __attribute__((packed));
408 } __attribute__((packed))
412 // lower 8 bits of 10 bit value (rest on overflow reg)
413 // this is the total number of scan lines minus one
414 typedef uint8_t vga_vertical_display_enable_end_reg;
417 // logical line width of the screen (including attrs)
418 // starting memory address of next character row is 2 or 4 times
420 typedef uint8_t vga_offset_reg;
424 struct vga_underline_location_reg {
428 uint8_t start_underline:5; // scan line in char where UL starts
429 uint8_t count_by_four:1; // memory addresses count by 4 (for dw)
430 uint8_t doubleword:1; // memory addresses are 32 bits
432 } __attribute__((packed));
433 } __attribute__((packed));
434 } __attribute__((packed))
438 // 8 bits of 10 bit quanity, rest are on overflow and maximum scan line reg
439 // scan line count at which vertical blanking goes on, minus one
440 typedef uint8_t vga_start_vertical_blanking_reg;
443 // scan line count at which vertical blanking goes off
444 typedef uint8_t vga_end_vertical_blanking_reg;
448 struct vga_crt_mode_control_reg {
453 // bit 13 of output mux come from rowscan, bit zero if zero
454 // otherwise from bit 13 of address counter
455 // ?? compatability with CGA
457 uint8_t select_row_scan_ctr:1;
458 // bit 14 of output mux comes from bit 1 of rowscan if zero
459 // otherwise from bit 14 of addres counter
462 uint8_t horizontal_retrace_select:1;
463 // select clock of vertical timing counter
464 // 0 = horiz retrace clock, 1=same / 2
466 uint8_t count_by_two:1;
467 // address counter source
468 // 0 = character clock
469 // 1 = character clock / 2 (word)
473 uint8_t address_wrap:1;
474 // is MA 13 or MA 15 output in MA 0 when in word address mode
476 uint8_t word_byte_mode:1;
477 // 0 = word mode memory access , 1= byte
480 // 0 = stop horizontal and vertical retrace
481 } __attribute__((packed));
482 } __attribute__((packed));
483 } __attribute__((packed))
487 // lower 8 bits of 10 bit counter; rest are on overflow and max scan line regs
488 // line counter is zeroed when it hits this value
489 typedef uint8_t vga_line_compare_reg;
492 Graphics Controller Registers
494 These registers control how the framebuffer / banks are accessed
495 from the host computer. How a memory write is translated is
496 determined by these settings.
504 struct vga_graphics_ctrl_addr_reg {
508 uint8_t graphics_address:4;
510 } __attribute__((packed));
511 } __attribute__((packed));
512 } __attribute__((packed))
516 // these are the values written to each map given memory write
517 // mode 0. While they are single bits, they are extended to full
519 struct vga_set_reset_reg {
523 uint8_t sr0:1; // bank 0
524 uint8_t sr1:1; // bank 1
525 uint8_t sr2:1; // bank 2
526 uint8_t sr3:1; // bank 3
528 } __attribute__((packed));
529 } __attribute__((packed));
530 } __attribute__((packed))
534 // these flags enable the use of the set/reset register values
535 // in writing the map when write mode 0 is used
536 struct vga_enable_set_reset_reg {
540 uint8_t esr0:1; // bank 0
541 uint8_t esr1:1; // bank 1
542 uint8_t esr2:1; // bank 2
543 uint8_t esr3:1; // bank 3
545 } __attribute__((packed));
546 } __attribute__((packed));
547 } __attribute__((packed))
551 // Color comparison values for one of the read modes
552 struct vga_color_compare_reg {
556 uint8_t cc0:1; // bank 0
557 uint8_t cc1:1; // bank 1
558 uint8_t cc2:1; // bank 2
559 uint8_t cc3:1; // bank 3
561 } __attribute__((packed));
562 } __attribute__((packed));
563 } __attribute__((packed))
567 // rotation amount and function for write mode 0 and others
568 struct vga_data_rotate_reg {
572 uint8_t rotate_count:3; // amount to ROR bits being written
573 uint8_t function:2; // function to use
579 } __attribute__((packed));
580 } __attribute__((packed));
581 } __attribute__((packed))
585 // which of the maps (banks) will be read from when a system read occurs
586 // Does not affect color compare reads
587 struct vga_read_map_select_reg {
591 uint8_t map_select:2; // which one you want to read
593 } __attribute__((packed));
594 } __attribute__((packed));
595 } __attribute__((packed))
599 // Graphics Mode DOES NOT MEAN graphics mode - it means
600 // the modes in which framebuffer reads/writes are done
601 struct vga_graphics_mode_reg {
605 uint8_t write_mode:2;
608 From the IBM docmentation:
610 0 0 Each memory map is written with the system data rotated by the count
611 in the Data Rotate register. If the set/reset function is enabled for a
612 specific map, that map receives the 8-bit value contained in the
615 0 1 Each memory map is written with the contents of the system latches.
616 These latches are loaded by a system read operation.
618 1 0 Memory map n (0 through 3) is filled with 8 bits of the value of data
621 1 1 Each memory map is written with the 8-bit value contained in the
622 Set/Reset register for that map (the Enable Set/Reset register has no
623 effect). Rotated system data is ANDed with the Bit Mask register to
624 form an 8-bit value that performs the same function as the Bit Mask
625 register in write modes 0 and 2 (see also Bit Mask register on
630 // 1 = read gets comparison of all maps and color compare
631 // 0 = read gets bits from selected map
633 // 1 = odd/even addressing as in CGMA
635 // notice that this is the OPPOSITE of the bit in the sequencer!
636 uint8_t shift_reg_mode:1;
637 // 1 = shift regs get odd bits from odd maps and even/even
638 uint8_t c256:1; // 1 = 256 color mode
639 // 0 = shift_reg_mode controls shift regs
641 } __attribute__((packed));
642 } __attribute__((packed));
643 } __attribute__((packed))
648 struct vga_misc_reg {
652 uint8_t graphics_mode:1;
653 // if on, then we are in a graphics mode
654 // if off, we are in a text mode
656 // if on, then low order bit of system address
657 // selects odd or even map
658 uint8_t memory_map:2;
659 // Controls mapping of regenerative buffer into address space
660 // 00 => A0000 for 128K
661 // 01 => A0000 for 64K
662 // 10 => B0000 for 32K
663 // 11 => B8000 for 32K
665 } __attribute__((packed));
666 } __attribute__((packed));
667 } __attribute__((packed))
672 struct vga_color_dont_care_reg {
680 // if off then the corresponding map is not
681 // considered in color comparison
683 } __attribute__((packed));
684 } __attribute__((packed));
685 } __attribute__((packed))
689 typedef uint8_t vga_bit_mask_reg;
690 // bit high means corresponding bit in each mask
691 // can be changed (used for write modes 0 and 2)
694 Attribute Controller Registers
696 The attribute controller essentially handles
697 attributes in text mode and palletes in graphics mode
699 Address AND WRITE: 0x3c0
702 The write protocol is to write the index to 0x3c0 followed by
703 the data. The read protocol is to write the index to 0x3c0
704 and then read from 0x3c1
706 IMPORTANT: write address, write data flips state back to write address
707 write address, read data DOES NOT
709 To reset to write address state, read input status register 1
713 struct vga_attribute_controller_address_reg {
717 uint8_t index:5; // actual address
718 uint8_t internal_palette_address_source:1;
719 // 0 => use the internal color palette (load the regs)
720 // 1 => use the external color palette
722 } __attribute__((packed));
723 } __attribute__((packed));
724 } __attribute__((packed))
728 Internal Palette Registers
732 Register k maps attribute k to the palette entry loaded in register k
734 struct vga_internal_palette_reg {
738 uint8_t palette_data:6; // which palette entry to use
740 } __attribute__((packed));
741 } __attribute__((packed));
742 } __attribute__((packed))
745 typedef struct vga_internal_palette_reg vga_internal_palette_regs[16];
748 struct vga_attribute_mode_control_reg {
752 uint8_t graphics:1; // graphics versus text mode
753 uint8_t mono_emul:1; // emulate an MDA
754 uint8_t enable_line_graphics_char_code:1;
755 // 1 => enable special line graphics characters
756 // and force 9th dot to be same as 8th dot of char
757 uint8_t enable_blink;
758 // 1 => MSB of the attribute means blink (8 colors + blink)
759 // 0 => MSB of the attribute means intensity (16 colors)
761 uint8_t pixel_panning:1;
762 // if 1, pixel panning reg set to 0 when line compare succeeds
763 uint8_t pixel_width:1;
764 // 1 => 8 bit color (256 colors)
765 uint8_t p54_select:1;
766 // select source of p5 and p6 inputs to DAC
767 // 0 => use internal palette regs
768 // 1 => use color select reg
769 } __attribute__((packed));
770 } __attribute__((packed));
771 } __attribute__((packed))
775 // this is the screen border color
776 typedef uint8_t vga_overscan_color_reg;
779 // Enable the corresponding display memory color plane
780 struct vga_color_plane_enable_reg {
784 uint8_t enable_color_plane:4;
786 } __attribute__((packed));
787 } __attribute__((packed));
788 } __attribute__((packed))
792 // number of pixels to shift the display to the left
793 struct vga_horizontal_pixel_pan_reg {
797 uint8_t horizontal_pixel_pan:4;
799 } __attribute__((packed));
800 } __attribute__((packed));
801 } __attribute__((packed))
806 // These allow for quick switching back and forth between
808 struct vga_color_select_reg {
817 } __attribute__((packed));
818 } __attribute__((packed));
819 } __attribute__((packed))
825 Used to derive the ultimate pixel colors that are rendered on the display
827 There are 256 palette registers
828 We can change any one or read any one
832 // The palette register that will returned on a data write
834 typedef uint8_t vga_dac_write_addr_reg;
837 // The palette register that will returned on a data read
839 typedef uint8_t vga_dac_read_addr_reg;
842 // Read or write of a palette register
844 // Successive references to this register increment
845 // the palette register index (for reads and writes separately)
846 // Three SUCCESSIVE WRITES ARE EXPECTED to set the 18 bit register
847 // Three SUCCESSIVE READS ARE EXPECTED to read out the register
848 // reads or writes are in order RED GREEN BLUE
849 // ADDRESS REG WRITE always resets
850 typedef uint8_t vga_dac_data_reg;
855 typedef uint8_t vga_dac_pixel_mask_reg;
857 // Palette register (256 of these)
858 // strictly speaking, each of these is 18 bits wide, 6 bits per channel
859 // We will provide reg&0x3f, reg>>8 & 0x3f, etc
860 // This is red, green, blue
861 typedef uint32_t vga_palette_reg;
865 // What attribute bytes mean in text mode
867 struct vga_attribute_byte {
871 uint8_t fore:3; //foreground color
872 uint8_t foreground_intensity_or_font_select:1; // depends on char map select reg
873 // character map selection is effected
874 // when memory_mode.extended meomory=1
875 // and the two character map enteries on character_map_select are
877 uint8_t back:3; //background color
878 uint8_t blinking_or_bg_intensity:1;
879 // attribute mode control.enableblink = 1 => blink
880 // =0 => intensity (16 colors of bg)
881 } __attribute__((packed));
882 } __attribute__((packed));
883 } __attribute__((packed));