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 // * review correctness of converted asm by comparing with RBIL
12 // * convert vbe/clext code
14 #include "bregs.h" // struct bregs
15 #include "biosvar.h" // GET_BDA
16 #include "util.h" // memset
17 #include "vgatables.h" // find_vga_entry
21 #define CONFIG_CIRRUS 0
24 #define DEBUG_VGA_POST 1
25 #define DEBUG_VGA_10 3
27 #define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
30 /****************************************************************
32 ****************************************************************/
35 call16_vgaint(u32 eax
, u32 ebx
)
47 perform_gray_scale_summing(u16 start
, u16 count
)
49 vgahw_screen_disable();
51 for (i
= start
; i
< start
+count
; i
++) {
53 vgahw_get_dac_regs(GET_SEG(SS
), rgb
, i
, 1);
55 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
56 u16 intensity
= ((77 * rgb
[0] + 151 * rgb
[1] + 28 * rgb
[2]) + 0x80) >> 8;
60 vgahw_set_dac_regs(GET_SEG(SS
), rgb
, i
, 1);
62 vgahw_screen_enable();
66 set_cursor_shape(u8 start
, u8 end
)
71 u16 curs
= (start
<< 8) + end
;
72 SET_BDA(cursor_type
, curs
);
74 u8 modeset_ctl
= GET_BDA(modeset_ctl
);
75 u16 cheight
= GET_BDA(char_height
);
76 if ((modeset_ctl
& 0x01) && (cheight
> 8) && (end
< 8) && (start
< 0x20)) {
77 if (end
!= (start
+ 1))
78 start
= ((start
+ 1) * cheight
/ 8) - 1;
80 start
= ((end
+ 1) * cheight
/ 8) - 2;
81 end
= ((end
+ 1) * cheight
/ 8) - 1;
83 vgahw_set_cursor_shape(start
, end
);
87 get_cursor_shape(u8 page
)
91 // FIXME should handle VGA 14/16 lines
92 return GET_BDA(cursor_type
);
96 set_cursor_pos(struct cursorpos cp
)
98 // Should not happen...
103 SET_BDA(cursor_pos
[cp
.page
], (cp
.y
<< 8) | cp
.x
);
105 // Set the hardware cursor
106 u8 current
= GET_BDA(video_page
);
107 if (cp
.page
!= current
)
110 // Get the dimensions
111 u16 nbcols
= GET_BDA(video_cols
);
112 u16 nbrows
= GET_BDA(video_rows
) + 1;
114 // Calculate the address knowing nbcols nbrows and page num
115 u16 address
= (SCREEN_IO_START(nbcols
, nbrows
, cp
.page
)
116 + cp
.x
+ cp
.y
* nbcols
);
118 vgahw_set_cursor_pos(address
);
121 static struct cursorpos
122 get_cursor_pos(u8 page
)
125 // special case - use current page
126 page
= GET_BDA(video_page
);
128 struct cursorpos cp
= { 0, 0, 0xfe };
131 // FIXME should handle VGA 14/16 lines
132 u16 xy
= GET_BDA(cursor_pos
[page
]);
133 struct cursorpos cp
= {xy
, xy
>>8, page
};
138 set_active_page(u8 page
)
144 struct vgamode_s
*vmode_g
= find_vga_entry(GET_BDA(video_mode
));
148 // Get pos curs pos for the right page
149 struct cursorpos cp
= get_cursor_pos(page
);
152 if (GET_GLOBAL(vmode_g
->memmodel
) & TEXT
) {
153 // Get the dimensions
154 u16 nbcols
= GET_BDA(video_cols
);
155 u16 nbrows
= GET_BDA(video_rows
) + 1;
157 // Calculate the address knowing nbcols nbrows and page num
158 address
= SCREEN_MEM_START(nbcols
, nbrows
, page
);
159 SET_BDA(video_pagestart
, address
);
162 address
= SCREEN_IO_START(nbcols
, nbrows
, page
);
164 struct VideoParam_s
*vparam_g
= GET_GLOBAL(vmode_g
->vparam
);
165 address
= page
* GET_GLOBAL(vparam_g
->slength
);
168 vgahw_set_active_page(address
);
170 // And change the BIOS page
171 SET_BDA(video_page
, page
);
173 dprintf(1, "Set active page %02x address %04x\n", page
, address
);
175 // Display the cursor, now the page is active
180 set_scan_lines(u8 lines
)
182 vgahw_set_scan_lines(lines
);
184 set_cursor_shape(0x06, 0x07);
186 set_cursor_shape(lines
- 4, lines
- 3);
187 SET_BDA(char_height
, lines
);
188 u16 vde
= vgahw_get_vde();
189 u8 rows
= vde
/ lines
;
190 SET_BDA(video_rows
, rows
- 1);
191 u16 cols
= GET_BDA(video_cols
);
192 SET_BDA(video_pagesize
, rows
* cols
* 2);
196 /****************************************************************
198 ****************************************************************/
200 // Scroll the screen one line. This function is designed to be called
201 // tail-recursive to reduce stack usage.
203 scroll_one(u16 nbrows
, u16 nbcols
, u8 page
)
205 struct cursorpos ul
= {0, 0, page
};
206 struct cursorpos lr
= {nbcols
-1, nbrows
-1, page
};
207 vgafb_scroll(1, -1, ul
, lr
);
210 // Write a character to the screen at a given position. Implement
211 // special characters and scroll the screen if necessary.
213 write_teletype(struct cursorpos
*pcp
, struct carattr ca
)
215 struct cursorpos cp
= *pcp
;
217 // Get the dimensions
218 u16 nbrows
= GET_BDA(video_rows
) + 1;
219 u16 nbcols
= GET_BDA(video_cols
);
237 struct carattr dummyca
= {' ', ca
.attr
, ca
.use_attr
};
238 vgafb_write_char(cp
, dummyca
);
240 } while (cp
.x
< nbcols
&& cp
.x
% 8);
243 vgafb_write_char(cp
, ca
);
247 // Do we need to wrap ?
248 if (cp
.x
== nbcols
) {
252 // Do we need to scroll ?
260 scroll_one(nbrows
, nbcols
, cp
.page
);
263 // Write out a buffer of alternating characters and attributes.
265 write_attr_string(struct cursorpos
*pcp
, u16 count
, u16 seg
, u8
*offset_far
)
268 u8 car
= GET_FARVAR(seg
, *offset_far
);
270 u8 attr
= GET_FARVAR(seg
, *offset_far
);
273 struct carattr ca
= {car
, attr
, 1};
274 write_teletype(pcp
, ca
);
278 // Write out a buffer of characters.
280 write_string(struct cursorpos
*pcp
, u8 attr
, u16 count
, u16 seg
, u8
*offset_far
)
283 u8 car
= GET_FARVAR(seg
, *offset_far
);
286 struct carattr ca
= {car
, attr
, 1};
287 write_teletype(pcp
, ca
);
292 /****************************************************************
293 * Save and restore bda state
294 ****************************************************************/
297 save_bda_state(u16 seg
, struct saveBDAstate
*info
)
299 SET_FARVAR(seg
, info
->video_mode
, GET_BDA(video_mode
));
300 SET_FARVAR(seg
, info
->video_cols
, GET_BDA(video_cols
));
301 SET_FARVAR(seg
, info
->video_pagesize
, GET_BDA(video_pagesize
));
302 SET_FARVAR(seg
, info
->crtc_address
, GET_BDA(crtc_address
));
303 SET_FARVAR(seg
, info
->video_rows
, GET_BDA(video_rows
));
304 SET_FARVAR(seg
, info
->char_height
, GET_BDA(char_height
));
305 SET_FARVAR(seg
, info
->video_ctl
, GET_BDA(video_ctl
));
306 SET_FARVAR(seg
, info
->video_switches
, GET_BDA(video_switches
));
307 SET_FARVAR(seg
, info
->modeset_ctl
, GET_BDA(modeset_ctl
));
308 SET_FARVAR(seg
, info
->cursor_type
, GET_BDA(cursor_type
));
311 SET_FARVAR(seg
, info
->cursor_pos
[i
], GET_BDA(cursor_pos
[i
]));
312 SET_FARVAR(seg
, info
->video_pagestart
, GET_BDA(video_pagestart
));
313 SET_FARVAR(seg
, info
->video_page
, GET_BDA(video_page
));
315 SET_FARVAR(seg
, info
->font0
, GET_IVT(0x1f));
316 SET_FARVAR(seg
, info
->font1
, GET_IVT(0x43));
320 restore_bda_state(u16 seg
, struct saveBDAstate
*info
)
322 SET_BDA(video_mode
, GET_FARVAR(seg
, info
->video_mode
));
323 SET_BDA(video_cols
, GET_FARVAR(seg
, info
->video_cols
));
324 SET_BDA(video_pagesize
, GET_FARVAR(seg
, info
->video_pagesize
));
325 SET_BDA(crtc_address
, GET_FARVAR(seg
, info
->crtc_address
));
326 SET_BDA(video_rows
, GET_FARVAR(seg
, info
->video_rows
));
327 SET_BDA(char_height
, GET_FARVAR(seg
, info
->char_height
));
328 SET_BDA(video_ctl
, GET_FARVAR(seg
, info
->video_ctl
));
329 SET_BDA(video_switches
, GET_FARVAR(seg
, info
->video_switches
));
330 SET_BDA(modeset_ctl
, GET_FARVAR(seg
, info
->modeset_ctl
));
331 SET_BDA(cursor_type
, GET_FARVAR(seg
, info
->cursor_type
));
333 for (i
= 0; i
< 8; i
++)
334 SET_BDA(cursor_pos
[i
], GET_FARVAR(seg
, info
->cursor_pos
[i
]));
335 SET_BDA(video_pagestart
, GET_FARVAR(seg
, info
->video_pagestart
));
336 SET_BDA(video_page
, GET_FARVAR(seg
, info
->video_page
));
338 SET_IVT(0x1f, GET_FARVAR(seg
, info
->font0
));
339 SET_IVT(0x43, GET_FARVAR(seg
, info
->font1
));
343 /****************************************************************
345 ****************************************************************/
349 handle_1000(struct bregs
*regs
)
351 u8 noclearmem
= regs
->al
& 0x80;
352 u8 mode
= regs
->al
& 0x7f;
363 cirrus_set_video_mode(mode
);
366 if (vbe_has_vbe_display())
367 dispi_set_enable(VBE_DISPI_DISABLED
);
369 // find the entry in the video modes
370 struct vgamode_s
*vmode_g
= find_vga_entry(mode
);
371 dprintf(1, "mode search %02x found %p\n", mode
, vmode_g
);
375 // Read the bios mode set control
376 u8 modeset_ctl
= GET_BDA(modeset_ctl
);
378 // Then we know the number of lines
381 // if palette loading (bit 3 of modeset ctl = 0)
382 if ((modeset_ctl
& 0x08) == 0) { // Set the PEL mask
383 vgahw_set_pel_mask(GET_GLOBAL(vmode_g
->pelmask
));
385 // From which palette
386 u8
*palette_g
= GET_GLOBAL(vmode_g
->dac
);
387 u16 palsize
= GET_GLOBAL(vmode_g
->dacsize
) / 3;
389 // Always 256*3 values
390 vgahw_set_dac_regs(get_global_seg(), palette_g
, 0, palsize
);
392 for (i
= palsize
; i
< 0x0100; i
++) {
393 static u8 rgb
[3] VAR16
;
394 vgahw_set_dac_regs(get_global_seg(), rgb
, i
, 1);
397 if ((modeset_ctl
& 0x02) == 0x02)
398 perform_gray_scale_summing(0x00, 0x100);
401 struct VideoParam_s
*vparam_g
= GET_GLOBAL(vmode_g
->vparam
);
402 vgahw_set_mode(vparam_g
);
404 if (noclearmem
== 0x00)
405 clear_screen(vmode_g
);
407 // Set CRTC address VGA or MDA
408 u16 crtc_addr
= VGAREG_VGA_CRTC_ADDRESS
;
409 if (GET_GLOBAL(vmode_g
->memmodel
) == MTEXT
)
410 crtc_addr
= VGAREG_MDA_CRTC_ADDRESS
;
413 u16 cheight
= GET_GLOBAL(vparam_g
->cheight
);
414 SET_BDA(video_mode
, mode
);
415 SET_BDA(video_cols
, GET_GLOBAL(vparam_g
->twidth
));
416 SET_BDA(video_pagesize
, GET_GLOBAL(vparam_g
->slength
));
417 SET_BDA(crtc_address
, crtc_addr
);
418 SET_BDA(video_rows
, GET_GLOBAL(vparam_g
->theightm1
));
419 SET_BDA(char_height
, cheight
);
420 SET_BDA(video_ctl
, (0x60 | noclearmem
));
421 SET_BDA(video_switches
, 0xF9);
422 SET_BDA(modeset_ctl
, GET_BDA(modeset_ctl
) & 0x7f);
424 // FIXME We nearly have the good tables. to be reworked
425 SET_BDA(dcc_index
, 0x08); // 8 is VGA should be ok for now
426 SET_BDA(video_savetable
427 , SEGOFF(get_global_seg(), (u32
)video_save_pointer_table
));
430 SET_BDA(video_msr
, 0x00); // Unavailable on vanilla vga, but...
431 SET_BDA(video_pal
, 0x00); // Unavailable on vanilla vga, but...
434 if (GET_GLOBAL(vmode_g
->memmodel
) & TEXT
)
435 set_cursor_shape(0x06, 0x07);
436 // Set cursor pos for page 0..7
438 for (i
= 0; i
< 8; i
++) {
439 struct cursorpos cp
= {0, 0, i
};
444 set_active_page(0x00);
446 // Write the fonts in memory
447 if (GET_GLOBAL(vmode_g
->memmodel
) & TEXT
) {
448 call16_vgaint(0x1104, 0);
449 call16_vgaint(0x1103, 0);
451 // Set the ints 0x1F and 0x43
452 SET_IVT(0x1f, SEGOFF(get_global_seg(), (u32
)&vgafont8
[128 * 8]));
456 SET_IVT(0x43, SEGOFF(get_global_seg(), (u32
)vgafont8
));
459 SET_IVT(0x43, SEGOFF(get_global_seg(), (u32
)vgafont14
));
462 SET_IVT(0x43, SEGOFF(get_global_seg(), (u32
)vgafont16
));
468 handle_1001(struct bregs
*regs
)
470 set_cursor_shape(regs
->ch
, regs
->cl
);
474 handle_1002(struct bregs
*regs
)
476 struct cursorpos cp
= {regs
->dl
, regs
->dh
, regs
->bh
};
481 handle_1003(struct bregs
*regs
)
483 regs
->cx
= get_cursor_shape(regs
->bh
);
484 struct cursorpos cp
= get_cursor_pos(regs
->bh
);
489 // Read light pen pos (unimplemented)
491 handle_1004(struct bregs
*regs
)
494 regs
->ax
= regs
->bx
= regs
->cx
= regs
->dx
= 0;
498 handle_1005(struct bregs
*regs
)
500 set_active_page(regs
->al
);
504 verify_scroll(struct bregs
*regs
, int dir
)
506 u8 page
= GET_BDA(video_page
);
507 struct cursorpos ul
= {regs
->cl
, regs
->ch
, page
};
508 struct cursorpos lr
= {regs
->dl
, regs
->dh
, page
};
510 u16 nbrows
= GET_BDA(video_rows
) + 1;
513 u16 nbcols
= GET_BDA(video_cols
);
517 if (ul
.x
> lr
.x
|| ul
.y
> lr
.y
)
520 u16 nblines
= regs
->al
;
521 if (!nblines
|| nblines
> lr
.y
- ul
.y
+ 1)
522 nblines
= lr
.y
- ul
.y
+ 1;
524 vgafb_scroll(dir
* nblines
, regs
->bh
, ul
, lr
);
528 handle_1006(struct bregs
*regs
)
530 verify_scroll(regs
, 1);
534 handle_1007(struct bregs
*regs
)
536 verify_scroll(regs
, -1);
540 handle_1008(struct bregs
*regs
)
542 struct carattr ca
= vgafb_read_char(get_cursor_pos(regs
->bh
));
548 write_chars(u8 page
, struct carattr ca
, u16 count
)
550 struct cursorpos cp
= get_cursor_pos(page
);
552 vgafb_write_char(cp
, ca
);
558 handle_1009(struct bregs
*regs
)
560 struct carattr ca
= {regs
->al
, regs
->bl
, 1};
561 write_chars(regs
->bh
, ca
, regs
->cx
);
565 handle_100a(struct bregs
*regs
)
567 struct carattr ca
= {regs
->al
, regs
->bl
, 0};
568 write_chars(regs
->bh
, ca
, regs
->cx
);
573 handle_100b00(struct bregs
*regs
)
575 vgahw_set_border_color(regs
->bl
);
579 handle_100b01(struct bregs
*regs
)
581 vgahw_set_palette(regs
->bl
);
585 handle_100bXX(struct bregs
*regs
)
591 handle_100b(struct bregs
*regs
)
594 case 0x00: handle_100b00(regs
); break;
595 case 0x01: handle_100b01(regs
); break;
596 default: handle_100bXX(regs
); break;
602 handle_100c(struct bregs
*regs
)
604 // XXX - page (regs->bh) is unused
605 vgafb_write_pixel(regs
->al
, regs
->cx
, regs
->dx
);
609 handle_100d(struct bregs
*regs
)
611 // XXX - page (regs->bh) is unused
612 regs
->al
= vgafb_read_pixel(regs
->cx
, regs
->dx
);
616 handle_100e(struct bregs
*regs
)
618 // Ralf Brown Interrupt list is WRONG on bh(page)
619 // We do output only on the current page !
620 struct carattr ca
= {regs
->al
, regs
->bl
, 0};
621 struct cursorpos cp
= get_cursor_pos(0xff);
622 write_teletype(&cp
, ca
);
627 handle_100f(struct bregs
*regs
)
629 regs
->bh
= GET_BDA(video_page
);
630 regs
->al
= GET_BDA(video_mode
) | (GET_BDA(video_ctl
) & 0x80);
631 regs
->ah
= GET_BDA(video_cols
);
636 handle_101000(struct bregs
*regs
)
640 vgahw_set_single_palette_reg(regs
->bl
, regs
->bh
);
644 handle_101001(struct bregs
*regs
)
646 vgahw_set_overscan_border_color(regs
->bh
);
650 handle_101002(struct bregs
*regs
)
652 vgahw_set_all_palette_reg(regs
->es
, (u8
*)(regs
->dx
+ 0));
656 handle_101003(struct bregs
*regs
)
658 vgahw_toggle_intensity(regs
->bl
);
662 handle_101007(struct bregs
*regs
)
666 regs
->bh
= vgahw_get_single_palette_reg(regs
->bl
);
670 handle_101008(struct bregs
*regs
)
672 regs
->bh
= vgahw_get_overscan_border_color();
676 handle_101009(struct bregs
*regs
)
678 vgahw_get_all_palette_reg(regs
->es
, (u8
*)(regs
->dx
+ 0));
682 handle_101010(struct bregs
*regs
)
684 u8 rgb
[3] = {regs
->dh
, regs
->ch
, regs
->cl
};
685 vgahw_set_dac_regs(GET_SEG(SS
), rgb
, regs
->bx
, 1);
689 handle_101012(struct bregs
*regs
)
691 vgahw_set_dac_regs(regs
->es
, (u8
*)(regs
->dx
+ 0), regs
->bx
, regs
->cx
);
695 handle_101013(struct bregs
*regs
)
697 vgahw_select_video_dac_color_page(regs
->bl
, regs
->bh
);
701 handle_101015(struct bregs
*regs
)
704 vgahw_get_dac_regs(GET_SEG(SS
), rgb
, regs
->bx
, 1);
711 handle_101017(struct bregs
*regs
)
713 vgahw_get_dac_regs(regs
->es
, (u8
*)(regs
->dx
+ 0), regs
->bx
, regs
->cx
);
717 handle_101018(struct bregs
*regs
)
719 vgahw_set_pel_mask(regs
->bl
);
723 handle_101019(struct bregs
*regs
)
725 regs
->bl
= vgahw_get_pel_mask();
729 handle_10101a(struct bregs
*regs
)
731 vgahw_read_video_dac_state(®s
->bl
, ®s
->bh
);
735 handle_10101b(struct bregs
*regs
)
737 perform_gray_scale_summing(regs
->bx
, regs
->cx
);
741 handle_1010XX(struct bregs
*regs
)
747 handle_1010(struct bregs
*regs
)
750 case 0x00: handle_101000(regs
); break;
751 case 0x01: handle_101001(regs
); break;
752 case 0x02: handle_101002(regs
); break;
753 case 0x03: handle_101003(regs
); break;
754 case 0x07: handle_101007(regs
); break;
755 case 0x08: handle_101008(regs
); break;
756 case 0x09: handle_101009(regs
); break;
757 case 0x10: handle_101010(regs
); break;
758 case 0x12: handle_101012(regs
); break;
759 case 0x13: handle_101013(regs
); break;
760 case 0x15: handle_101015(regs
); break;
761 case 0x17: handle_101017(regs
); break;
762 case 0x18: handle_101018(regs
); break;
763 case 0x19: handle_101019(regs
); break;
764 case 0x1a: handle_10101a(regs
); break;
765 case 0x1b: handle_10101b(regs
); break;
766 default: handle_1010XX(regs
); break;
772 handle_101100(struct bregs
*regs
)
774 vgafb_load_font(regs
->es
, (void*)(regs
->bp
+0), regs
->cx
775 , regs
->dx
, regs
->bl
, regs
->bh
);
779 handle_101101(struct bregs
*regs
)
781 vgafb_load_font(get_global_seg(), vgafont14
, 0x100, 0, regs
->bl
, 14);
785 handle_101102(struct bregs
*regs
)
787 vgafb_load_font(get_global_seg(), vgafont8
, 0x100, 0, regs
->bl
, 8);
791 handle_101103(struct bregs
*regs
)
793 vgahw_set_text_block_specifier(regs
->bl
);
797 handle_101104(struct bregs
*regs
)
799 vgafb_load_font(get_global_seg(), vgafont16
, 0x100, 0, regs
->bl
, 16);
803 handle_101110(struct bregs
*regs
)
805 vgafb_load_font(regs
->es
, (void*)(regs
->bp
+0), regs
->cx
806 , regs
->dx
, regs
->bl
, regs
->bh
);
807 set_scan_lines(regs
->bh
);
811 handle_101111(struct bregs
*regs
)
813 vgafb_load_font(get_global_seg(), vgafont14
, 0x100, 0, regs
->bl
, 14);
818 handle_101112(struct bregs
*regs
)
820 vgafb_load_font(get_global_seg(), vgafont8
, 0x100, 0, regs
->bl
, 8);
825 handle_101114(struct bregs
*regs
)
827 vgafb_load_font(get_global_seg(), vgafont16
, 0x100, 0, regs
->bl
, 16);
832 handle_101130(struct bregs
*regs
)
836 struct segoff_s so
= GET_IVT(0x1f);
838 regs
->bp
= so
.offset
;
842 struct segoff_s so
= GET_IVT(0x43);
844 regs
->bp
= so
.offset
;
848 regs
->es
= get_global_seg();
849 regs
->bp
= (u32
)vgafont14
;
852 regs
->es
= get_global_seg();
853 regs
->bp
= (u32
)vgafont8
;
856 regs
->es
= get_global_seg();
857 regs
->bp
= (u32
)vgafont8
+ 128 * 8;
860 regs
->es
= get_global_seg();
861 regs
->bp
= (u32
)vgafont14alt
;
864 regs
->es
= get_global_seg();
865 regs
->bp
= (u32
)vgafont16
;
868 regs
->es
= get_global_seg();
869 regs
->bp
= (u32
)vgafont16alt
;
872 dprintf(1, "Get font info BH(%02x) was discarded\n", regs
->bh
);
875 // Set byte/char of on screen font
876 regs
->cx
= GET_BDA(char_height
) & 0xff;
878 // Set Highest char row
879 regs
->dx
= GET_BDA(video_rows
);
883 handle_1011XX(struct bregs
*regs
)
889 handle_1011(struct bregs
*regs
)
892 case 0x00: handle_101100(regs
); break;
893 case 0x01: handle_101101(regs
); break;
894 case 0x02: handle_101102(regs
); break;
895 case 0x03: handle_101103(regs
); break;
896 case 0x04: handle_101104(regs
); break;
897 case 0x10: handle_101110(regs
); break;
898 case 0x11: handle_101111(regs
); break;
899 case 0x12: handle_101112(regs
); break;
900 case 0x14: handle_101114(regs
); break;
901 case 0x30: handle_101130(regs
); break;
902 default: handle_1011XX(regs
); break;
908 handle_101210(struct bregs
*regs
)
910 u16 crtc_addr
= GET_BDA(crtc_address
);
911 if (crtc_addr
== VGAREG_MDA_CRTC_ADDRESS
)
915 regs
->cx
= GET_BDA(video_switches
) & 0x0f;
919 handle_101230(struct bregs
*regs
)
921 u8 mctl
= GET_BDA(modeset_ctl
);
922 u8 vswt
= GET_BDA(video_switches
);
926 mctl
= (mctl
& ~0x10) | 0x80;
927 vswt
= (vswt
& ~0x0f) | 0x08;
932 vswt
= (vswt
& ~0x0f) | 0x09;
936 mctl
= (mctl
& ~0x80) | 0x10;
937 vswt
= (vswt
& ~0x0f) | 0x09;
940 dprintf(1, "Select vert res (%02x) was discarded\n", regs
->al
);
943 SET_BDA(modeset_ctl
, mctl
);
944 SET_BDA(video_switches
, vswt
);
949 handle_101231(struct bregs
*regs
)
951 u8 v
= (regs
->al
& 0x01) << 3;
952 u8 mctl
= GET_BDA(video_ctl
) & ~0x08;
953 SET_BDA(video_ctl
, mctl
| v
);
958 handle_101232(struct bregs
*regs
)
960 vgahw_enable_video_addressing(regs
->al
);
965 handle_101233(struct bregs
*regs
)
967 u8 v
= ((regs
->al
<< 1) & 0x02) ^ 0x02;
968 u8 v2
= GET_BDA(modeset_ctl
) & ~0x02;
969 SET_BDA(modeset_ctl
, v
| v2
);
974 handle_101234(struct bregs
*regs
)
976 u8 v
= (regs
->al
& 0x01) ^ 0x01;
977 u8 v2
= GET_BDA(modeset_ctl
) & ~0x01;
978 SET_BDA(modeset_ctl
, v
| v2
);
983 handle_101235(struct bregs
*regs
)
990 handle_101236(struct bregs
*regs
)
997 handle_1012XX(struct bregs
*regs
)
1003 handle_1012(struct bregs
*regs
)
1006 case 0x10: handle_101210(regs
); break;
1007 case 0x30: handle_101230(regs
); break;
1008 case 0x31: handle_101231(regs
); break;
1009 case 0x32: handle_101232(regs
); break;
1010 case 0x33: handle_101233(regs
); break;
1011 case 0x34: handle_101234(regs
); break;
1012 case 0x35: handle_101235(regs
); break;
1013 case 0x36: handle_101236(regs
); break;
1014 default: handle_1012XX(regs
); break;
1017 // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
1022 static void noinline
1023 handle_1013(struct bregs
*regs
)
1025 struct cursorpos cp
= {regs
->dl
, regs
->dh
, regs
->bh
};
1026 // if row=0xff special case : use current cursor position
1028 cp
= get_cursor_pos(cp
.page
);
1031 write_attr_string(&cp
, regs
->cx
, regs
->es
, (void*)(regs
->bp
+ 0));
1033 write_string(&cp
, regs
->bl
, regs
->cx
, regs
->es
, (void*)(regs
->bp
+ 0));
1041 handle_101a00(struct bregs
*regs
)
1043 regs
->bx
= GET_BDA(dcc_index
);
1048 handle_101a01(struct bregs
*regs
)
1050 SET_BDA(dcc_index
, regs
->bl
);
1051 dprintf(1, "Alternate Display code (%02x) was discarded\n", regs
->bh
);
1056 handle_101aXX(struct bregs
*regs
)
1062 handle_101a(struct bregs
*regs
)
1065 case 0x00: handle_101a00(regs
); break;
1066 case 0x01: handle_101a01(regs
); break;
1067 default: handle_101aXX(regs
); break;
1073 u16 static_functionality_off
;
1074 u16 static_functionality_seg
;
1094 handle_101b(struct bregs
*regs
)
1097 struct funcInfo
*info
= (void*)(regs
->di
+0);
1098 memset_far(seg
, info
, 0, sizeof(*info
));
1099 // Address of static functionality table
1100 SET_FARVAR(seg
, info
->static_functionality_off
, (u32
)static_functionality
);
1101 SET_FARVAR(seg
, info
->static_functionality_seg
, get_global_seg());
1103 // Hard coded copy from BIOS area. Should it be cleaner ?
1104 memcpy_far(seg
, info
->bda_0x49
, SEG_BDA
, (void*)0x49
1105 , sizeof(info
->bda_0x49
));
1106 memcpy_far(seg
, info
->bda_0x84
, SEG_BDA
, (void*)0x84
1107 , sizeof(info
->bda_0x84
));
1109 SET_FARVAR(seg
, info
->dcc_index
, GET_BDA(dcc_index
));
1110 SET_FARVAR(seg
, info
->colors
, 16);
1111 SET_FARVAR(seg
, info
->pages
, 8);
1112 SET_FARVAR(seg
, info
->scan_lines
, 2);
1113 SET_FARVAR(seg
, info
->video_mem
, 3);
1119 handle_101c00(struct bregs
*regs
)
1121 u16 flags
= regs
->cx
;
1124 size
+= sizeof(struct saveVideoHardware
);
1126 size
+= sizeof(struct saveBDAstate
);
1128 size
+= sizeof(struct saveDACcolors
);
1134 handle_101c01(struct bregs
*regs
)
1136 u16 flags
= regs
->cx
;
1138 void *data
= (void*)(regs
->bx
+0);
1140 vgahw_save_state(seg
, data
);
1141 data
+= sizeof(struct saveVideoHardware
);
1144 save_bda_state(seg
, data
);
1145 data
+= sizeof(struct saveBDAstate
);
1148 vgahw_save_dac_state(seg
, data
);
1153 handle_101c02(struct bregs
*regs
)
1155 u16 flags
= regs
->cx
;
1157 void *data
= (void*)(regs
->bx
+0);
1159 vgahw_restore_state(seg
, data
);
1160 data
+= sizeof(struct saveVideoHardware
);
1163 restore_bda_state(seg
, data
);
1164 data
+= sizeof(struct saveBDAstate
);
1167 vgahw_restore_dac_state(seg
, data
);
1172 handle_101cXX(struct bregs
*regs
)
1178 handle_101c(struct bregs
*regs
)
1181 case 0x00: handle_101c00(regs
); break;
1182 case 0x01: handle_101c01(regs
); break;
1183 case 0x02: handle_101c02(regs
); break;
1184 default: handle_101cXX(regs
); break;
1190 handle_104f00(struct bregs
*regs
)
1192 // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
1193 // XXX - OR cirrus_vesa_00h
1197 handle_104f01(struct bregs
*regs
)
1199 // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
1200 // XXX - OR cirrus_vesa_01h
1204 handle_104f02(struct bregs
*regs
)
1206 // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
1207 // XXX - OR cirrus_vesa_02h
1211 handle_104f03(struct bregs
*regs
)
1213 // XXX - vbe_biosfn_return_current_mode
1214 // XXX - OR cirrus_vesa_03h
1218 handle_104f04(struct bregs
*regs
)
1220 // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
1224 handle_104f05(struct bregs
*regs
)
1226 // XXX - vbe_biosfn_display_window_control
1227 // XXX - OR cirrus_vesa_05h
1231 handle_104f06(struct bregs
*regs
)
1233 // XXX - vbe_biosfn_set_get_logical_scan_line_length
1234 // XXX - OR cirrus_vesa_06h
1238 handle_104f07(struct bregs
*regs
)
1240 // XXX - vbe_biosfn_set_get_display_start
1241 // XXX - OR cirrus_vesa_07h
1245 handle_104f08(struct bregs
*regs
)
1247 // XXX - vbe_biosfn_set_get_dac_palette_format
1251 handle_104f0a(struct bregs
*regs
)
1253 // XXX - vbe_biosfn_return_protected_mode_interface
1257 handle_104fXX(struct bregs
*regs
)
1264 handle_104f(struct bregs
*regs
)
1266 if (! CONFIG_VBE
|| !vbe_has_vbe_display()) {
1267 handle_104fXX(regs
);
1272 case 0x00: handle_104f00(regs
); break;
1273 case 0x01: handle_104f01(regs
); break;
1274 case 0x02: handle_104f02(regs
); break;
1275 case 0x03: handle_104f03(regs
); break;
1276 case 0x04: handle_104f04(regs
); break;
1277 case 0x05: handle_104f05(regs
); break;
1278 case 0x06: handle_104f06(regs
); break;
1279 case 0x07: handle_104f07(regs
); break;
1280 case 0x08: handle_104f08(regs
); break;
1281 case 0x0a: handle_104f0a(regs
); break;
1282 default: handle_104fXX(regs
); break;
1288 handle_10XX(struct bregs
*regs
)
1293 // INT 10h Video Support Service Entry Point
1295 handle_10(struct bregs
*regs
)
1297 debug_enter(regs
, DEBUG_VGA_10
);
1299 case 0x00: handle_1000(regs
); break;
1300 case 0x01: handle_1001(regs
); break;
1301 case 0x02: handle_1002(regs
); break;
1302 case 0x03: handle_1003(regs
); break;
1303 case 0x04: handle_1004(regs
); break;
1304 case 0x05: handle_1005(regs
); break;
1305 case 0x06: handle_1006(regs
); break;
1306 case 0x07: handle_1007(regs
); break;
1307 case 0x08: handle_1008(regs
); break;
1308 case 0x09: handle_1009(regs
); break;
1309 case 0x0a: handle_100a(regs
); break;
1310 case 0x0b: handle_100b(regs
); break;
1311 case 0x0c: handle_100c(regs
); break;
1312 case 0x0d: handle_100d(regs
); break;
1313 case 0x0e: handle_100e(regs
); break;
1314 case 0x0f: handle_100f(regs
); break;
1315 case 0x10: handle_1010(regs
); break;
1316 case 0x11: handle_1011(regs
); break;
1317 case 0x12: handle_1012(regs
); break;
1318 case 0x13: handle_1013(regs
); break;
1319 case 0x1a: handle_101a(regs
); break;
1320 case 0x1b: handle_101b(regs
); break;
1321 case 0x1c: handle_101c(regs
); break;
1322 case 0x4f: handle_104f(regs
); break;
1323 default: handle_10XX(regs
); break;
1328 /****************************************************************
1330 ****************************************************************/
1333 init_bios_area(void)
1335 // init detected hardware BIOS Area
1336 // set 80x25 color (not clear from RBIL but usual)
1337 u16 eqf
= GET_BDA(equipment_list_flags
);
1338 SET_BDA(equipment_list_flags
, (eqf
& 0xffcf) | 0x20);
1340 // Just for the first int10 find its children
1342 // the default char height
1343 SET_BDA(char_height
, 0x10);
1346 SET_BDA(video_ctl
, 0x60);
1348 // Set the basic screen we have
1349 SET_BDA(video_switches
, 0xf9);
1351 // Set the basic modeset options
1352 SET_BDA(modeset_ctl
, 0x51);
1354 // Set the default MSR
1355 SET_BDA(video_msr
, 0x09);
1359 vga_post(struct bregs
*regs
)
1361 debug_enter(regs
, DEBUG_VGA_POST
);
1370 extern void entry_10(void);
1371 SET_IVT(0x10, SEGOFF(get_global_seg(), (u32
)entry_10
));
1376 // XXX - clear screen and display info
1379 SET_VGA(video_save_pointer_table
[0], (u32
)video_param_table
);
1380 SET_VGA(video_save_pointer_table
[1], get_global_seg());
1383 extern u8 _rom_header_size
, _rom_header_checksum
;
1384 SET_VGA(_rom_header_checksum
, 0);
1385 u8 sum
= -checksum_far(get_global_seg(), 0, _rom_header_size
* 512);
1386 SET_VGA(_rom_header_checksum
, sum
);