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 // * remove recursion from biosfn_write_teletype()
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 #include "bregs.h" // struct bregs
20 #include "biosvar.h" // GET_BDA
21 #include "util.h" // memset
22 #include "vgatables.h" // find_vga_entry
26 #define CONFIG_CIRRUS 0
29 #define DEBUG_VGA_POST 1
30 #define DEBUG_VGA_10 3
32 #define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
35 // ===================================================================
39 // ===================================================================
41 // -------------------------------------------------------------------
43 call16_vgaint(u32 eax, u32 ebx)
55 // ===================================================================
59 // ===================================================================
61 // -------------------------------------------------------------------
63 biosfn_perform_gray_scale_summing(u16 start, u16 count)
65 vgahw_screen_disable();
67 for (i = start; i < start+count; i++) {
69 vgahw_get_dac_regs(GET_SEG(SS), rgb, i, 1);
71 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
72 u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8;
76 vgahw_set_dac_regs(GET_SEG(SS), rgb, i, 1);
78 vgahw_screen_enable();
81 // -------------------------------------------------------------------
83 biosfn_set_cursor_shape(u8 CH, u8 CL)
88 u16 curs = (CH << 8) + CL;
89 SET_BDA(cursor_type, curs);
91 u8 modeset_ctl = GET_BDA(modeset_ctl);
92 u16 cheight = GET_BDA(char_height);
93 if ((modeset_ctl & 0x01) && (cheight > 8) && (CL < 8) && (CH < 0x20)) {
95 CH = ((CH + 1) * cheight / 8) - 1;
97 CH = ((CL + 1) * cheight / 8) - 2;
98 CL = ((CL + 1) * cheight / 8) - 1;
100 vgahw_set_cursor_shape(CH, CL);
104 biosfn_get_cursor_shape(u8 page)
108 // FIXME should handle VGA 14/16 lines
109 return GET_BDA(cursor_type);
112 // -------------------------------------------------------------------
114 biosfn_set_cursor_pos(u8 page, u16 cursor)
116 // Should not happen...
121 SET_BDA(cursor_pos[page], cursor);
123 // Set the hardware cursor
124 u8 current = GET_BDA(video_page);
128 // Get the dimensions
129 u16 nbcols = GET_BDA(video_cols);
130 u16 nbrows = GET_BDA(video_rows) + 1;
132 u8 xcurs = cursor & 0x00ff;
133 u8 ycurs = (cursor & 0xff00) >> 8;
135 // Calculate the address knowing nbcols nbrows and page num
136 u16 address = SCREEN_IO_START(nbcols, nbrows, page) + xcurs + ycurs * nbcols;
138 vgahw_set_cursor_pos(address);
142 biosfn_get_cursor_pos(u8 page)
146 // FIXME should handle VGA 14/16 lines
147 return GET_BDA(cursor_pos[page]);
150 // -------------------------------------------------------------------
152 biosfn_set_active_page(u8 page)
158 struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
162 // Get pos curs pos for the right page
163 u16 cursor = biosfn_get_cursor_pos(page);
166 if (GET_GLOBAL(vmode_g->class) == TEXT) {
167 // Get the dimensions
168 u16 nbcols = GET_BDA(video_cols);
169 u16 nbrows = GET_BDA(video_rows) + 1;
171 // Calculate the address knowing nbcols nbrows and page num
172 address = SCREEN_MEM_START(nbcols, nbrows, page);
173 SET_BDA(video_pagestart, address);
176 address = SCREEN_IO_START(nbcols, nbrows, page);
178 struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
179 address = page * GET_GLOBAL(vparam_g->slength);
182 vgahw_set_active_page(address);
184 // And change the BIOS page
185 SET_BDA(video_page, page);
187 dprintf(1, "Set active page %02x address %04x\n", page, address);
189 // Display the cursor, now the page is active
190 biosfn_set_cursor_pos(page, cursor);
194 biosfn_set_video_mode(u8 mode)
195 { // mode: Bit 7 is 1 if no clear screen
197 cirrus_set_video_mode(mode);
200 if (vbe_has_vbe_display())
201 dispi_set_enable(VBE_DISPI_DISABLED);
204 u8 noclearmem = mode & 0x80;
207 // find the entry in the video modes
208 struct vgamode_s *vmode_g = find_vga_entry(mode);
209 dprintf(1, "mode search %02x found %p\n", mode, vmode_g);
213 // Read the bios mode set control
214 u8 modeset_ctl = GET_BDA(modeset_ctl);
216 // Then we know the number of lines
219 // if palette loading (bit 3 of modeset ctl = 0)
220 if ((modeset_ctl & 0x08) == 0) { // Set the PEL mask
221 vgahw_set_pel_mask(GET_GLOBAL(vmode_g->pelmask));
223 // From which palette
224 u8 *palette_g = GET_GLOBAL(vmode_g->dac);
225 u16 palsize = GET_GLOBAL(vmode_g->dacsize) / 3;
227 // Always 256*3 values
228 vgahw_set_dac_regs(get_global_seg(), palette_g, 0, palsize);
230 for (i = palsize; i < 0x0100; i++) {
231 static u8 rgb[3] VAR16;
232 vgahw_set_dac_regs(get_global_seg(), rgb, i, 1);
235 if ((modeset_ctl & 0x02) == 0x02)
236 biosfn_perform_gray_scale_summing(0x00, 0x100);
239 struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
240 vgahw_set_mode(vparam_g);
242 if (noclearmem == 0x00)
243 clear_screen(vmode_g);
245 // Set CRTC address VGA or MDA
246 u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
247 if (GET_GLOBAL(vmode_g->memmodel) == MTEXT)
248 crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
251 u16 cheight = GET_GLOBAL(vparam_g->cheight);
252 SET_BDA(video_mode, mode);
253 SET_BDA(video_cols, GET_GLOBAL(vparam_g->twidth));
254 SET_BDA(video_pagesize, GET_GLOBAL(vparam_g->slength));
255 SET_BDA(crtc_address, crtc_addr);
256 SET_BDA(video_rows, GET_GLOBAL(vparam_g->theightm1));
257 SET_BDA(char_height, cheight);
258 SET_BDA(video_ctl, (0x60 | noclearmem));
259 SET_BDA(video_switches, 0xF9);
260 SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
262 // FIXME We nearly have the good tables. to be reworked
263 SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now
264 SET_BDA(video_savetable_ptr, (u32)video_save_pointer_table);
265 SET_BDA(video_savetable_seg, get_global_seg());
268 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
269 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
272 if (GET_GLOBAL(vmode_g->class) == TEXT)
273 biosfn_set_cursor_shape(0x06, 0x07);
274 // Set cursor pos for page 0..7
276 for (i = 0; i < 8; i++)
277 biosfn_set_cursor_pos(i, 0x0000);
280 biosfn_set_active_page(0x00);
282 // Write the fonts in memory
283 if (GET_GLOBAL(vmode_g->class) == TEXT) {
284 call16_vgaint(0x1104, 0);
285 call16_vgaint(0x1103, 0);
287 // Set the ints 0x1F and 0x43
288 SET_IVT(0x1f, get_global_seg(), (u32)&vgafont8[128 * 8]);
292 SET_IVT(0x43, get_global_seg(), (u32)vgafont8);
295 SET_IVT(0x43, get_global_seg(), (u32)vgafont14);
298 SET_IVT(0x43, get_global_seg(), (u32)vgafont16);
303 // -------------------------------------------------------------------
305 biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
306 { // flag = WITH_ATTR / NO_ATTR
307 // special case if page is 0xff, use current page
309 page = GET_BDA(video_page);
312 struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
316 // Get the cursor pos for the page
317 u16 cursor = biosfn_get_cursor_pos(page);
318 u8 xcurs = cursor & 0x00ff;
319 u8 ycurs = (cursor & 0xff00) >> 8;
321 // Get the dimensions
322 u16 nbrows = GET_BDA(video_rows) + 1;
323 u16 nbcols = GET_BDA(video_cols);
345 biosfn_write_teletype(' ', page, attr, flag);
346 cursor = biosfn_get_cursor_pos(page);
347 xcurs = cursor & 0x00ff;
348 ycurs = (cursor & 0xff00) >> 8;
349 } while (xcurs % 8 == 0);
353 if (flag == WITH_ATTR)
354 biosfn_write_char_attr(car, page, attr, 1);
356 biosfn_write_char_only(car, page, attr, 1);
360 // Do we need to wrap ?
361 if (xcurs == nbcols) {
365 // Do we need to scroll ?
366 if (ycurs == nbrows) {
367 if (GET_GLOBAL(vmode_g->class) == TEXT)
368 biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, page,
371 biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, page,
375 // Set the cursor for the page
379 biosfn_set_cursor_pos(page, cursor);
383 biosfn_write_string(u8 flag, u8 page, u8 attr, u16 count, u8 row, u8 col,
384 u16 seg, u8 *offset_far)
386 // Read curs info for the page
387 u16 oldcurs = biosfn_get_cursor_pos(page);
389 // if row=0xff special case : use current cursor position
391 col = oldcurs & 0x00ff;
392 row = (oldcurs & 0xff00) >> 8;
398 biosfn_set_cursor_pos(page, newcurs);
400 while (count-- != 0) {
401 u8 car = GET_FARVAR(seg, *offset_far);
403 if ((flag & 0x02) != 0) {
404 attr = GET_FARVAR(seg, *offset_far);
408 biosfn_write_teletype(car, page, attr, WITH_ATTR);
412 if ((flag & 0x01) == 0)
413 biosfn_set_cursor_pos(page, oldcurs);
417 set_scan_lines(u8 lines)
419 vgahw_set_scan_lines(lines);
421 biosfn_set_cursor_shape(0x06, 0x07);
423 biosfn_set_cursor_shape(lines - 4, lines - 3);
424 SET_BDA(char_height, lines);
425 u16 vde = vgahw_get_vde();
426 u8 rows = vde / lines;
427 SET_BDA(video_rows, rows - 1);
428 u16 cols = GET_BDA(video_cols);
429 SET_BDA(video_pagesize, rows * cols * 2);
433 biosfn_save_bda_state(u16 seg, struct saveBDAstate *info)
435 SET_FARVAR(seg, info->video_mode, GET_BDA(video_mode));
436 SET_FARVAR(seg, info->video_cols, GET_BDA(video_cols));
437 SET_FARVAR(seg, info->video_pagesize, GET_BDA(video_pagesize));
438 SET_FARVAR(seg, info->crtc_address, GET_BDA(crtc_address));
439 SET_FARVAR(seg, info->video_rows, GET_BDA(video_rows));
440 SET_FARVAR(seg, info->char_height, GET_BDA(char_height));
441 SET_FARVAR(seg, info->video_ctl, GET_BDA(video_ctl));
442 SET_FARVAR(seg, info->video_switches, GET_BDA(video_switches));
443 SET_FARVAR(seg, info->modeset_ctl, GET_BDA(modeset_ctl));
444 SET_FARVAR(seg, info->cursor_type, GET_BDA(cursor_type));
447 SET_FARVAR(seg, info->cursor_pos[i], GET_BDA(cursor_pos[i]));
448 SET_FARVAR(seg, info->video_pagestart, GET_BDA(video_pagestart));
449 SET_FARVAR(seg, info->video_page, GET_BDA(video_page));
451 SET_FARVAR(seg, *(u32*)&info->font0_off, GET_IVT(0x1f).segoff);
452 SET_FARVAR(seg, *(u32*)&info->font1_off, GET_IVT(0x43).segoff);
456 biosfn_restore_bda_state(u16 seg, struct saveBDAstate *info)
458 SET_BDA(video_mode, GET_FARVAR(seg, info->video_mode));
459 SET_BDA(video_cols, GET_FARVAR(seg, info->video_cols));
460 SET_BDA(video_pagesize, GET_FARVAR(seg, info->video_pagesize));
461 SET_BDA(crtc_address, GET_FARVAR(seg, info->crtc_address));
462 SET_BDA(video_rows, GET_FARVAR(seg, info->video_rows));
463 SET_BDA(char_height, GET_FARVAR(seg, info->char_height));
464 SET_BDA(video_ctl, GET_FARVAR(seg, info->video_ctl));
465 SET_BDA(video_switches, GET_FARVAR(seg, info->video_switches));
466 SET_BDA(modeset_ctl, GET_FARVAR(seg, info->modeset_ctl));
467 SET_BDA(cursor_type, GET_FARVAR(seg, info->cursor_type));
469 for (i = 0; i < 8; i++)
470 SET_BDA(cursor_pos[i], GET_FARVAR(seg, info->cursor_pos[i]));
471 SET_BDA(video_pagestart, GET_FARVAR(seg, info->video_pagestart));
472 SET_BDA(video_page, GET_FARVAR(seg, info->video_page));
474 SET_IVT(0x1f, GET_FARVAR(seg, info->font0_seg)
475 , GET_FARVAR(seg, info->font0_off));
476 SET_IVT(0x43, GET_FARVAR(seg, info->font1_seg)
477 , GET_FARVAR(seg, info->font1_off));
481 /****************************************************************
483 ****************************************************************/
486 handle_1000(struct bregs *regs)
489 biosfn_set_video_mode(regs->al);
490 switch(regs->al & 0x7F) {
509 handle_1001(struct bregs *regs)
511 biosfn_set_cursor_shape(regs->ch, regs->cl);
515 handle_1002(struct bregs *regs)
517 biosfn_set_cursor_pos(regs->bh, regs->dx);
521 handle_1003(struct bregs *regs)
523 regs->cx = biosfn_get_cursor_shape(regs->bh);
524 regs->dx = biosfn_get_cursor_pos(regs->bh);
527 // Read light pen pos (unimplemented)
529 handle_1004(struct bregs *regs)
532 regs->ax = regs->bx = regs->cx = regs->dx = 0;
536 handle_1005(struct bregs *regs)
538 biosfn_set_active_page(regs->al);
542 handle_1006(struct bregs *regs)
544 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
549 handle_1007(struct bregs *regs)
551 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
552 , 0xFF, SCROLL_DOWN);
556 handle_1008(struct bregs *regs)
559 biosfn_read_char_attr(regs->bh, ®s->ax);
563 handle_1009(struct bregs *regs)
566 biosfn_write_char_attr(regs->al, regs->bh, regs->bl, regs->cx);
570 handle_100a(struct bregs *regs)
573 biosfn_write_char_only(regs->al, regs->bh, regs->bl, regs->cx);
578 handle_100b00(struct bregs *regs)
580 vgahw_set_border_color(regs->bl);
584 handle_100b01(struct bregs *regs)
586 vgahw_set_palette(regs->bl);
590 handle_100bXX(struct bregs *regs)
596 handle_100b(struct bregs *regs)
599 case 0x00: handle_100b00(regs); break;
600 case 0x01: handle_100b01(regs); break;
601 default: handle_100bXX(regs); break;
607 handle_100c(struct bregs *regs)
610 biosfn_write_pixel(regs->bh, regs->al, regs->cx, regs->dx);
614 handle_100d(struct bregs *regs)
617 biosfn_read_pixel(regs->bh, regs->cx, regs->dx, ®s->ax);
621 handle_100e(struct bregs *regs)
623 // Ralf Brown Interrupt list is WRONG on bh(page)
624 // We do output only on the current page !
625 biosfn_write_teletype(regs->al, 0xff, regs->bl, NO_ATTR);
629 handle_100f(struct bregs *regs)
631 regs->bh = GET_BDA(video_page);
632 regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
633 regs->ah = GET_BDA(video_cols);
638 handle_101000(struct bregs *regs)
642 vgahw_set_single_palette_reg(regs->bl, regs->bh);
646 handle_101001(struct bregs *regs)
648 vgahw_set_overscan_border_color(regs->bh);
652 handle_101002(struct bregs *regs)
654 vgahw_set_all_palette_reg(regs->es, (u8*)(regs->dx + 0));
658 handle_101003(struct bregs *regs)
660 vgahw_toggle_intensity(regs->bl);
664 handle_101007(struct bregs *regs)
668 regs->bh = vgahw_get_single_palette_reg(regs->bl);
672 handle_101008(struct bregs *regs)
674 regs->bh = vgahw_get_overscan_border_color(regs);
678 handle_101009(struct bregs *regs)
680 vgahw_get_all_palette_reg(regs->es, (u8*)(regs->dx + 0));
684 handle_101010(struct bregs *regs)
686 u8 rgb[3] = {regs->dh, regs->ch, regs->cl};
687 vgahw_set_dac_regs(GET_SEG(SS), rgb, regs->bx, 1);
691 handle_101012(struct bregs *regs)
693 vgahw_set_dac_regs(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx);
697 handle_101013(struct bregs *regs)
699 vgahw_select_video_dac_color_page(regs->bl, regs->bh);
703 handle_101015(struct bregs *regs)
706 vgahw_get_dac_regs(GET_SEG(SS), rgb, regs->bx, 1);
713 handle_101017(struct bregs *regs)
715 vgahw_get_dac_regs(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx);
719 handle_101018(struct bregs *regs)
721 vgahw_set_pel_mask(regs->bl);
725 handle_101019(struct bregs *regs)
727 regs->bl = vgahw_get_pel_mask();
731 handle_10101a(struct bregs *regs)
733 vgahw_read_video_dac_state(®s->bl, ®s->bh);
737 handle_10101b(struct bregs *regs)
739 biosfn_perform_gray_scale_summing(regs->bx, regs->cx);
743 handle_1010XX(struct bregs *regs)
749 handle_1010(struct bregs *regs)
752 case 0x00: handle_101000(regs); break;
753 case 0x01: handle_101001(regs); break;
754 case 0x02: handle_101002(regs); break;
755 case 0x03: handle_101003(regs); break;
756 case 0x07: handle_101007(regs); break;
757 case 0x08: handle_101008(regs); break;
758 case 0x09: handle_101009(regs); break;
759 case 0x10: handle_101010(regs); break;
760 case 0x12: handle_101012(regs); break;
761 case 0x13: handle_101013(regs); break;
762 case 0x15: handle_101015(regs); break;
763 case 0x17: handle_101017(regs); break;
764 case 0x18: handle_101018(regs); break;
765 case 0x19: handle_101019(regs); break;
766 case 0x1a: handle_10101a(regs); break;
767 case 0x1b: handle_10101b(regs); break;
768 default: handle_1010XX(regs); break;
774 handle_101100(struct bregs *regs)
776 vgafb_load_font(regs->es, (void*)(regs->bp+0), regs->cx
777 , regs->dx, regs->bl, regs->bh);
781 handle_101101(struct bregs *regs)
783 vgafb_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14);
787 handle_101102(struct bregs *regs)
789 vgafb_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8);
793 handle_101103(struct bregs *regs)
795 vgahw_set_text_block_specifier(regs->bl);
799 handle_101104(struct bregs *regs)
801 vgafb_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16);
805 handle_101110(struct bregs *regs)
807 vgafb_load_font(regs->es, (void*)(regs->bp+0), regs->cx
808 , regs->dx, regs->bl, regs->bh);
809 set_scan_lines(regs->bh);
813 handle_101111(struct bregs *regs)
815 vgafb_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14);
820 handle_101112(struct bregs *regs)
822 vgafb_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8);
827 handle_101114(struct bregs *regs)
829 vgafb_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16);
834 handle_101130(struct bregs *regs)
838 u32 segoff = GET_IVT(0x1f).segoff;
839 regs->es = segoff >> 16;
844 u32 segoff = GET_IVT(0x43).segoff;
845 regs->es = segoff >> 16;
850 regs->es = get_global_seg();
851 regs->bp = (u32)vgafont14;
854 regs->es = get_global_seg();
855 regs->bp = (u32)vgafont8;
858 regs->es = get_global_seg();
859 regs->bp = (u32)vgafont8 + 128 * 8;
862 regs->es = get_global_seg();
863 regs->bp = (u32)vgafont14alt;
866 regs->es = get_global_seg();
867 regs->bp = (u32)vgafont16;
870 regs->es = get_global_seg();
871 regs->bp = (u32)vgafont16alt;
874 dprintf(1, "Get font info BH(%02x) was discarded\n", regs->bh);
877 // Set byte/char of on screen font
878 regs->cx = GET_BDA(char_height) & 0xff;
880 // Set Highest char row
881 regs->dx = GET_BDA(video_rows);
885 handle_1011XX(struct bregs *regs)
891 handle_1011(struct bregs *regs)
894 case 0x00: handle_101100(regs); break;
895 case 0x01: handle_101101(regs); break;
896 case 0x02: handle_101102(regs); break;
897 case 0x03: handle_101103(regs); break;
898 case 0x04: handle_101104(regs); break;
899 case 0x10: handle_101110(regs); break;
900 case 0x11: handle_101111(regs); break;
901 case 0x12: handle_101112(regs); break;
902 case 0x14: handle_101114(regs); break;
903 case 0x30: handle_101130(regs); break;
904 default: handle_1011XX(regs); break;
910 handle_101210(struct bregs *regs)
912 u16 crtc_addr = GET_BDA(crtc_address);
913 if (crtc_addr == VGAREG_MDA_CRTC_ADDRESS)
917 regs->cx = GET_BDA(video_switches) & 0x0f;
921 handle_101230(struct bregs *regs)
923 u8 mctl = GET_BDA(modeset_ctl);
924 u8 vswt = GET_BDA(video_switches);
928 mctl = (mctl & ~0x10) | 0x80;
929 vswt = (vswt & ~0x0f) | 0x08;
934 vswt = (vswt & ~0x0f) | 0x09;
938 mctl = (mctl & ~0x80) | 0x10;
939 vswt = (vswt & ~0x0f) | 0x09;
942 dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
945 SET_BDA(modeset_ctl, mctl);
946 SET_BDA(video_switches, vswt);
951 handle_101231(struct bregs *regs)
953 u8 v = (regs->al & 0x01) << 3;
954 u8 mctl = GET_BDA(video_ctl) & ~0x08;
955 SET_BDA(video_ctl, mctl | v);
960 handle_101232(struct bregs *regs)
962 vgahw_enable_video_addressing(regs->al);
967 handle_101233(struct bregs *regs)
969 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
970 u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
971 SET_BDA(modeset_ctl, v | v2);
976 handle_101234(struct bregs *regs)
978 u8 v = (regs->al & 0x01) ^ 0x01;
979 u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
980 SET_BDA(modeset_ctl, v | v2);
985 handle_101235(struct bregs *regs)
992 handle_101236(struct bregs *regs)
999 handle_1012XX(struct bregs *regs)
1005 handle_1012(struct bregs *regs)
1008 case 0x10: handle_101210(regs); break;
1009 case 0x30: handle_101230(regs); break;
1010 case 0x31: handle_101231(regs); break;
1011 case 0x32: handle_101232(regs); break;
1012 case 0x33: handle_101233(regs); break;
1013 case 0x34: handle_101234(regs); break;
1014 case 0x35: handle_101235(regs); break;
1015 case 0x36: handle_101236(regs); break;
1016 default: handle_1012XX(regs); break;
1019 // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
1024 handle_1013(struct bregs *regs)
1027 biosfn_write_string(regs->al, regs->bh, regs->bl, regs->cx
1028 , regs->dh, regs->dl, regs->es, (void*)(regs->bp + 0));
1033 handle_101a00(struct bregs *regs)
1035 regs->bx = GET_BDA(dcc_index);
1040 handle_101a01(struct bregs *regs)
1042 SET_BDA(dcc_index, regs->bl);
1043 dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
1048 handle_101aXX(struct bregs *regs)
1054 handle_101a(struct bregs *regs)
1057 case 0x00: handle_101a00(regs); break;
1058 case 0x01: handle_101a01(regs); break;
1059 default: handle_101aXX(regs); break;
1065 u16 static_functionality_off;
1066 u16 static_functionality_seg;
1086 handle_101b(struct bregs *regs)
1089 struct funcInfo *info = (void*)(regs->di+0);
1090 memset_far(seg, info, 0, sizeof(*info));
1091 // Address of static functionality table
1092 SET_FARVAR(seg, info->static_functionality_off, (u32)static_functionality);
1093 SET_FARVAR(seg, info->static_functionality_seg, get_global_seg());
1095 // Hard coded copy from BIOS area. Should it be cleaner ?
1096 memcpy_far(seg, info->bda_0x49, SEG_BDA, (void*)0x49, 30);
1097 memcpy_far(seg, info->bda_0x84, SEG_BDA, (void*)0x84, 3);
1099 SET_FARVAR(seg, info->dcc_index, GET_BDA(dcc_index));
1100 SET_FARVAR(seg, info->colors, 16);
1101 SET_FARVAR(seg, info->pages, 8);
1102 SET_FARVAR(seg, info->scan_lines, 2);
1103 SET_FARVAR(seg, info->video_mem, 3);
1109 handle_101c00(struct bregs *regs)
1111 u16 flags = regs->cx;
1114 size += sizeof(struct saveVideoHardware);
1116 size += sizeof(struct saveBDAstate);
1118 size += sizeof(struct saveDACcolors);
1124 handle_101c01(struct bregs *regs)
1126 u16 flags = regs->cx;
1128 void *data = (void*)(regs->bx+0);
1130 vgahw_save_state(seg, data);
1131 data += sizeof(struct saveVideoHardware);
1134 biosfn_save_bda_state(seg, data);
1135 data += sizeof(struct saveBDAstate);
1138 vgahw_save_dac_state(seg, data);
1143 handle_101c02(struct bregs *regs)
1145 u16 flags = regs->cx;
1147 void *data = (void*)(regs->bx+0);
1149 vgahw_restore_state(seg, data);
1150 data += sizeof(struct saveVideoHardware);
1153 biosfn_restore_bda_state(seg, data);
1154 data += sizeof(struct saveBDAstate);
1157 vgahw_restore_dac_state(seg, data);
1162 handle_101cXX(struct bregs *regs)
1168 handle_101c(struct bregs *regs)
1171 case 0x00: handle_101c00(regs); break;
1172 case 0x01: handle_101c01(regs); break;
1173 case 0x02: handle_101c02(regs); break;
1174 default: handle_101cXX(regs); break;
1180 handle_104f00(struct bregs *regs)
1182 // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
1183 // XXX - OR cirrus_vesa_00h
1187 handle_104f01(struct bregs *regs)
1189 // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
1190 // XXX - OR cirrus_vesa_01h
1194 handle_104f02(struct bregs *regs)
1196 // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
1197 // XXX - OR cirrus_vesa_02h
1201 handle_104f03(struct bregs *regs)
1203 // XXX - vbe_biosfn_return_current_mode
1204 // XXX - OR cirrus_vesa_03h
1208 handle_104f04(struct bregs *regs)
1210 // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
1214 handle_104f05(struct bregs *regs)
1216 // XXX - vbe_biosfn_display_window_control
1217 // XXX - OR cirrus_vesa_05h
1221 handle_104f06(struct bregs *regs)
1223 // XXX - vbe_biosfn_set_get_logical_scan_line_length
1224 // XXX - OR cirrus_vesa_06h
1228 handle_104f07(struct bregs *regs)
1230 // XXX - vbe_biosfn_set_get_display_start
1231 // XXX - OR cirrus_vesa_07h
1235 handle_104f08(struct bregs *regs)
1237 // XXX - vbe_biosfn_set_get_dac_palette_format
1241 handle_104f0a(struct bregs *regs)
1243 // XXX - vbe_biosfn_return_protected_mode_interface
1247 handle_104fXX(struct bregs *regs)
1254 handle_104f(struct bregs *regs)
1256 if (! CONFIG_VBE || !vbe_has_vbe_display()) {
1257 handle_104fXX(regs);
1262 case 0x00: handle_104f00(regs); break;
1263 case 0x01: handle_104f01(regs); break;
1264 case 0x02: handle_104f02(regs); break;
1265 case 0x03: handle_104f03(regs); break;
1266 case 0x04: handle_104f04(regs); break;
1267 case 0x05: handle_104f05(regs); break;
1268 case 0x06: handle_104f06(regs); break;
1269 case 0x07: handle_104f07(regs); break;
1270 case 0x08: handle_104f08(regs); break;
1271 case 0x0a: handle_104f0a(regs); break;
1272 default: handle_104fXX(regs); break;
1278 handle_10XX(struct bregs *regs)
1283 // INT 10h Video Support Service Entry Point
1285 handle_10(struct bregs *regs)
1287 debug_enter(regs, DEBUG_VGA_10);
1289 case 0x00: handle_1000(regs); break;
1290 case 0x01: handle_1001(regs); break;
1291 case 0x02: handle_1002(regs); break;
1292 case 0x03: handle_1003(regs); break;
1293 case 0x04: handle_1004(regs); break;
1294 case 0x05: handle_1005(regs); break;
1295 case 0x06: handle_1006(regs); break;
1296 case 0x07: handle_1007(regs); break;
1297 case 0x08: handle_1008(regs); break;
1298 case 0x09: handle_1009(regs); break;
1299 case 0x0a: handle_100a(regs); break;
1300 case 0x0b: handle_100b(regs); break;
1301 case 0x0c: handle_100c(regs); break;
1302 case 0x0d: handle_100d(regs); break;
1303 case 0x0e: handle_100e(regs); break;
1304 case 0x0f: handle_100f(regs); break;
1305 case 0x10: handle_1010(regs); break;
1306 case 0x11: handle_1011(regs); break;
1307 case 0x12: handle_1012(regs); break;
1308 case 0x13: handle_1013(regs); break;
1309 case 0x1a: handle_101a(regs); break;
1310 case 0x1b: handle_101b(regs); break;
1311 case 0x1c: handle_101c(regs); break;
1312 case 0x4f: handle_104f(regs); break;
1313 default: handle_10XX(regs); break;
1318 /****************************************************************
1320 ****************************************************************/
1325 // init detected hardware BIOS Area
1326 // set 80x25 color (not clear from RBIL but usual)
1327 u16 eqf = GET_BDA(equipment_list_flags);
1328 SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20);
1330 // Just for the first int10 find its children
1332 // the default char height
1333 SET_BDA(char_height, 0x10);
1336 SET_BDA(video_ctl, 0x60);
1338 // Set the basic screen we have
1339 SET_BDA(video_switches, 0xf9);
1341 // Set the basic modeset options
1342 SET_BDA(modeset_ctl, 0x51);
1344 // Set the default MSR
1345 SET_BDA(video_msr, 0x09);
1349 vga_post(struct bregs *regs)
1351 debug_enter(regs, DEBUG_VGA_POST);
1360 extern void entry_10(void);
1361 SET_IVT(0x10, get_global_seg(), (u32)entry_10);
1366 // XXX - clear screen and display info
1369 SET_VGA(video_save_pointer_table[0], (u32)video_param_table);
1370 SET_VGA(video_save_pointer_table[1], get_global_seg());
1373 extern u8 _rom_header_size, _rom_header_checksum;
1374 SET_VGA(_rom_header_checksum, 0);
1375 u8 sum = -checksum_far(get_global_seg(), 0, _rom_header_size * 512);
1376 SET_VGA(_rom_header_checksum, sum);