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 // 1 => address bank sequentially, map mask selects bank
204 // 0 => map mask register used to select bank
205 // 1 => lower 2 bits of address used to select bank
207 } __attribute__((packed));
208 } __attribute__((packed));
209 } __attribute__((packed));
212 CRT Controller Registers
214 These registers control the rendering of the framebuffer (the maps)
215 to the monitor. This includes text/graphics mode, and which kind of mode
217 It's important to understand that while the vertical resolution works
218 as you would expect, using scan lines, the horizontal resolution is
219 in terms of characters (char clocks), EVEN IF YOU ARE IN A GRAPHICS MODE
221 Another important thing to understand is that the modes defined in he
222 VGA/VESA bios are just convenient names for particular settings of
223 the CRT controller registers. Other options are also possible.
225 Address register is 0x3d4 or 0x3b4 depending on misc.ioaddr_sel
226 Data register is 0x3d5 or 0x3b5 depending on misc.ioaddr_sel
227 b4/5 is for mono compatability
231 struct vga_crt_addr_reg {
235 uint8_t crt_address:5;
237 } __attribute__((packed));
238 } __attribute__((packed));
239 } __attribute__((packed))
244 // Total number of chars in horizontal interval, including retrace
245 typedef uint8_t vga_horizontal_total_reg;
248 // text: number of displayed characters minus 1 (columns-1)
249 // graphic: horizontal resolution is cols*#dotclocks_per_charclock
250 typedef uint8_t vga_horizontal_display_enable_end_reg;
253 // horizontal characer count at which blanking starts
254 typedef uint8_t vga_start_horizontal_blanking_reg;
257 struct vga_end_horizontal_blanking_reg {
261 uint8_t end_blanking:5; // when blanking ends, in char clocks
262 // top bit in horizontal retrace
263 uint8_t display_enable_skew:2; // skew in character clocks
264 uint8_t reserved:1; // must be 1
265 } __attribute__((packed));
266 } __attribute__((packed));
267 } __attribute__((packed))
271 // screen centering: char position where horizontal retrace is active
272 typedef uint8_t vga_start_horizontal_retrace_pulse_reg;
275 struct vga_end_horizontal_retrace_reg {
279 uint8_t end_horizontal_retrace:5;
280 // horizontal char count where retrace inactive
281 uint8_t horizontal_retrace_delay:2;
282 // skew of retace signal in char clocks
283 uint8_t end_horizontal_blanking5:1;
284 // top bit in horizontal blanking
285 } __attribute__((packed));
286 } __attribute__((packed));
287 } __attribute__((packed))
291 // lower 8 bits of total number of scan lines minus 2
292 // There are 10 bits total, 2 of which are on the overflow reg
293 typedef uint8_t vga_vertical_total_reg;
296 struct vga_overflow_reg {
300 uint8_t vertical_total8:1; // vert total, bit 8
301 uint8_t vertical_disp_enable_end8:1; // bit 8
302 uint8_t vertical_retrace_start8:1; // bit 8
303 uint8_t vertical_blanking_start8:1; //bit 8
304 uint8_t line_compare8:1; // bit 8;
305 uint8_t vertical_total9:1; // vert total, bit 9
306 uint8_t vertical_disp_enable_end9:1; // bit 9
307 uint8_t vertical_retrace_start9:1; // bit 9
308 } __attribute__((packed));
309 } __attribute__((packed));
310 } __attribute__((packed))
314 struct vga_preset_row_scan_reg {
318 uint8_t start_row_scan_count:5;
319 // what the row counter begins at?
320 uint8_t byte_panning:2;
323 } __attribute__((packed));
324 } __attribute__((packed));
325 } __attribute__((packed))
329 struct vga_max_row_scan_reg {
333 uint8_t max_scan_line:5;
334 // scan lines per character row minus 1
335 uint8_t start_vertical_blanking9:1;
336 // bit 9 of this field
337 uint8_t line_compare9:1;
338 // bit 9 of this field
339 uint8_t double_scan:1; // 1=> 200 scan lines double to 400
340 } __attribute__((packed));
341 } __attribute__((packed));
342 } __attribute__((packed))
346 struct vga_cursor_start_reg {
350 uint8_t row_scan_cursor_begin:5;
351 // row at which the cursor begins
352 uint8_t cursor_off:1;
353 // bit 9 of this field
355 } __attribute__((packed));
356 } __attribute__((packed));
357 } __attribute__((packed))
361 struct vga_cursor_end_reg {
365 uint8_t row_scan_cursor_end:5;
366 // row at which the cursor ends
367 uint8_t cursor_skew:2;
368 // skew in cursor clocks
370 } __attribute__((packed));
371 } __attribute__((packed));
372 } __attribute__((packed))
377 // starting address of regenerative buffer (?)
378 typedef uint8_t vga_start_address_high_reg;
380 // starting address of regenerative buffer (?)
381 typedef uint8_t vga_start_address_low_reg;
385 typedef uint8_t vga_cursor_location_high_reg;
388 typedef uint8_t vga_cursor_location_low_reg;
391 // vertical retrace start - low 8 bits, 9th is on overflow register
392 typedef uint8_t vga_vertical_retrace_start_reg;
396 struct vga_vertical_retrace_end_reg {
400 uint8_t vertical_retrace_end:4;
401 uint8_t clear_vertical_interrupt:1; // 0 to clear interrupt
402 uint8_t enable_vertical_interrupt:1; // IRQ2 on vert retrace
403 uint8_t select_5_refresh_cycles:1; // Slower displays
404 uint8_t protect_regs:1; // 1=> indices 0..7 disabled
405 } __attribute__((packed));
406 } __attribute__((packed));
407 } __attribute__((packed))
411 // lower 8 bits of 10 bit value (rest on overflow reg)
412 // this is the total number of scan lines minus one
413 typedef uint8_t vga_vertical_display_enable_end_reg;
416 // logical line width of the screen (including attrs)
417 // starting memory address of next character row is 2 or 4 times
419 typedef uint8_t vga_offset_reg;
423 struct vga_underline_location_reg {
427 uint8_t start_underline:5; // scan line in char where UL starts
428 uint8_t count_by_four:1; // memory addresses count by 4 (for dw)
429 uint8_t doubleword:1; // memory addresses are 32 bits
431 } __attribute__((packed));
432 } __attribute__((packed));
433 } __attribute__((packed))
437 // 8 bits of 10 bit quanity, rest are on overflow and maximum scan line reg
438 // scan line count at which vertical blanking goes on, minus one
439 typedef uint8_t vga_start_vertical_blanking_reg;
442 // scan line count at which vertical blanking goes off
443 typedef uint8_t vga_end_vertical_blanking_reg;
447 struct vga_crt_mode_control_reg {
452 // bit 13 of output mux come from rowscan, bit zero if zero
453 // otherwise from bit 13 of address counter
454 // ?? compatability with CGA
456 uint8_t select_row_scan_ctr:1;
457 // bit 14 of output mux comes from bit 1 of rowscan if zero
458 // otherwise from bit 14 of addres counter
461 uint8_t horizontal_retrace_select:1;
462 // select clock of vertical timing counter
463 // 0 = horiz retrace clock, 1=same / 2
465 uint8_t count_by_two:1;
466 // address counter source
467 // 0 = character clock
468 // 1 = character clock / 2 (word)
472 uint8_t address_wrap:1;
473 // is MA 13 or MA 15 output in MA 0 when in word address mode
475 uint8_t word_byte_mode:1;
476 // 0 = word mode memory access , 1= byte
479 // 0 = stop horizontal and vertical retrace
480 } __attribute__((packed));
481 } __attribute__((packed));
482 } __attribute__((packed))
486 // lower 8 bits of 10 bit counter; rest are on overflow and max scan line regs
487 // line counter is zeroed when it hits this value
488 typedef uint8_t vga_line_compare_reg;
491 Graphics Controller Registers
493 These registers control how the framebuffer / banks are accessed
494 from the host computer. How a memory write is translated is
495 determined by these settings.
503 struct vga_graphics_ctrl_addr_reg {
507 uint8_t graphics_address:4;
509 } __attribute__((packed));
510 } __attribute__((packed));
511 } __attribute__((packed))
515 // these are the values written to each map given memory write
516 // mode 0. While they are single bits, they are extended to full
518 struct vga_set_reset_reg {
522 uint8_t sr0:1; // bank 0
523 uint8_t sr1:1; // bank 1
524 uint8_t sr2:1; // bank 2
525 uint8_t sr3:1; // bank 3
527 } __attribute__((packed));
528 } __attribute__((packed));
529 } __attribute__((packed))
533 // these flags enable the use of the set/reset register values
534 // in writing the map when write mode 0 is used
535 struct vga_enable_set_reset_reg {
539 uint8_t esr0:1; // bank 0
540 uint8_t esr1:1; // bank 1
541 uint8_t esr2:1; // bank 2
542 uint8_t esr3:1; // bank 3
544 } __attribute__((packed));
545 } __attribute__((packed));
546 } __attribute__((packed))
550 // Color comparison values for one of the read modes
551 struct vga_color_compare_reg {
555 uint8_t cc0:1; // bank 0
556 uint8_t cc1:1; // bank 1
557 uint8_t cc2:1; // bank 2
558 uint8_t cc3:1; // bank 3
560 } __attribute__((packed));
561 } __attribute__((packed));
562 } __attribute__((packed))
566 // rotation amount and function for write mode 0 and others
567 struct vga_data_rotate_reg {
571 uint8_t rotate_count:3; // amount to ROR bits being written
572 uint8_t function:2; // function to use
578 } __attribute__((packed));
579 } __attribute__((packed));
580 } __attribute__((packed))
584 // which of the maps (banks) will be read from when a system read occurs
585 // Does not affect color compare reads
586 struct vga_read_map_select_reg {
590 uint8_t map_select:2; // which one you want to read
592 } __attribute__((packed));
593 } __attribute__((packed));
594 } __attribute__((packed))
598 // Graphics Mode DOES NOT MEAN graphics mode - it means
599 // the modes in which framebuffer reads/writes are done
600 struct vga_graphics_mode_reg {
604 uint8_t write_mode:2;
607 From the IBM docmentation:
609 0 0 Each memory map is written with the system data rotated by the count
610 in the Data Rotate register. If the set/reset function is enabled for a
611 specific map, that map receives the 8-bit value contained in the
614 0 1 Each memory map is written with the contents of the system latches.
615 These latches are loaded by a system read operation.
617 1 0 Memory map n (0 through 3) is filled with 8 bits of the value of data
620 1 1 Each memory map is written with the 8-bit value contained in the
621 Set/Reset register for that map (the Enable Set/Reset register has no
622 effect). Rotated system data is ANDed with the Bit Mask register to
623 form an 8-bit value that performs the same function as the Bit Mask
624 register in write modes 0 and 2 (see also Bit Mask register on
629 // 1 = read gets comparison of all maps and color compare
630 // 0 = read gets bits from selected map
632 // 1 = odd/even addressing as in CGMA
633 uint8_t shift_reg_mode:1;
634 // 1 = shift regs get odd bits from odd maps and even/even
635 uint8_t c256:1; // 1 = 256 color mode
636 // 0 = shift_reg_mode controls shift regs
638 } __attribute__((packed));
639 } __attribute__((packed));
640 } __attribute__((packed))
645 struct vga_misc_reg {
649 uint8_t graphics_mode:1;
650 // if on, then we are in a graphics mode
651 // if off, we are in a text mode
653 // if on, then low order bit of system address
654 // selects odd or even map
655 uint8_t memory_map:2;
656 // Controls mapping of regenerative buffer into address space
657 // 00 => A0000 for 128K
658 // 01 => A0000 for 64K
659 // 10 => B0000 for 32K
660 // 11 => B8000 for 32K
662 } __attribute__((packed));
663 } __attribute__((packed));
664 } __attribute__((packed))
669 struct vga_color_dont_care_reg {
677 // if off then the corresponding map is not
678 // considered in color comparison
680 } __attribute__((packed));
681 } __attribute__((packed));
682 } __attribute__((packed))
686 typedef uint8_t vga_bit_mask_reg;
687 // bit high means corresponding bit in each mask
688 // can be changed (used for write modes 0 and 2)
691 Attribute Controller Registers
693 The attribute controller essentially handles
694 attributes in text mode and palletes in graphics mode
696 Address AND WRITE: 0x3c0
699 The write protocol is to write the index to 0x3c0 followed by
700 the data. The read protocol is to write the index to 0x3c0
701 and then read from 0x3c1
703 IMPORTANT: write address, write data flips state back to write address
704 write address, read data DOES NOT
706 To reset to write address state, read input status register 1
710 struct vga_attribute_controller_address_reg {
714 uint8_t index:5; // actual address
715 uint8_t internal_palette_address_source:1;
716 // 0 => use the internal color palette (load the regs)
717 // 1 => use the external color palette
719 } __attribute__((packed));
720 } __attribute__((packed));
721 } __attribute__((packed))
725 Internal Palette Registers
729 Register k maps attribute k to the palette entry loaded in register k
731 struct vga_internal_palette_reg {
735 uint8_t palette_data:6; // which palette entry to use
737 } __attribute__((packed));
738 } __attribute__((packed));
739 } __attribute__((packed))
742 typedef struct vga_internal_palette_reg vga_internal_palette_regs[16];
745 struct vga_attribute_mode_control_reg {
749 uint8_t graphics:1; // graphics versus text mode
750 uint8_t mono_emul:1; // emulate an MDA
751 uint8_t enable_line_graphics_char_code:1;
752 // 1 => enable special line graphics characters
753 // and force 9th dot to be same as 8th dot of char
754 uint8_t enable_blink;
755 // 1 => MSB of the attribute means blink (8 colors + blink)
756 // 0 => MSB of the attribute means intensity (16 colors)
758 uint8_t pixel_panning:1;
759 // if 1, pixel panning reg set to 0 when line compare succeeds
760 uint8_t pixel_width:1;
761 // 1 => 8 bit color (256 colors)
762 uint8_t p54_select:1;
763 // select source of p5 and p6 inputs to DAC
764 // 0 => use internal palette regs
765 // 1 => use color select reg
766 } __attribute__((packed));
767 } __attribute__((packed));
768 } __attribute__((packed))
772 // this is the screen border color
773 typedef uint8_t vga_overscan_color_reg;
776 // Enable the corresponding display memory color plane
777 struct vga_color_plane_enable_reg {
781 uint8_t enable_color_plane:4;
783 } __attribute__((packed));
784 } __attribute__((packed));
785 } __attribute__((packed))
789 // number of pixels to shift the display to the left
790 struct vga_horizontal_pixel_pan_reg {
794 uint8_t horizontal_pixel_pan:4;
796 } __attribute__((packed));
797 } __attribute__((packed));
798 } __attribute__((packed))
803 // These allow for quick switching back and forth between
805 struct vga_color_select_reg {
814 } __attribute__((packed));
815 } __attribute__((packed));
816 } __attribute__((packed))
822 Used to derive the ultimate pixel colors that are rendered on the display
824 There are 256 palette registers
825 We can change any one or read any one
829 // The palette register that will returned on a data write
831 typedef uint8_t vga_dac_write_addr_reg;
834 // The palette register that will returned on a data read
836 typedef uint8_t vga_dac_read_addr_reg;
839 // Read or write of a palette register
841 // Successive references to this register increment
842 // the palette register index (for reads and writes separately)
843 // Three SUCCESSIVE WRITES ARE EXPECTED to set the 18 bit register
844 // Three SUCCESSIVE READS ARE EXPECTED to read out the register
845 // reads or writes are in order RED GREEN BLUE
846 // ADDRESS REG WRITE always resets
847 typedef uint8_t vga_dac_data_reg;
852 typedef uint8_t vga_dac_pixel_mask_reg;
854 // Palette register (256 of these)
855 // strictly speaking, each of these is 18 bits wide, 6 bits per channel
856 // We will provide reg&0x3f, reg>>8 & 0x3f, etc
857 // This is red, green, blue
858 typedef uint32_t vga_palette_reg;
862 // What attribute bytes mean in text mode
864 struct vga_attribute_byte {
868 uint8_t fore:3; //foreground color
869 uint8_t foreground_intensity_or_font_select:1; // depends on char map select reg
870 // character map selection is effected
871 // when memory_mode.extended meomory=1
872 // and the two character map enteries on character_map_select are
874 uint8_t back:3; //background color
875 uint8_t blinking_or_bg_intensity:1;
876 // attribute mode control.enableblink = 1 => blink
877 // =0 => intensity (16 colors of bg)
878 } __attribute__((packed));
879 } __attribute__((packed));
880 } __attribute__((packed));