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) 2002 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
);
1543 // --------------------------------------------------------------------------------------------
1544 static void biosfn_set_overscan_border_color (value
)
1547 inb(VGAREG_ACTL_RESET
);
1548 outb(VGAREG_ACTL_ADDRESS
,0x11);
1549 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1552 // --------------------------------------------------------------------------------------------
1553 static void biosfn_set_all_palette_reg (seg
,offset
)
1554 Bit16u seg
;Bit16u offset
;
1558 inb(VGAREG_ACTL_RESET
);
1560 for(i
=0;i
<=0x10;i
++)
1562 outb(VGAREG_ACTL_ADDRESS
,i
);
1563 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1568 outb(VGAREG_ACTL_ADDRESS
,0x11);
1569 outb(VGAREG_ACTL_WRITE_DATA
,read_byte(seg
,offset
));
1572 // --------------------------------------------------------------------------------------------
1573 static void biosfn_toggle_intensity (state
)
1577 inb(VGAREG_ACTL_RESET
);
1579 outb(VGAREG_ACTL_ADDRESS
,0x10);
1580 value
=inb(VGAREG_ACTL_READ_DATA
);
1584 inb(VGAREG_ACTL_RESET
);
1585 outb(VGAREG_ACTL_ADDRESS
,0x10);
1586 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1589 // --------------------------------------------------------------------------------------------
1590 static void biosfn_get_single_palette_reg (reg
,value
)
1591 Bit8u reg
;Bit16u
*value
;
1592 {Bit16u ss
=get_SS();
1594 if(reg
<=ACTL_MAX_REG
)
1596 inb(VGAREG_ACTL_RESET
);
1597 outb(VGAREG_ACTL_ADDRESS
,reg
);
1598 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1602 // --------------------------------------------------------------------------------------------
1603 static void biosfn_read_overscan_border_color (value
)
1605 {Bit16u ss
=get_SS();
1607 inb(VGAREG_ACTL_RESET
);
1608 outb(VGAREG_ACTL_ADDRESS
,0x11);
1609 write_word(ss
,value
,((Bit16u
)inb(VGAREG_ACTL_READ_DATA
))<<8);
1612 // --------------------------------------------------------------------------------------------
1613 static void biosfn_get_all_palette_reg (seg
,offset
) Bit16u seg
;Bit16u offset
;
1617 inb(VGAREG_ACTL_RESET
);
1619 for(i
=0;i
<=0x10;i
++)
1621 outb(VGAREG_ACTL_ADDRESS
,i
);
1622 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1627 outb(VGAREG_ACTL_ADDRESS
,0x11);
1628 write_byte(seg
,offset
,inb(VGAREG_ACTL_READ_DATA
));
1631 // --------------------------------------------------------------------------------------------
1632 static void biosfn_set_single_dac_reg (reg
,g
,b
,r
)
1633 Bit16u reg
;Bit8u g
;Bit8u b
;Bit8u r
;
1635 outb(VGAREG_DAC_WRITE_ADDRESS
,reg
);
1636 outb(VGAREG_DAC_DATA
,r
);
1637 outb(VGAREG_DAC_DATA
,g
);
1638 outb(VGAREG_DAC_DATA
,b
);
1641 // --------------------------------------------------------------------------------------------
1642 static void biosfn_set_all_dac_reg (start
,count
,seg
,offset
)
1643 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1645 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1646 for(i
=0;i
<count
;i
++)
1647 {outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1648 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1649 outb(VGAREG_DAC_DATA
,read_byte(seg
,offset
++));
1653 // --------------------------------------------------------------------------------------------
1654 static void biosfn_select_video_dac_color_page (function
,page
)
1658 inb(VGAREG_ACTL_RESET
);
1659 outb(VGAREG_ACTL_ADDRESS
,0x10);
1661 value
=inb(VGAREG_ACTL_READ_DATA
);
1668 inb(VGAREG_ACTL_RESET
);
1669 outb(VGAREG_ACTL_ADDRESS
,0x10);
1670 outb(VGAREG_ACTL_WRITE_DATA
,value
);
1674 inb(VGAREG_ACTL_RESET
);
1675 outb(VGAREG_ACTL_ADDRESS
,0x14);
1677 outb(VGAREG_ACTL_WRITE_DATA
,page
&0x0f);
1679 outb(VGAREG_ACTL_WRITE_DATA
,(page
&0x03)<<2);
1683 // --------------------------------------------------------------------------------------------
1684 static void biosfn_read_single_dac_reg (reg
,tor
,togb
)
1685 Bit8u reg
;Bit16u
*tor
;Bit16u
*togb
;
1686 {Bit16u ss
=get_SS();
1689 outb(VGAREG_DAC_READ_ADDRESS
,reg
);
1690 r
=inb(VGAREG_DAC_DATA
);
1691 g
=inb(VGAREG_DAC_DATA
);
1692 b
=inb(VGAREG_DAC_DATA
);
1693 write_word(ss
,tor
,((Bit16u
)r
)<<8);
1694 write_word(ss
,togb
,(((Bit16u
)g
)<<8)+b
);
1697 // --------------------------------------------------------------------------------------------
1698 static void biosfn_read_all_dac_reg (start
,count
,seg
,offset
)
1699 Bit16u start
;Bit16u count
;Bit16u seg
;Bit16u offset
;
1701 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1702 for(i
=0;i
<count
;i
++)
1703 {write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1704 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1705 write_byte(seg
,offset
++,inb(VGAREG_DAC_DATA
));
1709 // --------------------------------------------------------------------------------------------
1710 static void biosfn_set_pel_mask (mask
)
1713 outb(VGAREG_PEL_MASK
,mask
);
1716 // --------------------------------------------------------------------------------------------
1717 static void biosfn_read_pel_mask (mask
)
1719 {Bit16u ss
=get_SS();
1721 write_word(ss
,mask
,inb(VGAREG_PEL_MASK
));
1724 // --------------------------------------------------------------------------------------------
1725 static void biosfn_read_video_dac_state (state
) Bit16u
*state
;
1726 {Bit16u ss
=get_SS();
1729 inb(VGAREG_ACTL_RESET
);
1730 outb(VGAREG_ACTL_ADDRESS
,0x10);
1731 mcr
=(inb(VGAREG_ACTL_READ_DATA
)>>7)&0x01;
1732 inb(VGAREG_ACTL_RESET
);
1733 outb(VGAREG_ACTL_ADDRESS
,0x14);
1734 csr
=inb(VGAREG_ACTL_READ_DATA
)&0x0f;
1735 if(mcr
==0)(csr
>>2)&0x03;
1737 write_word(ss
,state
,(mcr
<<8)+csr
);
1740 // --------------------------------------------------------------------------------------------
1741 static void biosfn_perform_gray_scale_summing (start
,count
)
1742 Bit16u start
;Bit16u count
;
1747 inb(VGAREG_ACTL_RESET
);
1748 outb(VGAREG_ACTL_ADDRESS
,0x10);
1749 d
=(inb(VGAREG_ACTL_READ_DATA
)>>6)&0x01;
1751 // depth is 8 or 6 bits
1756 // We start overwriting at
1757 outb(VGAREG_DAC_READ_ADDRESS
,start
);
1758 outb(VGAREG_DAC_WRITE_ADDRESS
,start
);
1760 for( index
= 0; index
< count
; index
++ )
1762 // get 6-bit wide RGB data values
1763 r
=inb( VGAREG_DAC_DATA
);
1764 g
=inb( VGAREG_DAC_DATA
);
1765 b
=inb( VGAREG_DAC_DATA
);
1767 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1768 i
= ( ( 77*r
+ 151*g
+ 28*b
) + 0x80 ) >> 8;
1772 // write new intensity value
1773 outb( VGAREG_DAC_DATA
, i
&0xff );
1774 outb( VGAREG_DAC_DATA
, i
&0xff );
1775 outb( VGAREG_DAC_DATA
, i
&0xff );
1779 // --------------------------------------------------------------------------------------------
1780 static void get_font_access()
1782 outw( VGAREG_SEQU_ADDRESS
, 0x0100 );
1783 outw( VGAREG_SEQU_ADDRESS
, 0x0402 );
1784 outw( VGAREG_SEQU_ADDRESS
, 0x0704 );
1785 outw( VGAREG_SEQU_ADDRESS
, 0x0300 );
1786 outw( VGAREG_GRDC_ADDRESS
, 0x0204 );
1787 outw( VGAREG_GRDC_ADDRESS
, 0x0005 );
1788 outw( VGAREG_GRDC_ADDRESS
, 0x0406 );
1791 static void release_font_access()
1793 outw( VGAREG_SEQU_ADDRESS
, 0x0100 );
1794 outw( VGAREG_SEQU_ADDRESS
, 0x0302 );
1795 outw( VGAREG_SEQU_ADDRESS
, 0x0304 );
1796 outw( VGAREG_SEQU_ADDRESS
, 0x0300 );
1797 outw( VGAREG_GRDC_ADDRESS
, 0x0004 );
1798 outw( VGAREG_GRDC_ADDRESS
, 0x1005 );
1799 outw( VGAREG_GRDC_ADDRESS
, 0x0e06 );
1809 static void set_scan_lines(lines
) Bit8u lines
;
1811 Bit16u cols
,page
,vde
;
1812 Bit8u crtc9
,ovl
,rows
;
1814 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
), 0x09);
1815 crtc9
= inb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1);
1816 crtc9
= (crtc9
& 0xe0) | (lines
- 1);
1817 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1, crtc9
);
1820 biosfn_set_cursor_shape(0x06,0x07);
1824 biosfn_set_cursor_shape(lines
-4,lines
-3);
1826 write_word(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
, lines
);
1827 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
), 0x12);
1828 vde
= inb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1);
1829 outb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
), 0x07);
1830 ovl
= inb(read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
)+1);
1831 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
1833 write_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
, rows
-1);
1834 cols
= read_word(BIOSMEM_SEG
,BIOSMEM_NB_COLS
);
1835 write_word(BIOSMEM_SEG
,BIOSMEM_PAGE_SIZE
, rows
* cols
* 2);
1838 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
;
1840 Bit16u blockaddr
,dest
,i
,src
;
1843 blockaddr
= BL
<< 13;
1847 dest
= blockaddr
+ (DX
+ i
) * 32;
1848 memcpyb(0xA000, dest
, ES
, src
, BH
);
1850 release_font_access();
1857 static void biosfn_load_text_8_14_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
1859 Bit16u blockaddr
,dest
,i
,src
;
1862 blockaddr
= BL
<< 13;
1863 for(i
=0;i
<0x100;i
++)
1866 dest
= blockaddr
+ i
* 32;
1867 memcpyb(0xA000, dest
, 0xC000, vgafont14
+src
, 14);
1869 release_font_access();
1876 static void biosfn_load_text_8_8_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
1878 Bit16u blockaddr
,dest
,i
,src
;
1881 blockaddr
= BL
<< 13;
1882 for(i
=0;i
<0x100;i
++)
1885 dest
= blockaddr
+ i
* 32;
1886 memcpyb(0xA000, dest
, 0xC000, vgafont8
+src
, 8);
1888 release_font_access();
1895 static void biosfn_set_text_block_specifier (BL
) Bit8u BL
;
1897 outb( VGAREG_SEQU_ADDRESS
, 0x03 );
1898 outb( VGAREG_SEQU_DATA
, BL
);
1901 static void biosfn_load_text_8_16_pat (AL
,BL
) Bit8u AL
;Bit8u BL
;
1903 Bit16u blockaddr
,dest
,i
,src
;
1906 blockaddr
= BL
<< 13;
1907 for(i
=0;i
<0x100;i
++)
1910 dest
= blockaddr
+ i
* 32;
1911 memcpyb(0xA000, dest
, 0xC000, vgafont16
+src
, 16);
1913 release_font_access();
1920 static void biosfn_load_gfx_8_8_chars (ES
,BP
) Bit16u ES
;Bit16u BP
;
1926 static void biosfn_load_gfx_user_chars (ES
,BP
,CX
,BL
,DL
) Bit16u ES
;Bit16u BP
;Bit16u CX
;Bit8u BL
;Bit8u DL
;
1932 static void biosfn_load_gfx_8_14_chars (BL
) Bit8u BL
;
1938 static void biosfn_load_gfx_8_8_dd_chars (BL
) Bit8u BL
;
1944 static void biosfn_load_gfx_8_16_chars (BL
) Bit8u BL
;
1950 // --------------------------------------------------------------------------------------------
1951 static void biosfn_get_font_info (BH
,ES
,BP
,CX
,DX
)
1952 Bit8u BH
;Bit16u
*ES
;Bit16u
*BP
;Bit16u
*CX
;Bit16u
*DX
;
1953 {Bit16u ss
=get_SS();
1957 write_word(ss
,ES
,read_word(0x00,0x1f*4));
1958 write_word(ss
,BP
,read_word(0x00,(0x1f*4)+2));
1961 write_word(ss
,ES
,read_word(0x00,0x43*4));
1962 write_word(ss
,BP
,read_word(0x00,(0x43*4)+2));
1965 write_word(ss
,ES
,0xC000);
1966 write_word(ss
,BP
,vgafont14
);
1969 write_word(ss
,ES
,0xC000);
1970 write_word(ss
,BP
,vgafont8
);
1973 write_word(ss
,ES
,0xC000);
1974 write_word(ss
,BP
,vgafont8
+128*8);
1977 write_word(ss
,ES
,0xC000);
1978 write_word(ss
,BP
,vgafont14alt
);
1981 write_word(ss
,ES
,0xC000);
1982 write_word(ss
,BP
,vgafont16
);
1985 write_word(ss
,ES
,0xC000);
1986 write_word(ss
,BP
,vgafont16alt
);
1990 printf("Get font info BH(%02x) was discarded\n",BH
);
1994 // Set byte/char of on screen font
1995 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_CHAR_HEIGHT
));
1997 // Set Highest char row
1998 write_word(ss
,DX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_NB_ROWS
));
2001 // --------------------------------------------------------------------------------------------
2002 static void biosfn_get_ega_info (BX
,CX
)
2003 Bit16u
*BX
;Bit16u
*CX
;
2004 {Bit16u ss
=get_SS();
2008 crtc
=read_word(BIOSMEM_SEG
,BIOSMEM_CRTC_ADDRESS
);
2009 if(crtc
==VGAREG_MDA_CRTC_ADDRESS
)
2010 write_word(ss
,BX
,(1<<8)+0x0003);
2012 write_word(ss
,BX
,0x0003);
2014 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2015 write_word(ss
,CX
,(switches
&0x0f));
2018 // --------------------------------------------------------------------------------------------
2019 static void biosfn_alternate_prtsc()
2026 // --------------------------------------------------------------------------------------------
2027 static void biosfn_select_vert_res (res
)
2029 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2030 Bit8u modeset
,switches
;
2032 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2033 switches
=read_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
);
2036 // set modeset ctl bit 7 and reset bit 4
2037 // set switches bit 3-0 to 0x08
2038 modeset
|=0x80;modeset
&=0xef;
2039 switches
&=0xf0;switches
|=0x08;
2042 // reset modeset ctl bit 7 and bit 4
2043 // set switches bit 3-0 to 0x09
2045 switches
&=0xf0;switches
|=0x09;
2048 // reset modeset ctl bit 7 and set bit 4
2049 // set switches bit 3-0 to 0x09
2050 modeset
|=0x10;modeset
&=0x7f;
2051 switches
&=0xf0;switches
|=0x09;
2055 printf("Select vert res (%02x) was discarded\n",res
);
2059 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2060 write_byte(BIOSMEM_SEG
,BIOSMEM_SWITCHES
,switches
);
2063 // --------------------------------------------------------------------------------------------
2064 static void biosfn_enable_default_palette_loading (disable
)
2069 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2072 if(disable
!=0x00)modeset
|=0x08;
2075 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2078 // --------------------------------------------------------------------------------------------
2079 static void biosfn_enable_video_addressing (disable
)
2084 misc
=inb(VGAREG_READ_MISC_OUTPUT
);
2086 if(disable
!=0x00) misc
&=0xfd;
2088 outb(VGAREG_WRITE_MISC_OUTPUT
,misc
);
2091 // --------------------------------------------------------------------------------------------
2092 static void biosfn_enable_grayscale_summing (disable
)
2097 modeset
=read_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
);
2099 // Bit 1 set if disable=0
2100 if(disable
==0x00)modeset
|=0x02;
2103 write_byte(BIOSMEM_SEG
,BIOSMEM_MODESET_CTL
,modeset
);
2106 // --------------------------------------------------------------------------------------------
2107 static void biosfn_enable_cursor_emulation (disable
)
2112 videoctl
=read_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
);
2114 // Bit 0 set if disable!=0
2115 if(disable
!=0x00)videoctl
|=0x01;
2116 else videoctl
&=0xfe;
2118 write_byte(BIOSMEM_SEG
,BIOSMEM_VIDEO_CTL
,videoctl
);
2121 // --------------------------------------------------------------------------------------------
2122 static void biosfn_switch_video_interface (AL
,ES
,DX
) Bit8u AL
;Bit16u ES
;Bit16u DX
;
2128 static void biosfn_enable_video_refresh_control (AL
) Bit8u AL
;
2135 // --------------------------------------------------------------------------------------------
2136 static void biosfn_write_string (flag
,page
,attr
,count
,row
,col
,seg
,offset
)
2137 Bit8u flag
;Bit8u page
;Bit8u attr
;Bit16u count
;Bit8u row
;Bit8u col
;Bit16u seg
;Bit16u offset
;
2139 Bit16u newcurs
,oldcurs
,dummy
;
2142 // Read curs info for the page
2143 biosfn_get_cursor_pos(page
,&dummy
,&oldcurs
);
2145 // if row=0xff special case : use current cursor position
2147 {col
=oldcurs
&0x00ff;
2148 row
=(oldcurs
&0xff00)>>8;
2151 newcurs
=row
; newcurs
<<=8; newcurs
+=col
;
2152 biosfn_set_cursor_pos(page
,newcurs
);
2156 car
=read_byte(seg
,offset
++);
2158 attr
=read_byte(seg
,offset
++);
2160 biosfn_write_teletype(car
,page
,attr
,WITH_ATTR
);
2163 // Set back curs pos
2165 biosfn_set_cursor_pos(page
,oldcurs
);
2168 // --------------------------------------------------------------------------------------------
2169 static void biosfn_read_display_code (BX
)
2173 write_word(ss
,BX
,(Bit16u
)read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2176 // --------------------------------------------------------------------------------------------
2177 static void biosfn_set_display_code (BL
,BH
)
2180 write_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
,BL
);
2183 printf("Alternate Display code (%02x) was discarded\n",BH
);
2187 // --------------------------------------------------------------------------------------------
2188 static void biosfn_read_state_info (BX
,ES
,DI
)
2189 Bit16u BX
;Bit16u ES
;Bit16u DI
;
2191 // Address of static functionality table
2192 write_word(ES
,DI
+0x00,&static_functionality
);
2193 write_word(ES
,DI
+0x02,0xC000);
2195 // Hard coded copy from BIOS area. Should it be cleaner ?
2196 memcpyb(ES
,DI
+0x04,BIOSMEM_SEG
,0x49,30);
2197 memcpyb(ES
,DI
+0x22,BIOSMEM_SEG
,0x84,3);
2199 write_byte(ES
,DI
+0x25,read_byte(BIOSMEM_SEG
,BIOSMEM_DCC_INDEX
));
2200 write_byte(ES
,DI
+0x26,0);
2201 write_byte(ES
,DI
+0x27,16);
2202 write_byte(ES
,DI
+0x28,0);
2203 write_byte(ES
,DI
+0x29,8);
2204 write_byte(ES
,DI
+0x2a,2);
2205 write_byte(ES
,DI
+0x2b,0);
2206 write_byte(ES
,DI
+0x2c,0);
2207 write_byte(ES
,DI
+0x31,3);
2208 write_byte(ES
,DI
+0x32,0);
2210 memsetb(ES
,DI
+0x33,0,13);
2213 // --------------------------------------------------------------------------------------------
2214 static void biosfn_read_video_state_size (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2220 static void biosfn_save_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2226 static void biosfn_restore_video_state (CX
,ES
,BX
) Bit16u CX
;Bit16u ES
;Bit16u BX
;
2233 // ============================================================================================
2237 // ============================================================================================
2239 // --------------------------------------------------------------------------------------------
2240 static Bit8u
find_vga_entry(mode
)
2244 for(i
=0;i
<=MODE_MAX
;i
++)
2245 if(vga_modes
[i
].svgamode
==mode
)
2252 /* =========================================================== */
2256 /* =========================================================== */
2258 // --------------------------------------------------------------------------------------------
2259 static void memsetb(seg
,offset
,value
,count
)
2274 mov cx
, 10[bp
] ; count
2277 mov ax
, 4[bp
] ; segment
2279 mov ax
, 6[bp
] ; offset
2281 mov al
, 8[bp
] ; value
2296 // --------------------------------------------------------------------------------------------
2297 static void memsetw(seg
,offset
,value
,count
)
2312 mov cx
, 10[bp
] ; count
2315 mov ax
, 4[bp
] ; segment
2317 mov ax
, 6[bp
] ; offset
2319 mov ax
, 8[bp
] ; value
2334 // --------------------------------------------------------------------------------------------
2335 static void memcpyb(dseg
,doffset
,sseg
,soffset
,count
)
2353 mov cx
, 12[bp
] ; count
2356 mov ax
, 4[bp
] ; dsegment
2358 mov ax
, 6[bp
] ; doffset
2360 mov ax
, 8[bp
] ; ssegment
2362 mov ax
, 10[bp
] ; soffset
2380 // --------------------------------------------------------------------------------------------
2381 static void memcpyw(dseg
,doffset
,sseg
,soffset
,count
)
2399 mov cx
, 12[bp
] ; count
2402 mov ax
, 4[bp
] ; dsegment
2404 mov ax
, 6[bp
] ; doffset
2406 mov ax
, 8[bp
] ; ssegment
2408 mov ax
, 10[bp
] ; soffset
2426 /* =========================================================== */
2428 * These functions where ripped from Kevin's rombios.c
2430 /* =========================================================== */
2432 // --------------------------------------------------------------------------------------------
2434 read_byte(seg
, offset
)
2444 mov ax
, 4[bp
] ; segment
2446 mov bx
, 6[bp
] ; offset
2448 ;; al
= return value (byte
)
2456 // --------------------------------------------------------------------------------------------
2458 read_word(seg
, offset
)
2468 mov ax
, 4[bp
] ; segment
2470 mov bx
, 6[bp
] ; offset
2472 ;; ax
= return value (word
)
2480 // --------------------------------------------------------------------------------------------
2482 write_byte(seg
, offset
, data
)
2494 mov ax
, 4[bp
] ; segment
2496 mov bx
, 6[bp
] ; offset
2497 mov al
, 8[bp
] ; data byte
2498 mov
[bx
], al
; write data byte
2507 // --------------------------------------------------------------------------------------------
2509 write_word(seg
, offset
, data
)
2521 mov ax
, 4[bp
] ; segment
2523 mov bx
, 6[bp
] ; offset
2524 mov ax
, 8[bp
] ; data word
2525 mov
[bx
], ax
; write data word
2534 // --------------------------------------------------------------------------------------------
2569 // --------------------------------------------------------------------------------------------
2591 // --------------------------------------------------------------------------------------------
2621 void unimplemented()
2623 printf("--> Unimplemented\n");
2628 printf("--> Unknown int10\n");
2632 // --------------------------------------------------------------------------------------------
2636 Bit8u c
, format_char
;
2638 unsigned format_width
, i
;
2640 Bit16u arg_seg
, arg
, digit
, nibble
, shift_count
;
2648 while (c
= read_byte(0xc000, s
)) {
2653 else if (in_format
) {
2654 if ( (c
>='0') && (c
<='9') ) {
2655 format_width
= (format_width
* 10) + (c
- '0');
2657 else if (c
== 'x') {
2658 arg_ptr
++; // increment to next arg
2659 arg
= read_word(arg_seg
, arg_ptr
);
2660 if (format_width
== 0)
2663 digit
= format_width
- 1;
2664 for (i
=0; i
<format_width
; i
++) {
2665 nibble
= (arg
>> (4 * digit
)) & 0x000f;
2667 outb(0x0500, nibble
+ '0');
2669 outb(0x0500, (nibble
- 10) + 'A');
2674 //else if (c == 'd') {
2689 // --------------------------------------------------------------------------------------------
2692 ;; DATA_SEG_DEFS_HERE
2696 .ascii
"vgabios ends here"
2700 ;; BLOCK_STRINGS_BEGIN