1 // ============================================================================================
5 // ============================================================================================
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
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
23 // ============================================================================================
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
28 // ============================================================================================
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 // ============================================================================================
58 static Bit8u
read_byte();
59 static Bit16u
read_word();
60 static void write_byte();
61 static void write_word();
67 static Bit16u
get_SS();
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_get_video_mode();
99 static void biosfn_set_single_palette_reg();
100 static void biosfn_set_overscan_border_color();
101 static void biosfn_set_all_palette_reg();
102 static void biosfn_toggle_intensity();
103 static void biosfn_get_single_palette_reg();
104 static void biosfn_read_overscan_border_color();
105 static void biosfn_get_all_palette_reg();
106 static void biosfn_set_single_dac_reg();
107 static void biosfn_set_all_dac_reg();
108 static void biosfn_select_video_dac_color_page();
109 static void biosfn_read_single_dac_reg();
110 static void biosfn_read_all_dac_reg();
111 static void biosfn_set_pel_mask();
112 static void biosfn_read_pel_mask();
113 static void biosfn_read_video_dac_state();
114 static void biosfn_perform_gray_scale_summing();
115 static void biosfn_load_text_user_pat();
116 static void biosfn_load_text_8_14_pat();
117 static void biosfn_load_text_8_8_pat();
118 static void biosfn_set_text_block_specifier();
119 static void biosfn_load_text_8_16_pat();
120 static void biosfn_load_gfx_8_8_chars();
121 static void biosfn_load_gfx_user_chars();
122 static void biosfn_load_gfx_8_14_chars();
123 static void biosfn_load_gfx_8_8_dd_chars();
124 static void biosfn_load_gfx_8_16_chars();
125 static void biosfn_get_font_info();
126 static void biosfn_get_ega_info();
127 static void biosfn_alternate_prtsc();
128 static void biosfn_select_vert_res();
129 static void biosfn_enable_default_palette_loading();
130 static void biosfn_enable_video_addressing();
131 static void biosfn_enable_grayscale_summing();
132 static void biosfn_enable_cursor_emulation();
133 static void biosfn_switch_video_interface();
134 static void biosfn_enable_video_refresh_control();
135 static void biosfn_write_string();
136 static void biosfn_read_display_code();
137 static void biosfn_set_display_code();
138 static void biosfn_read_state_info();
139 static void biosfn_read_video_state_size();
140 static void biosfn_save_video_state();
141 static void biosfn_restore_video_state();
143 // This is for compiling with gcc2 and gcc3
144 #define ASM_START #asm
145 #define ASM_END #endasm
169 .byte
0x55, 0xaa /* BIOS signature, required for BIOS extensions */
171 .byte
0x40 /* BIOS extension length in units of 512 bytes */
176 jmp vgabios_init_func
179 .ascii
"Plex86/Bochs VGABios"
183 // Info from Bart Oldeman
198 .ascii
"(C) 2003 the LGPL VGABios developers Team"
203 .ascii
"This VGA/VBE Bios is released under the GNU LGPL"
209 .ascii
"Please visit :"
211 .ascii
" . http://www.plex86.org"
213 .ascii
" . http://bochs.sourceforge.net"
215 .ascii
" . http://www.nongnu.org/vgabios"
221 ;; ============================================================================================
225 ;; ============================================================================================
231 ;; init basic bios vars
235 call _vbe_has_vbe_display
237 je init_no_vbe_display
239 ;; init vbe functions
246 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
248 ;; display splash screen
249 call _display_splash_screen
251 ;; init video mode
and clear the screen
255 ;; copy
and activate
8x16 font
268 call _vbe_display_info
279 vgabios_int10_handler
:
285 ;; We have to set ds to access the right data segment
297 #include "vgatables.h"
298 #include "vgafonts.h"
301 * Boot time harware inits
303 static void init_vga_card()
306 ;; switch to color mode
and enable CPU access
480 lines
311 ;; more than
64k
3C4
/04
323 printf("VGABios $Id$\n");
326 // --------------------------------------------------------------------------------------------
328 * Boot time bios area inits
330 static void init_bios_area()
332 // init detected hardware BIOS Area
333 write_word(BIOSMEM_SEG
,BIOSMEM_INITIAL_MODE
,read_word(BIOSMEM_SEG
,BIOSMEM_INITIAL_MODE
)&0xFFCF);
335 // Just for the first int10 find its children
337 // the default chat height
338 write_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,16);
341 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,0x60);
343 // Set the basic screen we have
344 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
346 // Set the basic modeset options
347 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,0x51);
349 // Set the default MSR
350 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x09);
353 // --------------------------------------------------------------------------------------------
355 * Boot time Splash screen
357 static void display_splash_screen()
361 // --------------------------------------------------------------------------------------------
366 static void display_info()
373 mov si
,#vgabios_version
376 ;;mov si
,#vgabios_copyright
377 ;;call _display_string
379 ;;call _display_string
381 mov si
,#vgabios_license
383 mov si
,#vgabios_website
388 static void display_string()
390 // Get length of string
417 // --------------------------------------------------------------------------------------------
419 // --------------------------------------------------------------------------------------------
421 * int10 main dispatcher
423 static void int10_func(DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, DS
, ES
, FLAGS
)
424 Bit16u DI
, SI
, BP
, SP
, BX
, DX
, CX
, AX
, ES
, DS
, FLAGS
;
427 // 0E is write char...
429 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX
,CX
,DX
);
436 biosfn_set_video_mode(GET_AL());
437 switch(GET_AL()&0x7F)
455 biosfn_set_cursor_shape(GET_CH(),GET_CL());
458 biosfn_set_cursor_pos(GET_BH(),DX
);
461 biosfn_get_cursor_pos(GET_BH(),&CX
,&DX
);
464 // Read light pen pos (unimplemented)
474 biosfn_set_active_page(GET_AL());
477 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP
);
480 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN
);
483 biosfn_read_char_attr(GET_BH(),&AX
);
486 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX
);
489 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX
);
493 biosfn_set_border_color(GET_BL());
495 biosfn_set_palette(GET_BL());
498 biosfn_write_pixel(GET_BH(),GET_AL(),CX
,DX
);
501 biosfn_read_pixel(GET_BH(),CX
,DX
,&AX
);
504 // Ralf Brown Interrupt list is WRONG on bh(page)
505 // We do output only on the current page !
506 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR
);
509 biosfn_get_video_mode(&AX
,&BX
);
515 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
518 biosfn_set_overscan_border_color(GET_BH());
521 biosfn_set_all_palette_reg(ES
,DX
);
524 biosfn_toggle_intensity(GET_BL());
527 biosfn_get_single_palette_reg(GET_BL(),&BX
);
530 biosfn_read_overscan_border_color(&BX
);
533 biosfn_get_all_palette_reg(ES
,DX
);
536 biosfn_set_single_dac_reg(BX
,GET_CH(),GET_CL(),GET_DH());
539 biosfn_set_all_dac_reg(BX
,CX
,ES
,DX
);
542 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
545 biosfn_read_single_dac_reg(GET_BL(),&DX
,&CX
);
548 biosfn_read_all_dac_reg(BX
,CX
,ES
,DX
);
551 biosfn_set_pel_mask(GET_BL());
554 biosfn_read_pel_mask(&BX
);
557 biosfn_read_video_dac_state(&BX
);
560 biosfn_perform_gray_scale_summing(BX
,CX
);
573 biosfn_load_text_user_pat(GET_AL(),ES
,BP
,CX
,DX
,GET_BL(),GET_BH());
577 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
581 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
584 biosfn_set_text_block_specifier(GET_BL());
588 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
591 biosfn_load_gfx_8_8_chars(ES
,BP
);
594 biosfn_load_gfx_user_chars(ES
,BP
,CX
,GET_BL(),GET_DL());
597 biosfn_load_gfx_8_14_chars(GET_BL());
600 biosfn_load_gfx_8_8_dd_chars(GET_BL());
603 biosfn_load_gfx_8_16_chars(GET_BL());
606 biosfn_get_font_info(GET_BH(),&ES
,&BP
,&CX
,&DX
);
619 biosfn_get_ega_info(&BX
,&CX
);
622 biosfn_alternate_prtsc();
625 biosfn_select_vert_res(GET_AL());
629 biosfn_enable_default_palette_loading(GET_AL());
633 biosfn_enable_video_addressing(GET_AL());
637 biosfn_enable_grayscale_summing(GET_AL());
641 biosfn_enable_cursor_emulation(GET_AL());
645 biosfn_switch_video_interface(GET_AL(),ES
,DX
);
649 biosfn_enable_video_refresh_control(GET_AL());
659 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX
,GET_DH(),GET_DL(),ES
,BP
);
665 biosfn_read_display_code(&BX
);
668 biosfn_set_display_code(GET_BL(),GET_BH());
678 biosfn_read_state_info(BX
,ES
,DI
);
685 biosfn_read_video_state_size(CX
,&BX
);
688 biosfn_save_video_state(CX
,ES
,BX
);
691 biosfn_restore_video_state(CX
,ES
,BX
);
703 if (vbe_has_vbe_display()) {
707 vbe_biosfn_return_controller_information(&AX
,ES
,DI
);
710 vbe_biosfn_return_mode_information(&AX
,CX
,ES
,DI
);
713 vbe_biosfn_set_mode(&AX
,BX
,ES
,DI
);
716 vbe_biosfn_return_current_mode(&AX
,&BX
);
727 vbe_biosfn_display_window_control(&AX
,BX
,&DX
);
730 vbe_biosfn_set_get_logical_scan_line_length(&AX
,&BX
,&CX
,&DX
);
733 vbe_biosfn_set_get_display_start(&AX
,BX
,CX
,DX
);
781 // ============================================================================================
785 // ============================================================================================
787 static void biosfn_set_video_mode(mode
) Bit8u mode
;
788 {// mode: Bit 7 is 1 if no clear screen
790 // Should we clear the screen ?
791 Bit8u noclearmem
=mode
&0x80;
792 Bit8u line
,mmask
,*palette
;
793 Bit16u i
,twidth
,theight
,cheight
;
794 Bit8u modeset_ctl
,video_ctl
,vga_switches
;
798 if (vbe_has_vbe_display()) {
799 dispi_set_enable(VBE_DISPI_DISABLED
);
806 // find the entry in the video modes
807 line
=find_vga_entry(mode
);
810 printf("mode search %02x found line %02x\n",mode
,line
);
816 twidth
=vga_modes
[line
].twidth
;
817 theight
=vga_modes
[line
].theight
;
818 cheight
=vga_modes
[line
].cheight
;
820 // Read the bios vga control
821 video_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
823 // Read the bios vga switches
824 vga_switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
826 // Read the bios mode set control
827 modeset_ctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
829 // Then we know the number of lines
832 // if palette loading (bit 3 of modeset ctl = 0)
833 if((modeset_ctl
&0x08)==0)
835 outb(VGAREG_PEL_MASK
,vga_modes
[line
].pelmask
);
837 // Set the whole dac always, from 0
838 outb(VGAREG_DAC_WRITE_ADDRESS
,0x00);
840 // From which palette
841 switch(vga_modes
[line
].dacmodel
)
857 // Always 256*3 values
858 for(i
=0;i
<0x0100;i
++)
859 {if(i
<=dac_regs
[vga_modes
[line
].dacmodel
])
860 {outb(VGAREG_DAC_DATA
,palette
[(i
*3)+0]);
861 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+1]);
862 outb(VGAREG_DAC_DATA
,palette
[(i
*3)+2]);
865 {outb(VGAREG_DAC_DATA
,0);
866 outb(VGAREG_DAC_DATA
,0);
867 outb(VGAREG_DAC_DATA
,0);
871 // Reset Attribute Ctl flip-flop
872 inb(VGAREG_ACTL_RESET
);
875 for(i
=0;i
<=ACTL_MAX_REG
;i
++)
876 {outb(VGAREG_ACTL_ADDRESS
,i
);
877 outb(VGAREG_ACTL_WRITE_DATA
,actl_regs
[vga_modes
[line
].actlmodel
][i
]);
881 for(i
=0;i
<=SEQU_MAX_REG
;i
++)
882 {outb(VGAREG_SEQU_ADDRESS
,i
);
883 outb(VGAREG_SEQU_DATA
,sequ_regs
[vga_modes
[line
].sequmodel
][i
]);
887 for(i
=0;i
<=GRDC_MAX_REG
;i
++)
888 {outb(VGAREG_GRDC_ADDRESS
,i
);
889 outb(VGAREG_GRDC_DATA
,grdc_regs
[vga_modes
[line
].grdcmodel
][i
]);
892 // Set CRTC address VGA or MDA
893 crtc_addr
=vga_modes
[line
].memmodel
==MTEXT
?VGAREG_MDA_CRTC_ADDRESS
:VGAREG_VGA_CRTC_ADDRESS
;
896 for(i
=0;i
<=CRTC_MAX_REG
;i
++)
898 outb(crtc_addr
+1,crtc_regs
[vga_modes
[line
].crtcmodel
][i
]);
901 // Set the misc register
902 outb(VGAREG_WRITE_MISC_OUTPUT
,vga_modes
[line
].miscreg
);
905 outb(VGAREG_ACTL_ADDRESS
,0x20);
906 inb(VGAREG_ACTL_RESET
);
910 if(vga_modes
[line
].class==TEXT
)
912 memsetw(vga_modes
[line
].sstart
,0,0x0720,0x4000); // 32k
918 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x4000); // 32k
922 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
923 mmask
= inb( VGAREG_SEQU_DATA
);
924 outb( VGAREG_SEQU_DATA
, 0x0f ); // all planes
925 memsetw(vga_modes
[line
].sstart
,0,0x0000,0x8000); // 64k
926 outb( VGAREG_SEQU_DATA
, mmask
);
932 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
,mode
|noclearmem
);
933 write_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
,twidth
);
934 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
,vga_modes
[line
].slength
);
935 write_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
,crtc_addr
);
936 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
,theight
-1);
937 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
,cheight
);
938 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,(0x60|noclearmem
));
939 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,0xF9);
940 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
)&0x7f);
942 // FIXME We nearly have the good tables. to be reworked
943 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,0x08); // 8 is VGA should be ok for now
944 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
,0x00);
945 write_word(BIOSMEM_SEG
,BIOSMEM_VS_POINTER
+2,0x00);
948 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MSR
,0x00); // Unavailable on vanilla vga, but...
949 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAL
,0x00); // Unavailable on vanilla vga, but...
952 if(vga_modes
[line
].class==TEXT
)
954 biosfn_set_cursor_shape(0x06,0x07);
957 // Set cursor pos for page 0..7
959 biosfn_set_cursor_pos(i
,0x0000);
962 biosfn_set_active_page(0x00);
964 // Write the fonts in memory
965 if(vga_modes
[line
].class==TEXT
)
967 biosfn_load_text_8_16_pat(0x04,0x00);
970 // Set the ints 0x1F and 0x43
972 SET_INT_VECTOR(0x1f, #0xC000, #vgafont8+128*8)
978 SET_INT_VECTOR(0x43, #0xC000, #vgafont8)
983 SET_INT_VECTOR(0x43, #0xC000, #vgafont14)
988 SET_INT_VECTOR(0x43, #0xC000, #vgafont16)
994 // --------------------------------------------------------------------------------------------
995 static void biosfn_set_cursor_shape (CH
,CL
)
997 {Bit16u cheight
,curs
;
1003 write_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
,curs
);
1005 cheight
= read_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
);
1006 if((cheight
>8) && (CL
<8) && (CH
<0x20))
1010 CH
= ((CH
+1) * cheight
/ 8) -1;
1014 CH
= ((CL
+1) * cheight
/ 8) - 2;
1016 CL
= ((CL
+1) * cheight
/ 8) - 1;
1019 // CTRC regs 0x0a and 0x0b
1020 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
),0x0a);
1021 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1,CH
);
1022 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
),0x0b);
1023 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1,CL
);
1026 // --------------------------------------------------------------------------------------------
1027 static void biosfn_set_cursor_pos (page
, cursor
)
1028 Bit8u page
;Bit16u cursor
;
1030 Bit8u xcurs
,ycurs
,current
;
1031 Bit16u nbcols
,nbrows
,address
;
1033 // Should not happen...
1037 write_word(BIOSMEM_SEG
, BIOSMEM_CURSOR_POS
+2*page
, cursor
);
1039 // Set the hardware cursor
1040 current
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1043 // Get the dimensions
1044 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1045 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1047 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1049 // Calculate the address knowing nbcols nbrows and page num
1050 address
=SCREEN_IO_START(nbcols
,nbrows
,page
)+xcurs
+ycurs
*nbcols
;
1052 // CRTC regs 0x0e and 0x0f
1053 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
),0x0e);
1054 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1,(address
&0xff00)>>8);
1055 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
),0x0f);
1056 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1,address
&0x00ff);
1060 // --------------------------------------------------------------------------------------------
1061 static void biosfn_get_cursor_pos (page
,shape
, pos
)
1062 Bit8u page
;Bit16u
*shape
;Bit16u
*pos
;
1067 write_word(ss
, shape
, 0);
1068 write_word(ss
, pos
, 0);
1071 // FIXME should handle VGA 14/16 lines
1072 write_word(ss
,shape
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_TYPE
));
1073 write_word(ss
,pos
,read_word(BIOSMEM_SEG
,BIOSMEM_CURSOR_POS
+page
*2));
1076 // --------------------------------------------------------------------------------------------
1077 static void biosfn_set_active_page (page
)
1080 Bit16u cursor
,dummy
;
1081 Bit16u nbcols
,nbrows
,address
;
1087 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1088 line
=find_vga_entry(mode
);
1089 if(line
==0xFF)return;
1091 // Get pos curs pos for the right page
1092 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1094 if(vga_modes
[line
].class==TEXT
)
1096 // Get the dimensions
1097 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1098 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1100 // Calculate the address knowing nbcols nbrows and page num
1101 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1102 write_word(BIOSMEM_SEG
,BIOSMEM_CURRENT_START
,address
);
1105 address
=SCREEN_IO_START(nbcols
,nbrows
,page
);
1109 address
= page
*vga_modes
[line
].slength
;
1112 // CRTC regs 0x0c and 0x0d
1113 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
),0x0c);
1114 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1,(address
&0xff00)>>8);
1115 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
),0x0d);
1116 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1,address
&0x00ff);
1118 // And change the BIOS page
1119 write_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
,page
);
1122 printf("Set active page %02x address %04x\n",page
,address
);
1125 // Display the cursor, now the page is active
1126 biosfn_set_cursor_pos(page
,cursor
);
1129 // --------------------------------------------------------------------------------------------
1130 static void biosfn_scroll (nblines
,attr
,rul
,cul
,rlr
,clr
,page
,dir
)
1131 Bit8u nblines
;Bit8u attr
;Bit8u rul
;Bit8u cul
;Bit8u rlr
;Bit8u clr
;Bit8u page
;Bit8u dir
;
1133 // page == 0xFF if current
1136 Bit16u nbcols
,nbrows
,i
;
1143 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1144 line
=find_vga_entry(mode
);
1145 if(line
==0xFF)return;
1147 // Get the dimensions
1148 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1149 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1151 // Get the current page
1153 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1155 if(vga_modes
[line
].class==TEXT
)
1157 // Compute the address
1158 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
);
1160 printf("Scroll, address %04x (%04x %04x %02x)\n",address
,nbrows
,nbcols
,page
);
1163 if(rlr
>=nbrows
)rlr
=nbrows
-1;
1164 if(clr
>=nbcols
)clr
=nbcols
-1;
1165 if(nblines
>nbrows
)nblines
=0;
1167 if(nblines
==0&&rul
==0&&cul
==0&&rlr
==nbrows
-1&&clr
==nbcols
-1)
1169 memsetw(vga_modes
[line
].sstart
,address
,(Bit16u
)attr
*0x100+' ',nbrows
*nbcols
);
1174 {for(i
=rul
;i
<=rlr
;i
++)
1176 if((i
+nblines
>rlr
)||(nblines
==0))
1177 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1179 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
+nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1183 {for(i
=rlr
;i
>=rul
;i
--)
1185 if((i
<rul
+nblines
)||(nblines
==0))
1186 memsetw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,(Bit16u
)attr
*0x100+' ',clr
-cul
+1);
1188 memcpyw(vga_modes
[line
].sstart
,address
+(i
*nbcols
+cul
)*2,vga_modes
[line
].sstart
,((i
-nblines
)*nbcols
+cul
)*2,clr
-cul
+1);
1197 printf("Scroll in graphics mode !\n");
1203 // --------------------------------------------------------------------------------------------
1204 static void biosfn_read_char_attr (page
,car
)
1205 Bit8u page
;Bit16u
*car
;
1206 {Bit16u ss
=get_SS();
1207 Bit8u xcurs
,ycurs
,mode
,line
;
1208 Bit16u nbcols
,nbrows
,address
;
1209 Bit16u cursor
,dummy
;
1212 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1213 line
=find_vga_entry(mode
);
1214 if(line
==0xFF)return;
1216 // Get the cursor pos for the page
1217 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1218 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1220 // Get the dimensions
1221 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1222 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1224 if(vga_modes
[line
].class==TEXT
)
1226 // Compute the address
1227 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1229 write_word(ss
,car
,read_word(vga_modes
[line
].sstart
,address
));
1240 // --------------------------------------------------------------------------------------------
1241 static void write_gfx_char(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
)
1242 Bit8u car
;Bit8u attr
;Bit8u xcurs
;Bit8u ycurs
;Bit8u nbcols
;Bit8u cheight
;
1246 Bit16u addr
,dest
,src
;
1258 addr
=xcurs
+ycurs
*cheight
*nbcols
;
1259 src
= car
* cheight
;
1260 outb( VGAREG_SEQU_ADDRESS
, 0x02 );
1261 mmask
= inb( VGAREG_SEQU_DATA
);
1262 for(i
=0;i
<cheight
;i
++)
1265 outb( VGAREG_SEQU_DATA
, 0x0f );
1266 write_byte(0xa000,dest
,0x00);
1267 outb( VGAREG_SEQU_DATA
, attr
& 0x0f );
1268 write_byte(0xa000,dest
,fdata
[src
+i
]);
1270 outb( VGAREG_SEQU_DATA
, mmask
);
1273 // --------------------------------------------------------------------------------------------
1274 static void biosfn_write_char_attr (car
,page
,attr
,count
)
1275 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1277 Bit8u cheight
,xcurs
,ycurs
,mode
,line
;
1278 Bit16u nbcols
,nbrows
,address
;
1279 Bit16u cursor
,dummy
;
1282 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1283 line
=find_vga_entry(mode
);
1284 if(line
==0xFF)return;
1286 // Get the cursor pos for the page
1287 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1288 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1290 // Get the dimensions
1291 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1292 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1294 if(vga_modes
[line
].class==TEXT
)
1296 // Compute the address
1297 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1299 dummy
=((Bit16u
)attr
<<8)+car
;
1300 memsetw(vga_modes
[line
].sstart
,address
,dummy
,count
);
1304 // FIXME gfx mode not complete
1305 if(vga_modes
[line
].memmodel
==PLANAR4
)
1307 cheight
=vga_modes
[line
].cheight
;
1308 while((count
-->0) && (xcurs
<nbcols
))
1310 write_gfx_char(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1323 // --------------------------------------------------------------------------------------------
1324 static void biosfn_write_char_only (car
,page
,attr
,count
)
1325 Bit8u car
;Bit8u page
;Bit8u attr
;Bit16u count
;
1327 Bit8u cheight
,xcurs
,ycurs
,mode
,line
;
1328 Bit16u nbcols
,nbrows
,address
;
1329 Bit16u cursor
,dummy
;
1332 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1333 line
=find_vga_entry(mode
);
1334 if(line
==0xFF)return;
1336 // Get the cursor pos for the page
1337 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1338 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1340 // Get the dimensions
1341 nbrows
=read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
)+1;
1342 nbcols
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1344 if(vga_modes
[line
].class==TEXT
)
1346 // Compute the address
1347 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1350 {write_byte(vga_modes
[line
].sstart
,address
,car
);
1356 // FIXME gfx mode not complete
1357 if(vga_modes
[line
].memmodel
==PLANAR4
)
1359 cheight
=vga_modes
[line
].cheight
;
1360 while((count
-->0) && (xcurs
<nbcols
))
1362 write_gfx_char(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1375 // --------------------------------------------------------------------------------------------
1376 static void biosfn_set_border_color (BL
) Bit8u BL
;
1377 // FIXME anybody using this function ?
1384 // --------------------------------------------------------------------------------------------
1385 static void biosfn_set_palette (BL
) Bit8u BL
;
1386 // FIXME anybody using this function ?
1393 // --------------------------------------------------------------------------------------------
1394 static void biosfn_write_pixel (BH
,AL
,CX
,DX
) Bit8u BH
;Bit8u AL
;Bit16u CX
;Bit16u DX
;
1395 // FIXME anybody using this function ?
1402 // --------------------------------------------------------------------------------------------
1403 static void biosfn_read_pixel (BH
,CX
,DX
,AX
) Bit8u BH
;Bit16u CX
;Bit16u DX
;Bit16u
*AX
;
1404 // FIXME anybody using this function ?
1411 // --------------------------------------------------------------------------------------------
1412 static void biosfn_write_teletype (car
, page
, attr
, flag
)
1413 Bit8u car
;Bit8u page
;Bit8u attr
;Bit8u flag
;
1414 {// flag = WITH_ATTR / NO_ATTR
1416 Bit8u cheight
,xcurs
,ycurs
,mode
,line
;
1417 Bit16u nbcols
,nbrows
,address
;
1418 Bit16u cursor
,dummy
;
1420 // special case if page is 0xff, use current page
1422 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
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
);
1461 biosfn_write_teletype(' ',page
,attr
,flag
);
1462 biosfn_get_cursor_pos(page
,&dummy
,&cursor
);
1463 xcurs
=cursor
&0x00ff;ycurs
=(cursor
&0xff00)>>8;
1469 if(vga_modes
[line
].class==TEXT
)
1471 // Compute the address
1472 address
=SCREEN_MEM_START(nbcols
,nbrows
,page
)+(xcurs
+ycurs
*nbcols
)*2;
1475 write_byte(vga_modes
[line
].sstart
,address
,car
);
1478 write_byte(vga_modes
[line
].sstart
,address
+1,attr
);
1482 // FIXME gfx mode not complete
1483 if(vga_modes
[line
].memmodel
==PLANAR4
)
1485 cheight
=vga_modes
[line
].cheight
;
1486 write_gfx_char(car
,attr
,xcurs
,ycurs
,nbcols
,cheight
);
1499 // Do we need to wrap ?
1505 // Do we need to scroll ?
1507 {biosfn_scroll(0x01,0x07,0,0,nbrows
-1,nbcols
-1,page
,SCROLL_UP
);
1511 // Set the cursor for the page
1512 cursor
=ycurs
; cursor
<<=8; cursor
+=xcurs
;
1513 biosfn_set_cursor_pos(page
,cursor
);
1516 // --------------------------------------------------------------------------------------------
1517 static void biosfn_get_video_mode (AX
,BX
)
1518 Bit16u
*AX
;Bit16u
*BX
;
1519 {Bit16u ss
=get_SS();
1523 page
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_PAGE
);
1524 mode
=read_byte(BIOSMEM_SEG
,BIOSMEM_CURRENT_MODE
);
1525 nbcars
=read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1527 write_word(ss
,AX
,(nbcars
<<8)+mode
);
1528 write_word(ss
,BX
,((Bit16u
)page
)<<8);
1531 // --------------------------------------------------------------------------------------------
1532 static void biosfn_set_single_palette_reg (reg
,value
)
1533 Bit8u reg
;Bit8u value
;
1535 if(reg
<=ACTL_MAX_REG
)
1537 inb(VGAREG_ACTL_RESET
);
1538 outb(VGAREG_ACTL_ADDRESS
,reg
);
1539 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1540 outb(VGAREG_ACTL_ADDRESS
,0x20);
1544 // --------------------------------------------------------------------------------------------
1545 static void biosfn_set_overscan_border_color (value
)
1548 inb(VGAREG_ACTL_RESET
);
1549 outb(VGAREG_ACTL_ADDRESS
,0x11);
1550 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1551 outb(VGAREG_ACTL_ADDRESS
,0x20);
1554 // --------------------------------------------------------------------------------------------
1555 static void biosfn_set_all_palette_reg (seg
,offset
)
1556 Bit16u seg
;Bit16u offset
;
1560 inb(VGAREG_ACTL_RESET
);
1564 outb(VGAREG_ACTL_ADDRESS
,i
);
1565 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1570 outb(VGAREG_ACTL_ADDRESS
,0x11);
1571 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1572 outb(VGAREG_ACTL_ADDRESS
,0x20);
1575 // --------------------------------------------------------------------------------------------
1576 static void biosfn_toggle_intensity (state
)
1580 inb(VGAREG_ACTL_RESET
);
1582 outb(VGAREG_ACTL_ADDRESS
,0x10);
1583 value
=inb(VGAREG_ACTL_READ_DATA
);
1586 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1587 outb(VGAREG_ACTL_ADDRESS
,0x20);
1590 // --------------------------------------------------------------------------------------------
1591 static void biosfn_get_single_palette_reg (reg
,value
)
1592 Bit8u reg
;Bit16u
*value
;
1593 {Bit16u ss
=get_SS();
1595 if(reg
<=ACTL_MAX_REG
)
1597 inb(VGAREG_ACTL_RESET
);
1598 outb(VGAREG_ACTL_ADDRESS
,reg
);
1599 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1600 inb(VGAREG_ACTL_RESET
);
1601 outb(VGAREG_ACTL_ADDRESS
,0x20);
1605 // --------------------------------------------------------------------------------------------
1606 static void biosfn_read_overscan_border_color (value
)
1608 {Bit16u ss
=get_SS();
1610 inb(VGAREG_ACTL_RESET
);
1611 outb(VGAREG_ACTL_ADDRESS
,0x11);
1612 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1613 outb(VGAREG_ACTL_ADDRESS
,0x20);
1616 // --------------------------------------------------------------------------------------------
1617 static void biosfn_get_all_palette_reg (seg
,offset
) Bit16u seg
;Bit16u offset
;
1622 for(i
=0;i
<=0x10;i
++)
1624 inb(VGAREG_ACTL_RESET
);
1625 outb(VGAREG_ACTL_ADDRESS
,i
);
1626 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1631 outb(VGAREG_ACTL_ADDRESS
,0x11);
1632 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1633 outb(VGAREG_ACTL_ADDRESS
,0x20);
1636 // --------------------------------------------------------------------------------------------
1637 static void biosfn_set_single_dac_reg (reg
,g
,b
,r
)
1638 Bit16u reg
;Bit8u g
;Bit8u b
;Bit8u r
;
1640 outb(VGAREG_DAC_WRITE_ADDRESS
,reg
);
1641 outb(VGAREG_DAC_DATA
,r
);
1642 outb(VGAREG_DAC_DATA
,g
);
1643 outb(VGAREG_DAC_DATA
,b
);
1646 // --------------------------------------------------------------------------------------------
1647 static void biosfn_set_all_dac_reg (start
,count
,seg
,offset
)
1648 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1650 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1651 for(i
=0;i
<count
;i
++)
1652 {outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1653 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1654 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1658 // --------------------------------------------------------------------------------------------
1659 static void biosfn_select_video_dac_color_page (function
,page
)
1663 inb(VGAREG_ACTL_RESET
);
1664 outb(VGAREG_ACTL_ADDRESS
,0x10);
1666 value
=inb(VGAREG_ACTL_READ_DATA
);
1672 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1676 inb(VGAREG_ACTL_RESET
);
1677 outb(VGAREG_ACTL_ADDRESS
,0x14);
1679 outb(VGAREG_ACTL_WRITE_DATA
,page
&0x0f);
1681 outb(VGAREG_ACTL_WRITE_DATA
,(page
&0x03)<<2);
1683 outb(VGAREG_ACTL_ADDRESS
,0x20);
1686 // --------------------------------------------------------------------------------------------
1687 static void biosfn_read_single_dac_reg (reg
,tor
,togb
)
1688 Bit8u reg
;Bit16u
*tor
;Bit16u
*togb
;
1689 {Bit16u ss
=get_SS();
1692 outb(VGAREG_DAC_READ_ADDRESS
,reg
);
1693 r
=inb(VGAREG_DAC_DATA
);
1694 g
=inb(VGAREG_DAC_DATA
);
1695 b
=inb(VGAREG_DAC_DATA
);
1696 write_word(ss
,tor
,((Bit16u
)r
)<<8);
1697 write_word(ss
,togb
,(((Bit16u
)g
)<<8)+b
);
1700 // --------------------------------------------------------------------------------------------
1701 static void biosfn_read_all_dac_reg (start
,count
,seg
,offset
)
1702 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1704 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1705 for(i
=0;i
<count
;i
++)
1706 {write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1707 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1708 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1712 // --------------------------------------------------------------------------------------------
1713 static void biosfn_set_pel_mask (mask
)
1716 outb(VGAREG_PEL_MASK
,mask
);
1719 // --------------------------------------------------------------------------------------------
1720 static void biosfn_read_pel_mask (mask
)
1722 {Bit16u ss
=get_SS();
1724 write_word(ss
,mask
,inb(VGAREG_PEL_MASK
));
1727 // --------------------------------------------------------------------------------------------
1728 static void biosfn_read_video_dac_state (state
) Bit16u
*state
;
1729 {Bit16u ss
=get_SS();
1732 inb(VGAREG_ACTL_RESET
);
1733 outb(VGAREG_ACTL_ADDRESS
,0x10);
1734 mcr
=(inb(VGAREG_ACTL_READ_DATA
)>>7)&0x01;
1735 inb(VGAREG_ACTL_RESET
);
1736 outb(VGAREG_ACTL_ADDRESS
,0x14);
1737 csr
=inb(VGAREG_ACTL_READ_DATA
)&0x0f;
1738 if(mcr
==0)(csr
>>2)&0x03;
1740 write_word(ss
,state
,(mcr
<<8)+csr
);
1741 outb(VGAREG_ACTL_ADDRESS
,0x20);
1744 // --------------------------------------------------------------------------------------------
1745 static void biosfn_perform_gray_scale_summing (start
,count
)
1746 Bit16u start
;Bit16u count
;
1751 inb(VGAREG_ACTL_RESET
);
1752 outb(VGAREG_ACTL_ADDRESS
,0x10);
1753 d
=(inb(VGAREG_ACTL_READ_DATA
)>>6)&0x01;
1755 // depth is 8 or 6 bits
1760 // We start overwriting at
1761 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1762 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1764 for( index
= 0; index
< count
; index
++ )
1766 // get 6-bit wide RGB data values
1767 r
=inb( VGAREG_DAC_DATA
);
1768 g
=inb( VGAREG_DAC_DATA
);
1769 b
=inb( VGAREG_DAC_DATA
);
1771 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1772 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
1776 // write new intensity value
1777 outb( VGAREG_DAC_DATA
, i
&0xff );
1778 outb( VGAREG_DAC_DATA
, i
&0xff );
1779 outb( VGAREG_DAC_DATA
, i
&0xff );
1781 outb(VGAREG_ACTL_ADDRESS
,0x20);
1784 // --------------------------------------------------------------------------------------------
1785 static void get_font_access()
1787 outw( VGAREG_SEQU_ADDRESS
, 0x0100 );
1788 outw( VGAREG_SEQU_ADDRESS
, 0x0402 );
1789 outw( VGAREG_SEQU_ADDRESS
, 0x0704 );
1790 outw( VGAREG_SEQU_ADDRESS
, 0x0300 );
1791 outw( VGAREG_GRDC_ADDRESS
, 0x0204 );
1792 outw( VGAREG_GRDC_ADDRESS
, 0x0005 );
1793 outw( VGAREG_GRDC_ADDRESS
, 0x0406 );
1796 static void release_font_access()
1798 outw( VGAREG_SEQU_ADDRESS
, 0x0100 );
1799 outw( VGAREG_SEQU_ADDRESS
, 0x0302 );
1800 outw( VGAREG_SEQU_ADDRESS
, 0x0304 );
1801 outw( VGAREG_SEQU_ADDRESS
, 0x0300 );
1802 outw( VGAREG_GRDC_ADDRESS
, 0x0004 );
1803 outw( VGAREG_GRDC_ADDRESS
, 0x1005 );
1804 outw( VGAREG_GRDC_ADDRESS
, 0x0e06 );
1814 static void set_scan_lines(lines
) Bit8u lines
;
1816 Bit16u cols
,page
,vde
;
1817 Bit8u crtc9
,ovl
,rows
;
1819 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
), 0x09);
1820 crtc9
= inb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1);
1821 crtc9
= (crtc9
& 0xe0) | (lines
- 1);
1822 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1, crtc9
);
1825 biosfn_set_cursor_shape(0x06,0x07);
1829 biosfn_set_cursor_shape(lines
-4,lines
-3);
1831 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
1832 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
), 0x12);
1833 vde
= inb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1);
1834 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
), 0x07);
1835 ovl
= inb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1);
1836 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
1838 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
1839 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1840 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
1843 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
;
1845 Bit16u blockaddr
,dest
,i
,src
;
1848 blockaddr
= BL
<< 13;
1852 dest
= blockaddr
+ (DX
+ i
) * 32;
1853 memcpyb(0xA000, dest
, ES
, src
, BH
);
1855 release_font_access();
1862 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
1864 Bit16u blockaddr
,dest
,i
,src
;
1867 blockaddr
= BL
<< 13;
1868 for(i
=0;i
<0x100;i
++)
1871 dest
= blockaddr
+ i
* 32;
1872 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
1874 release_font_access();
1881 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
1883 Bit16u blockaddr
,dest
,i
,src
;
1886 blockaddr
= BL
<< 13;
1887 for(i
=0;i
<0x100;i
++)
1890 dest
= blockaddr
+ i
* 32;
1891 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
1893 release_font_access();
1900 static void biosfn_set_text_block_specifier (BL
) Bit8u BL
;
1902 outb( VGAREG_SEQU_ADDRESS
, 0x03 );
1903 outb( VGAREG_SEQU_DATA
, BL
);
1906 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
1908 Bit16u blockaddr
,dest
,i
,src
;
1911 blockaddr
= BL
<< 13;
1912 for(i
=0;i
<0x100;i
++)
1915 dest
= blockaddr
+ i
* 32;
1916 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
1918 release_font_access();
1925 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
1931 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
1937 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
1943 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
1949 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
1955 // --------------------------------------------------------------------------------------------
1956 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
1957 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
1958 {Bit16u ss
=get_SS();
1962 write_word(ss
,ES
,read_word(0x00,0x1f*4));
1963 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
1966 write_word(ss
,ES
,read_word(0x00,0x43*4));
1967 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
1970 write_word(ss
,ES
,0xC000);
1971 write_word(ss
,BP
,vgafont14
);
1974 write_word(ss
,ES
,0xC000);
1975 write_word(ss
,BP
,vgafont8
);
1978 write_word(ss
,ES
,0xC000);
1979 write_word(ss
,BP
,vgafont8
+128*8);
1982 write_word(ss
,ES
,0xC000);
1983 write_word(ss
,BP
,vgafont14alt
);
1986 write_word(ss
,ES
,0xC000);
1987 write_word(ss
,BP
,vgafont16
);
1990 write_word(ss
,ES
,0xC000);
1991 write_word(ss
,BP
,vgafont16alt
);
1995 printf("Get font info BH(%02x) was discarded\n",BH
);
1999 // Set byte/char of on screen font
2000 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
2002 // Set Highest char row
2003 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2006 // --------------------------------------------------------------------------------------------
2007 static void biosfn_get_ega_info (BX
,CX
)
2008 Bit16u
*BX
;Bit16u
*CX
;
2009 {Bit16u ss
=get_SS();
2013 crtc
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2014 if(crtc
==VGAREG_MDA_CRTC_ADDRESS
)
2015 write_word(ss
,BX
,(1<<8)+0x0003);
2017 write_word(ss
,BX
,0x0003);
2019 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2020 write_word(ss
,CX
,(switches
&0x0f));
2023 // --------------------------------------------------------------------------------------------
2024 static void biosfn_alternate_prtsc()
2031 // --------------------------------------------------------------------------------------------
2032 static void biosfn_select_vert_res (res
)
2034 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2035 Bit8u modeset
,switches
;
2037 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2038 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2041 // set modeset ctl bit 7 and reset bit 4
2042 // set switches bit 3-0 to 0x08
2043 modeset
|=0x80;modeset
&=0xef;
2044 switches
&=0xf0;switches
|=0x08;
2047 // reset modeset ctl bit 7 and bit 4
2048 // set switches bit 3-0 to 0x09
2050 switches
&=0xf0;switches
|=0x09;
2053 // reset modeset ctl bit 7 and set bit 4
2054 // set switches bit 3-0 to 0x09
2055 modeset
|=0x10;modeset
&=0x7f;
2056 switches
&=0xf0;switches
|=0x09;
2060 printf("Select vert res (%02x) was discarded\n",res
);
2064 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2065 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2068 // --------------------------------------------------------------------------------------------
2069 static void biosfn_enable_default_palette_loading (disable
)
2074 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2077 if(disable
!=0x00)modeset
|=0x08;
2080 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2083 // --------------------------------------------------------------------------------------------
2084 static void biosfn_enable_video_addressing (disable
)
2089 misc
=inb(VGAREG_READ_MISC_OUTPUT
);
2091 if(disable
!=0x00) misc
&=0xfd;
2093 outb(VGAREG_WRITE_MISC_OUTPUT
,misc
);
2096 // --------------------------------------------------------------------------------------------
2097 static void biosfn_enable_grayscale_summing (disable
)
2102 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2104 // Bit 1 set if disable=0
2105 if(disable
==0x00)modeset
|=0x02;
2108 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2111 // --------------------------------------------------------------------------------------------
2112 static void biosfn_enable_cursor_emulation (disable
)
2117 videoctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
2119 // Bit 0 set if disable!=0
2120 if(disable
!=0x00)videoctl
|=0x01;
2121 else videoctl
&=0xfe;
2123 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,videoctl
);
2126 // --------------------------------------------------------------------------------------------
2127 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2133 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2140 // --------------------------------------------------------------------------------------------
2141 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2142 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2144 Bit16u newcurs
,oldcurs
,dummy
;
2147 // Read curs info for the page
2148 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2150 // if row=0xff special case : use current cursor position
2152 {col
=oldcurs
&0x00ff;
2153 row
=(oldcurs
&0xff00)>>8;
2156 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2157 biosfn_set_cursor_pos(page
,newcurs
);
2161 car
=read_byte(seg
,offset
++);
2163 attr
=read_byte(seg
,offset
++);
2165 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2168 // Set back curs pos
2170 biosfn_set_cursor_pos(page
,oldcurs
);
2173 // --------------------------------------------------------------------------------------------
2174 static void biosfn_read_display_code (BX
)
2178 write_word(ss
,BX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2181 // --------------------------------------------------------------------------------------------
2182 static void biosfn_set_display_code (BL
,BH
)
2185 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,BL
);
2188 printf("Alternate Display code (%02x) was discarded\n",BH
);
2192 // --------------------------------------------------------------------------------------------
2193 static void biosfn_read_state_info (BX
,ES
,DI
)
2194 Bit16u BX
;Bit16u ES
;Bit16u DI
;
2196 // Address of static functionality table
2197 write_word(ES
,DI
+0x00,&static_functionality
);
2198 write_word(ES
,DI
+0x02,0xC000);
2200 // Hard coded copy from BIOS area. Should it be cleaner ?
2201 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
2202 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
2204 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2205 write_byte(ES
,DI
+0x26,0);
2206 write_byte(ES
,DI
+0x27,16);
2207 write_byte(ES
,DI
+0x28,0);
2208 write_byte(ES
,DI
+0x29,8);
2209 write_byte(ES
,DI
+0x2a,2);
2210 write_byte(ES
,DI
+0x2b,0);
2211 write_byte(ES
,DI
+0x2c,0);
2212 write_byte(ES
,DI
+0x31,3);
2213 write_byte(ES
,DI
+0x32,0);
2215 memsetb(ES
,DI
+0x33,0,13);
2218 // --------------------------------------------------------------------------------------------
2219 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2225 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2231 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2238 // ============================================================================================
2242 // ============================================================================================
2244 // --------------------------------------------------------------------------------------------
2245 static Bit8u
find_vga_entry(mode
)
2249 for(i
=0;i
<=MODE_MAX
;i
++)
2250 if(vga_modes
[i
].svgamode
==mode
)
2257 /* =========================================================== */
2261 /* =========================================================== */
2263 // --------------------------------------------------------------------------------------------
2264 static void memsetb(seg
,offset
,value
,count
)
2279 mov cx
, 10[bp
] ; count
2282 mov ax
, 4[bp
] ; segment
2284 mov ax
, 6[bp
] ; offset
2286 mov al
, 8[bp
] ; value
2301 // --------------------------------------------------------------------------------------------
2302 static void memsetw(seg
,offset
,value
,count
)
2317 mov cx
, 10[bp
] ; count
2320 mov ax
, 4[bp
] ; segment
2322 mov ax
, 6[bp
] ; offset
2324 mov ax
, 8[bp
] ; value
2339 // --------------------------------------------------------------------------------------------
2340 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
2358 mov cx
, 12[bp
] ; count
2361 mov ax
, 4[bp
] ; dsegment
2363 mov ax
, 6[bp
] ; doffset
2365 mov ax
, 8[bp
] ; ssegment
2367 mov ax
, 10[bp
] ; soffset
2385 // --------------------------------------------------------------------------------------------
2386 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
2404 mov cx
, 12[bp
] ; count
2407 mov ax
, 4[bp
] ; dsegment
2409 mov ax
, 6[bp
] ; doffset
2411 mov ax
, 8[bp
] ; ssegment
2413 mov ax
, 10[bp
] ; soffset
2431 /* =========================================================== */
2433 * These functions where ripped from Kevin's rombios.c
2435 /* =========================================================== */
2437 // --------------------------------------------------------------------------------------------
2439 read_byte(seg
, offset
)
2449 mov ax
, 4[bp
] ; segment
2451 mov bx
, 6[bp
] ; offset
2453 ;; al
= return value (byte
)
2461 // --------------------------------------------------------------------------------------------
2463 read_word(seg
, offset
)
2473 mov ax
, 4[bp
] ; segment
2475 mov bx
, 6[bp
] ; offset
2477 ;; ax
= return value (word
)
2485 // --------------------------------------------------------------------------------------------
2487 write_byte(seg
, offset
, data
)
2499 mov ax
, 4[bp
] ; segment
2501 mov bx
, 6[bp
] ; offset
2502 mov al
, 8[bp
] ; data byte
2503 mov
[bx
], al
; write data byte
2512 // --------------------------------------------------------------------------------------------
2514 write_word(seg
, offset
, data
)
2526 mov ax
, 4[bp
] ; segment
2528 mov bx
, 6[bp
] ; offset
2529 mov ax
, 8[bp
] ; data word
2530 mov
[bx
], ax
; write data word
2539 // --------------------------------------------------------------------------------------------
2574 // --------------------------------------------------------------------------------------------
2596 // --------------------------------------------------------------------------------------------
2626 void unimplemented()
2628 printf("--> Unimplemented\n");
2633 printf("--> Unknown int10\n");
2637 // --------------------------------------------------------------------------------------------
2641 Bit8u c
, format_char
;
2643 unsigned format_width
, i
;
2645 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
2653 while (c
= read_byte(0xc000, s
)) {
2658 else if (in_format
) {
2659 if ( (c
>='0') && (c
<='9') ) {
2660 format_width
= (format_width
* 10) + (c
- '0');
2662 else if (c
== 'x') {
2663 arg_ptr
++; // increment to next arg
2664 arg
= read_word(arg_seg
, arg_ptr
);
2665 if (format_width
== 0)
2668 digit
= format_width
- 1;
2669 for (i
=0; i
<format_width
; i
++) {
2670 nibble
= (arg
>> (4 * digit
)) & 0x000f;
2672 outb(0x0500, nibble
+ '0');
2674 outb(0x0500, (nibble
- 10) + 'A');
2679 //else if (c == 'd') {
2694 // --------------------------------------------------------------------------------------------
2697 ;; DATA_SEG_DEFS_HERE
2701 .ascii
"vgabios ends here"
2705 ;; BLOCK_STRINGS_BEGIN