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 graphics rendering, attribute palette handling, corrected attribute processing
[palacios.git] / palacios / src / devices / vga_regs.h
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 #ifndef _VGA_REGS
20 #define _VGA_REGS
21
22 /*
23     General Purpose Registers 
24   
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
30
31 */
32
33 /* Read: 0x3cc; Write: 0x3c2 */
34 struct vga_misc_out_reg {
35     union {
36         uint8_t val;
37         struct {
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
42             uint8_t reserved:2;
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
45             uint8_t reserved2:1;
46         } __attribute__((packed));
47     } __attribute__((packed));
48 } __attribute__((packed));
49
50
51 /* Read: 0x3c2 */
52 struct vga_input_stat0_reg {
53     union {
54         uint8_t val;
55         struct {
56             uint8_t reserved:4;
57             uint8_t switch_sense:1; // type of display attached (mono/color)
58             uint8_t reserved2:2;
59             uint8_t crt_inter:1;   // vertical retrace interrupt pending;
60         } __attribute__((packed));
61     } __attribute__((packed));
62 } __attribute__((packed));
63
64
65 /* Read: 0x3?a  3ba for mono; 3da for cga set by misc.io_addr_sel */
66 struct vga_input_stat1_reg {
67     union {
68         uint8_t val;
69         struct {
70             uint8_t disp_en:1; // in horizontal or vertical retrace (drawing)
71             uint8_t reserved:2;
72             uint8_t vert_retrace:1; // in vertical retrace interval
73             uint8_t reserved2:4;
74         } __attribute__((packed));
75     } __attribute__((packed));
76 } __attribute__((packed));
77
78
79 /* Read: 0x3ca; Write: 0x3?a 3ba for mono 3da for color - set by misc.io_addr_sel*/
80 struct vga_feature_control_reg {
81     union {
82         uint8_t val;
83         struct {
84             uint8_t reserved:8; // per IBM spec
85         } __attribute__((packed));
86     } __attribute__((packed));
87 } __attribute__((packed));
88
89 /* Read: 0x3c3; Write: 0x3c3 */
90 struct vga_video_subsys_enable_reg {
91     union {
92         uint8_t val;
93         struct {
94             uint8_t reserved:8; // per IBM spec
95         } __attribute__((packed));
96     } __attribute__((packed));
97 } __attribute__((packed));
98
99 /* 
100    Sequencer Registers 
101   
102    These are all accessed via address and data registers.  
103   
104    Address register is 0x3c4, data register is 0x3c5
105 */
106
107 /* 0x3c4 */
108 struct vga_sequencer_addr_reg {
109     union {
110         uint8_t val;
111         struct {
112             uint8_t seq_address:3; 
113             uint8_t reserved:5; 
114         } __attribute__((packed));
115     } __attribute__((packed));
116 } __attribute__((packed))
117 ;
118
119 /* Index 0 */
120 struct vga_reset_reg {
121     union {
122         uint8_t val;
123         struct {
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
126                                    // write 11 to run
127             uint8_t reserved:6; 
128         } __attribute__((packed));
129     } __attribute__((packed));
130 } __attribute__((packed));
131
132 /* Index 1 */
133 struct vga_clocking_mode_reg {
134     union {
135         uint8_t val;
136         struct {
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
144                                    //    0       1          every 2nd
145                                    //    1       0          every 4th 
146             uint8_t screen_off:1;  // turn off display
147             uint8_t reserved2:2;   
148         } __attribute__((packed));
149     } __attribute__((packed));
150 } __attribute__((packed));
151
152 /* Index 2 */
153 struct vga_map_mask_reg {
154     union {
155         uint8_t val;
156         struct {
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
161             uint8_t reserved:4; 
162         } __attribute__((packed));
163     } __attribute__((packed));
164 } __attribute__((packed));
165
166 /* Index 3 */
167 struct vga_char_map_select_reg {
168     union {
169         uint8_t val;
170         struct {
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
175             uint8_t reserved:2; 
176             /*
177                For A: the map bits give the char sets at:
178                   000  1st 8K of map (bank) 2
179                   001  3rd 8K
180                   010  5th 8K
181                   011  7th 8K
182                   100  2nd 8K
183                   101  4th 8K
184                   110  6th 8K
185                   111  8th 8K
186  
187                Identical for B
188             */
189         } __attribute__((packed));
190     } __attribute__((packed));
191 } __attribute__((packed));
192
193 /* Index 4 */
194 struct vga_mem_mode_reg {
195     union {
196         uint8_t val;
197         struct {
198             uint8_t reserved:1;
199             uint8_t extended_memory:1; // 1=>256K RAM, 0=>64K
200             uint8_t odd_even:1;
201                 // 0 => even addresses go to BOTH banks 0 and 2, odd 1 and 3
202                 // 1 => address bank sequentially, map mask selects bank
203             uint8_t chain4:1;  
204                 // 0 => map mask register used to select bank
205                 // 1 => lower 2 bits of address used to select bank
206             uint8_t reserved2:4; 
207         } __attribute__((packed));
208     } __attribute__((packed));
209 } __attribute__((packed));
210
211 /*
212   CRT Controller Registers
213
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
216   
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
220
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.
224
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
228 */
229
230 /* 0x3b4 or 0x3d4 */
231 struct vga_crt_addr_reg {
232     union {
233         uint8_t val;
234         struct {
235             uint8_t crt_address:5; 
236             uint8_t reserved:3; 
237         } __attribute__((packed));
238     } __attribute__((packed));
239 } __attribute__((packed))
240 ;
241
242
243 /* index 0 */
244 // Total number of chars in horizontal interval, including retrace
245 typedef uint8_t vga_horizontal_total_reg;
246
247 /* index 1 */
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;
251
252 /* index 2 */
253 // horizontal characer count at which blanking starts
254 typedef uint8_t vga_start_horizontal_blanking_reg;
255
256 /* index 3 */
257 struct vga_end_horizontal_blanking_reg {
258     union {
259         uint8_t val;
260         struct {
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))
268 ;
269
270 /* index 4 */
271 // screen centering:  char position where horizontal retrace is active
272 typedef uint8_t vga_start_horizontal_retrace_pulse_reg;
273
274 /* index 5 */
275 struct vga_end_horizontal_retrace_reg {
276     union {
277         uint8_t val;
278         struct {
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))
288 ;
289
290 /* index 6 */
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;
294
295 /* index 7 */
296 struct vga_overflow_reg {
297     union {
298         uint8_t val;
299         struct {
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))
311 ;
312
313 /* index 8 */
314 struct vga_preset_row_scan_reg {
315     union {
316         uint8_t val;
317         struct {
318             uint8_t start_row_scan_count:5; 
319             // what the row counter begins at?
320             uint8_t byte_panning:2; 
321             // ?
322             uint8_t reserved:1;
323         } __attribute__((packed));
324     } __attribute__((packed));
325 } __attribute__((packed))
326 ;
327
328 /* index 9 */
329 struct vga_max_row_scan_reg {
330     union {
331         uint8_t val;
332         struct {
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))
343 ;
344
345 /* index 10 */
346 struct vga_cursor_start_reg {
347     union {
348         uint8_t val;
349         struct {
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
354             uint8_t reserved:2;
355         } __attribute__((packed));
356     } __attribute__((packed));
357 } __attribute__((packed))
358 ;
359
360 /* index 11 */
361 struct vga_cursor_end_reg {
362     union {
363         uint8_t val;
364         struct {
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
369             uint8_t reserved:1;
370         } __attribute__((packed));
371     } __attribute__((packed));
372 } __attribute__((packed))
373 ;
374
375
376 /* index 12 */
377 // starting address of regenerative buffer (?)
378 typedef uint8_t vga_start_address_high_reg;
379 /* index 13 */
380 // starting address of regenerative buffer (?)
381 typedef uint8_t vga_start_address_low_reg;
382
383 /* index 14 */
384 // cursor location
385 typedef uint8_t vga_cursor_location_high_reg;
386 /* index 15 */
387 // cursor location
388 typedef uint8_t vga_cursor_location_low_reg;
389
390 /* index 16 */
391 // vertical retrace start - low 8 bits, 9th is on overflow register
392 typedef uint8_t vga_vertical_retrace_start_reg;
393
394
395 /* index 17 */
396 struct vga_vertical_retrace_end_reg {
397     union {
398         uint8_t val;
399         struct {
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))
408 ;
409
410 /* index 18 */
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;
414
415 /* index 19 */
416 // logical line width of the screen (including attrs)
417 // starting memory address of next character row is 2 or 4 times
418 // this value
419 typedef uint8_t vga_offset_reg;
420
421
422 /* index 20 */
423 struct vga_underline_location_reg {
424     union {
425         uint8_t val;
426         struct {
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
430             uint8_t reserved:1;
431         } __attribute__((packed));
432     } __attribute__((packed));
433 } __attribute__((packed))
434 ;
435
436 /* index 21 */
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;
440
441 /* index 22 */
442 // scan line count at which vertical blanking goes off
443 typedef uint8_t vga_end_vertical_blanking_reg;
444
445
446 /* index 23 */
447 struct vga_crt_mode_control_reg {
448     union {
449         uint8_t val;
450         struct {
451             uint8_t cms0:1; 
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
455    
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
459             // ? CGA ?
460
461             uint8_t horizontal_retrace_select:1;
462             // select clock of vertical timing counter
463             // 0 = horiz retrace clock, 1=same / 2
464
465             uint8_t count_by_two:1;
466             // address counter source
467             // 0 = character clock
468             // 1 = character clock / 2 (word)
469
470             uint8_t reserved:1;
471
472             uint8_t address_wrap:1;
473             // is MA 13 or MA 15 output in MA 0 when in word address mode
474
475             uint8_t word_byte_mode:1;
476             // 0 = word mode memory access , 1= byte
477             
478             uint8_t reset:1;
479             // 0 = stop horizontal and vertical retrace
480         } __attribute__((packed));
481     } __attribute__((packed));
482 } __attribute__((packed))
483 ;
484
485 /* index 24 */
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;
489
490 /*
491    Graphics Controller Registers
492
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.
496
497    Address: 0x3ce
498    Data: 0x3cf
499
500 */
501
502 /* 0x3ce */
503 struct vga_graphics_ctrl_addr_reg {
504     union {
505         uint8_t val;
506         struct {
507             uint8_t graphics_address:4; 
508             uint8_t reserved:4; 
509         } __attribute__((packed));
510     } __attribute__((packed));
511 } __attribute__((packed))
512 ;
513
514 /* Index 0 */
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 
517 // bytes
518 struct vga_set_reset_reg {
519     union {
520         uint8_t val;
521         struct {
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
526             uint8_t reserved:4; 
527         } __attribute__((packed));
528     } __attribute__((packed));
529 } __attribute__((packed))
530 ;
531
532 /* Index 1 */
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 {
536     union {
537         uint8_t val;
538         struct {
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
543             uint8_t reserved:4; 
544         } __attribute__((packed));
545     } __attribute__((packed));
546 } __attribute__((packed))
547 ;
548
549 /* Index 2 */
550 // Color comparison values for one of the read modes
551 struct vga_color_compare_reg {
552     union {
553         uint8_t val;
554         struct {
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
559             uint8_t reserved:4; 
560         } __attribute__((packed));
561     } __attribute__((packed));
562 } __attribute__((packed))
563 ;
564
565 /* Index 3 */
566 // rotation amount and function for write mode 0 and others
567 struct vga_data_rotate_reg {
568     union {
569         uint8_t val;
570         struct {
571             uint8_t rotate_count:3; //  amount to ROR bits being written
572             uint8_t function:2;     // function to use
573             // 00 : NOP
574             // 01 : AND
575             // 10 : OR
576             // 11 : XOR
577             uint8_t reserved:3; 
578         } __attribute__((packed));
579     } __attribute__((packed));
580 } __attribute__((packed))
581 ;
582
583 /* Index 4 */
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 {
587     union {
588         uint8_t val;
589         struct {
590             uint8_t map_select:2; //  which one you want to read
591             uint8_t reserved:6; 
592         } __attribute__((packed));
593     } __attribute__((packed));
594 } __attribute__((packed))
595 ;
596
597 /* Index 5 */
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 {
601     union {
602         uint8_t val;
603         struct {
604             uint8_t write_mode:2; 
605             /* 
606               
607 From the IBM docmentation:
608
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
612 Set/Reset register.
613
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.
616
617 1 0 Memory map n (0 through 3) is filled with 8 bits of the value of data
618 bit n.
619
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
625 page 2-88).
626             */
627             uint8_t reserved:1;
628             uint8_t read_mode:1;
629             // 1 = read gets comparison of all maps and color compare
630             // 0 = read gets bits from selected map
631             uint8_t odd_even:1;
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
637             uint8_t reserved2:1; 
638         } __attribute__((packed));
639     } __attribute__((packed));
640 } __attribute__((packed))
641 ;
642
643 /* Index 6 */
644 // Misc
645 struct vga_misc_reg {
646     union {
647         uint8_t val;
648         struct {
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
652             uint8_t odd_even:1;
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
661             uint8_t reserved:4; 
662         } __attribute__((packed));
663     } __attribute__((packed));
664 } __attribute__((packed))
665 ;
666
667 /* Index 7 */
668 // Color don't care
669 struct vga_color_dont_care_reg {
670     union {
671         uint8_t val;
672         struct {
673             uint8_t dc_map0:1;
674             uint8_t dc_map1:1;
675             uint8_t dc_map2:1;
676             uint8_t dc_map3:1;
677             // if off then the corresponding map is not
678             // considered in color comparison
679             uint8_t reserved:4; 
680         } __attribute__((packed));
681     } __attribute__((packed));
682 } __attribute__((packed))
683 ;
684
685 /* Index 8 */
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)
689
690 /* 
691   Attribute Controller Registers
692
693   The attribute controller essentially handles
694   attributes in text mode and palletes in graphics mode
695
696   Address AND WRITE: 0x3c0
697   Read: 0x3c1
698
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
702
703   IMPORTANT: write address, write data flips state back to write address
704   write address, read data DOES NOT
705
706   To reset to write address state, read input status register 1
707 */
708
709 /* 0x3c0 */
710 struct vga_attribute_controller_address_reg {
711     union {
712         uint8_t val;
713         struct {
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
718             uint8_t reserved:2; 
719         } __attribute__((packed));
720     } __attribute__((packed));
721 } __attribute__((packed))
722 ;
723
724 /* 
725    Internal Palette Registers
726
727    Index 0..15
728
729    Register k maps attribute k to the palette entry loaded in register k
730 */
731 struct vga_internal_palette_reg {
732     union {
733         uint8_t val;
734         struct {
735             uint8_t palette_data:6;    // which palette entry to use
736             uint8_t reserved:2; 
737         } __attribute__((packed));
738     } __attribute__((packed));
739 } __attribute__((packed))
740 ;
741
742 typedef struct vga_internal_palette_reg vga_internal_palette_regs[16];
743
744 /* Index 16 */
745 struct vga_attribute_mode_control_reg {
746     union {
747         uint8_t val;
748         struct {
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)
757             uint8_t reserved:1;
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))
769 ;
770
771 /* Index 17 */
772 // this is the screen border color
773 typedef uint8_t vga_overscan_color_reg;
774
775 /* Index 18 */
776 // Enable the corresponding display memory color plane
777 struct vga_color_plane_enable_reg {
778     union {
779         uint8_t val;
780         struct {
781             uint8_t enable_color_plane:4;
782             uint8_t reserved:4; 
783         } __attribute__((packed));
784     } __attribute__((packed));
785 } __attribute__((packed))
786     ;
787
788 /* Index 19 */
789 // number of pixels to shift the display to the left
790 struct vga_horizontal_pixel_pan_reg {
791     union {
792         uint8_t val;
793         struct {
794             uint8_t horizontal_pixel_pan:4;
795             uint8_t reserved:4; 
796         } __attribute__((packed));
797     } __attribute__((packed));
798 } __attribute__((packed))
799     ;
800
801 /* Index 20 */
802 // color select
803 // These allow for quick switching back and forth between
804 // color palletes
805 struct vga_color_select_reg {
806     union {
807         uint8_t val;
808         struct {
809             uint8_t sc4:1;
810             uint8_t sc5:1;
811             uint8_t sc6:1;
812             uint8_t sc7:1;
813             uint8_t reserved:4; 
814         } __attribute__((packed));
815     } __attribute__((packed));
816 } __attribute__((packed))
817     ;
818
819 /*
820   DAC registers
821
822   Used to derive the ultimate pixel colors that are rendered on the display
823   
824   There are 256 palette registers
825   We can change any one or read any one
826 */
827
828 //
829 // The palette register that will returned on a data write
830 // 0x3c8
831 typedef uint8_t vga_dac_write_addr_reg;
832
833 //
834 // The palette register that will returned on a data read
835 // 0x3c7
836 typedef uint8_t vga_dac_read_addr_reg;
837
838 //
839 // Read or write of a palette register
840 // 0x3c9
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;
848
849 //
850 // Pixel Mask
851 // 0x3c6
852 typedef uint8_t vga_dac_pixel_mask_reg;
853
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; 
859
860
861 //
862 //  What attribute bytes mean in text mode
863 //
864 struct vga_attribute_byte {
865     union {
866         uint8_t val;
867         struct {
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 
873             // different
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));
881
882 #endif