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.


imported SEABIOS source tree
[palacios.git] / bios / seabios / vgasrc / clext.c
1 //  QEMU Cirrus CLGD 54xx VGABIOS Extension.
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 //  Copyright (c) 2004 Makoto Suzuki (suzu)
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "vgatables.h" // cirrus_init
9 #include "biosvar.h" // GET_GLOBAL
10 #include "util.h" // dprintf
11
12 struct cirrus_mode_s {
13     /* + 0 */
14     u16 mode;
15     u16 width;
16     u16 height;
17     u16 depth;
18     /* + 8 */
19     u16 hidden_dac; /* 0x3c6 */
20     u16 *seq; /* 0x3c4 */
21     u16 *graph; /* 0x3ce */
22     u16 *crtc; /* 0x3d4 */
23     /* +16 */
24     u8 bitsperpixel;
25     u8 vesacolortype;
26     u8 vesaredmask;
27     u8 vesaredpos;
28     u8 vesagreenmask;
29     u8 vesagreenpos;
30     u8 vesabluemask;
31     u8 vesabluepos;
32     /* +24 */
33     u8 vesareservedmask;
34     u8 vesareservedpos;
35 };
36
37 /* VGA */
38 static u16 cseq_vga[] VAR16 = {0x0007,0xffff};
39 static u16 cgraph_vga[] VAR16 = {0x0009,0x000a,0x000b,0xffff};
40 static u16 ccrtc_vga[] VAR16 = {0x001a,0x001b,0x001d,0xffff};
41
42 /* extensions */
43 static u16 cgraph_svgacolor[] VAR16 = {
44     0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08,
45     0x0009,0x000a,0x000b,
46     0xffff
47 };
48 /* 640x480x8 */
49 static u16 cseq_640x480x8[] VAR16 = {
50     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
51     0x580b,0x580c,0x580d,0x580e,
52     0x0412,0x0013,0x2017,
53     0x331b,0x331c,0x331d,0x331e,
54     0xffff
55 };
56 static u16 ccrtc_640x480x8[] VAR16 = {
57     0x2c11,
58     0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
59     0x4009,0x000c,0x000d,
60     0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
61     0x001a,0x221b,0x001d,
62     0xffff
63 };
64 /* 640x480x16 */
65 static u16 cseq_640x480x16[] VAR16 = {
66     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
67     0x580b,0x580c,0x580d,0x580e,
68     0x0412,0x0013,0x2017,
69     0x331b,0x331c,0x331d,0x331e,
70     0xffff
71 };
72 static u16 ccrtc_640x480x16[] VAR16 = {
73     0x2c11,
74     0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
75     0x4009,0x000c,0x000d,
76     0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
77     0x001a,0x221b,0x001d,
78     0xffff
79 };
80 /* 640x480x24 */
81 static u16 cseq_640x480x24[] VAR16 = {
82     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
83     0x580b,0x580c,0x580d,0x580e,
84     0x0412,0x0013,0x2017,
85     0x331b,0x331c,0x331d,0x331e,
86     0xffff
87 };
88 static u16 ccrtc_640x480x24[] VAR16 = {
89     0x2c11,
90     0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
91     0x4009,0x000c,0x000d,
92     0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
93     0x001a,0x321b,0x001d,
94     0xffff
95 };
96 /* 800x600x8 */
97 static u16 cseq_800x600x8[] VAR16 = {
98     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
99     0x230b,0x230c,0x230d,0x230e,
100     0x0412,0x0013,0x2017,
101     0x141b,0x141c,0x141d,0x141e,
102     0xffff
103 };
104 static u16 ccrtc_800x600x8[] VAR16 = {
105     0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
106     0x6009,0x000c,0x000d,
107     0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18,
108     0x001a,0x221b,0x001d,
109     0xffff
110 };
111 /* 800x600x16 */
112 static u16 cseq_800x600x16[] VAR16 = {
113     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
114     0x230b,0x230c,0x230d,0x230e,
115     0x0412,0x0013,0x2017,
116     0x141b,0x141c,0x141d,0x141e,
117     0xffff
118 };
119 static u16 ccrtc_800x600x16[] VAR16 = {
120     0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
121     0x6009,0x000c,0x000d,
122     0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18,
123     0x001a,0x221b,0x001d,
124     0xffff
125 };
126 /* 800x600x24 */
127 static u16 cseq_800x600x24[] VAR16 = {
128     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
129     0x230b,0x230c,0x230d,0x230e,
130     0x0412,0x0013,0x2017,
131     0x141b,0x141c,0x141d,0x141e,
132     0xffff
133 };
134 static u16 ccrtc_800x600x24[] VAR16 = {
135     0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
136     0x6009,0x000c,0x000d,
137     0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18,
138     0x001a,0x321b,0x001d,
139     0xffff
140 };
141 /* 1024x768x8 */
142 static u16 cseq_1024x768x8[] VAR16 = {
143     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
144     0x760b,0x760c,0x760d,0x760e,
145     0x0412,0x0013,0x2017,
146     0x341b,0x341c,0x341d,0x341e,
147     0xffff
148 };
149 static u16 ccrtc_1024x768x8[] VAR16 = {
150     0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
151     0x6009,0x000c,0x000d,
152     0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
153     0x001a,0x221b,0x001d,
154     0xffff
155 };
156 /* 1024x768x16 */
157 static u16 cseq_1024x768x16[] VAR16 = {
158     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
159     0x760b,0x760c,0x760d,0x760e,
160     0x0412,0x0013,0x2017,
161     0x341b,0x341c,0x341d,0x341e,
162     0xffff
163 };
164 static u16 ccrtc_1024x768x16[] VAR16 = {
165     0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
166     0x6009,0x000c,0x000d,
167     0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18,
168     0x001a,0x321b,0x001d,
169     0xffff
170 };
171 /* 1024x768x24 */
172 static u16 cseq_1024x768x24[] VAR16 = {
173     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
174     0x760b,0x760c,0x760d,0x760e,
175     0x0412,0x0013,0x2017,
176     0x341b,0x341c,0x341d,0x341e,
177     0xffff
178 };
179 static u16 ccrtc_1024x768x24[] VAR16 = {
180     0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
181     0x6009,0x000c,0x000d,
182     0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
183     0x001a,0x321b,0x001d,
184     0xffff
185 };
186 /* 1280x1024x8 */
187 static u16 cseq_1280x1024x8[] VAR16 = {
188     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
189     0x760b,0x760c,0x760d,0x760e,
190     0x0412,0x0013,0x2017,
191     0x341b,0x341c,0x341d,0x341e,
192     0xffff
193 };
194 static u16 ccrtc_1280x1024x8[] VAR16 = {
195     0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
196     0x6009,0x000c,0x000d,
197     0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
198     0x001a,0x221b,0x001d,
199     0xffff
200 };
201 /* 1280x1024x16 */
202 static u16 cseq_1280x1024x16[] VAR16 = {
203     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
204     0x760b,0x760c,0x760d,0x760e,
205     0x0412,0x0013,0x2017,
206     0x341b,0x341c,0x341d,0x341e,
207     0xffff
208 };
209 static u16 ccrtc_1280x1024x16[] VAR16 = {
210     0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
211     0x6009,0x000c,0x000d,
212     0x0310,0xff12,0x4013,0x4014,0xff15,0x2416,0xc317,0xff18,
213     0x001a,0x321b,0x001d,
214     0xffff
215 };
216
217 /* 1600x1200x8 */
218 static u16 cseq_1600x1200x8[] VAR16 = {
219     0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
220     0x760b,0x760c,0x760d,0x760e,
221     0x0412,0x0013,0x2017,
222     0x341b,0x341c,0x341d,0x341e,
223     0xffff
224 };
225 static u16 ccrtc_1600x1200x8[] VAR16 = {
226     0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
227     0x6009,0x000c,0x000d,
228     0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
229     0x001a,0x221b,0x001d,
230     0xffff
231 };
232
233 static struct cirrus_mode_s cirrus_modes[] VAR16 = {
234     {0x5f,640,480,8,0x00,
235      cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8,
236      4,0,0,0,0,0,0,0,0},
237     {0x64,640,480,16,0xe1,
238      cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
239      6,5,11,6,5,5,0,0,0},
240     {0x66,640,480,15,0xf0,
241      cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
242      6,5,10,5,5,5,0,1,15},
243     {0x71,640,480,24,0xe5,
244      cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24,
245      6,8,16,8,8,8,0,0,0},
246
247     {0x5c,800,600,8,0x00,
248      cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8,
249      4,0,0,0,0,0,0,0,0},
250     {0x65,800,600,16,0xe1,
251      cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
252      6,5,11,6,5,5,0,0,0},
253     {0x67,800,600,15,0xf0,
254      cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
255      6,5,10,5,5,5,0,1,15},
256
257     {0x60,1024,768,8,0x00,
258      cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8,
259      4,0,0,0,0,0,0,0,0},
260     {0x74,1024,768,16,0xe1,
261      cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
262      6,5,11,6,5,5,0,0,0},
263     {0x68,1024,768,15,0xf0,
264      cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
265      6,5,10,5,5,5,0,1,15},
266
267     {0x78,800,600,24,0xe5,
268      cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24,
269      6,8,16,8,8,8,0,0,0},
270     {0x79,1024,768,24,0xe5,
271      cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24,
272      6,8,16,8,8,8,0,0,0},
273
274     {0x6d,1280,1024,8,0x00,
275      cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8,
276      4,0,0,0,0,0,0,0,0},
277     {0x69,1280,1024,15,0xf0,
278      cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16,
279      6,5,10,5,5,5,0,1,15},
280     {0x75,1280,1024,16,0xe1,
281      cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16,
282      6,5,11,6,5,5,0,0,0},
283
284     {0x7b,1600,1200,8,0x00,
285      cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8,8,
286      4,0,0,0,0,0,0,0,0},
287
288     {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0,
289      0xff,0,0,0,0,0,0,0,0},
290 };
291
292 static struct cirrus_mode_s *
293 cirrus_get_modeentry(u8 mode)
294 {
295     struct cirrus_mode_s *table_g = cirrus_modes;
296     while (table_g < &cirrus_modes[ARRAY_SIZE(cirrus_modes)]) {
297         u16 tmode = GET_GLOBAL(table_g->mode);
298         if (tmode == mode)
299             return table_g;
300         table_g++;
301     }
302     return NULL;
303 }
304
305 static void
306 cirrus_switch_mode_setregs(u16 *data, u16 port)
307 {
308     for (;;) {
309         u16 val = GET_GLOBAL(*data);
310         if (val == 0xffff)
311             return;
312         outw(val, port);
313         data++;
314     }
315 }
316
317 static u16
318 cirrus_get_crtc(void)
319 {
320     if (inb(VGAREG_READ_MISC_OUTPUT) & 1)
321         return VGAREG_VGA_CRTC_ADDRESS;
322     return VGAREG_MDA_CRTC_ADDRESS;
323 }
324
325 static void
326 cirrus_switch_mode(struct cirrus_mode_s *table)
327 {
328     // Unlock cirrus special
329     outw(0x1206, VGAREG_SEQU_ADDRESS);
330     cirrus_switch_mode_setregs(GET_GLOBAL(table->seq), VGAREG_SEQU_ADDRESS);
331     cirrus_switch_mode_setregs(GET_GLOBAL(table->graph), VGAREG_GRDC_ADDRESS);
332     cirrus_switch_mode_setregs(GET_GLOBAL(table->crtc), cirrus_get_crtc());
333
334     outb(0x00, VGAREG_PEL_MASK);
335     inb(VGAREG_PEL_MASK);
336     inb(VGAREG_PEL_MASK);
337     inb(VGAREG_PEL_MASK);
338     inb(VGAREG_PEL_MASK);
339     outb(GET_GLOBAL(table->hidden_dac), VGAREG_PEL_MASK);
340     outb(0xff, VGAREG_PEL_MASK);
341
342     u8 vesacolortype = GET_GLOBAL(table->vesacolortype);
343     u8 v = vgahw_get_single_palette_reg(0x10) & 0xfe;
344     if (vesacolortype == 3)
345         v |= 0x41;
346     else if (vesacolortype)
347         v |= 0x01;
348     vgahw_set_single_palette_reg(0x10, v);
349 }
350
351 void
352 cirrus_set_video_mode(u8 mode)
353 {
354     dprintf(1, "cirrus mode %d\n", mode);
355     SET_BDA(vbe_mode, 0);
356     struct cirrus_mode_s *table_g = cirrus_get_modeentry(mode & 0x7f);
357     if (table_g) {
358         //XXX - cirrus_set_video_mode_extended(table);
359         return;
360     }
361     table_g = cirrus_get_modeentry(0xfe);
362     cirrus_switch_mode(table_g);
363     dprintf(1, "cirrus mode switch regular\n");
364 }
365
366 static int
367 cirrus_check(void)
368 {
369     outw(0x9206, VGAREG_SEQU_ADDRESS);
370     return inb(VGAREG_SEQU_DATA) == 0x12;
371 }
372
373 void
374 cirrus_init(void)
375 {
376     dprintf(1, "cirrus init\n");
377     if (! cirrus_check())
378         return;
379     dprintf(1, "cirrus init 2\n");
380
381     // memory setup
382     outb(0x0f, VGAREG_SEQU_ADDRESS);
383     u8 v = inb(VGAREG_SEQU_DATA);
384     outb(((v & 0x18) << 8) | 0x0a, VGAREG_SEQU_ADDRESS);
385     // set vga mode
386     outw(0x0007, VGAREG_SEQU_ADDRESS);
387     // reset bitblt
388     outw(0x0431, VGAREG_GRDC_ADDRESS);
389     outw(0x0031, VGAREG_GRDC_ADDRESS);
390 }