vgabios: Move stdvga_set_mode() to stdvgamodes.c.
[seabios.git] / vgasrc / stdvgamodes.c
1 // Standard VGA mode information.
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "vgabios.h" // struct VideoParamTableEntry_s
9 #include "biosvar.h" // GET_GLOBAL
10 #include "util.h" // memcpy_far
11 #include "stdvga.h" // stdvga_find_mode
12
13
14 /****************************************************************
15  * Video mode register definitions
16  ****************************************************************/
17
18 /* Mono */
19 static u8 palette0[] VAR16 = {
20   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
21   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
22   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
23   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
24   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
25   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
26   0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
27   0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
28   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
29   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
30   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
31   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
32   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
33   0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
34   0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
35   0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f
36 };
37
38 static u8 palette1[] VAR16 = {
39   0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
40   0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
41   0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
42   0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
43   0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
44   0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
45   0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
46   0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
47   0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
48   0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
49   0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
50   0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
51   0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
52   0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
53   0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
54   0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
55 };
56
57 static u8 palette2[] VAR16 = {
58   0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
59   0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
60   0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f,
61   0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
62   0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a,
63   0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a,
64   0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f,
65   0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f,
66   0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a,
67   0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a,
68   0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f,
69   0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f,
70   0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a,
71   0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a,
72   0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
73   0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
74 };
75
76 static u8 palette3[] VAR16 = {
77   0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
78   0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
79   0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
80   0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
81   0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b,
82   0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18,
83   0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28,
84   0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f,
85   0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f,
86   0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10,
87   0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00,
88   0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00,
89   0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f,
90   0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f,
91   0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f,
92   0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27,
93
94   0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f,
95   0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f,
96   0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37,
97   0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f,
98   0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f,
99   0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31,
100   0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d,
101   0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d,
102   0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a,
103   0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f,
104   0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c,
105   0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07,
106   0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00,
107   0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00,
108   0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15,
109   0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c,
110
111   0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c,
112   0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11,
113   0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e,
114   0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e,
115   0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18,
116   0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c,
117   0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c,
118   0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16,
119   0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14,
120   0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14,
121   0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a,
122   0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c,
123   0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10,
124   0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04,
125   0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00,
126   0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00,
127
128   0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c,
129   0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10,
130   0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10,
131   0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a,
132   0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08,
133   0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08,
134   0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e,
135   0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10,
136   0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10,
137   0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c,
138   0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b,
139   0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b,
140   0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f,
141   0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10,
142   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
143   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00
144 };
145
146 static u8 sequ_01[] VAR16 = { 0x08, 0x03, 0x00, 0x02 };
147 static u8 crtc_01[] VAR16 = {
148     0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
149     0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
150     0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
151     0xff };
152 static u8 actl_01[] VAR16 = {
153     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
154     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
155     0x0c, 0x00, 0x0f, 0x08 };
156 static u8 grdc_01[] VAR16 = {
157     0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff };
158 static u8 sequ_03[] VAR16 = { 0x00, 0x03, 0x00, 0x02 };
159 static u8 crtc_03[] VAR16 = {
160     0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
161     0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
162     0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
163     0xff };
164 static u8 sequ_04[] VAR16 = { 0x09, 0x03, 0x00, 0x02 };
165 static u8 crtc_04[] VAR16 = {
166     0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
167     0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168     0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
169     0xff };
170 static u8 actl_04[] VAR16 = {
171     0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
172     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
173     0x01, 0x00, 0x03, 0x00 };
174 static u8 grdc_04[] VAR16 = {
175     0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff };
176 static u8 sequ_06[] VAR16 = { 0x01, 0x01, 0x00, 0x06 };
177 static u8 crtc_06[] VAR16 = {
178     0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
179     0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180     0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2,
181     0xff };
182 static u8 actl_06[] VAR16 = {
183     0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
184     0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
185     0x01, 0x00, 0x01, 0x00 };
186 static u8 grdc_06[] VAR16 = {
187     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff };
188 static u8 crtc_07[] VAR16 = {
189     0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
190     0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
191     0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
192     0xff };
193 static u8 actl_07[] VAR16 = {
194     0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
195     0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
196     0x0e, 0x00, 0x0f, 0x08 };
197 static u8 grdc_07[] VAR16 = {
198     0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff };
199 static u8 sequ_0d[] VAR16 = { 0x09, 0x0f, 0x00, 0x06 };
200 static u8 crtc_0d[] VAR16 = {
201     0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
202     0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203     0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3,
204     0xff };
205 static u8 actl_0d[] VAR16 = {
206     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
207     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
208     0x01, 0x00, 0x0f, 0x00 };
209 static u8 grdc_0d[] VAR16 = {
210     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff };
211 static u8 sequ_0e[] VAR16 = { 0x01, 0x0f, 0x00, 0x06 };
212 static u8 crtc_0e[] VAR16 = {
213     0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
214     0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215     0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3,
216     0xff };
217 static u8 crtc_0f[] VAR16 = {
218     0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
219     0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220     0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
221     0xff };
222 static u8 actl_0f[] VAR16 = {
223     0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
224     0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
225     0x01, 0x00, 0x01, 0x00 };
226 static u8 actl_10[] VAR16 = {
227     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
228     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
229     0x01, 0x00, 0x0f, 0x00 };
230 static u8 crtc_11[] VAR16 = {
231     0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
232     0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233     0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
234     0xff };
235 static u8 actl_11[] VAR16 = {
236     0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f,
237     0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f,
238     0x01, 0x00, 0x0f, 0x00 };
239 static u8 sequ_13[] VAR16 = { 0x01, 0x0f, 0x00, 0x0e };
240 static u8 crtc_13[] VAR16 = {
241     0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
242     0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243     0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
244     0xff };
245 static u8 actl_13[] VAR16 = {
246     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
247     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
248     0x41, 0x00, 0x0f, 0x00 };
249 static u8 grdc_13[] VAR16 = {
250     0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff };
251 static u8 crtc_6A[] VAR16 = {
252     0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
253     0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254     0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3,
255     0xff };
256
257 #define PAL(x) x, sizeof(x)
258
259 struct stdvga_mode_s {
260     u16 mode;
261     struct vgamode_s info;
262
263     u8 pelmask;
264     u8 *dac;
265     u16 dacsize;
266     u8 *sequ_regs;
267     u8 miscreg;
268     u8 *crtc_regs;
269     u8 *actl_regs;
270     u8 *grdc_regs;
271 };
272
273 static struct stdvga_mode_s vga_modes[] VAR16 = {
274     //mode { model       tx   ty bpp cw ch  sstart    }
275     // pelm  dac            sequ     misc  crtc     actl     grdc
276     {0x00, { MM_TEXT,    40,  25, 4, 9, 16, SEG_CTEXT }
277      , 0xFF, PAL(palette2), sequ_01, 0x67, crtc_01, actl_01, grdc_01},
278     {0x01, { MM_TEXT,    40,  25, 4, 9, 16, SEG_CTEXT }
279      , 0xFF, PAL(palette2), sequ_01, 0x67, crtc_01, actl_01, grdc_01},
280     {0x02, { MM_TEXT,    80,  25, 4, 9, 16, SEG_CTEXT }
281      , 0xFF, PAL(palette2), sequ_03, 0x67, crtc_03, actl_01, grdc_01},
282     {0x03, { MM_TEXT,    80,  25, 4, 9, 16, SEG_CTEXT }
283      , 0xFF, PAL(palette2), sequ_03, 0x67, crtc_03, actl_01, grdc_01},
284     {0x04, { MM_CGA,    320, 200, 2, 8,  8, SEG_CTEXT }
285      , 0xFF, PAL(palette1), sequ_04, 0x63, crtc_04, actl_04, grdc_04},
286     {0x05, { MM_CGA,    320, 200, 2, 8,  8, SEG_CTEXT }
287      , 0xFF, PAL(palette1), sequ_04, 0x63, crtc_04, actl_04, grdc_04},
288     {0x06, { MM_CGA,    640, 200, 1, 8,  8, SEG_CTEXT }
289      , 0xFF, PAL(palette1), sequ_06, 0x63, crtc_06, actl_06, grdc_06},
290     {0x07, { MM_TEXT,    80,  25, 4, 9, 16, SEG_MTEXT }
291      , 0xFF, PAL(palette0), sequ_03, 0x66, crtc_07, actl_07, grdc_07},
292     {0x0D, { MM_PLANAR, 320, 200, 4, 8,  8, SEG_GRAPH }
293      , 0xFF, PAL(palette1), sequ_0d, 0x63, crtc_0d, actl_0d, grdc_0d},
294     {0x0E, { MM_PLANAR, 640, 200, 4, 8,  8, SEG_GRAPH }
295      , 0xFF, PAL(palette1), sequ_0e, 0x63, crtc_0e, actl_0d, grdc_0d},
296     {0x0F, { MM_PLANAR, 640, 350, 1, 8, 14, SEG_GRAPH }
297      , 0xFF, PAL(palette0), sequ_0e, 0xa3, crtc_0f, actl_0f, grdc_0d},
298     {0x10, { MM_PLANAR, 640, 350, 4, 8, 14, SEG_GRAPH }
299      , 0xFF, PAL(palette2), sequ_0e, 0xa3, crtc_0f, actl_10, grdc_0d},
300     {0x11, { MM_PLANAR, 640, 480, 1, 8, 16, SEG_GRAPH }
301      , 0xFF, PAL(palette2), sequ_0e, 0xe3, crtc_11, actl_11, grdc_0d},
302     {0x12, { MM_PLANAR, 640, 480, 4, 8, 16, SEG_GRAPH }
303      , 0xFF, PAL(palette2), sequ_0e, 0xe3, crtc_11, actl_10, grdc_0d},
304     {0x13, { MM_PACKED, 320, 200, 8, 8,  8, SEG_GRAPH }
305      , 0xFF, PAL(palette3), sequ_13, 0x63, crtc_13, actl_13, grdc_13},
306     {0x6A, { MM_PLANAR, 800, 600, 4, 8, 16, SEG_GRAPH }
307      , 0xFF, PAL(palette2), sequ_0e, 0xe3, crtc_6A, actl_10, grdc_0d},
308 };
309
310
311 /****************************************************************
312  * Mode functions
313  ****************************************************************/
314
315 static int
316 is_stdvga_mode(struct vgamode_s *vmode_g)
317 {
318     return (vmode_g >= &vga_modes[0].info
319             && vmode_g <= &vga_modes[ARRAY_SIZE(vga_modes)-1].info);
320 }
321
322 struct vgamode_s *
323 stdvga_find_mode(int mode)
324 {
325     int i;
326     for (i = 0; i < ARRAY_SIZE(vga_modes); i++) {
327         struct stdvga_mode_s *stdmode_g = &vga_modes[i];
328         if (GET_GLOBAL(stdmode_g->mode) == mode)
329             return &stdmode_g->info;
330     }
331     return NULL;
332 }
333
334 void
335 stdvga_list_modes(u16 seg, u16 *dest, u16 *last)
336 {
337     SET_FARVAR(seg, *dest, 0xffff);
338 }
339
340 void
341 stdvga_build_video_param(void)
342 {
343     static u8 parammodes[] VAR16 = {
344         0, 0, 0, 0, 0x04, 0x05, 0x06, 0x07,
345         0, 0, 0, 0, 0, 0x0d, 0x0e, 0,
346         0, 0x0f, 0x10, 0, 0, 0, 0, 0x01,
347         0x03, 0x07, 0x11, 0x12, 0x13
348     };
349
350     int i;
351     for (i=0; i<ARRAY_SIZE(parammodes); i++) {
352         int mode = GET_GLOBAL(parammodes[i]);
353         if (! mode)
354             continue;
355         struct VideoParam_s *vparam_g = &video_param_table[i];
356         struct vgamode_s *vmode_g = stdvga_find_mode(mode);
357         if (!vmode_g)
358             continue;
359         int width = GET_GLOBAL(vmode_g->width);
360         int height = GET_GLOBAL(vmode_g->height);
361         u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
362         int cheight = GET_GLOBAL(vmode_g->cheight);
363         if (memmodel == MM_TEXT) {
364             SET_VGA(vparam_g->twidth, width);
365             SET_VGA(vparam_g->theightm1, height-1);
366         } else {
367             int cwidth = GET_GLOBAL(vmode_g->cwidth);
368             SET_VGA(vparam_g->twidth, width / cwidth);
369             SET_VGA(vparam_g->theightm1, (height / cheight) - 1);
370         }
371         SET_VGA(vparam_g->cheight, cheight);
372         SET_VGA(vparam_g->slength, calc_page_size(memmodel, width, height));
373         struct stdvga_mode_s *stdmode_g = container_of(
374             vmode_g, struct stdvga_mode_s, info);
375         memcpy_far(get_global_seg(), vparam_g->sequ_regs
376                    , get_global_seg(), GET_GLOBAL(stdmode_g->sequ_regs)
377                    , ARRAY_SIZE(vparam_g->sequ_regs));
378         SET_VGA(vparam_g->miscreg, GET_GLOBAL(stdmode_g->miscreg));
379         memcpy_far(get_global_seg(), vparam_g->crtc_regs
380                    , get_global_seg(), GET_GLOBAL(stdmode_g->crtc_regs)
381                    , ARRAY_SIZE(vparam_g->crtc_regs));
382         memcpy_far(get_global_seg(), vparam_g->actl_regs
383                    , get_global_seg(), GET_GLOBAL(stdmode_g->actl_regs)
384                    , ARRAY_SIZE(vparam_g->actl_regs));
385         memcpy_far(get_global_seg(), vparam_g->grdc_regs
386                    , get_global_seg(), GET_GLOBAL(stdmode_g->grdc_regs)
387                    , ARRAY_SIZE(vparam_g->grdc_regs));
388     }
389 }
390
391 void
392 stdvga_override_crtc(int mode, u8 *crtc)
393 {
394     struct vgamode_s *vmode_g = stdvga_find_mode(mode);
395     if (!vmode_g)
396         return;
397     struct stdvga_mode_s *stdmode_g = container_of(
398         vmode_g, struct stdvga_mode_s, info);
399     SET_VGA(stdmode_g->crtc_regs, crtc);
400 }
401
402 static void
403 clear_screen(struct vgamode_s *vmode_g)
404 {
405     switch (GET_GLOBAL(vmode_g->memmodel)) {
406     case MM_TEXT:
407         memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024);
408         break;
409     case MM_CGA:
410         memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024);
411         break;
412     default:
413         // XXX - old code gets/sets/restores sequ register 2 to 0xf -
414         // but it should always be 0xf anyway.
415         memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024);
416     }
417 }
418
419 int
420 stdvga_set_mode(struct vgamode_s *vmode_g, int flags)
421 {
422     if (! is_stdvga_mode(vmode_g)) {
423         warn_internalerror();
424         return -1;
425     }
426     struct stdvga_mode_s *stdmode_g = container_of(
427         vmode_g, struct stdvga_mode_s, info);
428
429     // if palette loading (bit 3 of modeset ctl = 0)
430     if (!(flags & MF_NOPALETTE)) {    // Set the PEL mask
431         stdvga_pelmask_write(GET_GLOBAL(stdmode_g->pelmask));
432
433         // From which palette
434         u8 *palette_g = GET_GLOBAL(stdmode_g->dac);
435         u16 palsize = GET_GLOBAL(stdmode_g->dacsize) / 3;
436
437         // Always 256*3 values
438         stdvga_dac_write(get_global_seg(), palette_g, 0, palsize);
439         int i;
440         for (i = palsize; i < 0x0100; i++) {
441             static u8 rgb[3] VAR16;
442             stdvga_dac_write(get_global_seg(), rgb, i, 1);
443         }
444
445         if (flags & MF_GRAYSUM)
446             stdvga_perform_gray_scale_summing(0x00, 0x100);
447     }
448
449     // Set Attribute Ctl
450     u8 *regs = GET_GLOBAL(stdmode_g->actl_regs);
451     int i;
452     for (i = 0; i <= 0x13; i++)
453         stdvga_attr_write(i, GET_GLOBAL(regs[i]));
454     stdvga_attr_write(0x14, 0x00);
455
456     // Set Sequencer Ctl
457     stdvga_sequ_write(0x00, 0x03);
458     regs = GET_GLOBAL(stdmode_g->sequ_regs);
459     for (i = 1; i <= 4; i++)
460         stdvga_sequ_write(i, GET_GLOBAL(regs[i - 1]));
461
462     // Set Grafx Ctl
463     regs = GET_GLOBAL(stdmode_g->grdc_regs);
464     for (i = 0; i <= 8; i++)
465         stdvga_grdc_write(i, GET_GLOBAL(regs[i]));
466
467     // Set CRTC address VGA or MDA
468     u8 miscreg = GET_GLOBAL(stdmode_g->miscreg);
469     u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
470     if (!(miscreg & 1))
471         crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
472
473     // Disable CRTC write protection
474     stdvga_crtc_write(crtc_addr, 0x11, 0x00);
475     // Set CRTC regs
476     regs = GET_GLOBAL(stdmode_g->crtc_regs);
477     for (i = 0; i <= 0x18; i++)
478         stdvga_crtc_write(crtc_addr, i, GET_GLOBAL(regs[i]));
479
480     // Set the misc register
481     stdvga_misc_write(miscreg);
482
483     // Enable video
484     stdvga_attrindex_write(0x20);
485
486     // Clear screen
487     if (!(flags & MF_NOCLEARMEM))
488         clear_screen(vmode_g);
489
490     // Write the fonts in memory
491     u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
492     if (memmodel == MM_TEXT)
493         stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16);
494
495     return 0;
496 }