3 // Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
8 #include "stdvga.h" // stdvga_init
9 #include "ioport.h" // outb
10 #include "farptr.h" // SET_FARVAR
11 #include "biosvar.h" // GET_GLOBAL
12 #include "util.h" // memcpy_far
15 // * replace direct in/out calls with wrapper functions
18 /****************************************************************
20 ****************************************************************/
23 stdvga_screen_disable(void)
25 inb(VGAREG_ACTL_RESET);
26 outb(0x00, VGAREG_ACTL_ADDRESS);
30 stdvga_screen_enable(void)
32 inb(VGAREG_ACTL_RESET);
33 outb(0x20, VGAREG_ACTL_ADDRESS);
37 stdvga_set_border_color(u8 color)
39 inb(VGAREG_ACTL_RESET);
40 outb(0x00, VGAREG_ACTL_ADDRESS);
44 outb(v1, VGAREG_ACTL_WRITE_DATA);
48 for (i = 1; i < 4; i++) {
49 outb(i, VGAREG_ACTL_ADDRESS);
51 u8 cur = inb(VGAREG_ACTL_READ_DATA);
54 outb(cur, VGAREG_ACTL_WRITE_DATA);
56 outb(0x20, VGAREG_ACTL_ADDRESS);
60 stdvga_set_overscan_border_color(u8 color)
62 inb(VGAREG_ACTL_RESET);
63 outb(0x11, VGAREG_ACTL_ADDRESS);
64 outb(color, VGAREG_ACTL_WRITE_DATA);
65 outb(0x20, VGAREG_ACTL_ADDRESS);
69 stdvga_get_overscan_border_color(void)
71 inb(VGAREG_ACTL_RESET);
72 outb(0x11, VGAREG_ACTL_ADDRESS);
73 u8 v = inb(VGAREG_ACTL_READ_DATA);
74 inb(VGAREG_ACTL_RESET);
75 outb(0x20, VGAREG_ACTL_ADDRESS);
80 stdvga_set_palette(u8 palid)
82 inb(VGAREG_ACTL_RESET);
85 for (i = 1; i < 4; i++) {
86 outb(i, VGAREG_ACTL_ADDRESS);
88 u8 v = inb(VGAREG_ACTL_READ_DATA);
91 outb(v, VGAREG_ACTL_WRITE_DATA);
93 outb(0x20, VGAREG_ACTL_ADDRESS);
97 stdvga_set_single_palette_reg(u8 reg, u8 val)
99 inb(VGAREG_ACTL_RESET);
100 outb(reg, VGAREG_ACTL_ADDRESS);
101 outb(val, VGAREG_ACTL_WRITE_DATA);
102 outb(0x20, VGAREG_ACTL_ADDRESS);
106 stdvga_get_single_palette_reg(u8 reg)
108 inb(VGAREG_ACTL_RESET);
109 outb(reg, VGAREG_ACTL_ADDRESS);
110 u8 v = inb(VGAREG_ACTL_READ_DATA);
111 inb(VGAREG_ACTL_RESET);
112 outb(0x20, VGAREG_ACTL_ADDRESS);
117 stdvga_set_all_palette_reg(u16 seg, u8 *data_far)
119 inb(VGAREG_ACTL_RESET);
121 for (i = 0; i < 0x10; i++) {
122 outb(i, VGAREG_ACTL_ADDRESS);
123 u8 val = GET_FARVAR(seg, *data_far);
124 outb(val, VGAREG_ACTL_WRITE_DATA);
127 outb(0x11, VGAREG_ACTL_ADDRESS);
128 outb(GET_FARVAR(seg, *data_far), VGAREG_ACTL_WRITE_DATA);
129 outb(0x20, VGAREG_ACTL_ADDRESS);
133 stdvga_get_all_palette_reg(u16 seg, u8 *data_far)
136 for (i = 0; i < 0x10; i++) {
137 inb(VGAREG_ACTL_RESET);
138 outb(i, VGAREG_ACTL_ADDRESS);
139 SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
142 inb(VGAREG_ACTL_RESET);
143 outb(0x11, VGAREG_ACTL_ADDRESS);
144 SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
145 inb(VGAREG_ACTL_RESET);
146 outb(0x20, VGAREG_ACTL_ADDRESS);
150 stdvga_toggle_intensity(u8 flag)
152 inb(VGAREG_ACTL_RESET);
153 outb(0x10, VGAREG_ACTL_ADDRESS);
154 u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0xf7) | ((flag & 0x01) << 3);
155 outb(val, VGAREG_ACTL_WRITE_DATA);
156 outb(0x20, VGAREG_ACTL_ADDRESS);
160 stdvga_select_video_dac_color_page(u8 flag, u8 data)
162 inb(VGAREG_ACTL_RESET);
163 outb(0x10, VGAREG_ACTL_ADDRESS);
164 u8 val = inb(VGAREG_ACTL_READ_DATA);
165 if (!(flag & 0x01)) {
166 // select paging mode
167 val = (val & 0x7f) | (data << 7);
168 outb(val, VGAREG_ACTL_WRITE_DATA);
169 outb(0x20, VGAREG_ACTL_ADDRESS);
173 inb(VGAREG_ACTL_RESET);
174 outb(0x14, VGAREG_ACTL_ADDRESS);
178 outb(data, VGAREG_ACTL_WRITE_DATA);
179 outb(0x20, VGAREG_ACTL_ADDRESS);
183 stdvga_read_video_dac_state(u8 *pmode, u8 *curpage)
185 inb(VGAREG_ACTL_RESET);
186 outb(0x10, VGAREG_ACTL_ADDRESS);
187 u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
189 inb(VGAREG_ACTL_RESET);
190 outb(0x14, VGAREG_ACTL_ADDRESS);
191 u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
195 inb(VGAREG_ACTL_RESET);
196 outb(0x20, VGAREG_ACTL_ADDRESS);
203 /****************************************************************
205 ****************************************************************/
208 stdvga_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
210 outb(start, VGAREG_DAC_WRITE_ADDRESS);
212 outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
214 outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
216 outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
223 stdvga_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
225 outb(start, VGAREG_DAC_READ_ADDRESS);
227 SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
229 SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
231 SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
238 stdvga_set_pel_mask(u8 val)
240 outb(val, VGAREG_PEL_MASK);
244 stdvga_get_pel_mask(void)
246 return inb(VGAREG_PEL_MASK);
250 stdvga_save_dac_state(u16 seg, struct saveDACcolors *info)
252 /* XXX: check this */
253 SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
254 SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
255 SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK));
256 stdvga_get_dac_regs(seg, info->dac, 0, 256);
257 SET_FARVAR(seg, info->color_select, 0);
261 stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info)
263 outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK);
264 stdvga_set_dac_regs(seg, info->dac, 0, 256);
265 outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
269 /****************************************************************
271 ****************************************************************/
274 stdvga_sequ_write(u8 index, u8 value)
276 outw((value<<8) | index, VGAREG_SEQU_ADDRESS);
280 stdvga_grdc_write(u8 index, u8 value)
282 outw((value<<8) | index, VGAREG_GRDC_ADDRESS);
286 stdvga_set_text_block_specifier(u8 spec)
288 outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS);
292 /****************************************************************
294 ****************************************************************/
297 get_font_access(void)
299 outw(0x0100, VGAREG_SEQU_ADDRESS);
300 outw(0x0402, VGAREG_SEQU_ADDRESS);
301 outw(0x0704, VGAREG_SEQU_ADDRESS);
302 outw(0x0300, VGAREG_SEQU_ADDRESS);
303 outw(0x0204, VGAREG_GRDC_ADDRESS);
304 outw(0x0005, VGAREG_GRDC_ADDRESS);
305 outw(0x0406, VGAREG_GRDC_ADDRESS);
309 release_font_access(void)
311 outw(0x0100, VGAREG_SEQU_ADDRESS);
312 outw(0x0302, VGAREG_SEQU_ADDRESS);
313 outw(0x0304, VGAREG_SEQU_ADDRESS);
314 outw(0x0300, VGAREG_SEQU_ADDRESS);
315 u16 v = (inb(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
316 outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
317 outw(0x0004, VGAREG_GRDC_ADDRESS);
318 outw(0x1005, VGAREG_GRDC_ADDRESS);
322 stdvga_load_font(u16 seg, void *src_far, u16 count
323 , u16 start, u8 destflags, u8 fontsize)
326 u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11);
327 void *dest_far = (void*)(blockaddr + start*32);
329 for (i = 0; i < count; i++)
330 memcpy_far(SEG_GRAPH, dest_far + i*32
331 , seg, src_far + i*fontsize, fontsize);
332 release_font_access();
336 /****************************************************************
338 ****************************************************************/
341 stdvga_get_crtc(void)
343 if (inb(VGAREG_READ_MISC_OUTPUT) & 1)
344 return VGAREG_VGA_CRTC_ADDRESS;
345 return VGAREG_MDA_CRTC_ADDRESS;
349 stdvga_set_cursor_shape(u8 start, u8 end)
351 u16 crtc_addr = stdvga_get_crtc();
352 outb(0x0a, crtc_addr);
353 outb(start, crtc_addr + 1);
354 outb(0x0b, crtc_addr);
355 outb(end, crtc_addr + 1);
359 stdvga_set_active_page(u16 address)
361 u16 crtc_addr = stdvga_get_crtc();
362 outb(0x0c, crtc_addr);
363 outb((address & 0xff00) >> 8, crtc_addr + 1);
364 outb(0x0d, crtc_addr);
365 outb(address & 0x00ff, crtc_addr + 1);
369 stdvga_set_cursor_pos(u16 address)
371 u16 crtc_addr = stdvga_get_crtc();
372 outb(0x0e, crtc_addr);
373 outb((address & 0xff00) >> 8, crtc_addr + 1);
374 outb(0x0f, crtc_addr);
375 outb(address & 0x00ff, crtc_addr + 1);
379 stdvga_set_scan_lines(u8 lines)
381 u16 crtc_addr = stdvga_get_crtc();
382 outb(0x09, crtc_addr);
383 u8 crtc_r9 = inb(crtc_addr + 1);
384 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
385 outb(crtc_r9, crtc_addr + 1);
388 // Get vertical display end
392 u16 crtc_addr = stdvga_get_crtc();
393 outb(0x12, crtc_addr);
394 u16 vde = inb(crtc_addr + 1);
395 outb(0x07, crtc_addr);
396 u8 ovl = inb(crtc_addr + 1);
397 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
402 /****************************************************************
403 * Save/Restore/Set state
404 ****************************************************************/
407 stdvga_save_state(u16 seg, struct saveVideoHardware *info)
409 u16 crtc_addr = stdvga_get_crtc();
410 SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
411 SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
412 SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
413 inb(VGAREG_ACTL_RESET);
414 u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
415 SET_FARVAR(seg, info->actl_index, ar_index);
416 SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
419 for (i=0; i<4; i++) {
420 outb(i+1, VGAREG_SEQU_ADDRESS);
421 SET_FARVAR(seg, info->sequ_regs[i], inb(VGAREG_SEQU_DATA));
423 outb(0, VGAREG_SEQU_ADDRESS);
424 SET_FARVAR(seg, info->sequ0, inb(VGAREG_SEQU_DATA));
426 for (i=0; i<25; i++) {
428 SET_FARVAR(seg, info->crtc_regs[i], inb(crtc_addr + 1));
431 for (i=0; i<20; i++) {
432 inb(VGAREG_ACTL_RESET);
433 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
434 SET_FARVAR(seg, info->actl_regs[i], inb(VGAREG_ACTL_READ_DATA));
436 inb(VGAREG_ACTL_RESET);
438 for (i=0; i<9; i++) {
439 outb(i, VGAREG_GRDC_ADDRESS);
440 SET_FARVAR(seg, info->grdc_regs[i], inb(VGAREG_GRDC_DATA));
443 SET_FARVAR(seg, info->crtc_addr, crtc_addr);
445 /* XXX: read plane latches */
447 SET_FARVAR(seg, info->plane_latch[i], 0);
451 stdvga_restore_state(u16 seg, struct saveVideoHardware *info)
453 // Reset Attribute Ctl flip-flop
454 inb(VGAREG_ACTL_RESET);
456 u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
459 for (i=0; i<4; i++) {
460 outb(i+1, VGAREG_SEQU_ADDRESS);
461 outb(GET_FARVAR(seg, info->sequ_regs[i]), VGAREG_SEQU_DATA);
463 outb(0, VGAREG_SEQU_ADDRESS);
464 outb(GET_FARVAR(seg, info->sequ0), VGAREG_SEQU_DATA);
466 // Disable CRTC write protection
467 outw(0x0011, crtc_addr);
472 outb(GET_FARVAR(seg, info->crtc_regs[i]), crtc_addr + 1);
474 // select crtc base address
475 u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
476 if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
478 outb(v, VGAREG_WRITE_MISC_OUTPUT);
480 // enable write protection if needed
481 outb(0x11, crtc_addr);
482 outb(GET_FARVAR(seg, info->crtc_regs[0x11]), crtc_addr + 1);
485 u16 ar_index = GET_FARVAR(seg, info->actl_index);
486 inb(VGAREG_ACTL_RESET);
487 for (i=0; i<20; i++) {
488 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
489 outb(GET_FARVAR(seg, info->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
491 outb(ar_index, VGAREG_ACTL_ADDRESS);
492 inb(VGAREG_ACTL_RESET);
494 for (i=0; i<9; i++) {
495 outb(i, VGAREG_GRDC_ADDRESS);
496 outb(GET_FARVAR(seg, info->grdc_regs[i]), VGAREG_GRDC_DATA);
499 outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
500 outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
501 outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
502 outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
506 stdvga_set_mode(struct vgamode_s *vmode_g)
508 // Reset Attribute Ctl flip-flop
509 inb(VGAREG_ACTL_RESET);
512 u8 *regs = GET_GLOBAL(vmode_g->actl_regs);
514 for (i = 0; i <= 0x13; i++) {
515 outb(i, VGAREG_ACTL_ADDRESS);
516 outb(GET_GLOBAL(regs[i]), VGAREG_ACTL_WRITE_DATA);
518 outb(0x14, VGAREG_ACTL_ADDRESS);
519 outb(0x00, VGAREG_ACTL_WRITE_DATA);
522 outb(0, VGAREG_SEQU_ADDRESS);
523 outb(0x03, VGAREG_SEQU_DATA);
524 regs = GET_GLOBAL(vmode_g->sequ_regs);
525 for (i = 1; i <= 4; i++) {
526 outb(i, VGAREG_SEQU_ADDRESS);
527 outb(GET_GLOBAL(regs[i - 1]), VGAREG_SEQU_DATA);
531 regs = GET_GLOBAL(vmode_g->grdc_regs);
532 for (i = 0; i <= 8; i++) {
533 outb(i, VGAREG_GRDC_ADDRESS);
534 outb(GET_GLOBAL(regs[i]), VGAREG_GRDC_DATA);
537 // Set CRTC address VGA or MDA
538 u8 miscreg = GET_GLOBAL(vmode_g->miscreg);
539 u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
541 crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
543 // Disable CRTC write protection
544 outw(0x0011, crtc_addr);
546 regs = GET_GLOBAL(vmode_g->crtc_regs);
547 for (i = 0; i <= 0x18; i++) {
549 outb(GET_GLOBAL(regs[i]), crtc_addr + 1);
552 // Set the misc register
553 outb(miscreg, VGAREG_WRITE_MISC_OUTPUT);
556 outb(0x20, VGAREG_ACTL_ADDRESS);
557 inb(VGAREG_ACTL_RESET);
561 /****************************************************************
563 ****************************************************************/
566 stdvga_enable_video_addressing(u8 disable)
568 u8 v = (disable & 1) ? 0x00 : 0x02;
569 u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
570 outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
576 // switch to color mode and enable CPU access 480 lines
577 outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
578 // more than 64k 3C4/04
579 outb(0x04, VGAREG_SEQU_ADDRESS);
580 outb(0x02, VGAREG_SEQU_DATA);