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 / vgaio.c
1 // VGA io port access
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 "ioport.h" // outb
9 #include "farptr.h" // SET_FARVAR
10 #include "biosvar.h" // GET_BDA
11 #include "vgatables.h" // VGAREG_*
12
13 // TODO
14 //  * replace direct in/out calls with wrapper functions
15
16
17 /****************************************************************
18  * Attribute control
19  ****************************************************************/
20
21 void
22 vgahw_screen_disable(void)
23 {
24     inb(VGAREG_ACTL_RESET);
25     outb(0x00, VGAREG_ACTL_ADDRESS);
26 }
27
28 void
29 vgahw_screen_enable(void)
30 {
31     inb(VGAREG_ACTL_RESET);
32     outb(0x20, VGAREG_ACTL_ADDRESS);
33 }
34
35 void
36 vgahw_set_border_color(u8 color)
37 {
38     inb(VGAREG_ACTL_RESET);
39     outb(0x00, VGAREG_ACTL_ADDRESS);
40     u8 v1 = color & 0x0f;
41     if (v1 & 0x08)
42         v1 += 0x08;
43     outb(v1, VGAREG_ACTL_WRITE_DATA);
44
45     u8 v2 = color & 0x10;
46     int i;
47     for (i = 1; i < 4; i++) {
48         outb(i, VGAREG_ACTL_ADDRESS);
49
50         u8 cur = inb(VGAREG_ACTL_READ_DATA);
51         cur &= 0xef;
52         cur |= v2;
53         outb(cur, VGAREG_ACTL_WRITE_DATA);
54     }
55     outb(0x20, VGAREG_ACTL_ADDRESS);
56 }
57
58 void
59 vgahw_set_overscan_border_color(u8 color)
60 {
61     inb(VGAREG_ACTL_RESET);
62     outb(0x11, VGAREG_ACTL_ADDRESS);
63     outb(color, VGAREG_ACTL_WRITE_DATA);
64     outb(0x20, VGAREG_ACTL_ADDRESS);
65 }
66
67 u8
68 vgahw_get_overscan_border_color(void)
69 {
70     inb(VGAREG_ACTL_RESET);
71     outb(0x11, VGAREG_ACTL_ADDRESS);
72     u8 v = inb(VGAREG_ACTL_READ_DATA);
73     inb(VGAREG_ACTL_RESET);
74     outb(0x20, VGAREG_ACTL_ADDRESS);
75     return v;
76 }
77
78 void
79 vgahw_set_palette(u8 palid)
80 {
81     inb(VGAREG_ACTL_RESET);
82     palid &= 0x01;
83     int i;
84     for (i = 1; i < 4; i++) {
85         outb(i, VGAREG_ACTL_ADDRESS);
86
87         u8 v = inb(VGAREG_ACTL_READ_DATA);
88         v &= 0xfe;
89         v |= palid;
90         outb(v, VGAREG_ACTL_WRITE_DATA);
91     }
92     outb(0x20, VGAREG_ACTL_ADDRESS);
93 }
94
95 void
96 vgahw_set_single_palette_reg(u8 reg, u8 val)
97 {
98     inb(VGAREG_ACTL_RESET);
99     outb(reg, VGAREG_ACTL_ADDRESS);
100     outb(val, VGAREG_ACTL_WRITE_DATA);
101     outb(0x20, VGAREG_ACTL_ADDRESS);
102 }
103
104 u8
105 vgahw_get_single_palette_reg(u8 reg)
106 {
107     inb(VGAREG_ACTL_RESET);
108     outb(reg, VGAREG_ACTL_ADDRESS);
109     u8 v = inb(VGAREG_ACTL_READ_DATA);
110     inb(VGAREG_ACTL_RESET);
111     outb(0x20, VGAREG_ACTL_ADDRESS);
112     return v;
113 }
114
115 void
116 vgahw_set_all_palette_reg(u16 seg, u8 *data_far)
117 {
118     inb(VGAREG_ACTL_RESET);
119     int i;
120     for (i = 0; i < 0x10; i++) {
121         outb(i, VGAREG_ACTL_ADDRESS);
122         u8 val = GET_FARVAR(seg, *data_far);
123         outb(val, VGAREG_ACTL_WRITE_DATA);
124         data_far++;
125     }
126     outb(0x11, VGAREG_ACTL_ADDRESS);
127     outb(GET_FARVAR(seg, *data_far), VGAREG_ACTL_WRITE_DATA);
128     outb(0x20, VGAREG_ACTL_ADDRESS);
129 }
130
131 void
132 vgahw_get_all_palette_reg(u16 seg, u8 *data_far)
133 {
134     int i;
135     for (i = 0; i < 0x10; i++) {
136         inb(VGAREG_ACTL_RESET);
137         outb(i, VGAREG_ACTL_ADDRESS);
138         SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
139         data_far++;
140     }
141     inb(VGAREG_ACTL_RESET);
142     outb(0x11, VGAREG_ACTL_ADDRESS);
143     SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
144     inb(VGAREG_ACTL_RESET);
145     outb(0x20, VGAREG_ACTL_ADDRESS);
146 }
147
148 void
149 vgahw_toggle_intensity(u8 flag)
150 {
151     inb(VGAREG_ACTL_RESET);
152     outb(0x10, VGAREG_ACTL_ADDRESS);
153     u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0xf7) | ((flag & 0x01) << 3);
154     outb(val, VGAREG_ACTL_WRITE_DATA);
155     outb(0x20, VGAREG_ACTL_ADDRESS);
156 }
157
158 void
159 vgahw_select_video_dac_color_page(u8 flag, u8 data)
160 {
161     inb(VGAREG_ACTL_RESET);
162     outb(0x10, VGAREG_ACTL_ADDRESS);
163     u8 val = inb(VGAREG_ACTL_READ_DATA);
164     if (!(flag & 0x01)) {
165         // select paging mode
166         val = (val & 0x7f) | (data << 7);
167         outb(val, VGAREG_ACTL_WRITE_DATA);
168         outb(0x20, VGAREG_ACTL_ADDRESS);
169         return;
170     }
171     // select page
172     inb(VGAREG_ACTL_RESET);
173     outb(0x14, VGAREG_ACTL_ADDRESS);
174     if (!(val & 0x80))
175         data <<= 2;
176     data &= 0x0f;
177     outb(data, VGAREG_ACTL_WRITE_DATA);
178     outb(0x20, VGAREG_ACTL_ADDRESS);
179 }
180
181 void
182 vgahw_read_video_dac_state(u8 *pmode, u8 *curpage)
183 {
184     inb(VGAREG_ACTL_RESET);
185     outb(0x10, VGAREG_ACTL_ADDRESS);
186     u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
187
188     inb(VGAREG_ACTL_RESET);
189     outb(0x14, VGAREG_ACTL_ADDRESS);
190     u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
191     if (!(val1 & 0x01))
192         val2 >>= 2;
193
194     inb(VGAREG_ACTL_RESET);
195     outb(0x20, VGAREG_ACTL_ADDRESS);
196
197     *pmode = val1;
198     *curpage = val2;
199 }
200
201
202 /****************************************************************
203  * DAC control
204  ****************************************************************/
205
206 void
207 vgahw_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
208 {
209     outb(start, VGAREG_DAC_WRITE_ADDRESS);
210     while (count) {
211         outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
212         data_far++;
213         outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
214         data_far++;
215         outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
216         data_far++;
217         count--;
218     }
219 }
220
221 void
222 vgahw_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
223 {
224     outb(start, VGAREG_DAC_READ_ADDRESS);
225     while (count) {
226         SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
227         data_far++;
228         SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
229         data_far++;
230         SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
231         data_far++;
232         count--;
233     }
234 }
235
236 void
237 vgahw_set_pel_mask(u8 val)
238 {
239     outb(val, VGAREG_PEL_MASK);
240 }
241
242 u8
243 vgahw_get_pel_mask(void)
244 {
245     return inb(VGAREG_PEL_MASK);
246 }
247
248 void
249 vgahw_save_dac_state(u16 seg, struct saveDACcolors *info)
250 {
251     /* XXX: check this */
252     SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
253     SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
254     SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK));
255     vgahw_get_dac_regs(seg, info->dac, 0, 256);
256     SET_FARVAR(seg, info->color_select, 0);
257 }
258
259 void
260 vgahw_restore_dac_state(u16 seg, struct saveDACcolors *info)
261 {
262     outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK);
263     vgahw_set_dac_regs(seg, info->dac, 0, 256);
264     outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
265 }
266
267
268 /****************************************************************
269  * Memory control
270  ****************************************************************/
271
272 void
273 vgahw_sequ_write(u8 index, u8 value)
274 {
275     outw((value<<8) | index, VGAREG_SEQU_ADDRESS);
276 }
277
278 void
279 vgahw_grdc_write(u8 index, u8 value)
280 {
281     outw((value<<8) | index, VGAREG_GRDC_ADDRESS);
282 }
283
284 void
285 vgahw_set_text_block_specifier(u8 spec)
286 {
287     outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS);
288 }
289
290 void
291 get_font_access(void)
292 {
293     outw(0x0100, VGAREG_SEQU_ADDRESS);
294     outw(0x0402, VGAREG_SEQU_ADDRESS);
295     outw(0x0704, VGAREG_SEQU_ADDRESS);
296     outw(0x0300, VGAREG_SEQU_ADDRESS);
297     outw(0x0204, VGAREG_GRDC_ADDRESS);
298     outw(0x0005, VGAREG_GRDC_ADDRESS);
299     outw(0x0406, VGAREG_GRDC_ADDRESS);
300 }
301
302 void
303 release_font_access(void)
304 {
305     outw(0x0100, VGAREG_SEQU_ADDRESS);
306     outw(0x0302, VGAREG_SEQU_ADDRESS);
307     outw(0x0304, VGAREG_SEQU_ADDRESS);
308     outw(0x0300, VGAREG_SEQU_ADDRESS);
309     u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
310     outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
311     outw(0x0004, VGAREG_GRDC_ADDRESS);
312     outw(0x1005, VGAREG_GRDC_ADDRESS);
313 }
314
315
316 /****************************************************************
317  * CRTC registers
318  ****************************************************************/
319
320 static u16
321 get_crtc(void)
322 {
323     return GET_BDA(crtc_address);
324 }
325
326 void
327 vgahw_set_cursor_shape(u8 start, u8 end)
328 {
329     u16 crtc_addr = get_crtc();
330     outb(0x0a, crtc_addr);
331     outb(start, crtc_addr + 1);
332     outb(0x0b, crtc_addr);
333     outb(end, crtc_addr + 1);
334 }
335
336 void
337 vgahw_set_active_page(u16 address)
338 {
339     u16 crtc_addr = get_crtc();
340     outb(0x0c, crtc_addr);
341     outb((address & 0xff00) >> 8, crtc_addr + 1);
342     outb(0x0d, crtc_addr);
343     outb(address & 0x00ff, crtc_addr + 1);
344 }
345
346 void
347 vgahw_set_cursor_pos(u16 address)
348 {
349     u16 crtc_addr = get_crtc();
350     outb(0x0e, crtc_addr);
351     outb((address & 0xff00) >> 8, crtc_addr + 1);
352     outb(0x0f, crtc_addr);
353     outb(address & 0x00ff, crtc_addr + 1);
354 }
355
356 void
357 vgahw_set_scan_lines(u8 lines)
358 {
359     u16 crtc_addr = get_crtc();
360     outb(0x09, crtc_addr);
361     u8 crtc_r9 = inb(crtc_addr + 1);
362     crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
363     outb(crtc_r9, crtc_addr + 1);
364 }
365
366 // Get vertical display end
367 u16
368 vgahw_get_vde(void)
369 {
370     u16 crtc_addr = get_crtc();
371     outb(0x12, crtc_addr);
372     u16 vde = inb(crtc_addr + 1);
373     outb(0x07, crtc_addr);
374     u8 ovl = inb(crtc_addr + 1);
375     vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
376     return vde;
377 }
378
379
380 /****************************************************************
381  * Save/Restore/Set state
382  ****************************************************************/
383
384 void
385 vgahw_save_state(u16 seg, struct saveVideoHardware *info)
386 {
387     u16 crtc_addr = get_crtc();
388     SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
389     SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
390     SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
391     inb(VGAREG_ACTL_RESET);
392     u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
393     SET_FARVAR(seg, info->actl_index, ar_index);
394     SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
395
396     u16 i;
397     for (i=0; i<4; i++) {
398         outb(i+1, VGAREG_SEQU_ADDRESS);
399         SET_FARVAR(seg, info->sequ_regs[i], inb(VGAREG_SEQU_DATA));
400     }
401     outb(0, VGAREG_SEQU_ADDRESS);
402     SET_FARVAR(seg, info->sequ0, inb(VGAREG_SEQU_DATA));
403
404     for (i=0; i<25; i++) {
405         outb(i, crtc_addr);
406         SET_FARVAR(seg, info->crtc_regs[i], inb(crtc_addr + 1));
407     }
408
409     for (i=0; i<20; i++) {
410         inb(VGAREG_ACTL_RESET);
411         outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
412         SET_FARVAR(seg, info->actl_regs[i], inb(VGAREG_ACTL_READ_DATA));
413     }
414     inb(VGAREG_ACTL_RESET);
415
416     for (i=0; i<9; i++) {
417         outb(i, VGAREG_GRDC_ADDRESS);
418         SET_FARVAR(seg, info->grdc_regs[i], inb(VGAREG_GRDC_DATA));
419     }
420
421     SET_FARVAR(seg, info->crtc_addr, crtc_addr);
422
423     /* XXX: read plane latches */
424     for (i=0; i<4; i++)
425         SET_FARVAR(seg, info->plane_latch[i], 0);
426 }
427
428 void
429 vgahw_restore_state(u16 seg, struct saveVideoHardware *info)
430 {
431     // Reset Attribute Ctl flip-flop
432     inb(VGAREG_ACTL_RESET);
433
434     u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
435
436     u16 i;
437     for (i=0; i<4; i++) {
438         outb(i+1, VGAREG_SEQU_ADDRESS);
439         outb(GET_FARVAR(seg, info->sequ_regs[i]), VGAREG_SEQU_DATA);
440     }
441     outb(0, VGAREG_SEQU_ADDRESS);
442     outb(GET_FARVAR(seg, info->sequ0), VGAREG_SEQU_DATA);
443
444     // Disable CRTC write protection
445     outw(0x0011, crtc_addr);
446     // Set CRTC regs
447     for (i=0; i<25; i++)
448         if (i != 0x11) {
449             outb(i, crtc_addr);
450             outb(GET_FARVAR(seg, info->crtc_regs[i]), crtc_addr + 1);
451         }
452     // select crtc base address
453     u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
454     if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
455         v |= 0x01;
456     outb(v, VGAREG_WRITE_MISC_OUTPUT);
457
458     // enable write protection if needed
459     outb(0x11, crtc_addr);
460     outb(GET_FARVAR(seg, info->crtc_regs[0x11]), crtc_addr + 1);
461
462     // Set Attribute Ctl
463     u16 ar_index = GET_FARVAR(seg, info->actl_index);
464     inb(VGAREG_ACTL_RESET);
465     for (i=0; i<20; i++) {
466         outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
467         outb(GET_FARVAR(seg, info->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
468     }
469     outb(ar_index, VGAREG_ACTL_ADDRESS);
470     inb(VGAREG_ACTL_RESET);
471
472     for (i=0; i<9; i++) {
473         outb(i, VGAREG_GRDC_ADDRESS);
474         outb(GET_FARVAR(seg, info->grdc_regs[i]), VGAREG_GRDC_DATA);
475     }
476
477     outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
478     outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
479     outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
480     outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
481 }
482
483 void
484 vgahw_set_mode(struct VideoParam_s *vparam_g)
485 {
486     // Reset Attribute Ctl flip-flop
487     inb(VGAREG_ACTL_RESET);
488
489     // Set Attribute Ctl
490     u16 i;
491     for (i = 0; i <= 0x13; i++) {
492         outb(i, VGAREG_ACTL_ADDRESS);
493         outb(GET_GLOBAL(vparam_g->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
494     }
495     outb(0x14, VGAREG_ACTL_ADDRESS);
496     outb(0x00, VGAREG_ACTL_WRITE_DATA);
497
498     // Set Sequencer Ctl
499     outb(0, VGAREG_SEQU_ADDRESS);
500     outb(0x03, VGAREG_SEQU_DATA);
501     for (i = 1; i <= 4; i++) {
502         outb(i, VGAREG_SEQU_ADDRESS);
503         outb(GET_GLOBAL(vparam_g->sequ_regs[i - 1]), VGAREG_SEQU_DATA);
504     }
505
506     // Set Grafx Ctl
507     for (i = 0; i <= 8; i++) {
508         outb(i, VGAREG_GRDC_ADDRESS);
509         outb(GET_GLOBAL(vparam_g->grdc_regs[i]), VGAREG_GRDC_DATA);
510     }
511
512     // Set CRTC address VGA or MDA
513     u8 miscreg = GET_GLOBAL(vparam_g->miscreg);
514     u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
515     if (!(miscreg & 1))
516         crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
517
518     // Disable CRTC write protection
519     outw(0x0011, crtc_addr);
520     // Set CRTC regs
521     for (i = 0; i <= 0x18; i++) {
522         outb(i, crtc_addr);
523         outb(GET_GLOBAL(vparam_g->crtc_regs[i]), crtc_addr + 1);
524     }
525
526     // Set the misc register
527     outb(miscreg, VGAREG_WRITE_MISC_OUTPUT);
528
529     // Enable video
530     outb(0x20, VGAREG_ACTL_ADDRESS);
531     inb(VGAREG_ACTL_RESET);
532 }
533
534
535 /****************************************************************
536  * Misc
537  ****************************************************************/
538
539 void
540 vgahw_enable_video_addressing(u8 disable)
541 {
542     u8 v = (disable & 1) ? 0x00 : 0x02;
543     u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
544     outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
545 }
546
547 void
548 vgahw_init(void)
549 {
550     // switch to color mode and enable CPU access 480 lines
551     outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
552     // more than 64k 3C4/04
553     outb(0x04, VGAREG_SEQU_ADDRESS);
554     outb(0x02, VGAREG_SEQU_DATA);
555 }