1 // VGA bios implementation
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.
10 // * define structs for save/restore state
11 // * review correctness of converted asm by comparing with RBIL
12 // * refactor redundant code into sub-functions
13 // * See if there is a method to the in/out stuff that can be encapsulated.
14 // * remove "biosfn" prefixes
15 // * verify all funcs static
17 // * convert vbe/clext code
19 // * separate code into separate files
20 // * extract hw code from bios interfaces
22 #include "bregs.h" // struct bregs
23 #include "biosvar.h" // GET_BDA
24 #include "util.h" // memset
25 #include "vgatables.h" // find_vga_entry
29 #define CONFIG_CIRRUS 0
32 #define DEBUG_VGA_POST 1
33 #define DEBUG_VGA_10 3
35 #define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
38 // ===================================================================
42 // ===================================================================
44 // -------------------------------------------------------------------
46 call16_vgaint(u32 eax, u32 ebx)
58 // ===================================================================
62 // ===================================================================
64 // -------------------------------------------------------------------
66 biosfn_perform_gray_scale_summing(u16 start, u16 count)
68 inb(VGAREG_ACTL_RESET);
69 outb(0x00, VGAREG_ACTL_ADDRESS);
72 for (i = start; i < start+count; i++) {
73 // set read address and switch to read mode
74 outb(i, VGAREG_DAC_READ_ADDRESS);
75 // get 6-bit wide RGB data values
76 u8 r = inb(VGAREG_DAC_DATA);
77 u8 g = inb(VGAREG_DAC_DATA);
78 u8 b = inb(VGAREG_DAC_DATA);
80 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
81 u16 intensity = ((77 * r + 151 * g + 28 * b) + 0x80) >> 8;
86 // set write address and switch to write mode
87 outb(i, VGAREG_DAC_WRITE_ADDRESS);
88 // write new intensity value
89 outb(intensity & 0xff, VGAREG_DAC_DATA);
90 outb(intensity & 0xff, VGAREG_DAC_DATA);
91 outb(intensity & 0xff, VGAREG_DAC_DATA);
93 inb(VGAREG_ACTL_RESET);
94 outb(0x20, VGAREG_ACTL_ADDRESS);
97 // -------------------------------------------------------------------
99 biosfn_set_cursor_shape(u8 CH, u8 CL)
104 u16 curs = (CH << 8) + CL;
105 SET_BDA(cursor_type, curs);
107 u8 modeset_ctl = GET_BDA(modeset_ctl);
108 u16 cheight = GET_BDA(char_height);
109 if ((modeset_ctl & 0x01) && (cheight > 8) && (CL < 8) && (CH < 0x20)) {
111 CH = ((CH + 1) * cheight / 8) - 1;
113 CH = ((CL + 1) * cheight / 8) - 2;
114 CL = ((CL + 1) * cheight / 8) - 1;
116 // CTRC regs 0x0a and 0x0b
117 u16 crtc_addr = GET_BDA(crtc_address);
118 outb(0x0a, crtc_addr);
119 outb(CH, crtc_addr + 1);
120 outb(0x0b, crtc_addr);
121 outb(CL, crtc_addr + 1);
125 biosfn_get_cursor_shape(u8 page)
129 // FIXME should handle VGA 14/16 lines
130 return GET_BDA(cursor_type);
133 // -------------------------------------------------------------------
135 biosfn_set_cursor_pos(u8 page, u16 cursor)
137 // Should not happen...
142 SET_BDA(cursor_pos[page], cursor);
144 // Set the hardware cursor
145 u8 current = GET_BDA(video_page);
149 // Get the dimensions
150 u16 nbcols = GET_BDA(video_cols);
151 u16 nbrows = GET_BDA(video_rows) + 1;
153 u8 xcurs = cursor & 0x00ff;
154 u8 ycurs = (cursor & 0xff00) >> 8;
156 // Calculate the address knowing nbcols nbrows and page num
157 u16 address = SCREEN_IO_START(nbcols, nbrows, page) + xcurs + ycurs * nbcols;
159 // CRTC regs 0x0e and 0x0f
160 u16 crtc_addr = GET_BDA(crtc_address);
161 outb(0x0e, crtc_addr);
162 outb((address & 0xff00) >> 8, crtc_addr + 1);
163 outb(0x0f, crtc_addr);
164 outb(address & 0x00ff, crtc_addr + 1);
168 biosfn_get_cursor_pos(u8 page)
172 // FIXME should handle VGA 14/16 lines
173 return GET_BDA(cursor_pos[page]);
176 // -------------------------------------------------------------------
178 biosfn_set_active_page(u8 page)
184 struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
188 // Get pos curs pos for the right page
189 u16 cursor = biosfn_get_cursor_pos(page);
192 if (GET_GLOBAL(vmode_g->class) == TEXT) {
193 // Get the dimensions
194 u16 nbcols = GET_BDA(video_cols);
195 u16 nbrows = GET_BDA(video_rows) + 1;
197 // Calculate the address knowing nbcols nbrows and page num
198 address = SCREEN_MEM_START(nbcols, nbrows, page);
199 SET_BDA(video_pagestart, address);
202 address = SCREEN_IO_START(nbcols, nbrows, page);
204 struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
205 address = page * GET_GLOBAL(vparam_g->slength);
208 // CRTC regs 0x0c and 0x0d
209 u16 crtc_addr = GET_BDA(crtc_address);
210 outb(0x0c, crtc_addr);
211 outb((address & 0xff00) >> 8, crtc_addr + 1);
212 outb(0x0d, crtc_addr);
213 outb(address & 0x00ff, crtc_addr + 1);
215 // And change the BIOS page
216 SET_BDA(video_page, page);
218 dprintf(1, "Set active page %02x address %04x\n", page, address);
220 // Display the cursor, now the page is active
221 biosfn_set_cursor_pos(page, cursor);
225 biosfn_set_video_mode(u8 mode)
226 { // mode: Bit 7 is 1 if no clear screen
228 cirrus_set_video_mode(mode);
231 if (vbe_has_vbe_display())
232 dispi_set_enable(VBE_DISPI_DISABLED);
235 u8 noclearmem = mode & 0x80;
238 // find the entry in the video modes
239 struct vgamode_s *vmode_g = find_vga_entry(mode);
240 dprintf(1, "mode search %02x found %p\n", mode, vmode_g);
244 struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
245 u16 twidth = GET_GLOBAL(vparam_g->twidth);
246 u16 theightm1 = GET_GLOBAL(vparam_g->theightm1);
247 u16 cheight = GET_GLOBAL(vparam_g->cheight);
249 // Read the bios mode set control
250 u8 modeset_ctl = GET_BDA(modeset_ctl);
252 // Then we know the number of lines
255 // if palette loading (bit 3 of modeset ctl = 0)
256 if ((modeset_ctl & 0x08) == 0) { // Set the PEL mask
257 outb(GET_GLOBAL(vmode_g->pelmask), VGAREG_PEL_MASK);
259 // Set the whole dac always, from 0
260 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
262 // From which palette
263 u8 *palette_g = GET_GLOBAL(vmode_g->dac);
264 u16 palsize = GET_GLOBAL(vmode_g->dacsize) / 3;
265 // Always 256*3 values
267 for (i = 0; i < 0x0100; i++) {
269 outb(GET_GLOBAL(palette_g[(i * 3) + 0]), VGAREG_DAC_DATA);
270 outb(GET_GLOBAL(palette_g[(i * 3) + 1]), VGAREG_DAC_DATA);
271 outb(GET_GLOBAL(palette_g[(i * 3) + 2]), VGAREG_DAC_DATA);
273 outb(0, VGAREG_DAC_DATA);
274 outb(0, VGAREG_DAC_DATA);
275 outb(0, VGAREG_DAC_DATA);
278 if ((modeset_ctl & 0x02) == 0x02)
279 biosfn_perform_gray_scale_summing(0x00, 0x100);
281 // Reset Attribute Ctl flip-flop
282 inb(VGAREG_ACTL_RESET);
286 for (i = 0; i <= 0x13; i++) {
287 outb(i, VGAREG_ACTL_ADDRESS);
288 outb(GET_GLOBAL(vparam_g->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
290 outb(0x14, VGAREG_ACTL_ADDRESS);
291 outb(0x00, VGAREG_ACTL_WRITE_DATA);
294 outb(0, VGAREG_SEQU_ADDRESS);
295 outb(0x03, VGAREG_SEQU_DATA);
296 for (i = 1; i <= 4; i++) {
297 outb(i, VGAREG_SEQU_ADDRESS);
298 outb(GET_GLOBAL(vparam_g->sequ_regs[i - 1]), VGAREG_SEQU_DATA);
302 for (i = 0; i <= 8; i++) {
303 outb(i, VGAREG_GRDC_ADDRESS);
304 outb(GET_GLOBAL(vparam_g->grdc_regs[i]), VGAREG_GRDC_DATA);
307 // Set CRTC address VGA or MDA
308 u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
309 if (GET_GLOBAL(vmode_g->memmodel) == MTEXT)
310 crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
312 // Disable CRTC write protection
313 outw(0x0011, crtc_addr);
315 for (i = 0; i <= 0x18; i++) {
317 outb(GET_GLOBAL(vparam_g->crtc_regs[i]), crtc_addr + 1);
320 // Set the misc register
321 outb(GET_GLOBAL(vparam_g->miscreg), VGAREG_WRITE_MISC_OUTPUT);
324 outb(0x20, VGAREG_ACTL_ADDRESS);
325 inb(VGAREG_ACTL_RESET);
327 if (noclearmem == 0x00) {
328 if (GET_GLOBAL(vmode_g->class) == TEXT) {
329 memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024);
332 memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024);
334 outb(0x02, VGAREG_SEQU_ADDRESS);
335 u8 mmask = inb(VGAREG_SEQU_DATA);
336 outb(0x0f, VGAREG_SEQU_DATA); // all planes
337 memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024);
338 outb(mmask, VGAREG_SEQU_DATA);
343 SET_BDA(video_mode, mode);
344 SET_BDA(video_cols, twidth);
345 SET_BDA(video_pagesize, GET_GLOBAL(vparam_g->slength));
346 SET_BDA(crtc_address, crtc_addr);
347 SET_BDA(video_rows, theightm1);
348 SET_BDA(char_height, cheight);
349 SET_BDA(video_ctl, (0x60 | noclearmem));
350 SET_BDA(video_switches, 0xF9);
351 SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
353 // FIXME We nearly have the good tables. to be reworked
354 SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now
355 SET_BDA(video_savetable_ptr, (u32)video_save_pointer_table);
356 SET_BDA(video_savetable_seg, get_global_seg());
359 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
360 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
363 if (GET_GLOBAL(vmode_g->class) == TEXT)
364 biosfn_set_cursor_shape(0x06, 0x07);
365 // Set cursor pos for page 0..7
366 for (i = 0; i < 8; i++)
367 biosfn_set_cursor_pos(i, 0x0000);
370 biosfn_set_active_page(0x00);
372 // Write the fonts in memory
373 if (GET_GLOBAL(vmode_g->class) == TEXT) {
374 call16_vgaint(0x1104, 0);
375 call16_vgaint(0x1103, 0);
377 // Set the ints 0x1F and 0x43
378 SET_IVT(0x1f, get_global_seg(), (u32)&vgafont8[128 * 8]);
382 SET_IVT(0x43, get_global_seg(), (u32)vgafont8);
385 SET_IVT(0x43, get_global_seg(), (u32)vgafont14);
388 SET_IVT(0x43, get_global_seg(), (u32)vgafont16);
393 // -------------------------------------------------------------------
395 biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
396 { // flag = WITH_ATTR / NO_ATTR
397 // special case if page is 0xff, use current page
399 page = GET_BDA(video_page);
402 struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
406 // Get the cursor pos for the page
407 u16 cursor = biosfn_get_cursor_pos(page);
408 u8 xcurs = cursor & 0x00ff;
409 u8 ycurs = (cursor & 0xff00) >> 8;
411 // Get the dimensions
412 u16 nbrows = GET_BDA(video_rows) + 1;
413 u16 nbcols = GET_BDA(video_cols);
435 biosfn_write_teletype(' ', page, attr, flag);
436 cursor = biosfn_get_cursor_pos(page);
437 xcurs = cursor & 0x00ff;
438 ycurs = (cursor & 0xff00) >> 8;
439 } while (xcurs % 8 == 0);
443 if (flag == WITH_ATTR)
444 biosfn_write_char_attr(car, page, attr, 1);
446 biosfn_write_char_only(car, page, attr, 1);
450 // Do we need to wrap ?
451 if (xcurs == nbcols) {
455 // Do we need to scroll ?
456 if (ycurs == nbrows) {
457 if (GET_GLOBAL(vmode_g->class) == TEXT)
458 biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, page,
461 biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, page,
465 // Set the cursor for the page
469 biosfn_set_cursor_pos(page, cursor);
472 // -------------------------------------------------------------------
474 biosfn_get_video_mode(struct bregs *regs)
476 regs->bh = GET_BDA(video_page);
477 regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
478 regs->ah = GET_BDA(video_cols);
482 set_scan_lines(u8 lines)
484 u16 crtc_addr = GET_BDA(crtc_address);
485 outb(0x09, crtc_addr);
486 u8 crtc_r9 = inb(crtc_addr + 1);
487 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
488 outb(crtc_r9, crtc_addr + 1);
490 biosfn_set_cursor_shape(0x06, 0x07);
492 biosfn_set_cursor_shape(lines - 4, lines - 3);
493 SET_BDA(char_height, lines);
494 outb(0x12, crtc_addr);
495 u16 vde = inb(crtc_addr + 1);
496 outb(0x07, crtc_addr);
497 u8 ovl = inb(crtc_addr + 1);
498 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
499 u8 rows = vde / lines;
500 SET_BDA(video_rows, rows - 1);
501 u16 cols = GET_BDA(video_cols);
502 SET_BDA(video_pagesize, rows * cols * 2);
505 // -------------------------------------------------------------------
507 biosfn_get_font_info(u8 BH, u16 *ES, u16 *BP, u16 *CX, u16 *DX)
511 u32 segoff = GET_IVT(0x1f).segoff;
517 u32 segoff = GET_IVT(0x43).segoff;
523 *ES = get_global_seg();
524 *BP = (u32)vgafont14;
527 *ES = get_global_seg();
531 *ES = get_global_seg();
532 *BP = (u32)vgafont8 + 128 * 8;
535 *ES = get_global_seg();
536 *BP = (u32)vgafont14alt;
539 *ES = get_global_seg();
540 *BP = (u32)vgafont16;
543 *ES = get_global_seg();
544 *BP = (u32)vgafont16alt;
547 dprintf(1, "Get font info BH(%02x) was discarded\n", BH);
550 // Set byte/char of on screen font
551 *CX = GET_BDA(char_height) & 0xff;
553 // Set Highest char row
554 *DX = GET_BDA(video_rows);
557 // -------------------------------------------------------------------
559 biosfn_get_ega_info(struct bregs *regs)
561 regs->cx = GET_BDA(video_switches) & 0x0f;
562 regs->ax = GET_BDA(crtc_address);
563 if (regs->ax == VGAREG_MDA_CRTC_ADDRESS)
569 // -------------------------------------------------------------------
571 biosfn_select_vert_res(struct bregs *regs)
573 u8 mctl = GET_BDA(modeset_ctl);
574 u8 vswt = GET_BDA(video_switches);
579 mctl = (mctl & ~0x10) | 0x80;
580 vswt = (vswt & ~0x0f) | 0x08;
585 vswt = (vswt & ~0x0f) | 0x09;
589 mctl = (mctl & ~0x80) | 0x10;
590 vswt = (vswt & ~0x0f) | 0x09;
593 dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
596 SET_BDA(modeset_ctl, mctl);
597 SET_BDA(video_switches, vswt);
602 biosfn_enable_default_palette_loading(struct bregs *regs)
604 u8 v = (regs->al & 0x01) << 3;
605 u8 mctl = GET_BDA(video_ctl) & ~0x08;
606 SET_BDA(video_ctl, mctl | v);
612 biosfn_enable_grayscale_summing(struct bregs *regs)
614 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
615 u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
616 SET_BDA(modeset_ctl, v | v2);
621 biosfn_enable_cursor_emulation(struct bregs *regs)
623 u8 v = (regs->al & 0x01) ^ 0x01;
624 u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
625 SET_BDA(modeset_ctl, v | v2);
629 // -------------------------------------------------------------------
631 biosfn_write_string(u8 flag, u8 page, u8 attr, u16 count, u8 row, u8 col,
632 u16 seg, u8 *offset_far)
634 // Read curs info for the page
635 u16 oldcurs = biosfn_get_cursor_pos(page);
637 // if row=0xff special case : use current cursor position
639 col = oldcurs & 0x00ff;
640 row = (oldcurs & 0xff00) >> 8;
646 biosfn_set_cursor_pos(page, newcurs);
648 while (count-- != 0) {
649 u8 car = GET_FARVAR(seg, *offset_far);
651 if ((flag & 0x02) != 0) {
652 attr = GET_FARVAR(seg, *offset_far);
656 biosfn_write_teletype(car, page, attr, WITH_ATTR);
660 if ((flag & 0x01) == 0)
661 biosfn_set_cursor_pos(page, oldcurs);
664 // -------------------------------------------------------------------
666 biosfn_read_display_code(struct bregs *regs)
668 regs->bx = GET_BDA(dcc_index);
673 biosfn_set_display_code(struct bregs *regs)
675 SET_BDA(dcc_index, regs->bl);
676 dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
680 // -------------------------------------------------------------------
682 biosfn_read_state_info(u16 BX, u16 ES, u16 DI)
684 // Address of static functionality table
685 SET_FARVAR(ES, *(u16*)(DI + 0x00), (u32)static_functionality);
686 SET_FARVAR(ES, *(u16*)(DI + 0x02), get_global_seg());
688 // Hard coded copy from BIOS area. Should it be cleaner ?
689 memcpy_far(ES, (void*)(DI + 0x04), SEG_BDA, (void*)0x49, 30);
690 memcpy_far(ES, (void*)(DI + 0x22), SEG_BDA, (void*)0x84, 3);
692 SET_FARVAR(ES, *(u8*)(DI + 0x25), GET_BDA(dcc_index));
693 SET_FARVAR(ES, *(u8*)(DI + 0x26), 0);
694 SET_FARVAR(ES, *(u8*)(DI + 0x27), 16);
695 SET_FARVAR(ES, *(u8*)(DI + 0x28), 0);
696 SET_FARVAR(ES, *(u8*)(DI + 0x29), 8);
697 SET_FARVAR(ES, *(u8*)(DI + 0x2a), 2);
698 SET_FARVAR(ES, *(u8*)(DI + 0x2b), 0);
699 SET_FARVAR(ES, *(u8*)(DI + 0x2c), 0);
700 SET_FARVAR(ES, *(u8*)(DI + 0x31), 3);
701 SET_FARVAR(ES, *(u8*)(DI + 0x32), 0);
703 memset_far(ES, (void*)(DI + 0x33), 0, 13);
706 // -------------------------------------------------------------------
707 // -------------------------------------------------------------------
709 biosfn_read_video_state_size(u16 CX)
715 size += (5 + 8 + 5) * 2 + 6;
717 size += 3 + 256 * 3 + 1;
722 biosfn_save_video_state(u16 CX, u16 ES, u16 BX)
724 u16 crtc_addr = GET_BDA(crtc_address);
726 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_ADDRESS));
728 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr));
730 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_ADDRESS));
732 inb(VGAREG_ACTL_RESET);
733 u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
734 SET_FARVAR(ES, *(u8*)(BX+0), ar_index);
736 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_READ_FEATURE_CTL));
740 for (i = 1; i <= 4; i++) {
741 outb(i, VGAREG_SEQU_ADDRESS);
742 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
745 outb(0, VGAREG_SEQU_ADDRESS);
746 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
749 for (i = 0; i <= 0x18; i++) {
751 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr + 1));
755 for (i = 0; i <= 0x13; i++) {
756 inb(VGAREG_ACTL_RESET);
757 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
758 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_ACTL_READ_DATA));
761 inb(VGAREG_ACTL_RESET);
763 for (i = 0; i <= 8; i++) {
764 outb(i, VGAREG_GRDC_ADDRESS);
765 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_DATA));
769 SET_FARVAR(ES, *(u16*)(BX+0), crtc_addr);
772 /* XXX: read plane latches */
773 SET_FARVAR(ES, *(u8*)(BX+0), 0);
775 SET_FARVAR(ES, *(u8*)(BX+0), 0);
777 SET_FARVAR(ES, *(u8*)(BX+0), 0);
779 SET_FARVAR(ES, *(u8*)(BX+0), 0);
783 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_mode));
785 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_cols));
787 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagesize));
789 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(crtc_address));
791 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_rows));
793 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(char_height));
795 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_ctl));
797 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_switches));
799 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(modeset_ctl));
801 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_type));
804 for (i = 0; i < 8; i++) {
805 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_pos[i]));
808 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagestart));
810 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_page));
813 SET_FARVAR(ES, *(u32*)(BX+0), GET_IVT(0x1f).segoff);
815 SET_FARVAR(ES, *(u32*)(BX+0), GET_IVT(0x43).segoff);
819 /* XXX: check this */
820 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_STATE));
821 BX++; /* read/write mode dac */
822 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_WRITE_ADDRESS));
823 BX++; /* pix address */
824 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_PEL_MASK));
826 // Set the whole dac always, from 0
827 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
829 for (i = 0; i < 256 * 3; i++) {
830 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_DATA));
833 SET_FARVAR(ES, *(u8*)(BX+0), 0);
834 BX++; /* color select register */
840 biosfn_restore_video_state(u16 CX, u16 ES, u16 BX)
843 // Reset Attribute Ctl flip-flop
844 inb(VGAREG_ACTL_RESET);
846 u16 crtc_addr = GET_FARVAR(ES, *(u16*)(BX + 0x40));
851 for (i = 1; i <= 4; i++) {
852 outb(i, VGAREG_SEQU_ADDRESS);
853 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
856 outb(0, VGAREG_SEQU_ADDRESS);
857 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
860 // Disable CRTC write protection
861 outw(0x0011, crtc_addr);
863 for (i = 0; i <= 0x18; i++) {
866 outb(GET_FARVAR(ES, *(u8*)(BX+0)), crtc_addr + 1);
870 // select crtc base address
871 u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
872 if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
874 outb(v, VGAREG_WRITE_MISC_OUTPUT);
876 // enable write protection if needed
877 outb(0x11, crtc_addr);
878 outb(GET_FARVAR(ES, *(u8*)(BX - 0x18 + 0x11)), crtc_addr + 1);
881 u16 ar_index = GET_FARVAR(ES, *(u8*)(addr1 + 0x03));
882 inb(VGAREG_ACTL_RESET);
883 for (i = 0; i <= 0x13; i++) {
884 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
885 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_ACTL_WRITE_DATA);
888 outb(ar_index, VGAREG_ACTL_ADDRESS);
889 inb(VGAREG_ACTL_RESET);
891 for (i = 0; i <= 8; i++) {
892 outb(i, VGAREG_GRDC_ADDRESS);
893 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_GRDC_DATA);
896 BX += 2; /* crtc_addr */
897 BX += 4; /* plane latches */
899 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_SEQU_ADDRESS);
901 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr);
903 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_GRDC_ADDRESS);
906 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr - 0x4 + 0xa);
910 SET_BDA(video_mode, GET_FARVAR(ES, *(u8*)(BX+0)));
912 SET_BDA(video_cols, GET_FARVAR(ES, *(u16*)(BX+0)));
914 SET_BDA(video_pagesize, GET_FARVAR(ES, *(u16*)(BX+0)));
916 SET_BDA(crtc_address, GET_FARVAR(ES, *(u16*)(BX+0)));
918 SET_BDA(video_rows, GET_FARVAR(ES, *(u8*)(BX+0)));
920 SET_BDA(char_height, GET_FARVAR(ES, *(u16*)(BX+0)));
922 SET_BDA(video_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
924 SET_BDA(video_switches, GET_FARVAR(ES, *(u8*)(BX+0)));
926 SET_BDA(modeset_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
928 SET_BDA(cursor_type, GET_FARVAR(ES, *(u16*)(BX+0)));
931 for (i = 0; i < 8; i++) {
932 SET_BDA(cursor_pos[i], GET_FARVAR(ES, *(u16*)(BX+0)));
935 SET_BDA(video_pagestart, GET_FARVAR(ES, *(u16*)(BX+0)));
937 SET_BDA(video_page, GET_FARVAR(ES, *(u8*)(BX+0)));
940 SET_IVT(0x1f, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
942 SET_IVT(0x43, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
947 u16 v = GET_FARVAR(ES, *(u8*)(BX+0));
949 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_PEL_MASK);
951 // Set the whole dac always, from 0
952 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
954 for (i = 0; i < 256 * 3; i++) {
955 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_DAC_DATA);
959 outb(v, VGAREG_DAC_WRITE_ADDRESS);
965 /****************************************************************
967 ****************************************************************/
970 handle_1000(struct bregs *regs)
973 biosfn_set_video_mode(regs->al);
974 switch(regs->al & 0x7F) {
993 handle_1001(struct bregs *regs)
995 biosfn_set_cursor_shape(regs->ch, regs->cl);
999 handle_1002(struct bregs *regs)
1001 biosfn_set_cursor_pos(regs->bh, regs->dx);
1005 handle_1003(struct bregs *regs)
1007 regs->cx = biosfn_get_cursor_shape(regs->bh);
1008 regs->dx = biosfn_get_cursor_pos(regs->bh);
1011 // Read light pen pos (unimplemented)
1013 handle_1004(struct bregs *regs)
1016 regs->ax = regs->bx = regs->cx = regs->dx = 0;
1020 handle_1005(struct bregs *regs)
1022 biosfn_set_active_page(regs->al);
1026 handle_1006(struct bregs *regs)
1028 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
1033 handle_1007(struct bregs *regs)
1035 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
1036 , 0xFF, SCROLL_DOWN);
1040 handle_1008(struct bregs *regs)
1043 biosfn_read_char_attr(regs->bh, ®s->ax);
1047 handle_1009(struct bregs *regs)
1050 biosfn_write_char_attr(regs->al, regs->bh, regs->bl, regs->cx);
1054 handle_100a(struct bregs *regs)
1057 biosfn_write_char_only(regs->al, regs->bh, regs->bl, regs->cx);
1062 handle_100b00(struct bregs *regs)
1065 biosfn_set_border_color(regs);
1069 handle_100b01(struct bregs *regs)
1072 biosfn_set_palette(regs);
1076 handle_100bXX(struct bregs *regs)
1082 handle_100b(struct bregs *regs)
1085 case 0x00: handle_100b00(regs); break;
1086 case 0x01: handle_100b01(regs); break;
1087 default: handle_100bXX(regs); break;
1093 handle_100c(struct bregs *regs)
1096 biosfn_write_pixel(regs->bh, regs->al, regs->cx, regs->dx);
1100 handle_100d(struct bregs *regs)
1103 biosfn_read_pixel(regs->bh, regs->cx, regs->dx, ®s->ax);
1107 handle_100e(struct bregs *regs)
1109 // Ralf Brown Interrupt list is WRONG on bh(page)
1110 // We do output only on the current page !
1111 biosfn_write_teletype(regs->al, 0xff, regs->bl, NO_ATTR);
1115 handle_100f(struct bregs *regs)
1118 biosfn_get_video_mode(regs);
1123 handle_101000(struct bregs *regs)
1125 if (regs->bl > 0x14)
1127 biosfn_set_single_palette_reg(regs->bl, regs->bh);
1131 handle_101001(struct bregs *regs)
1134 biosfn_set_overscan_border_color(regs);
1138 handle_101002(struct bregs *regs)
1141 biosfn_set_all_palette_reg(regs);
1145 handle_101003(struct bregs *regs)
1148 biosfn_toggle_intensity(regs);
1152 handle_101007(struct bregs *regs)
1154 if (regs->bl > 0x14)
1156 regs->bh = biosfn_get_single_palette_reg(regs->bl);
1160 handle_101008(struct bregs *regs)
1163 biosfn_read_overscan_border_color(regs);
1167 handle_101009(struct bregs *regs)
1170 biosfn_get_all_palette_reg(regs);
1174 handle_101010(struct bregs *regs)
1177 biosfn_set_single_dac_reg(regs);
1181 handle_101012(struct bregs *regs)
1184 biosfn_set_all_dac_reg(regs);
1188 handle_101013(struct bregs *regs)
1191 biosfn_select_video_dac_color_page(regs);
1195 handle_101015(struct bregs *regs)
1198 biosfn_read_single_dac_reg(regs);
1202 handle_101017(struct bregs *regs)
1205 biosfn_read_all_dac_reg(regs);
1209 handle_101018(struct bregs *regs)
1212 biosfn_set_pel_mask(regs);
1216 handle_101019(struct bregs *regs)
1219 biosfn_read_pel_mask(regs);
1223 handle_10101a(struct bregs *regs)
1226 biosfn_read_video_dac_state(regs);
1230 handle_10101b(struct bregs *regs)
1232 biosfn_perform_gray_scale_summing(regs->bx, regs->cx);
1236 handle_1010XX(struct bregs *regs)
1242 handle_1010(struct bregs *regs)
1245 case 0x00: handle_101000(regs); break;
1246 case 0x01: handle_101001(regs); break;
1247 case 0x02: handle_101002(regs); break;
1248 case 0x03: handle_101003(regs); break;
1249 case 0x07: handle_101007(regs); break;
1250 case 0x08: handle_101008(regs); break;
1251 case 0x09: handle_101009(regs); break;
1252 case 0x10: handle_101010(regs); break;
1253 case 0x12: handle_101012(regs); break;
1254 case 0x13: handle_101013(regs); break;
1255 case 0x15: handle_101015(regs); break;
1256 case 0x17: handle_101017(regs); break;
1257 case 0x18: handle_101018(regs); break;
1258 case 0x19: handle_101019(regs); break;
1259 case 0x1a: handle_10101a(regs); break;
1260 case 0x1b: handle_10101b(regs); break;
1261 default: handle_1010XX(regs); break;
1267 handle_101100(struct bregs *regs)
1269 biosfn_load_text_user_pat(regs->es, regs->bp
1270 , regs->cx, regs->dx, regs->bl, regs->bh);
1274 handle_101101(struct bregs *regs)
1276 biosfn_load_text_8_14_pat(regs->bl);
1280 handle_101102(struct bregs *regs)
1282 biosfn_load_text_8_8_pat(regs->bl);
1286 handle_101103(struct bregs *regs)
1289 biosfn_set_text_block_specifier(regs);
1293 handle_101104(struct bregs *regs)
1295 biosfn_load_text_8_16_pat(regs->bl);
1299 handle_101110(struct bregs *regs)
1301 biosfn_load_text_user_pat(regs->es, regs->bp
1302 , regs->cx, regs->dx, regs->bl, regs->bh);
1303 set_scan_lines(regs->bh);
1307 handle_101111(struct bregs *regs)
1309 biosfn_load_text_8_14_pat(regs->bl);
1314 handle_101112(struct bregs *regs)
1316 biosfn_load_text_8_8_pat(regs->bl);
1321 handle_101114(struct bregs *regs)
1323 biosfn_load_text_8_16_pat(regs->bl);
1328 handle_101130(struct bregs *regs)
1331 biosfn_get_font_info(regs->bh, ®s->es, ®s->bp
1332 , ®s->cx, ®s->dx);
1336 handle_1011XX(struct bregs *regs)
1342 handle_1011(struct bregs *regs)
1345 case 0x00: handle_101100(regs); break;
1346 case 0x01: handle_101101(regs); break;
1347 case 0x02: handle_101102(regs); break;
1348 case 0x03: handle_101103(regs); break;
1349 case 0x04: handle_101104(regs); break;
1350 case 0x10: handle_101110(regs); break;
1351 case 0x11: handle_101111(regs); break;
1352 case 0x12: handle_101112(regs); break;
1353 case 0x14: handle_101114(regs); break;
1354 case 0x30: handle_101130(regs); break;
1355 default: handle_1011XX(regs); break;
1361 handle_101210(struct bregs *regs)
1364 biosfn_get_ega_info(regs);
1368 handle_101230(struct bregs *regs)
1371 biosfn_select_vert_res(regs);
1375 handle_101231(struct bregs *regs)
1378 biosfn_enable_default_palette_loading(regs);
1382 handle_101232(struct bregs *regs)
1385 biosfn_enable_video_addressing(regs);
1389 handle_101233(struct bregs *regs)
1392 biosfn_enable_grayscale_summing(regs);
1396 handle_101234(struct bregs *regs)
1399 biosfn_enable_cursor_emulation(regs);
1403 handle_101235(struct bregs *regs)
1410 handle_101236(struct bregs *regs)
1417 handle_1012XX(struct bregs *regs)
1423 handle_1012(struct bregs *regs)
1426 case 0x10: handle_101210(regs); break;
1427 case 0x30: handle_101230(regs); break;
1428 case 0x31: handle_101231(regs); break;
1429 case 0x32: handle_101232(regs); break;
1430 case 0x33: handle_101233(regs); break;
1431 case 0x34: handle_101234(regs); break;
1432 case 0x35: handle_101235(regs); break;
1433 case 0x36: handle_101236(regs); break;
1434 default: handle_1012XX(regs); break;
1437 // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
1442 handle_1013(struct bregs *regs)
1445 biosfn_write_string(regs->al, regs->bh, regs->bl, regs->cx
1446 , regs->dh, regs->dl, regs->es, (void*)(regs->bp + 0));
1451 handle_101a00(struct bregs *regs)
1454 biosfn_read_display_code(regs);
1458 handle_101a01(struct bregs *regs)
1461 biosfn_set_display_code(regs);
1465 handle_101aXX(struct bregs *regs)
1471 handle_101a(struct bregs *regs)
1474 case 0x00: handle_101a00(regs); break;
1475 case 0x01: handle_101a01(regs); break;
1476 default: handle_101aXX(regs); break;
1482 handle_101b(struct bregs *regs)
1485 biosfn_read_state_info(regs->bx, regs->es, regs->di);
1491 handle_101c00(struct bregs *regs)
1494 regs->bx = biosfn_read_video_state_size(regs->cx);
1498 handle_101c01(struct bregs *regs)
1501 biosfn_save_video_state(regs->cx, regs->es, regs->bx);
1505 handle_101c02(struct bregs *regs)
1508 biosfn_restore_video_state(regs->cx, regs->es, regs->bx);
1512 handle_101cXX(struct bregs *regs)
1518 handle_101c(struct bregs *regs)
1521 case 0x00: handle_101c00(regs); break;
1522 case 0x01: handle_101c01(regs); break;
1523 case 0x02: handle_101c02(regs); break;
1524 default: handle_101cXX(regs); break;
1530 handle_104f00(struct bregs *regs)
1532 // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
1533 // XXX - OR cirrus_vesa_00h
1537 handle_104f01(struct bregs *regs)
1539 // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
1540 // XXX - OR cirrus_vesa_01h
1544 handle_104f02(struct bregs *regs)
1546 // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
1547 // XXX - OR cirrus_vesa_02h
1551 handle_104f03(struct bregs *regs)
1553 // XXX - vbe_biosfn_return_current_mode
1554 // XXX - OR cirrus_vesa_03h
1558 handle_104f04(struct bregs *regs)
1560 // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
1564 handle_104f05(struct bregs *regs)
1566 // XXX - vbe_biosfn_display_window_control
1567 // XXX - OR cirrus_vesa_05h
1571 handle_104f06(struct bregs *regs)
1573 // XXX - vbe_biosfn_set_get_logical_scan_line_length
1574 // XXX - OR cirrus_vesa_06h
1578 handle_104f07(struct bregs *regs)
1580 // XXX - vbe_biosfn_set_get_display_start
1581 // XXX - OR cirrus_vesa_07h
1585 handle_104f08(struct bregs *regs)
1587 // XXX - vbe_biosfn_set_get_dac_palette_format
1591 handle_104f0a(struct bregs *regs)
1593 // XXX - vbe_biosfn_return_protected_mode_interface
1597 handle_104fXX(struct bregs *regs)
1604 handle_104f(struct bregs *regs)
1606 if (! CONFIG_VBE || !vbe_has_vbe_display()) {
1607 handle_104fXX(regs);
1612 case 0x00: handle_104f00(regs); break;
1613 case 0x01: handle_104f01(regs); break;
1614 case 0x02: handle_104f02(regs); break;
1615 case 0x03: handle_104f03(regs); break;
1616 case 0x04: handle_104f04(regs); break;
1617 case 0x05: handle_104f05(regs); break;
1618 case 0x06: handle_104f06(regs); break;
1619 case 0x07: handle_104f07(regs); break;
1620 case 0x08: handle_104f08(regs); break;
1621 case 0x0a: handle_104f0a(regs); break;
1622 default: handle_104fXX(regs); break;
1628 handle_10XX(struct bregs *regs)
1633 // INT 10h Video Support Service Entry Point
1635 handle_10(struct bregs *regs)
1637 debug_enter(regs, DEBUG_VGA_10);
1639 case 0x00: handle_1000(regs); break;
1640 case 0x01: handle_1001(regs); break;
1641 case 0x02: handle_1002(regs); break;
1642 case 0x03: handle_1003(regs); break;
1643 case 0x04: handle_1004(regs); break;
1644 case 0x05: handle_1005(regs); break;
1645 case 0x06: handle_1006(regs); break;
1646 case 0x07: handle_1007(regs); break;
1647 case 0x08: handle_1008(regs); break;
1648 case 0x09: handle_1009(regs); break;
1649 case 0x0a: handle_100a(regs); break;
1650 case 0x0b: handle_100b(regs); break;
1651 case 0x0c: handle_100c(regs); break;
1652 case 0x0d: handle_100d(regs); break;
1653 case 0x0e: handle_100e(regs); break;
1654 case 0x0f: handle_100f(regs); break;
1655 case 0x10: handle_1010(regs); break;
1656 case 0x11: handle_1011(regs); break;
1657 case 0x12: handle_1012(regs); break;
1658 case 0x13: handle_1013(regs); break;
1659 case 0x1a: handle_101a(regs); break;
1660 case 0x1b: handle_101b(regs); break;
1661 case 0x1c: handle_101c(regs); break;
1662 case 0x4f: handle_104f(regs); break;
1663 default: handle_10XX(regs); break;
1668 /****************************************************************
1670 ****************************************************************/
1675 // init detected hardware BIOS Area
1676 // set 80x25 color (not clear from RBIL but usual)
1677 u16 eqf = GET_BDA(equipment_list_flags);
1678 SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20);
1680 // Just for the first int10 find its children
1682 // the default char height
1683 SET_BDA(char_height, 0x10);
1686 SET_BDA(video_ctl, 0x60);
1688 // Set the basic screen we have
1689 SET_BDA(video_switches, 0xf9);
1691 // Set the basic modeset options
1692 SET_BDA(modeset_ctl, 0x51);
1694 // Set the default MSR
1695 SET_BDA(video_msr, 0x09);
1699 vga_post(struct bregs *regs)
1701 debug_enter(regs, DEBUG_VGA_POST);
1710 extern void entry_10(void);
1711 SET_IVT(0x10, get_global_seg(), (u32)entry_10);
1716 // XXX - clear screen and display info
1719 SET_VGA(video_save_pointer_table[0], (u32)video_param_table);
1720 SET_VGA(video_save_pointer_table[1], get_global_seg());
1723 extern u8 _rom_header_size, _rom_header_checksum;
1724 SET_VGA(_rom_header_checksum, 0);
1725 u8 sum = -checksum_far(get_global_seg(), 0, _rom_header_size * 512);
1726 SET_VGA(_rom_header_checksum, sum);