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 // * introduce "struct vregs", or add ebp to struct bregs.
11 // * Integrate vga_modes/pallete?/line_to_vpti/dac_regs/video_param_table
12 // * define structs for save/restore state
13 // * review correctness of converted asm by comparing with RBIL
14 // * more syntax cleanups
15 // * refactor redundant code into sub-functions
16 // * See if there is a method to the in/out stuff that can be encapsulated.
17 // * remove "biosfn" prefixes
18 // * don't hardcode 0xc000
19 // * add defs for 0xa000/0xb800
20 // * verify all funcs static
22 // * convert vbe/clext code
24 // * separate code into separate files
25 // * extract hw code from bios interfaces
27 #include "bregs.h" // struct bregs
28 #include "biosvar.h" // GET_BDA
29 #include "util.h" // memset
30 #include "vgatables.h" // vga_modes
34 #define CONFIG_CIRRUS 0
37 #define DEBUG_VGA_POST 1
38 #define DEBUG_VGA_10 3
40 #define SET_VGA(var, val) SET_FARVAR(0xc000, (var), (val))
43 // ===================================================================
47 // ===================================================================
49 // -------------------------------------------------------------------
51 find_vga_entry(u8 mode)
54 for (i = 0; i <= MODE_MAX; i++)
55 if (GET_GLOBAL(vga_modes[i].svgamode) == mode)
61 call16_vgaint(u32 eax, u32 ebx)
74 memcpy16_far(u16 d_seg, void *d_far, u16 s_seg, const void *s_far, size_t len)
76 memcpy_far(d_seg, d_far, s_seg, s_far, len);
80 // ===================================================================
84 // ===================================================================
86 // -------------------------------------------------------------------
88 biosfn_perform_gray_scale_summing(u16 start, u16 count)
94 inb(VGAREG_ACTL_RESET);
95 outb(0x00, VGAREG_ACTL_ADDRESS);
97 for (index = 0; index < count; index++) {
98 // set read address and switch to read mode
99 outb(start, VGAREG_DAC_READ_ADDRESS);
100 // get 6-bit wide RGB data values
101 r = inb(VGAREG_DAC_DATA);
102 g = inb(VGAREG_DAC_DATA);
103 b = inb(VGAREG_DAC_DATA);
105 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
106 i = ((77 * r + 151 * g + 28 * b) + 0x80) >> 8;
111 // set write address and switch to write mode
112 outb(start, VGAREG_DAC_WRITE_ADDRESS);
113 // write new intensity value
114 outb(i & 0xff, VGAREG_DAC_DATA);
115 outb(i & 0xff, VGAREG_DAC_DATA);
116 outb(i & 0xff, VGAREG_DAC_DATA);
119 inb(VGAREG_ACTL_RESET);
120 outb(0x20, VGAREG_ACTL_ADDRESS);
123 // -------------------------------------------------------------------
125 biosfn_set_cursor_shape(u8 CH, u8 CL)
127 u16 cheight, curs, crtc_addr;
133 curs = (CH << 8) + CL;
134 SET_BDA(cursor_type, curs);
136 modeset_ctl = GET_BDA(modeset_ctl);
137 cheight = GET_BDA(char_height);
138 if ((modeset_ctl & 0x01) && (cheight > 8) && (CL < 8) && (CH < 0x20)) {
139 if (CL != (CH + 1)) {
140 CH = ((CH + 1) * cheight / 8) - 1;
142 CH = ((CL + 1) * cheight / 8) - 2;
144 CL = ((CL + 1) * cheight / 8) - 1;
146 // CTRC regs 0x0a and 0x0b
147 crtc_addr = GET_BDA(crtc_address);
148 outb(0x0a, crtc_addr);
149 outb(CH, crtc_addr + 1);
150 outb(0x0b, crtc_addr);
151 outb(CL, crtc_addr + 1);
154 // -------------------------------------------------------------------
156 biosfn_set_cursor_pos(u8 page, u16 cursor)
158 u8 xcurs, ycurs, current;
159 u16 nbcols, nbrows, address, crtc_addr;
161 // Should not happen...
166 SET_BDA(cursor_pos[page], cursor);
168 // Set the hardware cursor
169 current = GET_BDA(video_page);
170 if (page == current) {
171 // Get the dimensions
172 nbcols = GET_BDA(video_cols);
173 nbrows = GET_BDA(video_rows) + 1;
175 xcurs = cursor & 0x00ff;
176 ycurs = (cursor & 0xff00) >> 8;
178 // Calculate the address knowing nbcols nbrows and page num
180 SCREEN_IO_START(nbcols, nbrows, page) + xcurs + ycurs * nbcols;
182 // CRTC regs 0x0e and 0x0f
183 crtc_addr = GET_BDA(crtc_address);
184 outb(0x0e, crtc_addr);
185 outb((address & 0xff00) >> 8, crtc_addr + 1);
186 outb(0x0f, crtc_addr);
187 outb(address & 0x00ff, crtc_addr + 1);
191 // -------------------------------------------------------------------
193 biosfn_get_cursor_pos(u8 page, u16 *shape, u16 *pos)
201 // FIXME should handle VGA 14/16 lines
202 *shape = GET_BDA(cursor_type);
203 *pos = GET_BDA(cursor_pos[page]);
206 // -------------------------------------------------------------------
208 biosfn_set_active_page(u8 page)
210 u16 cursor, dummy, crtc_addr;
211 u16 nbcols, nbrows, address;
218 mode = GET_BDA(video_mode);
219 line = find_vga_entry(mode);
223 // Get pos curs pos for the right page
224 biosfn_get_cursor_pos(page, &dummy, &cursor);
226 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
227 // Get the dimensions
228 nbcols = GET_BDA(video_cols);
229 nbrows = GET_BDA(video_rows) + 1;
231 // Calculate the address knowing nbcols nbrows and page num
232 address = SCREEN_MEM_START(nbcols, nbrows, page);
233 SET_BDA(video_pagestart, address);
236 address = SCREEN_IO_START(nbcols, nbrows, page);
238 address = page * GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].slength);
241 // CRTC regs 0x0c and 0x0d
242 crtc_addr = GET_BDA(crtc_address);
243 outb(0x0c, crtc_addr);
244 outb((address & 0xff00) >> 8, crtc_addr + 1);
245 outb(0x0d, crtc_addr);
246 outb(address & 0x00ff, crtc_addr + 1);
248 // And change the BIOS page
249 SET_BDA(video_page, page);
251 dprintf(1, "Set active page %02x address %04x\n", page, address);
253 // Display the cursor, now the page is active
254 biosfn_set_cursor_pos(page, cursor);
258 biosfn_set_video_mode(u8 mode)
259 { // mode: Bit 7 is 1 if no clear screen
260 // Should we clear the screen ?
261 u8 noclearmem = mode & 0x80;
262 u8 line, mmask, *palette, vpti;
263 u16 i, twidth, theightm1, cheight;
264 u8 modeset_ctl, video_ctl, vga_switches;
267 cirrus_set_video_mode(mode);
270 if (vbe_has_vbe_display())
271 dispi_set_enable(VBE_DISPI_DISABLED);
277 // find the entry in the video modes
278 line = find_vga_entry(mode);
280 dprintf(1, "mode search %02x found line %02x\n", mode, line);
285 vpti = GET_GLOBAL(line_to_vpti[line]);
286 twidth = GET_GLOBAL(video_param_table[vpti].twidth);
287 theightm1 = GET_GLOBAL(video_param_table[vpti].theightm1);
288 cheight = GET_GLOBAL(video_param_table[vpti].cheight);
290 // Read the bios vga control
291 video_ctl = GET_BDA(video_ctl);
293 // Read the bios vga switches
294 vga_switches = GET_BDA(video_switches);
296 // Read the bios mode set control
297 modeset_ctl = GET_BDA(modeset_ctl);
299 // Then we know the number of lines
302 // if palette loading (bit 3 of modeset ctl = 0)
303 if ((modeset_ctl & 0x08) == 0) { // Set the PEL mask
304 outb(GET_GLOBAL(vga_modes[line].pelmask), VGAREG_PEL_MASK);
306 // Set the whole dac always, from 0
307 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
309 // From which palette
310 switch (GET_GLOBAL(vga_modes[line].dacmodel)) {
325 // Always 256*3 values
326 for (i = 0; i < 0x0100; i++) {
327 if (i <= GET_GLOBAL(dac_regs[GET_GLOBAL(vga_modes[line].dacmodel)])) {
328 outb(GET_GLOBAL(palette[(i * 3) + 0]), VGAREG_DAC_DATA);
329 outb(GET_GLOBAL(palette[(i * 3) + 1]), VGAREG_DAC_DATA);
330 outb(GET_GLOBAL(palette[(i * 3) + 2]), VGAREG_DAC_DATA);
332 outb(0, VGAREG_DAC_DATA);
333 outb(0, VGAREG_DAC_DATA);
334 outb(0, VGAREG_DAC_DATA);
337 if ((modeset_ctl & 0x02) == 0x02)
338 biosfn_perform_gray_scale_summing(0x00, 0x100);
340 // Reset Attribute Ctl flip-flop
341 inb(VGAREG_ACTL_RESET);
344 for (i = 0; i <= 0x13; i++) {
345 outb(i, VGAREG_ACTL_ADDRESS);
346 outb(GET_GLOBAL(video_param_table[vpti].actl_regs[i])
347 , VGAREG_ACTL_WRITE_DATA);
349 outb(0x14, VGAREG_ACTL_ADDRESS);
350 outb(0x00, VGAREG_ACTL_WRITE_DATA);
353 outb(0, VGAREG_SEQU_ADDRESS);
354 outb(0x03, VGAREG_SEQU_DATA);
355 for (i = 1; i <= 4; i++) {
356 outb(i, VGAREG_SEQU_ADDRESS);
357 outb(GET_GLOBAL(video_param_table[vpti].sequ_regs[i - 1])
362 for (i = 0; i <= 8; i++) {
363 outb(i, VGAREG_GRDC_ADDRESS);
364 outb(GET_GLOBAL(video_param_table[vpti].grdc_regs[i])
368 // Set CRTC address VGA or MDA
369 u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
370 if (GET_GLOBAL(vga_modes[line].memmodel) == MTEXT)
371 crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
373 // Disable CRTC write protection
374 outw(0x0011, crtc_addr);
376 for (i = 0; i <= 0x18; i++) {
378 outb(GET_GLOBAL(video_param_table[vpti].crtc_regs[i]), crtc_addr + 1);
381 // Set the misc register
382 outb(GET_GLOBAL(video_param_table[vpti].miscreg), VGAREG_WRITE_MISC_OUTPUT);
385 outb(0x20, VGAREG_ACTL_ADDRESS);
386 inb(VGAREG_ACTL_RESET);
388 if (noclearmem == 0x00) {
389 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
390 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
391 , 0, 0x0720, 32*1024);
394 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
395 , 0, 0x0000, 32*1024);
397 outb(0x02, VGAREG_SEQU_ADDRESS);
398 mmask = inb(VGAREG_SEQU_DATA);
399 outb(0x0f, VGAREG_SEQU_DATA); // all planes
400 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
401 , 0, 0x0000, 64*1024);
402 outb(mmask, VGAREG_SEQU_DATA);
407 SET_BDA(video_mode, mode);
408 SET_BDA(video_cols, twidth);
409 SET_BDA(video_pagesize, GET_GLOBAL(video_param_table[vpti].slength));
410 SET_BDA(crtc_address, crtc_addr);
411 SET_BDA(video_rows, theightm1);
412 SET_BDA(char_height, cheight);
413 SET_BDA(video_ctl, (0x60 | noclearmem));
414 SET_BDA(video_switches, 0xF9);
415 SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
417 // FIXME We nearly have the good tables. to be reworked
418 SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now
419 SET_BDA(video_savetable_ptr, (u32)video_save_pointer_table);
420 SET_BDA(video_savetable_seg, 0xc000);
423 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
424 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
427 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
428 biosfn_set_cursor_shape(0x06, 0x07);
429 // Set cursor pos for page 0..7
430 for (i = 0; i < 8; i++)
431 biosfn_set_cursor_pos(i, 0x0000);
434 biosfn_set_active_page(0x00);
436 // Write the fonts in memory
437 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
438 call16_vgaint(0x1104, 0);
439 call16_vgaint(0x1103, 0);
441 // Set the ints 0x1F and 0x43
442 SET_IVT(0x1f, 0xC000, (u32)&vgafont8[128 * 8]);
446 SET_IVT(0x43, 0xC000, (u32)vgafont8);
449 SET_IVT(0x43, 0xC000, (u32)vgafont14);
452 SET_IVT(0x43, 0xC000, (u32)vgafont16);
457 // -------------------------------------------------------------------
459 vgamem_copy_pl4(u8 xstart, u8 ysrc, u8 ydest, u8 cols, u8 nbcols,
462 u16 src = ysrc * cheight * nbcols + xstart;
463 u16 dest = ydest * cheight * nbcols + xstart;
464 outw(0x0105, VGAREG_GRDC_ADDRESS);
466 for (i = 0; i < cheight; i++)
467 memcpy_far(0xa000, (void*)(dest + i * nbcols)
468 , 0xa000, (void*)(src + i * nbcols), cols);
469 outw(0x0005, VGAREG_GRDC_ADDRESS);
472 // -------------------------------------------------------------------
474 vgamem_fill_pl4(u8 xstart, u8 ystart, u8 cols, u8 nbcols, u8 cheight,
477 u16 dest = ystart * cheight * nbcols + xstart;
478 outw(0x0205, VGAREG_GRDC_ADDRESS);
480 for (i = 0; i < cheight; i++)
481 memset_far(0xa000, (void*)(dest + i * nbcols), attr, cols);
482 outw(0x0005, VGAREG_GRDC_ADDRESS);
485 // -------------------------------------------------------------------
487 vgamem_copy_cga(u8 xstart, u8 ysrc, u8 ydest, u8 cols, u8 nbcols,
490 u16 src = ((ysrc * cheight * nbcols) >> 1) + xstart;
491 u16 dest = ((ydest * cheight * nbcols) >> 1) + xstart;
493 for (i = 0; i < cheight; i++)
495 memcpy_far(0xb800, (void*)(0x2000 + dest + (i >> 1) * nbcols)
496 , 0xb800, (void*)(0x2000 + src + (i >> 1) * nbcols)
499 memcpy_far(0xb800, (void*)(dest + (i >> 1) * nbcols)
500 , 0xb800, (void*)(src + (i >> 1) * nbcols), cols);
503 // -------------------------------------------------------------------
505 vgamem_fill_cga(u8 xstart, u8 ystart, u8 cols, u8 nbcols, u8 cheight,
508 u16 dest = ((ystart * cheight * nbcols) >> 1) + xstart;
510 for (i = 0; i < cheight; i++)
512 memset_far(0xb800, (void*)(0x2000 + dest + (i >> 1) * nbcols)
515 memset_far(0xb800, (void*)(dest + (i >> 1) * nbcols), attr, cols);
518 // -------------------------------------------------------------------
520 biosfn_scroll(u8 nblines, u8 attr, u8 rul, u8 cul, u8 rlr, u8 clr, u8 page,
523 // page == 0xFF if current
525 u8 mode, line, cheight, bpp, cols;
526 u16 nbcols, nbrows, i;
534 mode = GET_BDA(video_mode);
535 line = find_vga_entry(mode);
539 // Get the dimensions
540 nbrows = GET_BDA(video_rows) + 1;
541 nbcols = GET_BDA(video_cols);
543 // Get the current page
545 page = GET_BDA(video_page);
551 if (nblines > nbrows)
553 cols = clr - cul + 1;
555 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
556 // Compute the address
557 void *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page));
558 dprintf(3, "Scroll, address %p (%d %d %02x)\n"
559 , address, nbrows, nbcols, page);
561 if (nblines == 0 && rul == 0 && cul == 0 && rlr == nbrows - 1
562 && clr == nbcols - 1) {
563 memset16_far(GET_GLOBAL(vga_modes[line].sstart), address
564 , (u16)attr * 0x100 + ' ', nbrows * nbcols * 2);
565 } else { // if Scroll up
566 if (dir == SCROLL_UP) {
567 for (i = rul; i <= rlr; i++) {
568 if ((i + nblines > rlr) || (nblines == 0))
569 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
570 , address + (i * nbcols + cul) * 2
571 , (u16)attr * 0x100 + ' ', cols * 2);
573 memcpy16_far(GET_GLOBAL(vga_modes[line].sstart)
574 , address + (i * nbcols + cul) * 2
575 , GET_GLOBAL(vga_modes[line].sstart)
576 , (void*)(((i + nblines) * nbcols + cul) * 2)
580 for (i = rlr; i >= rul; i--) {
581 if ((i < rul + nblines) || (nblines == 0))
582 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
583 , address + (i * nbcols + cul) * 2
584 , (u16)attr * 0x100 + ' ', cols * 2);
586 memcpy16_far(GET_GLOBAL(vga_modes[line].sstart)
587 , address + (i * nbcols + cul) * 2
588 , GET_GLOBAL(vga_modes[line].sstart)
589 , (void*)(((i - nblines) * nbcols + cul) * 2)
597 // FIXME gfx mode not complete
598 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
599 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
602 if (nblines == 0 && rul == 0 && cul == 0 && rlr == nbrows - 1
603 && clr == nbcols - 1) {
604 outw(0x0205, VGAREG_GRDC_ADDRESS);
605 memset_far(GET_GLOBAL(vga_modes[line].sstart), 0, attr,
606 nbrows * nbcols * cheight);
607 outw(0x0005, VGAREG_GRDC_ADDRESS);
608 } else { // if Scroll up
609 if (dir == SCROLL_UP) {
610 for (i = rul; i <= rlr; i++) {
611 if ((i + nblines > rlr) || (nblines == 0))
612 vgamem_fill_pl4(cul, i, cols, nbcols, cheight,
615 vgamem_copy_pl4(cul, i + nblines, i, cols,
619 for (i = rlr; i >= rul; i--) {
620 if ((i < rul + nblines) || (nblines == 0))
621 vgamem_fill_pl4(cul, i, cols, nbcols, cheight,
624 vgamem_copy_pl4(cul, i, i - nblines, cols,
633 bpp = GET_GLOBAL(vga_modes[line].pixbits);
634 if (nblines == 0 && rul == 0 && cul == 0 && rlr == nbrows - 1
635 && clr == nbcols - 1) {
636 memset_far(GET_GLOBAL(vga_modes[line].sstart), 0, attr,
637 nbrows * nbcols * cheight * bpp);
645 if (dir == SCROLL_UP) {
646 for (i = rul; i <= rlr; i++) {
647 if ((i + nblines > rlr) || (nblines == 0))
648 vgamem_fill_cga(cul, i, cols, nbcols, cheight,
651 vgamem_copy_cga(cul, i + nblines, i, cols,
655 for (i = rlr; i >= rul; i--) {
656 if ((i < rul + nblines) || (nblines == 0))
657 vgamem_fill_cga(cul, i, cols, nbcols, cheight,
660 vgamem_copy_cga(cul, i, i - nblines, cols,
669 dprintf(1, "Scroll in graphics mode\n");
674 // -------------------------------------------------------------------
676 biosfn_read_char_attr(u8 page, u16 *car)
678 u8 xcurs, ycurs, mode, line;
683 mode = GET_BDA(video_mode);
684 line = find_vga_entry(mode);
688 // Get the cursor pos for the page
689 biosfn_get_cursor_pos(page, &dummy, &cursor);
690 xcurs = cursor & 0x00ff;
691 ycurs = (cursor & 0xff00) >> 8;
693 // Get the dimensions
694 nbrows = GET_BDA(video_rows) + 1;
695 nbcols = GET_BDA(video_cols);
697 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
698 // Compute the address
699 u16 *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
700 + (xcurs + ycurs * nbcols) * 2);
702 *car = GET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), *address);
705 dprintf(1, "Read char in graphics mode\n");
709 // -------------------------------------------------------------------
711 write_gfx_char_pl4(u8 car, u8 attr, u8 xcurs, u8 ycurs, u8 nbcols,
728 addr = xcurs + ycurs * cheight * nbcols;
730 outw(0x0f02, VGAREG_SEQU_ADDRESS);
731 outw(0x0205, VGAREG_GRDC_ADDRESS);
733 outw(0x1803, VGAREG_GRDC_ADDRESS);
735 outw(0x0003, VGAREG_GRDC_ADDRESS);
736 for (i = 0; i < cheight; i++) {
737 u8 *dest = (void*)(addr + i * nbcols);
738 for (j = 0; j < 8; j++) {
740 outw((mask << 8) | 0x08, VGAREG_GRDC_ADDRESS);
741 GET_FARVAR(0xa000, *dest);
742 if (GET_GLOBAL(fdata[src + i]) & mask)
743 SET_FARVAR(0xa000, *dest, attr & 0x0f);
745 SET_FARVAR(0xa000, *dest, 0x00);
748 outw(0xff08, VGAREG_GRDC_ADDRESS);
749 outw(0x0005, VGAREG_GRDC_ADDRESS);
750 outw(0x0003, VGAREG_GRDC_ADDRESS);
753 // -------------------------------------------------------------------
755 write_gfx_char_cga(u8 car, u8 attr, u8 xcurs, u8 ycurs, u8 nbcols, u8 bpp)
757 u8 *fdata = vgafont8;
758 u16 addr = (xcurs * bpp) + ycurs * 320;
761 for (i = 0; i < 8; i++) {
762 u8 *dest = (void*)(addr + (i >> 1) * 80);
769 data = GET_FARVAR(0xb800, *dest);
771 for (j = 0; j < 8; j++) {
772 if (GET_GLOBAL(fdata[src + i]) & mask) {
774 data ^= (attr & 0x01) << (7 - j);
776 data |= (attr & 0x01) << (7 - j);
780 SET_FARVAR(0xb800, *dest, data);
785 data = GET_FARVAR(0xb800, *dest);
787 for (j = 0; j < 4; j++) {
788 if (GET_GLOBAL(fdata[src + i]) & mask) {
790 data ^= (attr & 0x03) << ((3 - j) * 2);
792 data |= (attr & 0x03) << ((3 - j) * 2);
796 SET_FARVAR(0xb800, *dest, data);
803 // -------------------------------------------------------------------
805 write_gfx_char_lin(u8 car, u8 attr, u8 xcurs, u8 ycurs, u8 nbcols)
807 u8 *fdata = vgafont8;
808 u16 addr = xcurs * 8 + ycurs * nbcols * 64;
811 for (i = 0; i < 8; i++) {
812 u8 *dest = (void*)(addr + i * nbcols * 8);
815 for (j = 0; j < 8; j++) {
817 if (GET_GLOBAL(fdata[src + i]) & mask)
819 SET_FARVAR(0xa000, dest[j], data);
825 // -------------------------------------------------------------------
827 biosfn_write_char_attr(u8 car, u8 page, u8 attr, u16 count)
829 u8 cheight, xcurs, ycurs, mode, line, bpp;
834 mode = GET_BDA(video_mode);
835 line = find_vga_entry(mode);
839 // Get the cursor pos for the page
840 biosfn_get_cursor_pos(page, &dummy, &cursor);
841 xcurs = cursor & 0x00ff;
842 ycurs = (cursor & 0xff00) >> 8;
844 // Get the dimensions
845 nbrows = GET_BDA(video_rows) + 1;
846 nbcols = GET_BDA(video_cols);
848 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
849 // Compute the address
850 void *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
851 + (xcurs + ycurs * nbcols) * 2);
853 dummy = ((u16)attr << 8) + car;
854 memset16_far(GET_GLOBAL(vga_modes[line].sstart), address, dummy
857 // FIXME gfx mode not complete
858 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
859 bpp = GET_GLOBAL(vga_modes[line].pixbits);
860 while ((count-- > 0) && (xcurs < nbcols)) {
861 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
864 write_gfx_char_pl4(car, attr, xcurs, ycurs, nbcols,
868 write_gfx_char_cga(car, attr, xcurs, ycurs, nbcols, bpp);
871 write_gfx_char_lin(car, attr, xcurs, ycurs, nbcols);
879 // -------------------------------------------------------------------
881 biosfn_write_char_only(u8 car, u8 page, u8 attr, u16 count)
883 u8 cheight, xcurs, ycurs, mode, line, bpp;
888 mode = GET_BDA(video_mode);
889 line = find_vga_entry(mode);
893 // Get the cursor pos for the page
894 biosfn_get_cursor_pos(page, &dummy, &cursor);
895 xcurs = cursor & 0x00ff;
896 ycurs = (cursor & 0xff00) >> 8;
898 // Get the dimensions
899 nbrows = GET_BDA(video_rows) + 1;
900 nbcols = GET_BDA(video_cols);
902 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
903 // Compute the address
904 u8 *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
905 + (xcurs + ycurs * nbcols) * 2);
906 while (count-- > 0) {
907 SET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), *address, car);
911 // FIXME gfx mode not complete
912 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
913 bpp = GET_GLOBAL(vga_modes[line].pixbits);
914 while ((count-- > 0) && (xcurs < nbcols)) {
915 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
918 write_gfx_char_pl4(car, attr, xcurs, ycurs, nbcols,
922 write_gfx_char_cga(car, attr, xcurs, ycurs, nbcols, bpp);
925 write_gfx_char_lin(car, attr, xcurs, ycurs, nbcols);
935 // -------------------------------------------------------------------
937 biosfn_set_border_color(struct bregs *regs)
939 inb(VGAREG_ACTL_RESET);
940 outb(0x00, VGAREG_ACTL_ADDRESS);
941 u8 al = regs->bl & 0x0f;
944 outb(al, VGAREG_ACTL_WRITE_DATA);
945 u8 bl = regs->bl & 0x10;
948 for (i = 1; i < 4; i++) {
949 outb(i, VGAREG_ACTL_ADDRESS);
951 al = inb(VGAREG_ACTL_READ_DATA);
954 outb(al, VGAREG_ACTL_WRITE_DATA);
956 outb(0x20, VGAREG_ACTL_ADDRESS);
960 biosfn_set_palette(struct bregs *regs)
962 inb(VGAREG_ACTL_RESET);
963 u8 bl = regs->bl & 0x01;
965 for (i = 1; i < 4; i++) {
966 outb(i, VGAREG_ACTL_ADDRESS);
968 u8 al = inb(VGAREG_ACTL_READ_DATA);
971 outb(al, VGAREG_ACTL_WRITE_DATA);
973 outb(0x20, VGAREG_ACTL_ADDRESS);
976 // -------------------------------------------------------------------
978 biosfn_write_pixel(u8 BH, u8 AL, u16 CX, u16 DX)
983 u8 mode = GET_BDA(video_mode);
984 u8 line = find_vga_entry(mode);
987 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
991 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
994 addr = (void*)(CX / 8 + DX * GET_BDA(video_cols));
995 mask = 0x80 >> (CX & 0x07);
996 outw((mask << 8) | 0x08, VGAREG_GRDC_ADDRESS);
997 outw(0x0205, VGAREG_GRDC_ADDRESS);
998 data = GET_FARVAR(0xa000, *addr);
1000 outw(0x1803, VGAREG_GRDC_ADDRESS);
1001 SET_FARVAR(0xa000, *addr, AL);
1002 outw(0xff08, VGAREG_GRDC_ADDRESS);
1003 outw(0x0005, VGAREG_GRDC_ADDRESS);
1004 outw(0x0003, VGAREG_GRDC_ADDRESS);
1007 if (GET_GLOBAL(vga_modes[line].pixbits) == 2)
1008 addr = (void*)((CX >> 2) + (DX >> 1) * 80);
1010 addr = (void*)((CX >> 3) + (DX >> 1) * 80);
1013 data = GET_FARVAR(0xb800, *addr);
1014 if (GET_GLOBAL(vga_modes[line].pixbits) == 2) {
1015 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1016 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1018 attr = (AL & 0x01) << (7 - (CX & 0x07));
1019 mask = 0x01 << (7 - (CX & 0x07));
1027 SET_FARVAR(0xb800, *addr, data);
1030 addr = (void*)(CX + DX * (GET_BDA(video_cols) * 8));
1031 SET_FARVAR(0xa000, *addr, AL);
1036 // -------------------------------------------------------------------
1038 biosfn_read_pixel(u8 BH, u16 CX, u16 DX, u16 *AX)
1040 u8 mode, line, mask, attr, data, i;
1043 mode = GET_BDA(video_mode);
1044 line = find_vga_entry(mode);
1047 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
1051 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
1054 addr = (void*)(CX / 8 + DX * GET_BDA(video_cols));
1055 mask = 0x80 >> (CX & 0x07);
1057 for (i = 0; i < 4; i++) {
1058 outw((i << 8) | 0x04, VGAREG_GRDC_ADDRESS);
1059 data = GET_FARVAR(0xa000, *addr) & mask;
1061 attr |= (0x01 << i);
1065 addr = (void*)((CX >> 2) + (DX >> 1) * 80);
1068 data = GET_FARVAR(0xb800, *addr);
1069 if (GET_GLOBAL(vga_modes[line].pixbits) == 2)
1070 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1072 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1075 addr = (void*)(CX + DX * (GET_BDA(video_cols) * 8));
1076 attr = GET_FARVAR(0xa000, *addr);
1079 *AX = (*AX & 0xff00) | attr;
1082 // -------------------------------------------------------------------
1084 biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
1085 { // flag = WITH_ATTR / NO_ATTR
1086 u8 cheight, xcurs, ycurs, mode, line, bpp;
1090 // special case if page is 0xff, use current page
1092 page = GET_BDA(video_page);
1095 mode = GET_BDA(video_mode);
1096 line = find_vga_entry(mode);
1100 // Get the cursor pos for the page
1101 biosfn_get_cursor_pos(page, &dummy, &cursor);
1102 xcurs = cursor & 0x00ff;
1103 ycurs = (cursor & 0xff00) >> 8;
1105 // Get the dimensions
1106 nbrows = GET_BDA(video_rows) + 1;
1107 nbcols = GET_BDA(video_cols);
1129 biosfn_write_teletype(' ', page, attr, flag);
1130 biosfn_get_cursor_pos(page, &dummy, &cursor);
1131 xcurs = cursor & 0x00ff;
1132 ycurs = (cursor & 0xff00) >> 8;
1133 } while (xcurs % 8 == 0);
1138 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
1139 // Compute the address
1140 u8 *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
1141 + (xcurs + ycurs * nbcols) * 2);
1143 SET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), address[0], car);
1144 if (flag == WITH_ATTR)
1145 SET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), address[1], attr);
1147 // FIXME gfx mode not complete
1148 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
1149 bpp = GET_GLOBAL(vga_modes[line].pixbits);
1150 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
1153 write_gfx_char_pl4(car, attr, xcurs, ycurs, nbcols,
1157 write_gfx_char_cga(car, attr, xcurs, ycurs, nbcols, bpp);
1160 write_gfx_char_lin(car, attr, xcurs, ycurs, nbcols);
1167 // Do we need to wrap ?
1168 if (xcurs == nbcols) {
1172 // Do we need to scroll ?
1173 if (ycurs == nbrows) {
1174 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
1175 biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, page,
1178 biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, page,
1182 // Set the cursor for the page
1186 biosfn_set_cursor_pos(page, cursor);
1189 // -------------------------------------------------------------------
1191 biosfn_get_video_mode(struct bregs *regs)
1193 regs->bh = GET_BDA(video_page);
1194 regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
1195 regs->ah = GET_BDA(video_cols);
1198 // -------------------------------------------------------------------
1200 biosfn_set_overscan_border_color(struct bregs *regs)
1202 inb(VGAREG_ACTL_RESET);
1203 outb(0x11, VGAREG_ACTL_ADDRESS);
1204 outb(regs->bh, VGAREG_ACTL_WRITE_DATA);
1205 outb(0x20, VGAREG_ACTL_ADDRESS);
1208 // -------------------------------------------------------------------
1210 biosfn_set_all_palette_reg(struct bregs *regs)
1212 inb(VGAREG_ACTL_RESET);
1214 u8 *data = (u8*)(regs->dx + 0);
1216 for (i = 0; i < 0x10; i++) {
1217 outb(i, VGAREG_ACTL_ADDRESS);
1218 u8 val = GET_FARVAR(regs->es, *data);
1219 outb(val, VGAREG_ACTL_WRITE_DATA);
1222 outb(0x11, VGAREG_ACTL_ADDRESS);
1223 outb(GET_FARVAR(regs->es, *data), VGAREG_ACTL_WRITE_DATA);
1224 outb(0x20, VGAREG_ACTL_ADDRESS);
1227 // -------------------------------------------------------------------
1229 biosfn_toggle_intensity(struct bregs *regs)
1231 inb(VGAREG_ACTL_RESET);
1232 outb(0x10, VGAREG_ACTL_ADDRESS);
1233 u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0x7f) | ((regs->bl & 0x01) << 3);
1234 outb(val, VGAREG_ACTL_WRITE_DATA);
1235 outb(0x20, VGAREG_ACTL_ADDRESS);
1238 // -------------------------------------------------------------------
1240 biosfn_set_single_palette_reg(u8 reg, u8 val)
1242 inb(VGAREG_ACTL_RESET);
1243 outb(reg, VGAREG_ACTL_ADDRESS);
1244 outb(val, VGAREG_ACTL_WRITE_DATA);
1245 outb(0x20, VGAREG_ACTL_ADDRESS);
1248 // -------------------------------------------------------------------
1250 biosfn_get_single_palette_reg(u8 reg)
1252 inb(VGAREG_ACTL_RESET);
1253 outb(reg, VGAREG_ACTL_ADDRESS);
1254 u8 v = inb(VGAREG_ACTL_READ_DATA);
1255 inb(VGAREG_ACTL_RESET);
1256 outb(0x20, VGAREG_ACTL_ADDRESS);
1260 // -------------------------------------------------------------------
1262 biosfn_read_overscan_border_color(struct bregs *regs)
1264 inb(VGAREG_ACTL_RESET);
1265 outb(0x11, VGAREG_ACTL_ADDRESS);
1266 regs->bh = inb(VGAREG_ACTL_READ_DATA);
1267 inb(VGAREG_ACTL_RESET);
1268 outb(0x20, VGAREG_ACTL_ADDRESS);
1271 // -------------------------------------------------------------------
1273 biosfn_get_all_palette_reg(struct bregs *regs)
1275 u8 *data = (u8*)(regs->dx + 0);
1277 for (i = 0; i < 0x10; i++) {
1278 inb(VGAREG_ACTL_RESET);
1279 outb(i, VGAREG_ACTL_ADDRESS);
1280 SET_FARVAR(regs->es, *data, inb(VGAREG_ACTL_READ_DATA));
1283 inb(VGAREG_ACTL_RESET);
1284 outb(0x11, VGAREG_ACTL_ADDRESS);
1285 SET_FARVAR(regs->es, *data, inb(VGAREG_ACTL_READ_DATA));
1286 inb(VGAREG_ACTL_RESET);
1287 outb(0x20, VGAREG_ACTL_ADDRESS);
1290 // -------------------------------------------------------------------
1292 biosfn_set_single_dac_reg(struct bregs *regs)
1294 outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
1295 outb(regs->dh, VGAREG_DAC_DATA);
1296 outb(regs->ch, VGAREG_DAC_DATA);
1297 outb(regs->cl, VGAREG_DAC_DATA);
1300 // -------------------------------------------------------------------
1302 biosfn_set_all_dac_reg(struct bregs *regs)
1304 outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
1305 u8 *data = (u8*)(regs->dx + 0);
1306 int count = regs->cx;
1308 outb(GET_FARVAR(regs->es, *data), VGAREG_DAC_DATA);
1310 outb(GET_FARVAR(regs->es, *data), VGAREG_DAC_DATA);
1312 outb(GET_FARVAR(regs->es, *data), VGAREG_DAC_DATA);
1318 // -------------------------------------------------------------------
1320 biosfn_select_video_dac_color_page(struct bregs *regs)
1322 inb(VGAREG_ACTL_RESET);
1323 outb(0x10, VGAREG_ACTL_ADDRESS);
1324 u8 val = inb(VGAREG_ACTL_READ_DATA);
1325 if (!(regs->bl & 0x01)) {
1326 val = (val & 0x7f) | (regs->bh << 7);
1327 outb(val, VGAREG_ACTL_WRITE_DATA);
1328 outb(0x20, VGAREG_ACTL_ADDRESS);
1331 inb(VGAREG_ACTL_RESET);
1332 outb(0x14, VGAREG_ACTL_ADDRESS);
1337 outb(bh, VGAREG_ACTL_WRITE_DATA);
1338 outb(0x20, VGAREG_ACTL_ADDRESS);
1341 // -------------------------------------------------------------------
1343 biosfn_read_single_dac_reg(struct bregs *regs)
1345 outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
1346 regs->dh = inb(VGAREG_DAC_DATA);
1347 regs->ch = inb(VGAREG_DAC_DATA);
1348 regs->cl = inb(VGAREG_DAC_DATA);
1351 // -------------------------------------------------------------------
1353 biosfn_read_all_dac_reg(struct bregs *regs)
1355 outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
1356 u8 *data = (u8*)(regs->dx + 0);
1357 int count = regs->cx;
1359 SET_FARVAR(regs->es, *data, inb(VGAREG_DAC_DATA));
1361 SET_FARVAR(regs->es, *data, inb(VGAREG_DAC_DATA));
1363 SET_FARVAR(regs->es, *data, inb(VGAREG_DAC_DATA));
1369 // -------------------------------------------------------------------
1371 biosfn_set_pel_mask(struct bregs *regs)
1373 outb(regs->bl, VGAREG_PEL_MASK);
1376 // -------------------------------------------------------------------
1378 biosfn_read_pel_mask(struct bregs *regs)
1380 regs->bl = inb(VGAREG_PEL_MASK);
1383 // -------------------------------------------------------------------
1385 biosfn_read_video_dac_state(struct bregs *regs)
1387 inb(VGAREG_ACTL_RESET);
1388 outb(0x10, VGAREG_ACTL_ADDRESS);
1389 u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
1391 inb(VGAREG_ACTL_RESET);
1392 outb(0x14, VGAREG_ACTL_ADDRESS);
1393 u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
1397 inb(VGAREG_ACTL_RESET);
1398 outb(0x20, VGAREG_ACTL_ADDRESS);
1404 // -------------------------------------------------------------------
1408 outw(0x0100, VGAREG_SEQU_ADDRESS);
1409 outw(0x0402, VGAREG_SEQU_ADDRESS);
1410 outw(0x0704, VGAREG_SEQU_ADDRESS);
1411 outw(0x0300, VGAREG_SEQU_ADDRESS);
1412 outw(0x0204, VGAREG_GRDC_ADDRESS);
1413 outw(0x0005, VGAREG_GRDC_ADDRESS);
1414 outw(0x0406, VGAREG_GRDC_ADDRESS);
1418 release_font_access()
1420 outw(0x0100, VGAREG_SEQU_ADDRESS);
1421 outw(0x0302, VGAREG_SEQU_ADDRESS);
1422 outw(0x0304, VGAREG_SEQU_ADDRESS);
1423 outw(0x0300, VGAREG_SEQU_ADDRESS);
1424 u16 v = inw(VGAREG_READ_MISC_OUTPUT);
1425 v = ((v & 0x01) << 10) | 0x0a06;
1426 outw(v, VGAREG_GRDC_ADDRESS);
1427 outw(0x0004, VGAREG_GRDC_ADDRESS);
1428 outw(0x1005, VGAREG_GRDC_ADDRESS);
1432 set_scan_lines(u8 lines)
1434 u16 crtc_addr, cols, vde;
1435 u8 crtc_r9, ovl, rows;
1437 crtc_addr = GET_BDA(crtc_address);
1438 outb(0x09, crtc_addr);
1439 crtc_r9 = inb(crtc_addr + 1);
1440 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
1441 outb(crtc_r9, crtc_addr + 1);
1443 biosfn_set_cursor_shape(0x06, 0x07);
1445 biosfn_set_cursor_shape(lines - 4, lines - 3);
1446 SET_BDA(char_height, lines);
1447 outb(0x12, crtc_addr);
1448 vde = inb(crtc_addr + 1);
1449 outb(0x07, crtc_addr);
1450 ovl = inb(crtc_addr + 1);
1451 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
1453 SET_BDA(video_rows, rows - 1);
1454 cols = GET_BDA(video_cols);
1455 SET_BDA(video_pagesize, rows * cols * 2);
1459 biosfn_load_text_user_pat(u8 AL, u16 ES, u16 BP, u16 CX, u16 DX, u8 BL,
1463 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1465 for (i = 0; i < CX; i++) {
1466 void *src = (void*)(BP + i * BH);
1467 void *dest = (void*)(blockaddr + (DX + i) * 32);
1468 memcpy_far(0xA000, dest, ES, src, BH);
1470 release_font_access();
1476 biosfn_load_text_8_14_pat(u8 AL, u8 BL)
1479 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1481 for (i = 0; i < 0x100; i++) {
1483 void *dest = (void*)(blockaddr + i * 32);
1484 memcpy_far(0xA000, dest, 0xC000, &vgafont14[src], 14);
1486 release_font_access();
1492 biosfn_load_text_8_8_pat(u8 AL, u8 BL)
1495 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1497 for (i = 0; i < 0x100; i++) {
1499 void *dest = (void*)(blockaddr + i * 32);
1500 memcpy_far(0xA000, dest, 0xC000, &vgafont8[src], 8);
1502 release_font_access();
1507 // -------------------------------------------------------------------
1509 biosfn_set_text_block_specifier(struct bregs *regs)
1511 outw((regs->bl << 8) | 0x03, VGAREG_SEQU_ADDRESS);
1514 // -------------------------------------------------------------------
1516 biosfn_load_text_8_16_pat(u8 AL, u8 BL)
1519 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1521 for (i = 0; i < 0x100; i++) {
1523 void *dest = (void*)(blockaddr + i * 32);
1524 memcpy_far(0xA000, dest, 0xC000, &vgafont16[src], 16);
1526 release_font_access();
1531 // -------------------------------------------------------------------
1533 biosfn_get_font_info(u8 BH, u16 *ES, u16 *BP, u16 *CX, u16 *DX)
1537 u32 segoff = GET_IVT(0x1f).segoff;
1543 u32 segoff = GET_IVT(0x43).segoff;
1550 *BP = (u32)vgafont14;
1554 *BP = (u32)vgafont8;
1558 *BP = (u32)vgafont8 + 128 * 8;
1562 *BP = (u32)vgafont14alt;
1566 *BP = (u32)vgafont16;
1570 *BP = (u32)vgafont16alt;
1573 dprintf(1, "Get font info BH(%02x) was discarded\n", BH);
1576 // Set byte/char of on screen font
1577 *CX = GET_BDA(char_height) & 0xff;
1579 // Set Highest char row
1580 *DX = GET_BDA(video_rows);
1583 // -------------------------------------------------------------------
1585 biosfn_get_ega_info(struct bregs *regs)
1587 regs->cx = GET_BDA(video_switches) & 0x0f;
1588 regs->ax = GET_BDA(crtc_address);
1589 if (regs->ax == VGAREG_MDA_CRTC_ADDRESS)
1595 // -------------------------------------------------------------------
1597 biosfn_select_vert_res(struct bregs *regs)
1599 u8 mctl = GET_BDA(modeset_ctl);
1600 u8 vswt = GET_BDA(video_switches);
1605 mctl = (mctl & ~0x10) | 0x80;
1606 vswt = (vswt & ~0x0f) | 0x08;
1611 vswt = (vswt & ~0x0f) | 0x09;
1615 mctl = (mctl & ~0x80) | 0x10;
1616 vswt = (vswt & ~0x0f) | 0x09;
1619 dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
1622 SET_BDA(modeset_ctl, mctl);
1623 SET_BDA(video_switches, vswt);
1628 biosfn_enable_default_palette_loading(struct bregs *regs)
1630 u8 v = (regs->al & 0x01) << 3;
1631 u8 mctl = GET_BDA(video_ctl) & ~0x08;
1632 SET_BDA(video_ctl, mctl | v);
1637 biosfn_enable_video_addressing(struct bregs *regs)
1639 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
1640 u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
1641 outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
1647 biosfn_enable_grayscale_summing(struct bregs *regs)
1649 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
1650 u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
1651 SET_BDA(modeset_ctl, v | v2);
1656 biosfn_enable_cursor_emulation(struct bregs *regs)
1658 u8 v = (regs->al & 0x01) ^ 0x01;
1659 u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
1660 SET_BDA(modeset_ctl, v | v2);
1664 // -------------------------------------------------------------------
1666 biosfn_write_string(u8 flag, u8 page, u8 attr, u16 count, u8 row, u8 col,
1667 u16 seg, u8 *offset)
1669 u16 newcurs, oldcurs, dummy;
1672 // Read curs info for the page
1673 biosfn_get_cursor_pos(page, &dummy, &oldcurs);
1675 // if row=0xff special case : use current cursor position
1677 col = oldcurs & 0x00ff;
1678 row = (oldcurs & 0xff00) >> 8;
1684 biosfn_set_cursor_pos(page, newcurs);
1686 while (count-- != 0) {
1687 car = GET_FARVAR(seg, *offset);
1689 if ((flag & 0x02) != 0) {
1690 attr = GET_FARVAR(seg, *offset);
1694 biosfn_write_teletype(car, page, attr, WITH_ATTR);
1697 // Set back curs pos
1698 if ((flag & 0x01) == 0)
1699 biosfn_set_cursor_pos(page, oldcurs);
1702 // -------------------------------------------------------------------
1704 biosfn_read_display_code(struct bregs *regs)
1706 regs->bx = GET_BDA(dcc_index);
1711 biosfn_set_display_code(struct bregs *regs)
1713 SET_BDA(dcc_index, regs->bl);
1714 dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
1718 // -------------------------------------------------------------------
1720 biosfn_read_state_info(u16 BX, u16 ES, u16 DI)
1722 // Address of static functionality table
1723 SET_FARVAR(ES, *(u16*)(DI + 0x00), (u32)static_functionality);
1724 SET_FARVAR(ES, *(u16*)(DI + 0x02), 0xC000);
1726 // Hard coded copy from BIOS area. Should it be cleaner ?
1727 memcpy_far(ES, (void*)(DI + 0x04), SEG_BDA, (void*)0x49, 30);
1728 memcpy_far(ES, (void*)(DI + 0x22), SEG_BDA, (void*)0x84, 3);
1730 SET_FARVAR(ES, *(u8*)(DI + 0x25), GET_BDA(dcc_index));
1731 SET_FARVAR(ES, *(u8*)(DI + 0x26), 0);
1732 SET_FARVAR(ES, *(u8*)(DI + 0x27), 16);
1733 SET_FARVAR(ES, *(u8*)(DI + 0x28), 0);
1734 SET_FARVAR(ES, *(u8*)(DI + 0x29), 8);
1735 SET_FARVAR(ES, *(u8*)(DI + 0x2a), 2);
1736 SET_FARVAR(ES, *(u8*)(DI + 0x2b), 0);
1737 SET_FARVAR(ES, *(u8*)(DI + 0x2c), 0);
1738 SET_FARVAR(ES, *(u8*)(DI + 0x31), 3);
1739 SET_FARVAR(ES, *(u8*)(DI + 0x32), 0);
1741 memset_far(ES, (void*)(DI + 0x33), 0, 13);
1744 // -------------------------------------------------------------------
1745 // -------------------------------------------------------------------
1747 biosfn_read_video_state_size(u16 CX)
1753 size += (5 + 8 + 5) * 2 + 6;
1755 size += 3 + 256 * 3 + 1;
1760 biosfn_save_video_state(u16 CX, u16 ES, u16 BX)
1762 u16 i, crtc_addr, ar_index;
1764 crtc_addr = GET_BDA(crtc_address);
1766 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_ADDRESS));
1768 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr));
1770 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_ADDRESS));
1772 inb(VGAREG_ACTL_RESET);
1773 ar_index = inb(VGAREG_ACTL_ADDRESS);
1774 SET_FARVAR(ES, *(u8*)(BX+0), ar_index);
1776 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_READ_FEATURE_CTL));
1779 for (i = 1; i <= 4; i++) {
1780 outb(i, VGAREG_SEQU_ADDRESS);
1781 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
1784 outb(0, VGAREG_SEQU_ADDRESS);
1785 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
1788 for (i = 0; i <= 0x18; i++) {
1790 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr + 1));
1794 for (i = 0; i <= 0x13; i++) {
1795 inb(VGAREG_ACTL_RESET);
1796 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
1797 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_ACTL_READ_DATA));
1800 inb(VGAREG_ACTL_RESET);
1802 for (i = 0; i <= 8; i++) {
1803 outb(i, VGAREG_GRDC_ADDRESS);
1804 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_DATA));
1808 SET_FARVAR(ES, *(u16*)(BX+0), crtc_addr);
1811 /* XXX: read plane latches */
1812 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1814 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1816 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1818 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1822 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_mode));
1824 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_cols));
1826 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagesize));
1828 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(crtc_address));
1830 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_rows));
1832 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(char_height));
1834 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_ctl));
1836 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_switches));
1838 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(modeset_ctl));
1840 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_type));
1842 for (i = 0; i < 8; i++) {
1843 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_pos[i]));
1846 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagestart));
1848 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_page));
1851 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x1f * 4)));
1853 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x1f * 4 + 2)));
1855 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x43 * 4)));
1857 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x43 * 4 + 2)));
1861 /* XXX: check this */
1862 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_STATE));
1863 BX++; /* read/write mode dac */
1864 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_WRITE_ADDRESS));
1865 BX++; /* pix address */
1866 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_PEL_MASK));
1868 // Set the whole dac always, from 0
1869 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
1870 for (i = 0; i < 256 * 3; i++) {
1871 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_DATA));
1874 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1875 BX++; /* color select register */
1881 biosfn_restore_video_state(u16 CX, u16 ES, u16 BX)
1883 u16 i, crtc_addr, v, addr1, ar_index;
1886 // Reset Attribute Ctl flip-flop
1887 inb(VGAREG_ACTL_RESET);
1889 crtc_addr = GET_FARVAR(ES, *(u16*)(BX + 0x40));
1893 for (i = 1; i <= 4; i++) {
1894 outb(i, VGAREG_SEQU_ADDRESS);
1895 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
1898 outb(0, VGAREG_SEQU_ADDRESS);
1899 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
1902 // Disable CRTC write protection
1903 outw(0x0011, crtc_addr);
1905 for (i = 0; i <= 0x18; i++) {
1908 outb(GET_FARVAR(ES, *(u8*)(BX+0)), crtc_addr + 1);
1912 // select crtc base address
1913 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
1914 if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
1916 outb(v, VGAREG_WRITE_MISC_OUTPUT);
1918 // enable write protection if needed
1919 outb(0x11, crtc_addr);
1920 outb(GET_FARVAR(ES, *(u8*)(BX - 0x18 + 0x11)), crtc_addr + 1);
1922 // Set Attribute Ctl
1923 ar_index = GET_FARVAR(ES, *(u8*)(addr1 + 0x03));
1924 inb(VGAREG_ACTL_RESET);
1925 for (i = 0; i <= 0x13; i++) {
1926 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
1927 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_ACTL_WRITE_DATA);
1930 outb(ar_index, VGAREG_ACTL_ADDRESS);
1931 inb(VGAREG_ACTL_RESET);
1933 for (i = 0; i <= 8; i++) {
1934 outb(i, VGAREG_GRDC_ADDRESS);
1935 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_GRDC_DATA);
1938 BX += 2; /* crtc_addr */
1939 BX += 4; /* plane latches */
1941 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_SEQU_ADDRESS);
1943 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr);
1945 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_GRDC_ADDRESS);
1948 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr - 0x4 + 0xa);
1952 SET_BDA(video_mode, GET_FARVAR(ES, *(u8*)(BX+0)));
1954 SET_BDA(video_cols, GET_FARVAR(ES, *(u16*)(BX+0)));
1956 SET_BDA(video_pagesize, GET_FARVAR(ES, *(u16*)(BX+0)));
1958 SET_BDA(crtc_address, GET_FARVAR(ES, *(u16*)(BX+0)));
1960 SET_BDA(video_rows, GET_FARVAR(ES, *(u8*)(BX+0)));
1962 SET_BDA(char_height, GET_FARVAR(ES, *(u16*)(BX+0)));
1964 SET_BDA(video_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
1966 SET_BDA(video_switches, GET_FARVAR(ES, *(u8*)(BX+0)));
1968 SET_BDA(modeset_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
1970 SET_BDA(cursor_type, GET_FARVAR(ES, *(u16*)(BX+0)));
1972 for (i = 0; i < 8; i++) {
1973 SET_BDA(cursor_pos[i], GET_FARVAR(ES, *(u16*)(BX+0)));
1976 SET_BDA(video_pagestart, GET_FARVAR(ES, *(u16*)(BX+0)));
1978 SET_BDA(video_page, GET_FARVAR(ES, *(u8*)(BX+0)));
1981 SET_IVT(0x1f, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
1983 SET_IVT(0x43, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
1988 v = GET_FARVAR(ES, *(u8*)(BX+0));
1990 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_PEL_MASK);
1992 // Set the whole dac always, from 0
1993 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
1994 for (i = 0; i < 256 * 3; i++) {
1995 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_DAC_DATA);
1999 outb(v, VGAREG_DAC_WRITE_ADDRESS);
2005 /****************************************************************
2006 * VGA int 10 handler
2007 ****************************************************************/
2010 handle_1000(struct bregs *regs)
2013 biosfn_set_video_mode(regs->al);
2014 switch(regs->al & 0x7F) {
2033 handle_1001(struct bregs *regs)
2035 biosfn_set_cursor_shape(regs->ch, regs->cl);
2039 handle_1002(struct bregs *regs)
2041 biosfn_set_cursor_pos(regs->bh, regs->dx);
2045 handle_1003(struct bregs *regs)
2047 biosfn_get_cursor_pos(regs->bh, ®s->cx, ®s->dx);
2050 // Read light pen pos (unimplemented)
2052 handle_1004(struct bregs *regs)
2055 regs->ax = regs->bx = regs->cx = regs->dx = 0;
2059 handle_1005(struct bregs *regs)
2061 biosfn_set_active_page(regs->al);
2065 handle_1006(struct bregs *regs)
2067 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
2072 handle_1007(struct bregs *regs)
2074 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
2075 , 0xFF, SCROLL_DOWN);
2079 handle_1008(struct bregs *regs)
2082 biosfn_read_char_attr(regs->bh, ®s->ax);
2086 handle_1009(struct bregs *regs)
2089 biosfn_write_char_attr(regs->al, regs->bh, regs->bl, regs->cx);
2093 handle_100a(struct bregs *regs)
2096 biosfn_write_char_only(regs->al, regs->bh, regs->bl, regs->cx);
2101 handle_100b00(struct bregs *regs)
2104 biosfn_set_border_color(regs);
2108 handle_100b01(struct bregs *regs)
2111 biosfn_set_palette(regs);
2115 handle_100bXX(struct bregs *regs)
2121 handle_100b(struct bregs *regs)
2124 case 0x00: handle_100b00(regs); break;
2125 case 0x01: handle_100b01(regs); break;
2126 default: handle_100bXX(regs); break;
2132 handle_100c(struct bregs *regs)
2135 biosfn_write_pixel(regs->bh, regs->al, regs->cx, regs->dx);
2139 handle_100d(struct bregs *regs)
2142 biosfn_read_pixel(regs->bh, regs->cx, regs->dx, ®s->ax);
2146 handle_100e(struct bregs *regs)
2148 // Ralf Brown Interrupt list is WRONG on bh(page)
2149 // We do output only on the current page !
2150 biosfn_write_teletype(regs->al, 0xff, regs->bl, NO_ATTR);
2154 handle_100f(struct bregs *regs)
2157 biosfn_get_video_mode(regs);
2162 handle_101000(struct bregs *regs)
2164 if (regs->bl > 0x14)
2166 biosfn_set_single_palette_reg(regs->bl, regs->bh);
2170 handle_101001(struct bregs *regs)
2173 biosfn_set_overscan_border_color(regs);
2177 handle_101002(struct bregs *regs)
2180 biosfn_set_all_palette_reg(regs);
2184 handle_101003(struct bregs *regs)
2187 biosfn_toggle_intensity(regs);
2191 handle_101007(struct bregs *regs)
2193 if (regs->bl > 0x14)
2195 regs->bh = biosfn_get_single_palette_reg(regs->bl);
2199 handle_101008(struct bregs *regs)
2202 biosfn_read_overscan_border_color(regs);
2206 handle_101009(struct bregs *regs)
2209 biosfn_get_all_palette_reg(regs);
2213 handle_101010(struct bregs *regs)
2216 biosfn_set_single_dac_reg(regs);
2220 handle_101012(struct bregs *regs)
2223 biosfn_set_all_dac_reg(regs);
2227 handle_101013(struct bregs *regs)
2230 biosfn_select_video_dac_color_page(regs);
2234 handle_101015(struct bregs *regs)
2237 biosfn_read_single_dac_reg(regs);
2241 handle_101017(struct bregs *regs)
2244 biosfn_read_all_dac_reg(regs);
2248 handle_101018(struct bregs *regs)
2251 biosfn_set_pel_mask(regs);
2255 handle_101019(struct bregs *regs)
2258 biosfn_read_pel_mask(regs);
2262 handle_10101a(struct bregs *regs)
2265 biosfn_read_video_dac_state(regs);
2269 handle_10101b(struct bregs *regs)
2271 biosfn_perform_gray_scale_summing(regs->bx, regs->cx);
2275 handle_1010XX(struct bregs *regs)
2281 handle_1010(struct bregs *regs)
2284 case 0x00: handle_101000(regs); break;
2285 case 0x01: handle_101001(regs); break;
2286 case 0x02: handle_101002(regs); break;
2287 case 0x03: handle_101003(regs); break;
2288 case 0x07: handle_101007(regs); break;
2289 case 0x08: handle_101008(regs); break;
2290 case 0x09: handle_101009(regs); break;
2291 case 0x10: handle_101010(regs); break;
2292 case 0x12: handle_101012(regs); break;
2293 case 0x13: handle_101013(regs); break;
2294 case 0x15: handle_101015(regs); break;
2295 case 0x17: handle_101017(regs); break;
2296 case 0x18: handle_101018(regs); break;
2297 case 0x19: handle_101019(regs); break;
2298 case 0x1a: handle_10101a(regs); break;
2299 case 0x1b: handle_10101b(regs); break;
2300 default: handle_1010XX(regs); break;
2306 handle_101100(struct bregs *regs)
2309 biosfn_load_text_user_pat(regs->al, regs->es, 0 // XXX - regs->bp
2310 , regs->cx, regs->dx, regs->bl, regs->bh);
2314 handle_101101(struct bregs *regs)
2317 biosfn_load_text_8_14_pat(regs->al, regs->bl);
2321 handle_101102(struct bregs *regs)
2324 biosfn_load_text_8_8_pat(regs->al, regs->bl);
2328 handle_101103(struct bregs *regs)
2331 biosfn_set_text_block_specifier(regs);
2335 handle_101104(struct bregs *regs)
2338 biosfn_load_text_8_16_pat(regs->al, regs->bl);
2342 handle_101110(struct bregs *regs)
2344 handle_101100(regs);
2348 handle_101111(struct bregs *regs)
2350 handle_101101(regs);
2354 handle_101112(struct bregs *regs)
2356 handle_101102(regs);
2360 handle_101114(struct bregs *regs)
2362 handle_101104(regs);
2366 handle_101130(struct bregs *regs)
2369 biosfn_get_font_info(regs->bh, ®s->es, 0 // ®s->bp
2370 , ®s->cx, ®s->dx);
2374 handle_1011XX(struct bregs *regs)
2380 handle_1011(struct bregs *regs)
2383 case 0x00: handle_101100(regs); break;
2384 case 0x01: handle_101101(regs); break;
2385 case 0x02: handle_101102(regs); break;
2386 case 0x03: handle_101103(regs); break;
2387 case 0x04: handle_101104(regs); break;
2388 case 0x10: handle_101110(regs); break;
2389 case 0x11: handle_101111(regs); break;
2390 case 0x12: handle_101112(regs); break;
2391 case 0x14: handle_101114(regs); break;
2392 case 0x30: handle_101130(regs); break;
2393 default: handle_1011XX(regs); break;
2399 handle_101210(struct bregs *regs)
2402 biosfn_get_ega_info(regs);
2406 handle_101230(struct bregs *regs)
2409 biosfn_select_vert_res(regs);
2413 handle_101231(struct bregs *regs)
2416 biosfn_enable_default_palette_loading(regs);
2420 handle_101232(struct bregs *regs)
2423 biosfn_enable_video_addressing(regs);
2427 handle_101233(struct bregs *regs)
2430 biosfn_enable_grayscale_summing(regs);
2434 handle_101234(struct bregs *regs)
2437 biosfn_enable_cursor_emulation(regs);
2441 handle_101235(struct bregs *regs)
2448 handle_101236(struct bregs *regs)
2455 handle_1012XX(struct bregs *regs)
2461 handle_1012(struct bregs *regs)
2464 case 0x10: handle_101210(regs); break;
2465 case 0x30: handle_101230(regs); break;
2466 case 0x31: handle_101231(regs); break;
2467 case 0x32: handle_101232(regs); break;
2468 case 0x33: handle_101233(regs); break;
2469 case 0x34: handle_101234(regs); break;
2470 case 0x35: handle_101235(regs); break;
2471 case 0x36: handle_101236(regs); break;
2472 default: handle_1012XX(regs); break;
2475 // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
2480 handle_1013(struct bregs *regs)
2483 biosfn_write_string(regs->al, regs->bh, regs->bl, regs->cx
2484 , regs->dh, regs->dl, regs->es, 0); // regs->bp);
2489 handle_101a00(struct bregs *regs)
2492 biosfn_read_display_code(regs);
2496 handle_101a01(struct bregs *regs)
2499 biosfn_set_display_code(regs);
2503 handle_101aXX(struct bregs *regs)
2509 handle_101a(struct bregs *regs)
2512 case 0x00: handle_101a00(regs); break;
2513 case 0x01: handle_101a01(regs); break;
2514 default: handle_101aXX(regs); break;
2520 handle_101b(struct bregs *regs)
2523 biosfn_read_state_info(regs->bx, regs->es, regs->di);
2529 handle_101c00(struct bregs *regs)
2532 regs->bx = biosfn_read_video_state_size(regs->cx);
2536 handle_101c01(struct bregs *regs)
2539 biosfn_save_video_state(regs->cx, regs->es, regs->bx);
2543 handle_101c02(struct bregs *regs)
2546 biosfn_restore_video_state(regs->cx, regs->es, regs->bx);
2550 handle_101cXX(struct bregs *regs)
2556 handle_101c(struct bregs *regs)
2559 case 0x00: handle_101c00(regs); break;
2560 case 0x01: handle_101c01(regs); break;
2561 case 0x02: handle_101c02(regs); break;
2562 default: handle_101cXX(regs); break;
2568 handle_104f00(struct bregs *regs)
2570 // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
2571 // XXX - OR cirrus_vesa_00h
2575 handle_104f01(struct bregs *regs)
2577 // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
2578 // XXX - OR cirrus_vesa_01h
2582 handle_104f02(struct bregs *regs)
2584 // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
2585 // XXX - OR cirrus_vesa_02h
2589 handle_104f03(struct bregs *regs)
2591 // XXX - vbe_biosfn_return_current_mode
2592 // XXX - OR cirrus_vesa_03h
2596 handle_104f04(struct bregs *regs)
2598 // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
2602 handle_104f05(struct bregs *regs)
2604 // XXX - vbe_biosfn_display_window_control
2605 // XXX - OR cirrus_vesa_05h
2609 handle_104f06(struct bregs *regs)
2611 // XXX - vbe_biosfn_set_get_logical_scan_line_length
2612 // XXX - OR cirrus_vesa_06h
2616 handle_104f07(struct bregs *regs)
2618 // XXX - vbe_biosfn_set_get_display_start
2619 // XXX - OR cirrus_vesa_07h
2623 handle_104f08(struct bregs *regs)
2625 // XXX - vbe_biosfn_set_get_dac_palette_format
2629 handle_104f0a(struct bregs *regs)
2631 // XXX - vbe_biosfn_return_protected_mode_interface
2635 handle_104fXX(struct bregs *regs)
2642 handle_104f(struct bregs *regs)
2645 handle_104fXX(regs);
2649 // XXX - check vbe_has_vbe_display()?
2652 case 0x00: handle_104f00(regs); break;
2653 case 0x01: handle_104f01(regs); break;
2654 case 0x02: handle_104f02(regs); break;
2655 case 0x03: handle_104f03(regs); break;
2656 case 0x04: handle_104f04(regs); break;
2657 case 0x05: handle_104f05(regs); break;
2658 case 0x06: handle_104f06(regs); break;
2659 case 0x07: handle_104f07(regs); break;
2660 case 0x08: handle_104f08(regs); break;
2661 case 0x0a: handle_104f0a(regs); break;
2662 default: handle_104fXX(regs); break;
2668 handle_10XX(struct bregs *regs)
2673 // INT 10h Video Support Service Entry Point
2675 handle_10(struct bregs *regs)
2677 debug_enter(regs, DEBUG_VGA_10);
2679 case 0x00: handle_1000(regs); break;
2680 case 0x01: handle_1001(regs); break;
2681 case 0x02: handle_1002(regs); break;
2682 case 0x03: handle_1003(regs); break;
2683 case 0x04: handle_1004(regs); break;
2684 case 0x05: handle_1005(regs); break;
2685 case 0x06: handle_1006(regs); break;
2686 case 0x07: handle_1007(regs); break;
2687 case 0x08: handle_1008(regs); break;
2688 case 0x09: handle_1009(regs); break;
2689 case 0x0a: handle_100a(regs); break;
2690 case 0x0b: handle_100b(regs); break;
2691 case 0x0c: handle_100c(regs); break;
2692 case 0x0d: handle_100d(regs); break;
2693 case 0x0e: handle_100e(regs); break;
2694 case 0x0f: handle_100f(regs); break;
2695 case 0x10: handle_1010(regs); break;
2696 case 0x11: handle_1011(regs); break;
2697 case 0x12: handle_1012(regs); break;
2698 case 0x13: handle_1013(regs); break;
2699 case 0x1a: handle_101a(regs); break;
2700 case 0x1b: handle_101b(regs); break;
2701 case 0x1c: handle_101c(regs); break;
2702 case 0x4f: handle_104f(regs); break;
2703 default: handle_10XX(regs); break;
2708 /****************************************************************
2710 ****************************************************************/
2715 // init detected hardware BIOS Area
2716 // set 80x25 color (not clear from RBIL but usual)
2717 u16 eqf = GET_BDA(equipment_list_flags);
2718 SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20);
2720 // Just for the first int10 find its children
2722 // the default char height
2723 SET_BDA(char_height, 0x10);
2726 SET_BDA(video_ctl, 0x60);
2728 // Set the basic screen we have
2729 SET_BDA(video_switches, 0xf9);
2731 // Set the basic modeset options
2732 SET_BDA(modeset_ctl, 0x51);
2734 // Set the default MSR
2735 SET_BDA(video_msr, 0x09);
2741 // switch to color mode and enable CPU access 480 lines
2742 outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
2743 // more than 64k 3C4/04
2744 outb(0x04, VGAREG_SEQU_ADDRESS);
2745 outb(0x02, VGAREG_SEQU_DATA);
2749 vga_post(struct bregs *regs)
2751 debug_enter(regs, DEBUG_VGA_POST);
2759 extern void entry_10(void);
2760 SET_IVT(0x10, 0xC000, (u32)entry_10);
2765 // XXX - clear screen and display info
2768 SET_VGA(video_save_pointer_table[0], (u32)video_param_table);
2769 SET_VGA(video_save_pointer_table[1], 0xC000);
2772 extern u8 _rom_header_size, _rom_header_checksum;
2773 SET_VGA(_rom_header_checksum, 0);
2774 u8 sum = -checksum_far(0xC000, 0, _rom_header_size * 512);
2775 SET_VGA(_rom_header_checksum, sum);