- functions biosfn_get_video_mode() and biosfn_read_display_code() rewritten
[vgabios.git] / vgabios.c
blob0fd69f8720cfdfea4224a819d7bb46c5e4aa2cbe
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // ============================================================================================
24 //
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
27 //
28 // ============================================================================================
29 //
30 // This file contains code ripped from :
31 // - rombios.c of plex86
33 // This VGA Bios contains fonts from :
34 // - fntcol16.zip (c) by Joseph Gil avalable at :
35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36 // These fonts are public domain
38 // This VGA Bios is based on information taken from :
39 // - Kevin Lawton's vga card emulation for bochs/plex86
40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42 // - Michael Abrash's Graphics Programming Black Book
43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44 // - DOSEMU 1.0.1 source code for several tables values and formulas
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
49 // ============================================================================================
51 #include "vgabios.h"
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
57 /* Declares */
58 static Bit8u read_byte();
59 static Bit16u read_word();
60 static void write_byte();
61 static void write_word();
62 static Bit8u inb();
63 static Bit16u inw();
64 static void outb();
65 static void outw();
67 static Bit16u get_SS();
69 // Output
70 static void printf();
71 static void unimplemented();
72 static void unknown();
74 static void init_vga_card();
75 static void init_bios_area();
77 static Bit8u find_vga_entry();
79 static void memsetb();
80 static void memsetw();
81 static void memcpyb();
82 static void memcpyw();
84 static void biosfn_set_video_mode();
85 static void biosfn_set_cursor_shape();
86 static void biosfn_set_cursor_pos();
87 static void biosfn_get_cursor_pos();
88 static void biosfn_set_active_page();
89 static void biosfn_scroll();
90 static void biosfn_read_char_attr();
91 static void biosfn_write_char_attr();
92 static void biosfn_write_char_only();
93 static void biosfn_set_border_color();
94 static void biosfn_set_palette();
95 static void biosfn_write_pixel();
96 static void biosfn_read_pixel();
97 static void biosfn_write_teletype();
98 static void biosfn_set_single_palette_reg();
99 static void biosfn_set_overscan_border_color();
100 static void biosfn_set_all_palette_reg();
101 static void biosfn_toggle_intensity();
102 static void biosfn_get_single_palette_reg();
103 static void biosfn_read_overscan_border_color();
104 static void biosfn_get_all_palette_reg();
105 static void biosfn_set_single_dac_reg();
106 static void biosfn_set_all_dac_reg();
107 static void biosfn_select_video_dac_color_page();
108 static void biosfn_read_single_dac_reg();
109 static void biosfn_read_all_dac_reg();
110 static void biosfn_set_pel_mask();
111 static void biosfn_read_pel_mask();
112 static void biosfn_read_video_dac_state();
113 static void biosfn_perform_gray_scale_summing();
114 static void biosfn_load_text_user_pat();
115 static void biosfn_load_text_8_14_pat();
116 static void biosfn_load_text_8_8_pat();
117 static void biosfn_set_text_block_specifier();
118 static void biosfn_load_text_8_16_pat();
119 static void biosfn_load_gfx_8_8_chars();
120 static void biosfn_load_gfx_user_chars();
121 static void biosfn_load_gfx_8_14_chars();
122 static void biosfn_load_gfx_8_8_dd_chars();
123 static void biosfn_load_gfx_8_16_chars();
124 static void biosfn_get_font_info();
125 static void biosfn_get_ega_info();
126 static void biosfn_alternate_prtsc();
127 static void biosfn_select_vert_res();
128 static void biosfn_enable_default_palette_loading();
129 static void biosfn_enable_video_addressing();
130 static void biosfn_enable_grayscale_summing();
131 static void biosfn_enable_cursor_emulation();
132 static void biosfn_switch_video_interface();
133 static void biosfn_enable_video_refresh_control();
134 static void biosfn_write_string();
135 static void biosfn_set_display_code();
136 static void biosfn_read_state_info();
137 static void biosfn_read_video_state_size();
138 static void biosfn_save_video_state();
139 static void biosfn_restore_video_state();
141 // This is for compiling with gcc2 and gcc3
142 #define ASM_START #asm
143 #define ASM_END #endasm
145 ASM_START
147 biosmem_seg = 0x40
148 biosmem_current_mode = 0x49
149 biosmem_nb_cols = 0x4a
150 biosmem_current_page = 0x62
151 biosmem_video_ctl = 0x87
152 biosmem_dcc_index = 0x8a
154 MACRO SET_INT_VECTOR
155 push ds
156 xor ax, ax
157 mov ds, ax
158 mov ax, ?3
159 mov ?1*4, ax
160 mov ax, ?2
161 mov ?1*4+2, ax
162 pop ds
163 MEND
165 ASM_END
167 ASM_START
168 .text
169 .rom
170 .org 0
172 use16 386
174 vgabios_start:
175 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
177 .byte 0x40 /* BIOS extension length in units of 512 bytes */
180 vgabios_entry_point:
182 jmp vgabios_init_func
184 vgabios_name:
185 .ascii "Plex86/Bochs VGABios"
186 .ascii " "
187 .byte 0x00
189 // Info from Bart Oldeman
190 .org 0x1e
191 .ascii "IBM"
192 .byte 0x00
194 vgabios_version:
195 #ifndef VGABIOS_VERS
196 .ascii "current-cvs"
197 #else
198 .ascii VGABIOS_VERS
199 #endif
200 .ascii " "
202 vgabios_date:
203 .ascii VGABIOS_DATE
204 .byte 0x0a,0x0d
205 .byte 0x00
207 vgabios_copyright:
208 .ascii "(C) 2003 the LGPL VGABios developers Team"
209 .byte 0x0a,0x0d
210 .byte 0x00
212 vgabios_license:
213 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
214 .byte 0x0a,0x0d
215 .byte 0x0a,0x0d
216 .byte 0x00
218 vgabios_website:
219 .ascii "Please visit :"
220 .byte 0x0a,0x0d
221 ;;.ascii " . http://www.plex86.org"
222 ;;.byte 0x0a,0x0d
223 .ascii " . http://bochs.sourceforge.net"
224 .byte 0x0a,0x0d
225 .ascii " . http://www.nongnu.org/vgabios"
226 .byte 0x0a,0x0d
227 .byte 0x0a,0x0d
228 .byte 0x00
231 ;; ============================================================================================
233 ;; Init Entry point
235 ;; ============================================================================================
236 vgabios_init_func:
238 ;; init vga card
239 call _init_vga_card
241 ;; init basic bios vars
242 call _init_bios_area
244 #ifdef VBE
245 ;; init vbe functions
246 call _vbe_init
247 #endif
249 ;; set int10 vect
250 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
252 ;; display splash screen
253 call _display_splash_screen
255 ;; init video mode and clear the screen
256 mov ax,#0x0003
257 int #0x10
259 ;; show info
260 call _display_info
262 #ifdef VBE
263 ;; show vbe info
264 call _vbe_display_info
265 #endif
268 retf
269 ASM_END
272 * int10 handled here
274 ASM_START
275 vgabios_int10_handler:
276 pushf
277 cmp ah, #0x0f
278 jne int10_l1
279 call biosfn_get_video_mode
280 jmp int10_end
281 int10_l1:
282 cmp ax, #0x1a00
283 jne int10_normal
284 call biosfn_read_display_code
285 jmp int10_end
287 int10_normal:
288 push es
289 push ds
290 pusha
292 ;; We have to set ds to access the right data segment
293 mov bx, #0xc000
294 mov ds, bx
295 call _int10_func
297 popa
298 pop ds
299 pop es
300 int10_end:
301 popf
302 iret
303 ASM_END
305 #include "vgatables.h"
306 #include "vgafonts.h"
309 * Boot time harware inits
311 static void init_vga_card()
313 ASM_START
314 ;; switch to color mode and enable CPU access 480 lines
315 mov dx, #0x3C2
316 mov al, #0xC3
317 outb dx,al
319 ;; more than 64k 3C4/04
320 mov dx, #0x3C4
321 mov al, #0x04
322 outb dx,al
325 mov dx, #0x3C5
326 mov al, #0x02
327 outb dx,al
329 ASM_END
331 printf("VGABios $Id$\n");
334 // --------------------------------------------------------------------------------------------
336 * Boot time bios area inits
338 static void init_bios_area()
340 // init detected hardware BIOS Area
341 write_word(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,read_word(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0xFFCF);
343 // Just for the first int10 find its children
345 // the default chat height
346 write_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16);
348 // Clear the screen
349 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,0x60);
351 // Set the basic screen we have
352 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
354 // Set the basic modeset options
355 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,0x51);
357 // Set the default MSR
358 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x09);
361 // --------------------------------------------------------------------------------------------
363 * Boot time Splash screen
365 static void display_splash_screen()
369 // --------------------------------------------------------------------------------------------
371 * Tell who we are
374 static void display_info()
376 ASM_START
377 mov ax,#0xc000
378 mov ds,ax
379 mov si,#vgabios_name
380 call _display_string
381 mov si,#vgabios_version
382 call _display_string
384 ;;mov si,#vgabios_copyright
385 ;;call _display_string
386 ;;mov si,#crlf
387 ;;call _display_string
389 mov si,#vgabios_license
390 call _display_string
391 mov si,#vgabios_website
392 call _display_string
393 ASM_END
396 static void display_string()
398 // Get length of string
399 ASM_START
400 mov ax,ds
401 mov es,ax
402 mov di,si
403 xor cx,cx
404 not cx
405 xor al,al
407 repne
408 scasb
409 not cx
410 dec cx
411 push cx
413 mov ax,#0x0300
414 mov bx,#0x0000
415 int #0x10
417 pop cx
418 mov ax,#0x1301
419 mov bx,#0x000b
420 mov bp,si
421 int #0x10
422 ASM_END
425 // --------------------------------------------------------------------------------------------
427 // --------------------------------------------------------------------------------------------
429 * int10 main dispatcher
431 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
432 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
434 #ifdef DEBUG
435 // 0E is write char...
436 if(GET_AH()!=0x0E)
437 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
438 #endif
440 // BIOS functions
441 switch(GET_AH())
443 case 0x00:
444 biosfn_set_video_mode(GET_AL());
445 switch(GET_AL()&0x7F)
446 {case 6:
447 SET_AL(0x3F);
448 break;
449 case 0:
450 case 1:
451 case 2:
452 case 3:
453 case 4:
454 case 5:
455 case 7:
456 SET_AL(0x30);
457 break;
458 default:
459 SET_AL(0x20);
461 break;
462 case 0x01:
463 biosfn_set_cursor_shape(GET_CH(),GET_CL());
464 break;
465 case 0x02:
466 biosfn_set_cursor_pos(GET_BH(),DX);
467 break;
468 case 0x03:
469 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
470 break;
471 case 0x04:
472 // Read light pen pos (unimplemented)
473 #ifdef DEBUG
474 unimplemented();
475 #endif
476 AX=0x00;
477 BX=0x00;
478 CX=0x00;
479 DX=0x00;
480 break;
481 case 0x05:
482 biosfn_set_active_page(GET_AL());
483 break;
484 case 0x06:
485 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
486 break;
487 case 0x07:
488 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
489 break;
490 case 0x08:
491 biosfn_read_char_attr(GET_BH(),&AX);
492 break;
493 case 0x09:
494 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
495 break;
496 case 0x0A:
497 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
498 break;
499 case 0x0B:
500 if(GET_BH()==0x00)
501 biosfn_set_border_color(GET_BL());
502 else
503 biosfn_set_palette(GET_BL());
504 break;
505 case 0x0C:
506 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
507 break;
508 case 0x0D:
509 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
510 break;
511 case 0x0E:
512 // Ralf Brown Interrupt list is WRONG on bh(page)
513 // We do output only on the current page !
514 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
515 break;
516 case 0x10:
517 switch(GET_AL())
519 case 0x00:
520 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
521 break;
522 case 0x01:
523 biosfn_set_overscan_border_color(GET_BH());
524 break;
525 case 0x02:
526 biosfn_set_all_palette_reg(ES,DX);
527 break;
528 case 0x03:
529 biosfn_toggle_intensity(GET_BL());
530 break;
531 case 0x07:
532 biosfn_get_single_palette_reg(GET_BL(),&BX);
533 break;
534 case 0x08:
535 biosfn_read_overscan_border_color(&BX);
536 break;
537 case 0x09:
538 biosfn_get_all_palette_reg(ES,DX);
539 break;
540 case 0x10:
541 biosfn_set_single_dac_reg(BX,GET_CH(),GET_CL(),GET_DH());
542 break;
543 case 0x12:
544 biosfn_set_all_dac_reg(BX,CX,ES,DX);
545 break;
546 case 0x13:
547 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
548 break;
549 case 0x15:
550 biosfn_read_single_dac_reg(GET_BL(),&DX,&CX);
551 break;
552 case 0x17:
553 biosfn_read_all_dac_reg(BX,CX,ES,DX);
554 break;
555 case 0x18:
556 biosfn_set_pel_mask(GET_BL());
557 break;
558 case 0x19:
559 biosfn_read_pel_mask(&BX);
560 break;
561 case 0x1A:
562 biosfn_read_video_dac_state(&BX);
563 break;
564 case 0x1B:
565 biosfn_perform_gray_scale_summing(BX,CX);
566 break;
567 #ifdef DEBUG
568 default:
569 unknown();
570 #endif
572 break;
573 case 0x11:
574 switch(GET_AL())
576 case 0x00:
577 case 0x10:
578 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
579 break;
580 case 0x01:
581 case 0x11:
582 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
583 break;
584 case 0x02:
585 case 0x12:
586 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
587 break;
588 case 0x03:
589 biosfn_set_text_block_specifier(GET_BL());
590 break;
591 case 0x04:
592 case 0x14:
593 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
594 break;
595 case 0x20:
596 biosfn_load_gfx_8_8_chars(ES,BP);
597 break;
598 case 0x21:
599 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
600 break;
601 case 0x22:
602 biosfn_load_gfx_8_14_chars(GET_BL());
603 break;
604 case 0x23:
605 biosfn_load_gfx_8_8_dd_chars(GET_BL());
606 break;
607 case 0x24:
608 biosfn_load_gfx_8_16_chars(GET_BL());
609 break;
610 case 0x30:
611 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
612 break;
613 #ifdef DEBUG
614 default:
615 unknown();
616 #endif
619 break;
620 case 0x12:
621 switch(GET_BL())
623 case 0x10:
624 biosfn_get_ega_info(&BX,&CX);
625 break;
626 case 0x20:
627 biosfn_alternate_prtsc();
628 break;
629 case 0x30:
630 biosfn_select_vert_res(GET_AL());
631 SET_AL(0x12);
632 break;
633 case 0x31:
634 biosfn_enable_default_palette_loading(GET_AL());
635 SET_AL(0x12);
636 break;
637 case 0x32:
638 biosfn_enable_video_addressing(GET_AL());
639 SET_AL(0x12);
640 break;
641 case 0x33:
642 biosfn_enable_grayscale_summing(GET_AL());
643 SET_AL(0x12);
644 break;
645 case 0x34:
646 biosfn_enable_cursor_emulation(GET_AL());
647 SET_AL(0x12);
648 break;
649 case 0x35:
650 biosfn_switch_video_interface(GET_AL(),ES,DX);
651 SET_AL(0x12);
652 break;
653 case 0x36:
654 biosfn_enable_video_refresh_control(GET_AL());
655 SET_AL(0x12);
656 break;
657 #ifdef DEBUG
658 default:
659 unknown();
660 #endif
662 break;
663 case 0x13:
664 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
665 break;
666 case 0x1A:
667 switch(GET_AL())
669 case 0x01:
670 biosfn_set_display_code(GET_BL(),GET_BH());
671 break;
672 #ifdef DEBUG
673 default:
674 unknown();
675 #endif
677 SET_AL(0x1A);
678 break;
679 case 0x1B:
680 biosfn_read_state_info(BX,ES,DI);
681 SET_AL(0x1B);
682 break;
683 case 0x1C:
684 switch(GET_AL())
686 case 0x00:
687 biosfn_read_video_state_size(CX,&BX);
688 break;
689 case 0x01:
690 biosfn_save_video_state(CX,ES,BX);
691 break;
692 case 0x02:
693 biosfn_restore_video_state(CX,ES,BX);
694 break;
695 #ifdef DEBUG
696 default:
697 unknown();
698 #endif
700 SET_AL(0x1C);
701 break;
703 #ifdef VBE
704 case 0x4f:
705 if (vbe_has_vbe_display()) {
706 switch(GET_AL())
708 case 0x00:
709 vbe_biosfn_return_controller_information(&AX,ES,DI);
710 break;
711 case 0x01:
712 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
713 break;
714 case 0x02:
715 vbe_biosfn_set_mode(&AX,BX,ES,DI);
716 break;
717 case 0x03:
718 vbe_biosfn_return_current_mode(&AX,&BX);
719 break;
720 case 0x04:
721 //FIXME
722 #ifdef DEBUG
723 unimplemented();
724 #endif
725 // function failed
726 AX=0x100;
727 break;
728 case 0x05:
729 vbe_biosfn_display_window_control(&AX,BX,&DX);
730 break;
731 case 0x06:
732 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
733 break;
734 case 0x07:
735 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
736 break;
737 case 0x08:
738 //FIXME
739 #ifdef DEBUG
740 unimplemented();
741 #endif
742 // function failed
743 AX=0x100;
744 break;
745 case 0x09:
746 //FIXME
747 #ifdef DEBUG
748 unimplemented();
749 #endif
750 // function failed
751 AX=0x100;
752 break;
753 case 0x0A:
754 //FIXME
755 #ifdef DEBUG
756 unimplemented();
757 #endif
758 // function failed
759 AX=0x100;
760 break;
761 #ifdef DEBUG
762 default:
763 unknown();
764 #endif
765 // function failed
766 AX=0x100;
769 else {
770 // No VBE display
771 AX=0x0100;
773 break;
774 #endif
776 #ifdef DEBUG
777 default:
778 unknown();
779 #endif
783 // ============================================================================================
785 // BIOS functions
787 // ============================================================================================
789 static void biosfn_set_video_mode(mode) Bit8u mode;
790 {// mode: Bit 7 is 1 if no clear screen
792 // Should we clear the screen ?
793 Bit8u noclearmem=mode&0x80;
794 Bit8u line,mmask,*palette;
795 Bit16u i,twidth,theight,cheight;
796 Bit8u modeset_ctl,video_ctl,vga_switches;
797 Bit16u crtc_addr;
799 #ifdef VBE
800 if (vbe_has_vbe_display()) {
801 dispi_set_enable(VBE_DISPI_DISABLED);
803 #endif // def VBE
805 // The real mode
806 mode=mode&0x7f;
808 // find the entry in the video modes
809 line=find_vga_entry(mode);
811 #ifdef DEBUG
812 printf("mode search %02x found line %02x\n",mode,line);
813 #endif
815 if(line==0xFF)
816 return;
818 twidth=vga_modes[line].twidth;
819 theight=vga_modes[line].theight;
820 cheight=vga_modes[line].cheight;
822 // Read the bios vga control
823 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
825 // Read the bios vga switches
826 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
828 // Read the bios mode set control
829 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
831 // Then we know the number of lines
832 // FIXME
834 // if palette loading (bit 3 of modeset ctl = 0)
835 if((modeset_ctl&0x08)==0)
836 {// Set the PEL mask
837 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
839 // Set the whole dac always, from 0
840 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
842 // From which palette
843 switch(vga_modes[line].dacmodel)
844 {case 0:
845 palette=&palette0;
846 break;
847 case 1:
848 palette=&palette1;
849 break;
850 case 2:
851 palette=&palette2;
852 break;
853 case 3:
854 palette=&palette3;
855 break;
859 // Always 256*3 values
860 for(i=0;i<0x0100;i++)
861 {if(i<=dac_regs[vga_modes[line].dacmodel])
862 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
863 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
864 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
866 else
867 {outb(VGAREG_DAC_DATA,0);
868 outb(VGAREG_DAC_DATA,0);
869 outb(VGAREG_DAC_DATA,0);
873 // Reset Attribute Ctl flip-flop
874 inb(VGAREG_ACTL_RESET);
876 // Set Attribute Ctl
877 for(i=0;i<=ACTL_MAX_REG;i++)
878 {outb(VGAREG_ACTL_ADDRESS,i);
879 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
882 // Set Sequencer Ctl
883 for(i=0;i<=SEQU_MAX_REG;i++)
884 {outb(VGAREG_SEQU_ADDRESS,i);
885 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
888 // Set Grafx Ctl
889 for(i=0;i<=GRDC_MAX_REG;i++)
890 {outb(VGAREG_GRDC_ADDRESS,i);
891 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
894 // Set CRTC address VGA or MDA
895 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
897 // Set CRTC regs
898 for(i=0;i<=CRTC_MAX_REG;i++)
899 {outb(crtc_addr,i);
900 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
903 // Set the misc register
904 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
906 // Enable video
907 outb(VGAREG_ACTL_ADDRESS,0x20);
908 inb(VGAREG_ACTL_RESET);
910 if(noclearmem==0x00)
912 if(vga_modes[line].class==TEXT)
914 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
916 else
918 if(mode<0x0d)
920 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
922 else
924 outb( VGAREG_SEQU_ADDRESS, 0x02 );
925 mmask = inb( VGAREG_SEQU_DATA );
926 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
927 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
928 outb( VGAREG_SEQU_DATA, mmask );
933 // Set the BIOS mem
934 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
935 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
936 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
937 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
938 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
939 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
940 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
941 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
942 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
944 // FIXME We nearly have the good tables. to be reworked
945 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
946 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
947 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
949 // FIXME
950 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
951 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
953 // Set cursor shape
954 if(vga_modes[line].class==TEXT)
956 biosfn_set_cursor_shape(0x06,0x07);
959 // Set cursor pos for page 0..7
960 for(i=0;i<8;i++)
961 biosfn_set_cursor_pos(i,0x0000);
963 // Set active page 0
964 biosfn_set_active_page(0x00);
966 // Write the fonts in memory
967 if(vga_modes[line].class==TEXT)
969 ASM_START
970 ;; copy and activate 8x16 font
971 mov ax, #0x1104
972 mov bl, #0x00
973 int #0x10
974 mov ax, #0x1103
975 mov bl, #0x00
976 int #0x10
977 ASM_END
980 // Set the ints 0x1F and 0x43
981 ASM_START
982 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
983 ASM_END
985 switch(cheight)
986 {case 8:
987 ASM_START
988 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
989 ASM_END
990 break;
991 case 14:
992 ASM_START
993 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
994 ASM_END
995 break;
996 case 16:
997 ASM_START
998 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
999 ASM_END
1000 break;
1004 // --------------------------------------------------------------------------------------------
1005 static void biosfn_set_cursor_shape (CH,CL)
1006 Bit8u CH;Bit8u CL;
1007 {Bit16u cheight,curs,crtc_addr;
1009 CH&=0x3f;
1010 CL&=0x1f;
1012 curs=(CH<<8)+CL;
1013 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1015 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1016 if((cheight>8) && (CL<8) && (CH<0x20))
1018 if(CL!=(CH+1))
1020 CH = ((CH+1) * cheight / 8) -1;
1022 else
1024 CH = ((CL+1) * cheight / 8) - 2;
1026 CL = ((CL+1) * cheight / 8) - 1;
1029 // CTRC regs 0x0a and 0x0b
1030 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1031 outb(crtc_addr,0x0a);
1032 outb(crtc_addr+1,CH);
1033 outb(crtc_addr,0x0b);
1034 outb(crtc_addr+1,CL);
1037 // --------------------------------------------------------------------------------------------
1038 static void biosfn_set_cursor_pos (page, cursor)
1039 Bit8u page;Bit16u cursor;
1041 Bit8u xcurs,ycurs,current;
1042 Bit16u nbcols,nbrows,address,crtc_addr;
1044 // Should not happen...
1045 if(page>7)return;
1047 // Bios cursor pos
1048 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1050 // Set the hardware cursor
1051 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1052 if(page==current)
1054 // Get the dimensions
1055 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1056 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1058 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1060 // Calculate the address knowing nbcols nbrows and page num
1061 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1063 // CRTC regs 0x0e and 0x0f
1064 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1065 outb(crtc_addr,0x0e);
1066 outb(crtc_addr+1,(address&0xff00)>>8);
1067 outb(crtc_addr,0x0f);
1068 outb(crtc_addr+1,address&0x00ff);
1072 // --------------------------------------------------------------------------------------------
1073 static void biosfn_get_cursor_pos (page,shape, pos)
1074 Bit8u page;Bit16u *shape;Bit16u *pos;
1076 Bit16u ss=get_SS();
1078 // Default
1079 write_word(ss, shape, 0);
1080 write_word(ss, pos, 0);
1082 if(page>7)return;
1083 // FIXME should handle VGA 14/16 lines
1084 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1085 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1088 // --------------------------------------------------------------------------------------------
1089 static void biosfn_set_active_page (page)
1090 Bit8u page;
1092 Bit16u cursor,dummy,crtc_addr;
1093 Bit16u nbcols,nbrows,address;
1094 Bit8u mode,line;
1096 if(page>7)return;
1098 // Get the mode
1099 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1100 line=find_vga_entry(mode);
1101 if(line==0xFF)return;
1103 // Get pos curs pos for the right page
1104 biosfn_get_cursor_pos(page,&dummy,&cursor);
1106 if(vga_modes[line].class==TEXT)
1108 // Get the dimensions
1109 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1110 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1112 // Calculate the address knowing nbcols nbrows and page num
1113 address=SCREEN_MEM_START(nbcols,nbrows,page);
1114 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1116 // Start address
1117 address=SCREEN_IO_START(nbcols,nbrows,page);
1119 else
1121 address = page*vga_modes[line].slength;
1124 // CRTC regs 0x0c and 0x0d
1125 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1126 outb(crtc_addr,0x0c);
1127 outb(crtc_addr+1,(address&0xff00)>>8);
1128 outb(crtc_addr,0x0d);
1129 outb(crtc_addr+1,address&0x00ff);
1131 // And change the BIOS page
1132 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1134 #ifdef DEBUG
1135 printf("Set active page %02x address %04x\n",page,address);
1136 #endif
1138 // Display the cursor, now the page is active
1139 biosfn_set_cursor_pos(page,cursor);
1142 // --------------------------------------------------------------------------------------------
1143 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1144 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1146 // page == 0xFF if current
1148 Bit8u mode,line;
1149 Bit16u nbcols,nbrows,i;
1150 Bit16u address;
1152 if(rul>rlr)return;
1153 if(cul>clr)return;
1155 // Get the mode
1156 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1157 line=find_vga_entry(mode);
1158 if(line==0xFF)return;
1160 // Get the dimensions
1161 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1162 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1164 // Get the current page
1165 if(page==0xFF)
1166 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1168 if(vga_modes[line].class==TEXT)
1170 // Compute the address
1171 address=SCREEN_MEM_START(nbcols,nbrows,page);
1172 #ifdef DEBUG
1173 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1174 #endif
1176 if(rlr>=nbrows)rlr=nbrows-1;
1177 if(clr>=nbcols)clr=nbcols-1;
1178 if(nblines>nbrows)nblines=0;
1180 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1182 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1184 else
1185 {// if Scroll up
1186 if(dir==SCROLL_UP)
1187 {for(i=rul;i<=rlr;i++)
1189 if((i+nblines>rlr)||(nblines==0))
1190 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1191 else
1192 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1195 else
1196 {for(i=rlr;i>=rul;i--)
1198 if((i<rul+nblines)||(nblines==0))
1199 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1200 else
1201 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1206 else
1208 // FIXME gfx mode
1209 #ifdef DEBUG
1210 printf("Scroll in graphics mode ");
1211 unimplemented();
1212 #endif
1216 // --------------------------------------------------------------------------------------------
1217 static void biosfn_read_char_attr (page,car)
1218 Bit8u page;Bit16u *car;
1219 {Bit16u ss=get_SS();
1220 Bit8u xcurs,ycurs,mode,line;
1221 Bit16u nbcols,nbrows,address;
1222 Bit16u cursor,dummy;
1224 // Get the mode
1225 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1226 line=find_vga_entry(mode);
1227 if(line==0xFF)return;
1229 // Get the cursor pos for the page
1230 biosfn_get_cursor_pos(page,&dummy,&cursor);
1231 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1233 // Get the dimensions
1234 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1235 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1237 if(vga_modes[line].class==TEXT)
1239 // Compute the address
1240 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1242 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1244 else
1246 // FIXME gfx mode
1247 #ifdef DEBUG
1248 unimplemented();
1249 #endif
1253 // --------------------------------------------------------------------------------------------
1254 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1255 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1257 Bit8u i,mmask;
1258 Bit8u *fdata;
1259 Bit16u addr,dest,src;
1261 switch(cheight)
1262 {case 14:
1263 fdata = &vgafont14;
1264 break;
1265 case 16:
1266 fdata = &vgafont16;
1267 break;
1268 default:
1269 fdata = &vgafont8;
1271 addr=xcurs+ycurs*cheight*nbcols;
1272 src = car * cheight;
1273 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1274 mmask = inb( VGAREG_SEQU_DATA );
1275 for(i=0;i<cheight;i++)
1277 dest=addr+i*nbcols;
1278 outb( VGAREG_SEQU_DATA, 0x0f );
1279 write_byte(0xa000,dest,0x00);
1280 outb( VGAREG_SEQU_DATA, attr & 0x0f );
1281 write_byte(0xa000,dest,fdata[src+i]);
1283 outb( VGAREG_SEQU_DATA, mmask );
1286 // --------------------------------------------------------------------------------------------
1287 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1288 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1290 Bit8u i,j,mask,data;
1291 Bit8u *fdata;
1292 Bit16u addr,dest,src;
1294 fdata = &vgafont8;
1295 addr=(xcurs*bpp)+ycurs*320;
1296 src = car * 8;
1297 for(i=0;i<8;i++)
1299 dest=addr+(i>>1)*80;
1300 if (i & 1) dest += 0x2000;
1301 mask = 0x80;
1302 if (bpp == 1)
1304 if (attr & 0x80)
1306 data = read_byte(0xb800,dest);
1308 else
1310 data = 0x00;
1312 for(j=0;j<8;j++)
1314 if (fdata[src+i] & mask)
1316 if (attr & 0x80)
1318 data ^= (attr & 0x01) << (7-j);
1320 else
1322 data |= (attr & 0x01) << (7-j);
1325 mask >>= 1;
1327 write_byte(0xb800,dest,data);
1329 else
1331 while (mask > 0)
1333 if (attr & 0x80)
1335 data = read_byte(0xb800,dest);
1337 else
1339 data = 0x00;
1341 for(j=0;j<4;j++)
1343 if (fdata[src+i] & mask)
1345 if (attr & 0x80)
1347 data ^= (attr & 0x03) << ((3-j)*2);
1349 else
1351 data |= (attr & 0x03) << ((3-j)*2);
1354 mask >>= 1;
1356 write_byte(0xb800,dest,data);
1357 dest += 1;
1363 // --------------------------------------------------------------------------------------------
1364 static void biosfn_write_char_attr (car,page,attr,count)
1365 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1367 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1368 Bit16u nbcols,nbrows,address;
1369 Bit16u cursor,dummy;
1371 // Get the mode
1372 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1373 line=find_vga_entry(mode);
1374 if(line==0xFF)return;
1376 // Get the cursor pos for the page
1377 biosfn_get_cursor_pos(page,&dummy,&cursor);
1378 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1380 // Get the dimensions
1381 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1382 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1384 if(vga_modes[line].class==TEXT)
1386 // Compute the address
1387 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1389 dummy=((Bit16u)attr<<8)+car;
1390 memsetw(vga_modes[line].sstart,address,dummy,count);
1392 else
1394 // FIXME gfx mode not complete
1395 cheight=vga_modes[line].cheight;
1396 bpp=vga_modes[line].pixbits;
1397 while((count-->0) && (xcurs<nbcols))
1399 if(vga_modes[line].memmodel==PLANAR4)
1401 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1403 else if(vga_modes[line].memmodel==CGA)
1405 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1407 else
1409 #ifdef DEBUG
1410 unimplemented();
1411 #endif
1413 xcurs++;
1418 // --------------------------------------------------------------------------------------------
1419 static void biosfn_write_char_only (car,page,attr,count)
1420 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1422 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1423 Bit16u nbcols,nbrows,address;
1424 Bit16u cursor,dummy;
1426 // Get the mode
1427 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1428 line=find_vga_entry(mode);
1429 if(line==0xFF)return;
1431 // Get the cursor pos for the page
1432 biosfn_get_cursor_pos(page,&dummy,&cursor);
1433 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1435 // Get the dimensions
1436 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1437 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1439 if(vga_modes[line].class==TEXT)
1441 // Compute the address
1442 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1444 while(count-->0)
1445 {write_byte(vga_modes[line].sstart,address,car);
1446 address+=2;
1449 else
1451 // FIXME gfx mode not complete
1452 cheight=vga_modes[line].cheight;
1453 bpp=vga_modes[line].pixbits;
1454 while((count-->0) && (xcurs<nbcols))
1456 if(vga_modes[line].memmodel==PLANAR4)
1458 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1460 else if(vga_modes[line].memmodel==CGA)
1462 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1464 else
1466 #ifdef DEBUG
1467 unimplemented();
1468 #endif
1470 xcurs++;
1475 // --------------------------------------------------------------------------------------------
1476 static void biosfn_set_border_color (BL) Bit8u BL;
1477 // FIXME anybody using this function ?
1479 #ifdef DEBUG
1480 unimplemented();
1481 #endif
1484 // --------------------------------------------------------------------------------------------
1485 static void biosfn_set_palette (BL) Bit8u BL;
1486 // FIXME anybody using this function ?
1488 #ifdef DEBUG
1489 unimplemented();
1490 #endif
1493 // --------------------------------------------------------------------------------------------
1494 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1496 Bit8u mode,line,mask,attr;
1497 Bit16u addr,data;
1499 // Get the mode
1500 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1501 line=find_vga_entry(mode);
1502 if(line==0xFF)return;
1503 if(vga_modes[line].class==TEXT)return;
1505 if(vga_modes[line].memmodel==CGA)
1507 if(vga_modes[line].pixbits==2)
1509 addr=(CX>>2)+(DX>>1)*80;
1511 else
1513 addr=(CX>>3)+(DX>>1)*80;
1515 if (DX & 1) addr += 0x2000;
1516 data = read_byte(0xb800,addr);
1517 if(vga_modes[line].pixbits==2)
1519 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1520 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1522 else
1524 attr = (AL & 0x01) << (7 - (CX & 0x07));
1525 mask = 0x01 << (7 - (CX & 0x07));
1527 if (AL & 0x80)
1529 data ^= attr;
1531 else
1533 data &= ~mask;
1534 data |= attr;
1536 write_byte(0xb800,addr,data);
1538 else if(vga_modes[line].memmodel==LINEAR8)
1540 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1541 write_byte(0xa000,addr,AL);
1543 else
1545 #ifdef DEBUG
1546 unimplemented();
1547 #endif
1551 // --------------------------------------------------------------------------------------------
1552 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1554 Bit8u mode,line,attr;
1555 Bit16u addr,data;
1556 Bit16u ss=get_SS();
1558 // Get the mode
1559 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1560 line=find_vga_entry(mode);
1561 if(line==0xFF)return;
1562 if(vga_modes[line].class==TEXT)return;
1564 if(vga_modes[line].memmodel==CGA)
1566 addr=(CX>>2)+(DX>>1)*80;
1567 if (DX & 1) addr += 0x2000;
1568 data = read_byte(0xb800,addr);
1569 if(vga_modes[line].pixbits==2)
1571 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1573 else
1575 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1578 else if(vga_modes[line].memmodel==LINEAR8)
1580 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1581 attr=read_byte(0xa000,addr);
1583 else
1585 #ifdef DEBUG
1586 unimplemented();
1587 #endif
1588 attr = 0;
1590 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1593 // --------------------------------------------------------------------------------------------
1594 static void biosfn_write_teletype (car, page, attr, flag)
1595 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1596 {// flag = WITH_ATTR / NO_ATTR
1598 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1599 Bit16u nbcols,nbrows,address;
1600 Bit16u cursor,dummy;
1602 // special case if page is 0xff, use current page
1603 if(page==0xff)
1604 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1606 // FIXME gfx mode
1608 // Get the mode
1609 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1610 line=find_vga_entry(mode);
1611 if(line==0xFF)return;
1613 // Get the cursor pos for the page
1614 biosfn_get_cursor_pos(page,&dummy,&cursor);
1615 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1617 // Get the dimensions
1618 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1619 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1621 switch(car)
1623 case 7:
1624 //FIXME should beep
1625 break;
1627 case 8:
1628 if(xcurs>0)xcurs--;
1629 break;
1631 case '\r':
1632 xcurs=0;
1633 break;
1635 case '\n':
1636 xcurs=0;
1637 ycurs++;
1638 break;
1640 case '\t':
1643 biosfn_write_teletype(' ',page,attr,flag);
1644 biosfn_get_cursor_pos(page,&dummy,&cursor);
1645 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1646 }while(xcurs%8==0);
1647 break;
1649 default:
1651 if(vga_modes[line].class==TEXT)
1653 // Compute the address
1654 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1656 // Write the char
1657 write_byte(vga_modes[line].sstart,address,car);
1659 if(flag==WITH_ATTR)
1660 write_byte(vga_modes[line].sstart,address+1,attr);
1662 else
1664 // FIXME gfx mode not complete
1665 cheight=vga_modes[line].cheight;
1666 bpp=vga_modes[line].pixbits;
1667 if(vga_modes[line].memmodel==PLANAR4)
1669 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1671 else if(vga_modes[line].memmodel==CGA)
1673 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1675 else
1677 #ifdef DEBUG
1678 unimplemented();
1679 #endif
1683 xcurs++;
1686 // Do we need to wrap ?
1687 if(xcurs==nbcols)
1688 {xcurs=0;
1689 ycurs++;
1692 // Do we need to scroll ?
1693 if(ycurs==nbrows)
1694 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1695 ycurs-=1;
1698 // Set the cursor for the page
1699 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1700 biosfn_set_cursor_pos(page,cursor);
1703 // --------------------------------------------------------------------------------------------
1704 ASM_START
1705 biosfn_get_video_mode:
1706 push ds
1707 mov ax, #biosmem_seg
1708 mov ds, ax
1709 push bx
1710 mov bx, #biosmem_current_page
1711 mov al, [bx]
1712 pop bx
1713 mov bh, al
1714 push bx
1715 mov bx, #biosmem_video_ctl
1716 mov ah, [bx]
1717 and ah, #0x80
1718 mov bx, #biosmem_current_mode
1719 mov al, [bx]
1720 or al, ah
1721 mov bx, #biosmem_nb_cols
1722 mov ah, [bx]
1723 pop bx
1724 pop ds
1726 ASM_END
1728 // --------------------------------------------------------------------------------------------
1729 static void biosfn_set_single_palette_reg (reg,value)
1730 Bit8u reg;Bit8u value;
1732 if(reg<=ACTL_MAX_REG)
1734 inb(VGAREG_ACTL_RESET);
1735 outb(VGAREG_ACTL_ADDRESS,reg);
1736 outb(VGAREG_ACTL_WRITE_DATA,value);
1737 outb(VGAREG_ACTL_ADDRESS,0x20);
1741 // --------------------------------------------------------------------------------------------
1742 static void biosfn_set_overscan_border_color (value)
1743 Bit8u value;
1745 inb(VGAREG_ACTL_RESET);
1746 outb(VGAREG_ACTL_ADDRESS,0x11);
1747 outb(VGAREG_ACTL_WRITE_DATA,value);
1748 outb(VGAREG_ACTL_ADDRESS,0x20);
1751 // --------------------------------------------------------------------------------------------
1752 static void biosfn_set_all_palette_reg (seg,offset)
1753 Bit16u seg;Bit16u offset;
1755 Bit8u i;
1757 inb(VGAREG_ACTL_RESET);
1758 // First the colors
1759 for(i=0;i<0x10;i++)
1761 outb(VGAREG_ACTL_ADDRESS,i);
1762 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1763 offset++;
1766 // Then the border
1767 outb(VGAREG_ACTL_ADDRESS,0x11);
1768 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1769 outb(VGAREG_ACTL_ADDRESS,0x20);
1772 // --------------------------------------------------------------------------------------------
1773 static void biosfn_toggle_intensity (state)
1774 Bit8u state;
1775 {Bit8u value;
1776 state&=0x01;
1777 inb(VGAREG_ACTL_RESET);
1779 outb(VGAREG_ACTL_ADDRESS,0x10);
1780 value=inb(VGAREG_ACTL_READ_DATA);
1781 value&=0xf7;
1782 value|=state<<3;
1783 outb(VGAREG_ACTL_WRITE_DATA,value);
1784 outb(VGAREG_ACTL_ADDRESS,0x20);
1787 // --------------------------------------------------------------------------------------------
1788 static void biosfn_get_single_palette_reg (reg,value)
1789 Bit8u reg;Bit16u *value;
1790 {Bit16u ss=get_SS();
1792 if(reg<=ACTL_MAX_REG)
1794 inb(VGAREG_ACTL_RESET);
1795 outb(VGAREG_ACTL_ADDRESS,reg);
1796 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1797 inb(VGAREG_ACTL_RESET);
1798 outb(VGAREG_ACTL_ADDRESS,0x20);
1802 // --------------------------------------------------------------------------------------------
1803 static void biosfn_read_overscan_border_color (value)
1804 Bit16u *value;
1805 {Bit16u ss=get_SS();
1807 inb(VGAREG_ACTL_RESET);
1808 outb(VGAREG_ACTL_ADDRESS,0x11);
1809 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1810 outb(VGAREG_ACTL_ADDRESS,0x20);
1813 // --------------------------------------------------------------------------------------------
1814 static void biosfn_get_all_palette_reg (seg,offset) Bit16u seg;Bit16u offset;
1816 Bit8u i;
1818 // First the colors
1819 for(i=0;i<0x10;i++)
1821 inb(VGAREG_ACTL_RESET);
1822 outb(VGAREG_ACTL_ADDRESS,i);
1823 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1824 offset++;
1827 // Then the border
1828 outb(VGAREG_ACTL_ADDRESS,0x11);
1829 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1830 outb(VGAREG_ACTL_ADDRESS,0x20);
1833 // --------------------------------------------------------------------------------------------
1834 static void biosfn_set_single_dac_reg (reg,g,b,r)
1835 Bit16u reg;Bit8u g;Bit8u b;Bit8u r;
1837 outb(VGAREG_DAC_WRITE_ADDRESS,reg);
1838 outb(VGAREG_DAC_DATA,r);
1839 outb(VGAREG_DAC_DATA,g);
1840 outb(VGAREG_DAC_DATA,b);
1843 // --------------------------------------------------------------------------------------------
1844 static void biosfn_set_all_dac_reg (start,count,seg,offset)
1845 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1846 {Bit16u i;
1847 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1848 for(i=0;i<count;i++)
1849 {outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1850 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1851 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1855 // --------------------------------------------------------------------------------------------
1856 static void biosfn_select_video_dac_color_page (function,page)
1857 Bit8u function;
1858 {Bit8u value;
1860 inb(VGAREG_ACTL_RESET);
1861 outb(VGAREG_ACTL_ADDRESS,0x10);
1863 value=inb(VGAREG_ACTL_READ_DATA);
1864 function&=0x01;
1865 if(function==0)
1866 {// set paging code
1867 value&=0x7f;
1868 value|=page<<7;
1869 outb(VGAREG_ACTL_WRITE_DATA,value);
1871 else
1872 {// select page
1873 inb(VGAREG_ACTL_RESET);
1874 outb(VGAREG_ACTL_ADDRESS,0x14);
1875 if(value&0x80)
1876 outb(VGAREG_ACTL_WRITE_DATA,page&0x0f);
1877 else
1878 outb(VGAREG_ACTL_WRITE_DATA,(page&0x03)<<2);
1880 outb(VGAREG_ACTL_ADDRESS,0x20);
1883 // --------------------------------------------------------------------------------------------
1884 static void biosfn_read_single_dac_reg (reg,tor,togb)
1885 Bit8u reg;Bit16u *tor;Bit16u *togb;
1886 {Bit16u ss=get_SS();
1887 Bit8u r,g,b;
1889 outb(VGAREG_DAC_READ_ADDRESS,reg);
1890 r=inb(VGAREG_DAC_DATA);
1891 g=inb(VGAREG_DAC_DATA);
1892 b=inb(VGAREG_DAC_DATA);
1893 write_word(ss,tor,((Bit16u)r)<<8);
1894 write_word(ss,togb,(((Bit16u)g)<<8)+b);
1897 // --------------------------------------------------------------------------------------------
1898 static void biosfn_read_all_dac_reg (start,count,seg,offset)
1899 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1900 {Bit16u i;
1901 outb(VGAREG_DAC_READ_ADDRESS,start);
1902 for(i=0;i<count;i++)
1903 {write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1904 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1905 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1909 // --------------------------------------------------------------------------------------------
1910 static void biosfn_set_pel_mask (mask)
1911 Bit8u mask;
1913 outb(VGAREG_PEL_MASK,mask);
1916 // --------------------------------------------------------------------------------------------
1917 static void biosfn_read_pel_mask (mask)
1918 Bit16u *mask;
1919 {Bit16u ss=get_SS();
1921 write_word(ss,mask,inb(VGAREG_PEL_MASK));
1924 // --------------------------------------------------------------------------------------------
1925 static void biosfn_read_video_dac_state (state) Bit16u *state;
1926 {Bit16u ss=get_SS();
1927 Bit8u mcr,csr;
1929 inb(VGAREG_ACTL_RESET);
1930 outb(VGAREG_ACTL_ADDRESS,0x10);
1931 mcr=(inb(VGAREG_ACTL_READ_DATA)>>7)&0x01;
1932 inb(VGAREG_ACTL_RESET);
1933 outb(VGAREG_ACTL_ADDRESS,0x14);
1934 csr=inb(VGAREG_ACTL_READ_DATA)&0x0f;
1935 if(mcr==0)(csr>>2)&0x03;
1937 write_word(ss,state,(mcr<<8)+csr);
1938 outb(VGAREG_ACTL_ADDRESS,0x20);
1941 // --------------------------------------------------------------------------------------------
1942 static void biosfn_perform_gray_scale_summing (start,count)
1943 Bit16u start;Bit16u count;
1944 {Bit8u r,g,b,d;
1945 Bit16u i,m;
1946 Bit16u index;
1948 inb(VGAREG_ACTL_RESET);
1949 outb(VGAREG_ACTL_ADDRESS,0x10);
1950 d=(inb(VGAREG_ACTL_READ_DATA)>>6)&0x01;
1952 // depth is 8 or 6 bits
1953 if(d==0)m=0x3f;
1954 else m=0xff;
1957 // We start overwriting at
1958 outb(VGAREG_DAC_READ_ADDRESS,start);
1959 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1961 for( index = 0; index < count; index++ )
1963 // get 6-bit wide RGB data values
1964 r=inb( VGAREG_DAC_DATA );
1965 g=inb( VGAREG_DAC_DATA );
1966 b=inb( VGAREG_DAC_DATA );
1968 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1969 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
1971 if(i>m)i=m;
1973 // write new intensity value
1974 outb( VGAREG_DAC_DATA, i&0xff );
1975 outb( VGAREG_DAC_DATA, i&0xff );
1976 outb( VGAREG_DAC_DATA, i&0xff );
1978 outb(VGAREG_ACTL_ADDRESS,0x20);
1981 // --------------------------------------------------------------------------------------------
1982 static void get_font_access()
1984 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1985 outw( VGAREG_SEQU_ADDRESS, 0x0402 );
1986 outw( VGAREG_SEQU_ADDRESS, 0x0704 );
1987 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
1988 outw( VGAREG_GRDC_ADDRESS, 0x0204 );
1989 outw( VGAREG_GRDC_ADDRESS, 0x0005 );
1990 outw( VGAREG_GRDC_ADDRESS, 0x0406 );
1993 static void release_font_access()
1995 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1996 outw( VGAREG_SEQU_ADDRESS, 0x0302 );
1997 outw( VGAREG_SEQU_ADDRESS, 0x0304 );
1998 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
1999 outw( VGAREG_GRDC_ADDRESS, 0x0004 );
2000 outw( VGAREG_GRDC_ADDRESS, 0x1005 );
2001 outw( VGAREG_GRDC_ADDRESS, 0x0e06 );
2004 ASM_START
2005 idiv_u:
2006 xor dx,dx
2007 div bx
2009 ASM_END
2011 static void set_scan_lines(lines) Bit8u lines;
2013 Bit16u crtc_addr,cols,page,vde;
2014 Bit8u crtc_r9,ovl,rows;
2016 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2017 outb(crtc_addr, 0x09);
2018 crtc_r9 = inb(crtc_addr+1);
2019 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2020 outb(crtc_addr+1, crtc_r9);
2021 if(lines==8)
2023 biosfn_set_cursor_shape(0x06,0x07);
2025 else
2027 biosfn_set_cursor_shape(lines-4,lines-3);
2029 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2030 outb(crtc_addr, 0x12);
2031 vde = inb(crtc_addr+1);
2032 outb(crtc_addr, 0x07);
2033 ovl = inb(crtc_addr+1);
2034 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2035 rows = vde / lines;
2036 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2037 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2038 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2041 static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH;
2043 Bit16u blockaddr,dest,i,src;
2045 get_font_access();
2046 blockaddr = BL << 13;
2047 for(i=0;i<CX;i++)
2049 src = BP + i * BH;
2050 dest = blockaddr + (DX + i) * 32;
2051 memcpyb(0xA000, dest, ES, src, BH);
2053 release_font_access();
2054 if(AL>=0x10)
2056 set_scan_lines(BH);
2060 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2062 Bit16u blockaddr,dest,i,src;
2064 get_font_access();
2065 blockaddr = BL << 13;
2066 for(i=0;i<0x100;i++)
2068 src = i * 14;
2069 dest = blockaddr + i * 32;
2070 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2072 release_font_access();
2073 if(AL>=0x10)
2075 set_scan_lines(14);
2079 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2081 Bit16u blockaddr,dest,i,src;
2083 get_font_access();
2084 blockaddr = BL << 13;
2085 for(i=0;i<0x100;i++)
2087 src = i * 8;
2088 dest = blockaddr + i * 32;
2089 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2091 release_font_access();
2092 if(AL>=0x10)
2094 set_scan_lines(8);
2098 static void biosfn_set_text_block_specifier (BL) Bit8u BL;
2100 outb( VGAREG_SEQU_ADDRESS, 0x03 );
2101 outb( VGAREG_SEQU_DATA, BL );
2104 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2106 Bit16u blockaddr,dest,i,src;
2108 get_font_access();
2109 blockaddr = BL << 13;
2110 for(i=0;i<0x100;i++)
2112 src = i * 16;
2113 dest = blockaddr + i * 32;
2114 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2116 release_font_access();
2117 if(AL>=0x10)
2119 set_scan_lines(16);
2123 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2125 #ifdef DEBUG
2126 unimplemented();
2127 #endif
2129 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2131 #ifdef DEBUG
2132 unimplemented();
2133 #endif
2135 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2137 #ifdef DEBUG
2138 unimplemented();
2139 #endif
2141 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2143 #ifdef DEBUG
2144 unimplemented();
2145 #endif
2147 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2149 #ifdef DEBUG
2150 unimplemented();
2151 #endif
2153 // --------------------------------------------------------------------------------------------
2154 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2155 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2156 {Bit16u ss=get_SS();
2158 switch(BH)
2159 {case 0x00:
2160 write_word(ss,ES,read_word(0x00,0x1f*4));
2161 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2162 break;
2163 case 0x01:
2164 write_word(ss,ES,read_word(0x00,0x43*4));
2165 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2166 break;
2167 case 0x02:
2168 write_word(ss,ES,0xC000);
2169 write_word(ss,BP,vgafont14);
2170 break;
2171 case 0x03:
2172 write_word(ss,ES,0xC000);
2173 write_word(ss,BP,vgafont8);
2174 break;
2175 case 0x04:
2176 write_word(ss,ES,0xC000);
2177 write_word(ss,BP,vgafont8+128*8);
2178 break;
2179 case 0x05:
2180 write_word(ss,ES,0xC000);
2181 write_word(ss,BP,vgafont14alt);
2182 break;
2183 case 0x06:
2184 write_word(ss,ES,0xC000);
2185 write_word(ss,BP,vgafont16);
2186 break;
2187 case 0x07:
2188 write_word(ss,ES,0xC000);
2189 write_word(ss,BP,vgafont16alt);
2190 break;
2191 default:
2192 #ifdef DEBUG
2193 printf("Get font info BH(%02x) was discarded\n",BH);
2194 #endif
2195 return;
2197 // Set byte/char of on screen font
2198 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2200 // Set Highest char row
2201 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2204 // --------------------------------------------------------------------------------------------
2205 static void biosfn_get_ega_info (BX,CX)
2206 Bit16u *BX;Bit16u *CX;
2207 {Bit16u ss=get_SS();
2208 Bit16u crtc;
2209 Bit8u switches;
2211 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2212 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2213 write_word(ss,BX,(1<<8)+0x0003);
2214 else
2215 write_word(ss,BX,0x0003);
2217 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2218 write_word(ss,CX,(switches&0x0f));
2221 // --------------------------------------------------------------------------------------------
2222 static void biosfn_alternate_prtsc()
2224 #ifdef DEBUG
2225 unimplemented();
2226 #endif
2229 // --------------------------------------------------------------------------------------------
2230 static void biosfn_select_vert_res (res)
2231 Bit8u res;
2232 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2233 Bit8u modeset,switches;
2235 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2236 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2237 switch(res)
2238 {case 0x00:
2239 // set modeset ctl bit 7 and reset bit 4
2240 // set switches bit 3-0 to 0x08
2241 modeset|=0x80;modeset&=0xef;
2242 switches&=0xf0;switches|=0x08;
2243 break;
2244 case 0x01:
2245 // reset modeset ctl bit 7 and bit 4
2246 // set switches bit 3-0 to 0x09
2247 modeset&=0x6f;
2248 switches&=0xf0;switches|=0x09;
2249 break;
2250 case 0x02:
2251 // reset modeset ctl bit 7 and set bit 4
2252 // set switches bit 3-0 to 0x09
2253 modeset|=0x10;modeset&=0x7f;
2254 switches&=0xf0;switches|=0x09;
2255 break;
2256 default:
2257 #ifdef DEBUG
2258 printf("Select vert res (%02x) was discarded\n",res);
2259 #endif
2260 return;
2262 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2263 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2266 // --------------------------------------------------------------------------------------------
2267 static void biosfn_enable_default_palette_loading (disable)
2268 Bit8u disable;
2270 Bit8u modeset;
2272 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2274 // Bit 3
2275 if(disable!=0x00)modeset|=0x08;
2276 else modeset&=0xf7;
2278 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2281 // --------------------------------------------------------------------------------------------
2282 static void biosfn_enable_video_addressing (disable)
2283 Bit8u disable;
2285 Bit8u misc;
2287 misc=inb(VGAREG_READ_MISC_OUTPUT);
2288 // bit 1, 0 disable
2289 if(disable!=0x00) misc&=0xfd;
2290 else misc|=0x02;
2291 outb(VGAREG_WRITE_MISC_OUTPUT,misc);
2294 // --------------------------------------------------------------------------------------------
2295 static void biosfn_enable_grayscale_summing (disable)
2296 Bit8u disable;
2298 Bit8u modeset;
2300 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2302 // Bit 1 set if disable=0
2303 if(disable==0x00)modeset|=0x02;
2304 else modeset&=0xfd;
2306 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2309 // --------------------------------------------------------------------------------------------
2310 static void biosfn_enable_cursor_emulation (disable)
2311 Bit8u disable;
2313 Bit8u videoctl;
2315 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2317 // Bit 0 set if disable!=0
2318 if(disable!=0x00)videoctl|=0x01;
2319 else videoctl&=0xfe;
2321 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2324 // --------------------------------------------------------------------------------------------
2325 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2327 #ifdef DEBUG
2328 unimplemented();
2329 #endif
2331 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2333 #ifdef DEBUG
2334 unimplemented();
2335 #endif
2338 // --------------------------------------------------------------------------------------------
2339 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2340 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2342 Bit16u newcurs,oldcurs,dummy;
2343 Bit8u car,carattr;
2345 // Read curs info for the page
2346 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2348 // if row=0xff special case : use current cursor position
2349 if(row==0xff)
2350 {col=oldcurs&0x00ff;
2351 row=(oldcurs&0xff00)>>8;
2354 newcurs=row; newcurs<<=8; newcurs+=col;
2355 biosfn_set_cursor_pos(page,newcurs);
2357 while(count--!=0)
2359 car=read_byte(seg,offset++);
2360 if((flag&0x02)!=0)
2361 attr=read_byte(seg,offset++);
2363 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2366 // Set back curs pos
2367 if((flag&0x01)==0)
2368 biosfn_set_cursor_pos(page,oldcurs);
2371 // --------------------------------------------------------------------------------------------
2372 ASM_START
2373 biosfn_read_display_code:
2374 push ds
2375 push ax
2376 mov ax, #biosmem_seg
2377 mov ds, ax
2378 mov bx, #biosmem_dcc_index
2379 mov al, [bx]
2380 mov bl, al
2381 xor bh, bh
2382 pop ax
2383 pop ds
2385 ASM_END
2387 // --------------------------------------------------------------------------------------------
2388 static void biosfn_set_display_code (BL,BH)
2389 Bit8u BL;Bit8u BH;
2391 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,BL);
2393 #ifdef DEBUG
2394 printf("Alternate Display code (%02x) was discarded\n",BH);
2395 #endif
2398 // --------------------------------------------------------------------------------------------
2399 static void biosfn_read_state_info (BX,ES,DI)
2400 Bit16u BX;Bit16u ES;Bit16u DI;
2402 // Address of static functionality table
2403 write_word(ES,DI+0x00,&static_functionality);
2404 write_word(ES,DI+0x02,0xC000);
2406 // Hard coded copy from BIOS area. Should it be cleaner ?
2407 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2408 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2410 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2411 write_byte(ES,DI+0x26,0);
2412 write_byte(ES,DI+0x27,16);
2413 write_byte(ES,DI+0x28,0);
2414 write_byte(ES,DI+0x29,8);
2415 write_byte(ES,DI+0x2a,2);
2416 write_byte(ES,DI+0x2b,0);
2417 write_byte(ES,DI+0x2c,0);
2418 write_byte(ES,DI+0x31,3);
2419 write_byte(ES,DI+0x32,0);
2421 memsetb(ES,DI+0x33,0,13);
2424 // --------------------------------------------------------------------------------------------
2425 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2427 #ifdef DEBUG
2428 unimplemented();
2429 #endif
2431 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2433 #ifdef DEBUG
2434 unimplemented();
2435 #endif
2437 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2439 #ifdef DEBUG
2440 unimplemented();
2441 #endif
2444 // ============================================================================================
2446 // Video Utils
2448 // ============================================================================================
2450 // --------------------------------------------------------------------------------------------
2451 static Bit8u find_vga_entry(mode)
2452 Bit8u mode;
2454 Bit8u i,line=0xFF;
2455 for(i=0;i<=MODE_MAX;i++)
2456 if(vga_modes[i].svgamode==mode)
2457 {line=i;
2458 break;
2460 return line;
2463 /* =========================================================== */
2465 * Misc Utils
2467 /* =========================================================== */
2469 // --------------------------------------------------------------------------------------------
2470 static void memsetb(seg,offset,value,count)
2471 Bit16u seg;
2472 Bit16u offset;
2473 Bit16u value;
2474 Bit16u count;
2476 ASM_START
2477 push bp
2478 mov bp, sp
2480 push ax
2481 push cx
2482 push es
2483 push di
2485 mov cx, 10[bp] ; count
2486 cmp cx, #0x00
2487 je memsetb_end
2488 mov ax, 4[bp] ; segment
2489 mov es, ax
2490 mov ax, 6[bp] ; offset
2491 mov di, ax
2492 mov al, 8[bp] ; value
2495 stosb
2497 memsetb_end:
2498 pop di
2499 pop es
2500 pop cx
2501 pop ax
2503 pop bp
2504 ASM_END
2507 // --------------------------------------------------------------------------------------------
2508 static void memsetw(seg,offset,value,count)
2509 Bit16u seg;
2510 Bit16u offset;
2511 Bit16u value;
2512 Bit16u count;
2514 ASM_START
2515 push bp
2516 mov bp, sp
2518 push ax
2519 push cx
2520 push es
2521 push di
2523 mov cx, 10[bp] ; count
2524 cmp cx, #0x00
2525 je memsetw_end
2526 mov ax, 4[bp] ; segment
2527 mov es, ax
2528 mov ax, 6[bp] ; offset
2529 mov di, ax
2530 mov ax, 8[bp] ; value
2533 stosw
2535 memsetw_end:
2536 pop di
2537 pop es
2538 pop cx
2539 pop ax
2541 pop bp
2542 ASM_END
2545 // --------------------------------------------------------------------------------------------
2546 static void memcpyb(dseg,doffset,sseg,soffset,count)
2547 Bit16u dseg;
2548 Bit16u doffset;
2549 Bit16u sseg;
2550 Bit16u soffset;
2551 Bit16u count;
2553 ASM_START
2554 push bp
2555 mov bp, sp
2557 push ax
2558 push cx
2559 push es
2560 push di
2561 push ds
2562 push si
2564 mov cx, 12[bp] ; count
2565 cmp cx, #0x0000
2566 je memcpyb_end
2567 mov ax, 4[bp] ; dsegment
2568 mov es, ax
2569 mov ax, 6[bp] ; doffset
2570 mov di, ax
2571 mov ax, 8[bp] ; ssegment
2572 mov ds, ax
2573 mov ax, 10[bp] ; soffset
2574 mov si, ax
2577 movsb
2579 memcpyb_end:
2580 pop si
2581 pop ds
2582 pop di
2583 pop es
2584 pop cx
2585 pop ax
2587 pop bp
2588 ASM_END
2591 // --------------------------------------------------------------------------------------------
2592 static void memcpyw(dseg,doffset,sseg,soffset,count)
2593 Bit16u dseg;
2594 Bit16u doffset;
2595 Bit16u sseg;
2596 Bit16u soffset;
2597 Bit16u count;
2599 ASM_START
2600 push bp
2601 mov bp, sp
2603 push ax
2604 push cx
2605 push es
2606 push di
2607 push ds
2608 push si
2610 mov cx, 12[bp] ; count
2611 cmp cx, #0x0000
2612 je memcpyw_end
2613 mov ax, 4[bp] ; dsegment
2614 mov es, ax
2615 mov ax, 6[bp] ; doffset
2616 mov di, ax
2617 mov ax, 8[bp] ; ssegment
2618 mov ds, ax
2619 mov ax, 10[bp] ; soffset
2620 mov si, ax
2623 movsw
2625 memcpyw_end:
2626 pop si
2627 pop ds
2628 pop di
2629 pop es
2630 pop cx
2631 pop ax
2633 pop bp
2634 ASM_END
2637 /* =========================================================== */
2639 * These functions where ripped from Kevin's rombios.c
2641 /* =========================================================== */
2643 // --------------------------------------------------------------------------------------------
2644 static Bit8u
2645 read_byte(seg, offset)
2646 Bit16u seg;
2647 Bit16u offset;
2649 ASM_START
2650 push bp
2651 mov bp, sp
2653 push bx
2654 push ds
2655 mov ax, 4[bp] ; segment
2656 mov ds, ax
2657 mov bx, 6[bp] ; offset
2658 mov al, [bx]
2659 ;; al = return value (byte)
2660 pop ds
2661 pop bx
2663 pop bp
2664 ASM_END
2667 // --------------------------------------------------------------------------------------------
2668 static Bit16u
2669 read_word(seg, offset)
2670 Bit16u seg;
2671 Bit16u offset;
2673 ASM_START
2674 push bp
2675 mov bp, sp
2677 push bx
2678 push ds
2679 mov ax, 4[bp] ; segment
2680 mov ds, ax
2681 mov bx, 6[bp] ; offset
2682 mov ax, [bx]
2683 ;; ax = return value (word)
2684 pop ds
2685 pop bx
2687 pop bp
2688 ASM_END
2691 // --------------------------------------------------------------------------------------------
2692 static void
2693 write_byte(seg, offset, data)
2694 Bit16u seg;
2695 Bit16u offset;
2696 Bit8u data;
2698 ASM_START
2699 push bp
2700 mov bp, sp
2702 push ax
2703 push bx
2704 push ds
2705 mov ax, 4[bp] ; segment
2706 mov ds, ax
2707 mov bx, 6[bp] ; offset
2708 mov al, 8[bp] ; data byte
2709 mov [bx], al ; write data byte
2710 pop ds
2711 pop bx
2712 pop ax
2714 pop bp
2715 ASM_END
2718 // --------------------------------------------------------------------------------------------
2719 static void
2720 write_word(seg, offset, data)
2721 Bit16u seg;
2722 Bit16u offset;
2723 Bit16u data;
2725 ASM_START
2726 push bp
2727 mov bp, sp
2729 push ax
2730 push bx
2731 push ds
2732 mov ax, 4[bp] ; segment
2733 mov ds, ax
2734 mov bx, 6[bp] ; offset
2735 mov ax, 8[bp] ; data word
2736 mov [bx], ax ; write data word
2737 pop ds
2738 pop bx
2739 pop ax
2741 pop bp
2742 ASM_END
2745 // --------------------------------------------------------------------------------------------
2746 Bit8u
2747 inb(port)
2748 Bit16u port;
2750 ASM_START
2751 push bp
2752 mov bp, sp
2754 push dx
2755 mov dx, 4[bp]
2756 in al, dx
2757 pop dx
2759 pop bp
2760 ASM_END
2763 Bit16u
2764 inw(port)
2765 Bit16u port;
2767 ASM_START
2768 push bp
2769 mov bp, sp
2771 push dx
2772 mov dx, 4[bp]
2773 in ax, dx
2774 pop dx
2776 pop bp
2777 ASM_END
2780 // --------------------------------------------------------------------------------------------
2781 void
2782 outb(port, val)
2783 Bit16u port;
2784 Bit8u val;
2786 ASM_START
2787 push bp
2788 mov bp, sp
2790 push ax
2791 push dx
2792 mov dx, 4[bp]
2793 mov al, 6[bp]
2794 out dx, al
2795 pop dx
2796 pop ax
2798 pop bp
2799 ASM_END
2802 // --------------------------------------------------------------------------------------------
2803 void
2804 outw(port, val)
2805 Bit16u port;
2806 Bit16u val;
2808 ASM_START
2809 push bp
2810 mov bp, sp
2812 push ax
2813 push dx
2814 mov dx, 4[bp]
2815 mov ax, 6[bp]
2816 out dx, ax
2817 pop dx
2818 pop ax
2820 pop bp
2821 ASM_END
2824 Bit16u get_SS()
2826 ASM_START
2827 mov ax, ss
2828 ASM_END
2831 #ifdef DEBUG
2832 void unimplemented()
2834 printf("--> Unimplemented\n");
2837 void unknown()
2839 printf("--> Unknown int10\n");
2841 #endif
2843 // --------------------------------------------------------------------------------------------
2844 void printf(s)
2845 Bit8u *s;
2847 Bit8u c, format_char;
2848 Boolean in_format;
2849 unsigned format_width, i;
2850 Bit16u *arg_ptr;
2851 Bit16u arg_seg, arg, digit, nibble, shift_count;
2853 arg_ptr = &s;
2854 arg_seg = get_SS();
2856 in_format = 0;
2857 format_width = 0;
2859 while (c = read_byte(0xc000, s)) {
2860 if ( c == '%' ) {
2861 in_format = 1;
2862 format_width = 0;
2864 else if (in_format) {
2865 if ( (c>='0') && (c<='9') ) {
2866 format_width = (format_width * 10) + (c - '0');
2868 else if (c == 'x') {
2869 arg_ptr++; // increment to next arg
2870 arg = read_word(arg_seg, arg_ptr);
2871 if (format_width == 0)
2872 format_width = 4;
2873 i = 0;
2874 digit = format_width - 1;
2875 for (i=0; i<format_width; i++) {
2876 nibble = (arg >> (4 * digit)) & 0x000f;
2877 if (nibble <= 9)
2878 outb(0x0500, nibble + '0');
2879 else
2880 outb(0x0500, (nibble - 10) + 'A');
2881 digit--;
2883 in_format = 0;
2885 //else if (c == 'd') {
2886 // in_format = 0;
2887 // }
2889 else {
2890 outb(0x0500, c);
2892 s ++;
2896 #ifdef VBE
2897 #include "vbe.c"
2898 #endif
2900 // --------------------------------------------------------------------------------------------
2902 ASM_START
2903 ;; DATA_SEG_DEFS_HERE
2904 ASM_END
2906 ASM_START
2907 .ascii "vgabios ends here"
2908 .byte 0x00
2909 vgabios_end:
2910 .byte 0xCB
2911 ;; BLOCK_STRINGS_BEGIN
2912 ASM_END