1 // ============================================================================================
5 // ============================================================================================
7 // Copyright (C) 2001-2008 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 // ============================================================================================
60 static Bit8u read_byte();
61 static Bit16u read_word();
62 static void write_byte();
63 static void write_word();
69 static Bit16u get_SS();
73 static void unimplemented();
74 static void unknown();
76 static Bit8u find_vga_entry();
78 static void memsetb();
79 static void memsetw();
80 static void memcpyb();
81 static void memcpyw();
83 static void biosfn_set_video_mode();
84 static void biosfn_set_cursor_shape();
85 static void biosfn_set_cursor_pos();
86 static void biosfn_get_cursor_pos();
87 static void biosfn_set_active_page();
88 static void biosfn_scroll();
89 static void biosfn_read_char_attr();
90 static void biosfn_write_char_attr();
91 static void biosfn_write_char_only();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_perform_gray_scale_summing();
96 static void biosfn_load_text_user_pat();
97 static void biosfn_load_text_8_14_pat();
98 static void biosfn_load_text_8_8_pat();
99 static void biosfn_load_text_8_16_pat();
100 static void biosfn_load_gfx_8_8_chars();
101 static void biosfn_load_gfx_user_chars();
102 static void biosfn_load_gfx_8_14_chars();
103 static void biosfn_load_gfx_8_8_dd_chars();
104 static void biosfn_load_gfx_8_16_chars();
105 static void biosfn_get_font_info();
106 static void biosfn_alternate_prtsc();
107 static void biosfn_switch_video_interface();
108 static void biosfn_enable_video_refresh_control();
109 static void biosfn_write_string();
110 static void biosfn_read_state_info();
111 static void biosfn_read_video_state_size();
112 static Bit16u biosfn_save_video_state();
113 static Bit16u biosfn_restore_video_state();
114 extern Bit8u video_save_pointer_table[];
116 // This is for compiling with gcc2 and gcc3
117 #define ASM_START #asm
118 #define ASM_END #endasm
143 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
145 .byte 0x40 /* BIOS extension length in units of 512 bytes */
150 jmp vgabios_init_func
154 .word vgabios_pci_data
157 // Info from Bart Oldeman
163 .ascii "Plex86/Bochs VGABios"
184 .ascii "(C) 2008 the LGPL VGABios developers Team"
189 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
195 .ascii "Please visit :"
197 ;;.ascii " . http://www.plex86.org"
199 .ascii " . http://bochs.sourceforge.net"
201 .ascii " . http://www.nongnu.org/vgabios"
211 .word 0x00b8 // CLGD5446
217 #error "Unknown PCI vendor and device id"
223 .byte 0x0 // class,hi: vga display
224 .word 0x300 // class,lo: vga display
225 .word 0x40 // bios size
227 .byte 0 // intel x86 data
228 .byte 0x80 // last image
233 ;; ============================================================================================
237 ;; ============================================================================================
243 ;; init basic bios vars
247 ;; init vbe functions
252 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
258 ;; display splash screen
259 call _display_splash_screen
261 ;; init video mode and clear the screen
270 call vbe_display_info
275 call cirrus_display_info
285 vgabios_int10_handler:
300 call biosfn_get_video_mode
315 call biosfn_set_text_block_specifier
322 call biosfn_get_ega_info
327 call biosfn_select_vert_res
332 call biosfn_enable_default_palette_loading
337 call biosfn_enable_video_addressing
342 call biosfn_enable_grayscale_summing
347 call biosfn_enable_cursor_emulation
365 jne int10_test_vbe_05
366 call vbe_biosfn_return_current_mode
370 jne int10_test_vbe_06
371 call vbe_biosfn_display_window_control
375 jne int10_test_vbe_07
376 call vbe_biosfn_set_get_logical_scan_line_length
380 jne int10_test_vbe_08
381 call vbe_biosfn_set_get_display_start
385 jne int10_test_vbe_0A
386 call vbe_biosfn_set_get_dac_palette_format
391 call vbe_biosfn_return_protected_mode_interface
400 ;; We have to set ds to access the right data segment
413 #include "vgatables.h"
414 #include "vgafonts.h"
417 * Boot time harware inits
421 ;; switch to color mode and enable CPU access 480 lines
426 ;; more than 64k 3C4/04
434 #if defined(USE_BX_INFO) || defined(DEBUG)
435 mov bx, #msg_vga_init
443 #if defined(USE_BX_INFO) || defined(DEBUG)
445 .ascii "VGABios $Id$"
450 // --------------------------------------------------------------------------------------------
452 * Boot time bios area inits
457 mov ax, # BIOSMEM_SEG
460 ;; init detected hardware BIOS Area
461 mov bx, # BIOSMEM_INITIAL_MODE
464 ;; set 80x25 color (not clear from RBIL but usual)
468 ;; Just for the first int10 find its children
470 ;; the default char height
471 mov bx, # BIOSMEM_CHAR_HEIGHT
476 mov bx, # BIOSMEM_VIDEO_CTL
480 ;; Set the basic screen we have
481 mov bx, # BIOSMEM_SWITCHES
485 ;; Set the basic modeset options
486 mov bx, # BIOSMEM_MODESET_CTL
490 ;; Set the default MSR
491 mov bx, # BIOSMEM_CURRENT_MSR
498 _video_save_pointer_table:
499 .word _video_param_table
502 .word 0 /* XXX: fill it */
505 .word 0 /* XXX: fill it */
508 .word 0 /* XXX: fill it */
511 .word 0 /* XXX: fill it */
514 .word 0 /* XXX: fill it */
517 .word 0 /* XXX: fill it */
522 // --------------------------------------------------------------------------------------------
524 * Boot time Splash screen
526 static void display_splash_screen()
530 // --------------------------------------------------------------------------------------------
535 static void display_info()
542 mov si,#vgabios_version
545 ;;mov si,#vgabios_copyright
546 ;;call _display_string
548 ;;call _display_string
550 mov si,#vgabios_license
552 mov si,#vgabios_website
557 static void display_string()
559 // Get length of string
586 // --------------------------------------------------------------------------------------------
588 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
589 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
591 // 0E is write char...
593 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
597 // --------------------------------------------------------------------------------------------
599 * int10 main dispatcher
601 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
602 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
609 biosfn_set_video_mode(GET_AL());
610 switch(GET_AL()&0x7F)
628 biosfn_set_cursor_shape(GET_CH(),GET_CL());
631 biosfn_set_cursor_pos(GET_BH(),DX);
634 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
637 // Read light pen pos (unimplemented)
647 biosfn_set_active_page(GET_AL());
650 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
653 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
656 biosfn_read_char_attr(GET_BH(),&AX);
659 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
662 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
665 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
668 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
671 // Ralf Brown Interrupt list is WRONG on bh(page)
672 // We do output only on the current page !
673 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
676 // All other functions of group AH=0x10 rewritten in assembler
677 biosfn_perform_gray_scale_summing(BX,CX);
684 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
688 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
692 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
696 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
699 biosfn_load_gfx_8_8_chars(ES,BP);
702 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
705 biosfn_load_gfx_8_14_chars(GET_BL());
708 biosfn_load_gfx_8_8_dd_chars(GET_BL());
711 biosfn_load_gfx_8_16_chars(GET_BL());
714 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
727 biosfn_alternate_prtsc();
730 biosfn_switch_video_interface(GET_AL(),ES,DX);
734 biosfn_enable_video_refresh_control(GET_AL());
744 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
747 biosfn_read_state_info(BX,ES,DI);
754 biosfn_read_video_state_size(CX,&BX);
757 biosfn_save_video_state(CX,ES,BX);
760 biosfn_restore_video_state(CX,ES,BX);
772 if (vbe_has_vbe_display()) {
776 vbe_biosfn_return_controller_information(&AX,ES,DI);
779 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
782 vbe_biosfn_set_mode(&AX,BX,ES,DI);
785 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
825 // ============================================================================================
829 // ============================================================================================
831 static void biosfn_set_video_mode(mode) Bit8u mode;
832 {// mode: Bit 7 is 1 if no clear screen
834 // Should we clear the screen ?
835 Bit8u noclearmem=mode&0x80;
836 Bit8u line,mmask,*palette,vpti;
837 Bit16u i,twidth,theightm1,cheight;
838 Bit8u modeset_ctl,video_ctl,vga_switches;
842 if (vbe_has_vbe_display()) {
843 dispi_set_enable(VBE_DISPI_DISABLED);
850 // find the entry in the video modes
851 line=find_vga_entry(mode);
854 printf("mode search %02x found line %02x\n",mode,line);
860 vpti=line_to_vpti[line];
861 twidth=video_param_table[vpti].twidth;
862 theightm1=video_param_table[vpti].theightm1;
863 cheight=video_param_table[vpti].cheight;
865 // Read the bios vga control
866 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
868 // Read the bios vga switches
869 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
871 // Read the bios mode set control
872 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
874 // Then we know the number of lines
877 // if palette loading (bit 3 of modeset ctl = 0)
878 if((modeset_ctl&0x08)==0)
880 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
882 // Set the whole dac always, from 0
883 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
885 // From which palette
886 switch(vga_modes[line].dacmodel)
900 // Always 256*3 values
901 for(i=0;i<0x0100;i++)
902 {if(i<=dac_regs[vga_modes[line].dacmodel])
903 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
904 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
905 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
908 {outb(VGAREG_DAC_DATA,0);
909 outb(VGAREG_DAC_DATA,0);
910 outb(VGAREG_DAC_DATA,0);
913 if((modeset_ctl&0x02)==0x02)
915 biosfn_perform_gray_scale_summing(0x00, 0x100);
919 // Reset Attribute Ctl flip-flop
920 inb(VGAREG_ACTL_RESET);
924 {outb(VGAREG_ACTL_ADDRESS,i);
925 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
927 outb(VGAREG_ACTL_ADDRESS,0x14);
928 outb(VGAREG_ACTL_WRITE_DATA,0x00);
931 outb(VGAREG_SEQU_ADDRESS,0);
932 outb(VGAREG_SEQU_DATA,0x03);
934 {outb(VGAREG_SEQU_ADDRESS,i);
935 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
940 {outb(VGAREG_GRDC_ADDRESS,i);
941 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
944 // Set CRTC address VGA or MDA
945 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
947 // Disable CRTC write protection
948 outw(crtc_addr,0x0011);
952 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
955 // Set the misc register
956 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
959 outb(VGAREG_ACTL_ADDRESS,0x20);
960 inb(VGAREG_ACTL_RESET);
964 if(vga_modes[line].class==TEXT)
966 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
972 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
976 outb( VGAREG_SEQU_ADDRESS, 0x02 );
977 mmask = inb( VGAREG_SEQU_DATA );
978 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
979 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
980 outb( VGAREG_SEQU_DATA, mmask );
986 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
987 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
988 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
989 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
990 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
991 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
992 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
993 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
994 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
996 // FIXME We nearly have the good tables. to be reworked
997 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
998 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
999 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
1002 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
1003 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
1006 if(vga_modes[line].class==TEXT)
1008 biosfn_set_cursor_shape(0x06,0x07);
1011 // Set cursor pos for page 0..7
1013 biosfn_set_cursor_pos(i,0x0000);
1015 // Set active page 0
1016 biosfn_set_active_page(0x00);
1018 // Write the fonts in memory
1019 if(vga_modes[line].class==TEXT)
1022 ;; copy and activate 8x16 font
1032 // Set the ints 0x1F and 0x43
1034 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1040 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1045 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1050 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1056 // --------------------------------------------------------------------------------------------
1057 static void biosfn_set_cursor_shape (CH,CL)
1059 {Bit16u cheight,curs,crtc_addr;
1066 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1068 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1069 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1070 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1074 CH = ((CH+1) * cheight / 8) -1;
1078 CH = ((CL+1) * cheight / 8) - 2;
1080 CL = ((CL+1) * cheight / 8) - 1;
1083 // CTRC regs 0x0a and 0x0b
1084 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1085 outb(crtc_addr,0x0a);
1086 outb(crtc_addr+1,CH);
1087 outb(crtc_addr,0x0b);
1088 outb(crtc_addr+1,CL);
1091 // --------------------------------------------------------------------------------------------
1092 static void biosfn_set_cursor_pos (page, cursor)
1093 Bit8u page;Bit16u cursor;
1095 Bit8u xcurs,ycurs,current;
1096 Bit16u nbcols,nbrows,address,crtc_addr;
1098 // Should not happen...
1102 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1104 // Set the hardware cursor
1105 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1108 // Get the dimensions
1109 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1110 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1112 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1114 // Calculate the address knowing nbcols nbrows and page num
1115 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1117 // CRTC regs 0x0e and 0x0f
1118 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1119 outb(crtc_addr,0x0e);
1120 outb(crtc_addr+1,(address&0xff00)>>8);
1121 outb(crtc_addr,0x0f);
1122 outb(crtc_addr+1,address&0x00ff);
1126 // --------------------------------------------------------------------------------------------
1127 static void biosfn_get_cursor_pos (page,shape, pos)
1128 Bit8u page;Bit16u *shape;Bit16u *pos;
1133 write_word(ss, shape, 0);
1134 write_word(ss, pos, 0);
1137 // FIXME should handle VGA 14/16 lines
1138 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1139 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1142 // --------------------------------------------------------------------------------------------
1143 static void biosfn_set_active_page (page)
1146 Bit16u cursor,dummy,crtc_addr;
1147 Bit16u nbcols,nbrows,address;
1153 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1154 line=find_vga_entry(mode);
1155 if(line==0xFF)return;
1157 // Get pos curs pos for the right page
1158 biosfn_get_cursor_pos(page,&dummy,&cursor);
1160 if(vga_modes[line].class==TEXT)
1162 // Get the dimensions
1163 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1164 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1166 // Calculate the address knowing nbcols nbrows and page num
1167 address=SCREEN_MEM_START(nbcols,nbrows,page);
1168 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1171 address=SCREEN_IO_START(nbcols,nbrows,page);
1175 address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
1178 // CRTC regs 0x0c and 0x0d
1179 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1180 outb(crtc_addr,0x0c);
1181 outb(crtc_addr+1,(address&0xff00)>>8);
1182 outb(crtc_addr,0x0d);
1183 outb(crtc_addr+1,address&0x00ff);
1185 // And change the BIOS page
1186 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1189 printf("Set active page %02x address %04x\n",page,address);
1192 // Display the cursor, now the page is active
1193 biosfn_set_cursor_pos(page,cursor);
1196 // --------------------------------------------------------------------------------------------
1197 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1198 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1203 src=ysrc*cheight*nbcols+xstart;
1204 dest=ydest*cheight*nbcols+xstart;
1205 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1206 for(i=0;i<cheight;i++)
1208 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1210 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1213 // --------------------------------------------------------------------------------------------
1214 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1215 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1220 dest=ystart*cheight*nbcols+xstart;
1221 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1222 for(i=0;i<cheight;i++)
1224 memsetb(0xa000,dest+i*nbcols,attr,cols);
1226 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1229 // --------------------------------------------------------------------------------------------
1230 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1231 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1236 src=((ysrc*cheight*nbcols)>>1)+xstart;
1237 dest=((ydest*cheight*nbcols)>>1)+xstart;
1238 for(i=0;i<cheight;i++)
1241 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1243 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1247 // --------------------------------------------------------------------------------------------
1248 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1249 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1254 dest=((ystart*cheight*nbcols)>>1)+xstart;
1255 for(i=0;i<cheight;i++)
1258 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1260 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1264 // --------------------------------------------------------------------------------------------
1265 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1266 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1268 // page == 0xFF if current
1270 Bit8u mode,line,cheight,bpp,cols;
1271 Bit16u nbcols,nbrows,i;
1278 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1279 line=find_vga_entry(mode);
1280 if(line==0xFF)return;
1282 // Get the dimensions
1283 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1284 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1286 // Get the current page
1288 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1290 if(rlr>=nbrows)rlr=nbrows-1;
1291 if(clr>=nbcols)clr=nbcols-1;
1292 if(nblines>nbrows)nblines=0;
1295 if(vga_modes[line].class==TEXT)
1297 // Compute the address
1298 address=SCREEN_MEM_START(nbcols,nbrows,page);
1300 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1303 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1305 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1310 {for(i=rul;i<=rlr;i++)
1312 if((i+nblines>rlr)||(nblines==0))
1313 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1315 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1319 {for(i=rlr;i>=rul;i--)
1321 if((i<rul+nblines)||(nblines==0))
1322 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1324 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1332 // FIXME gfx mode not complete
1333 cheight=video_param_table[line_to_vpti[line]].cheight;
1334 switch(vga_modes[line].memmodel)
1338 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1340 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1341 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1342 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1347 {for(i=rul;i<=rlr;i++)
1349 if((i+nblines>rlr)||(nblines==0))
1350 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1352 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1356 {for(i=rlr;i>=rul;i--)
1358 if((i<rul+nblines)||(nblines==0))
1359 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1361 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1368 bpp=vga_modes[line].pixbits;
1369 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1371 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1383 {for(i=rul;i<=rlr;i++)
1385 if((i+nblines>rlr)||(nblines==0))
1386 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1388 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1392 {for(i=rlr;i>=rul;i--)
1394 if((i<rul+nblines)||(nblines==0))
1395 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1397 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1405 printf("Scroll in graphics mode ");
1412 // --------------------------------------------------------------------------------------------
1413 static void biosfn_read_char_attr (page,car)
1414 Bit8u page;Bit16u *car;
1415 {Bit16u ss=get_SS();
1416 Bit8u xcurs,ycurs,mode,line;
1417 Bit16u nbcols,nbrows,address;
1418 Bit16u cursor,dummy;
1421 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1422 line=find_vga_entry(mode);
1423 if(line==0xFF)return;
1425 // Get the cursor pos for the page
1426 biosfn_get_cursor_pos(page,&dummy,&cursor);
1427 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1429 // Get the dimensions
1430 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1431 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1433 if(vga_modes[line].class==TEXT)
1435 // Compute the address
1436 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1438 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1449 // --------------------------------------------------------------------------------------------
1450 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1451 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1455 Bit16u addr,dest,src;
1467 addr=xcurs+ycurs*cheight*nbcols;
1468 src = car * cheight;
1469 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1470 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1473 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1477 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1479 for(i=0;i<cheight;i++)
1485 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1486 read_byte(0xa000,dest);
1487 if(fdata[src+i]&mask)
1489 write_byte(0xa000,dest,attr&0x0f);
1493 write_byte(0xa000,dest,0x00);
1498 mov dx, # VGAREG_GRDC_ADDRESS
1508 // --------------------------------------------------------------------------------------------
1509 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1510 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1512 Bit8u i,j,mask,data;
1514 Bit16u addr,dest,src;
1517 addr=(xcurs*bpp)+ycurs*320;
1521 dest=addr+(i>>1)*80;
1522 if (i & 1) dest += 0x2000;
1528 data = read_byte(0xb800,dest);
1536 if (fdata[src+i] & mask)
1540 data ^= (attr & 0x01) << (7-j);
1544 data |= (attr & 0x01) << (7-j);
1549 write_byte(0xb800,dest,data);
1557 data = read_byte(0xb800,dest);
1565 if (fdata[src+i] & mask)
1569 data ^= (attr & 0x03) << ((3-j)*2);
1573 data |= (attr & 0x03) << ((3-j)*2);
1578 write_byte(0xb800,dest,data);
1585 // --------------------------------------------------------------------------------------------
1586 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1587 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1589 Bit8u i,j,mask,data;
1591 Bit16u addr,dest,src;
1594 addr=xcurs*8+ycurs*nbcols*64;
1598 dest=addr+i*nbcols*8;
1603 if (fdata[src+i] & mask)
1607 write_byte(0xa000,dest+j,data);
1613 // --------------------------------------------------------------------------------------------
1614 static void biosfn_write_char_attr (car,page,attr,count)
1615 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1617 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1618 Bit16u nbcols,nbrows,address;
1619 Bit16u cursor,dummy;
1622 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1623 line=find_vga_entry(mode);
1624 if(line==0xFF)return;
1626 // Get the cursor pos for the page
1627 biosfn_get_cursor_pos(page,&dummy,&cursor);
1628 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1630 // Get the dimensions
1631 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1632 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1634 if(vga_modes[line].class==TEXT)
1636 // Compute the address
1637 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1639 dummy=((Bit16u)attr<<8)+car;
1640 memsetw(vga_modes[line].sstart,address,dummy,count);
1644 // FIXME gfx mode not complete
1645 cheight=video_param_table[line_to_vpti[line]].cheight;
1646 bpp=vga_modes[line].pixbits;
1647 while((count-->0) && (xcurs<nbcols))
1649 switch(vga_modes[line].memmodel)
1653 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1656 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1659 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1671 // --------------------------------------------------------------------------------------------
1672 static void biosfn_write_char_only (car,page,attr,count)
1673 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1675 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1676 Bit16u nbcols,nbrows,address;
1677 Bit16u cursor,dummy;
1680 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1681 line=find_vga_entry(mode);
1682 if(line==0xFF)return;
1684 // Get the cursor pos for the page
1685 biosfn_get_cursor_pos(page,&dummy,&cursor);
1686 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1688 // Get the dimensions
1689 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1690 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1692 if(vga_modes[line].class==TEXT)
1694 // Compute the address
1695 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1698 {write_byte(vga_modes[line].sstart,address,car);
1704 // FIXME gfx mode not complete
1705 cheight=video_param_table[line_to_vpti[line]].cheight;
1706 bpp=vga_modes[line].pixbits;
1707 while((count-->0) && (xcurs<nbcols))
1709 switch(vga_modes[line].memmodel)
1713 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1716 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1719 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1731 // --------------------------------------------------------------------------------------------
1735 je biosfn_set_border_color
1737 je biosfn_set_palette
1742 biosfn_set_border_color:
1747 mov dx, # VGAREG_ACTL_RESET
1749 mov dx, # VGAREG_ACTL_ADDRESS
1762 mov dx, # VGAREG_ACTL_ADDRESS
1765 mov dx, # VGAREG_ACTL_READ_DATA
1769 mov dx, # VGAREG_ACTL_ADDRESS
1773 jne set_intensity_loop
1786 mov dx, # VGAREG_ACTL_RESET
1790 set_cga_palette_loop:
1791 mov dx, # VGAREG_ACTL_ADDRESS
1794 mov dx, # VGAREG_ACTL_READ_DATA
1798 mov dx, # VGAREG_ACTL_ADDRESS
1802 jne set_cga_palette_loop
1812 // --------------------------------------------------------------------------------------------
1813 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1815 Bit8u mode,line,mask,attr,data;
1819 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1820 line=find_vga_entry(mode);
1821 if(line==0xFF)return;
1822 if(vga_modes[line].class==TEXT)return;
1824 switch(vga_modes[line].memmodel)
1828 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1829 mask = 0x80 >> (CX & 0x07);
1830 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1831 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1832 data = read_byte(0xa000,addr);
1835 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1837 write_byte(0xa000,addr,AL);
1839 mov dx, # VGAREG_GRDC_ADDRESS
1849 if(vga_modes[line].pixbits==2)
1851 addr=(CX>>2)+(DX>>1)*80;
1855 addr=(CX>>3)+(DX>>1)*80;
1857 if (DX & 1) addr += 0x2000;
1858 data = read_byte(0xb800,addr);
1859 if(vga_modes[line].pixbits==2)
1861 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1862 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1866 attr = (AL & 0x01) << (7 - (CX & 0x07));
1867 mask = 0x01 << (7 - (CX & 0x07));
1878 write_byte(0xb800,addr,data);
1881 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1882 write_byte(0xa000,addr,AL);
1891 // --------------------------------------------------------------------------------------------
1892 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1894 Bit8u mode,line,mask,attr,data,i;
1899 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1900 line=find_vga_entry(mode);
1901 if(line==0xFF)return;
1902 if(vga_modes[line].class==TEXT)return;
1904 switch(vga_modes[line].memmodel)
1908 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1909 mask = 0x80 >> (CX & 0x07);
1913 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1914 data = read_byte(0xa000,addr) & mask;
1915 if (data > 0) attr |= (0x01 << i);
1919 addr=(CX>>2)+(DX>>1)*80;
1920 if (DX & 1) addr += 0x2000;
1921 data = read_byte(0xb800,addr);
1922 if(vga_modes[line].pixbits==2)
1924 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1928 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1932 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1933 attr=read_byte(0xa000,addr);
1941 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1944 // --------------------------------------------------------------------------------------------
1945 static void biosfn_write_teletype (car, page, attr, flag)
1946 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1947 {// flag = WITH_ATTR / NO_ATTR
1949 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1950 Bit16u nbcols,nbrows,address;
1951 Bit16u cursor,dummy;
1953 // special case if page is 0xff, use current page
1955 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1958 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1959 line=find_vga_entry(mode);
1960 if(line==0xFF)return;
1962 // Get the cursor pos for the page
1963 biosfn_get_cursor_pos(page,&dummy,&cursor);
1964 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1966 // Get the dimensions
1967 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1968 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1991 biosfn_write_teletype(' ',page,attr,flag);
1992 biosfn_get_cursor_pos(page,&dummy,&cursor);
1993 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1999 if(vga_modes[line].class==TEXT)
2001 // Compute the address
2002 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
2005 write_byte(vga_modes[line].sstart,address,car);
2008 write_byte(vga_modes[line].sstart,address+1,attr);
2012 // FIXME gfx mode not complete
2013 cheight=video_param_table[line_to_vpti[line]].cheight;
2014 bpp=vga_modes[line].pixbits;
2015 switch(vga_modes[line].memmodel)
2019 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
2022 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
2025 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
2036 // Do we need to wrap ?
2042 // Do we need to scroll ?
2045 if(vga_modes[line].class==TEXT)
2047 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
2048 attr=read_byte(vga_modes[line].sstart,address+1);
2049 biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2053 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2058 // Set the cursor for the page
2059 cursor=ycurs; cursor<<=8; cursor+=xcurs;
2060 biosfn_set_cursor_pos(page,cursor);
2063 // --------------------------------------------------------------------------------------------
2065 biosfn_get_video_mode:
2067 mov ax, # BIOSMEM_SEG
2070 mov bx, # BIOSMEM_CURRENT_PAGE
2075 mov bx, # BIOSMEM_VIDEO_CTL
2078 mov bx, # BIOSMEM_CURRENT_MODE
2081 mov bx, # BIOSMEM_NB_COLS
2088 // --------------------------------------------------------------------------------------------
2093 jmp biosfn_set_single_palette_reg
2097 jmp biosfn_set_overscan_border_color
2101 jmp biosfn_set_all_palette_reg
2105 jmp biosfn_toggle_intensity
2109 jmp biosfn_get_single_palette_reg
2113 jmp biosfn_read_overscan_border_color
2117 jmp biosfn_get_all_palette_reg
2121 jmp biosfn_set_single_dac_reg
2125 jmp biosfn_set_all_dac_reg
2129 jmp biosfn_select_video_dac_color_page
2133 jmp biosfn_read_single_dac_reg
2137 jmp biosfn_read_all_dac_reg
2141 jmp biosfn_set_pel_mask
2145 jmp biosfn_read_pel_mask
2148 jne int10_group_10_unknown
2149 jmp biosfn_read_video_dac_state
2150 int10_group_10_unknown:
2156 biosfn_set_single_palette_reg:
2161 mov dx, # VGAREG_ACTL_RESET
2163 mov dx, # VGAREG_ACTL_ADDRESS
2176 // --------------------------------------------------------------------------------------------
2178 biosfn_set_overscan_border_color:
2181 call biosfn_set_single_palette_reg
2186 // --------------------------------------------------------------------------------------------
2188 biosfn_set_all_palette_reg:
2194 mov dx, # VGAREG_ACTL_RESET
2197 mov dx, # VGAREG_ACTL_ADDRESS
2207 jne set_palette_loop
2222 // --------------------------------------------------------------------------------------------
2224 biosfn_toggle_intensity:
2228 mov dx, # VGAREG_ACTL_RESET
2230 mov dx, # VGAREG_ACTL_ADDRESS
2233 mov dx, # VGAREG_ACTL_READ_DATA
2239 mov dx, # VGAREG_ACTL_ADDRESS
2249 // --------------------------------------------------------------------------------------------
2251 biosfn_get_single_palette_reg:
2256 mov dx, # VGAREG_ACTL_RESET
2258 mov dx, # VGAREG_ACTL_ADDRESS
2261 mov dx, # VGAREG_ACTL_READ_DATA
2264 mov dx, # VGAREG_ACTL_RESET
2266 mov dx, # VGAREG_ACTL_ADDRESS
2275 // --------------------------------------------------------------------------------------------
2277 biosfn_read_overscan_border_color:
2281 call biosfn_get_single_palette_reg
2289 // --------------------------------------------------------------------------------------------
2291 biosfn_get_all_palette_reg:
2299 mov dx, # VGAREG_ACTL_RESET
2301 mov dx, # VGAREG_ACTL_ADDRESS
2304 mov dx, # VGAREG_ACTL_READ_DATA
2311 jne get_palette_loop
2312 mov dx, # VGAREG_ACTL_RESET
2314 mov dx, # VGAREG_ACTL_ADDRESS
2317 mov dx, # VGAREG_ACTL_READ_DATA
2321 mov dx, # VGAREG_ACTL_RESET
2323 mov dx, # VGAREG_ACTL_ADDRESS
2333 // --------------------------------------------------------------------------------------------
2335 biosfn_set_single_dac_reg:
2338 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2341 mov dx, # VGAREG_DAC_DATA
2355 // --------------------------------------------------------------------------------------------
2357 biosfn_set_all_dac_reg:
2362 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2368 mov dx, # VGAREG_DAC_DATA
2391 // --------------------------------------------------------------------------------------------
2393 biosfn_select_video_dac_color_page:
2397 mov dx, # VGAREG_ACTL_RESET
2399 mov dx, # VGAREG_ACTL_ADDRESS
2402 mov dx, # VGAREG_ACTL_READ_DATA
2409 mov dx, # VGAREG_ACTL_ADDRESS
2414 mov dx, # VGAREG_ACTL_RESET
2416 mov dx, # VGAREG_ACTL_ADDRESS
2436 // --------------------------------------------------------------------------------------------
2438 biosfn_read_single_dac_reg:
2441 mov dx, # VGAREG_DAC_READ_ADDRESS
2446 mov dx, # VGAREG_DAC_DATA
2459 // --------------------------------------------------------------------------------------------
2461 biosfn_read_all_dac_reg:
2466 mov dx, # VGAREG_DAC_READ_ADDRESS
2472 mov dx, # VGAREG_DAC_DATA
2495 // --------------------------------------------------------------------------------------------
2497 biosfn_set_pel_mask:
2500 mov dx, # VGAREG_PEL_MASK
2508 // --------------------------------------------------------------------------------------------
2510 biosfn_read_pel_mask:
2513 mov dx, # VGAREG_PEL_MASK
2521 // --------------------------------------------------------------------------------------------
2523 biosfn_read_video_dac_state:
2526 mov dx, # VGAREG_ACTL_RESET
2528 mov dx, # VGAREG_ACTL_ADDRESS
2531 mov dx, # VGAREG_ACTL_READ_DATA
2535 mov dx, # VGAREG_ACTL_RESET
2537 mov dx, # VGAREG_ACTL_ADDRESS
2540 mov dx, # VGAREG_ACTL_READ_DATA
2548 mov dx, # VGAREG_ACTL_RESET
2550 mov dx, # VGAREG_ACTL_ADDRESS
2558 // --------------------------------------------------------------------------------------------
2559 static void biosfn_perform_gray_scale_summing (start,count)
2560 Bit16u start;Bit16u count;
2565 inb(VGAREG_ACTL_RESET);
2566 outb(VGAREG_ACTL_ADDRESS,0x00);
2568 for( index = 0; index < count; index++ )
2570 // set read address and switch to read mode
2571 outb(VGAREG_DAC_READ_ADDRESS,start);
2572 // get 6-bit wide RGB data values
2573 r=inb( VGAREG_DAC_DATA );
2574 g=inb( VGAREG_DAC_DATA );
2575 b=inb( VGAREG_DAC_DATA );
2577 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2578 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2582 // set write address and switch to write mode
2583 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2584 // write new intensity value
2585 outb( VGAREG_DAC_DATA, i&0xff );
2586 outb( VGAREG_DAC_DATA, i&0xff );
2587 outb( VGAREG_DAC_DATA, i&0xff );
2590 inb(VGAREG_ACTL_RESET);
2591 outb(VGAREG_ACTL_ADDRESS,0x20);
2594 // --------------------------------------------------------------------------------------------
2595 static void get_font_access()
2598 mov dx, # VGAREG_SEQU_ADDRESS
2607 mov dx, # VGAREG_GRDC_ADDRESS
2617 static void release_font_access()
2620 mov dx, # VGAREG_SEQU_ADDRESS
2629 mov dx, # VGAREG_READ_MISC_OUTPUT
2636 mov dx, # VGAREG_GRDC_ADDRESS
2652 static void set_scan_lines(lines) Bit8u lines;
2654 Bit16u crtc_addr,cols,page,vde;
2655 Bit8u crtc_r9,ovl,rows;
2657 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2658 outb(crtc_addr, 0x09);
2659 crtc_r9 = inb(crtc_addr+1);
2660 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2661 outb(crtc_addr+1, crtc_r9);
2664 biosfn_set_cursor_shape(0x06,0x07);
2668 biosfn_set_cursor_shape(lines-4,lines-3);
2670 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2671 outb(crtc_addr, 0x12);
2672 vde = inb(crtc_addr+1);
2673 outb(crtc_addr, 0x07);
2674 ovl = inb(crtc_addr+1);
2675 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2677 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2678 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2679 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2682 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;
2684 Bit16u blockaddr,dest,i,src;
2687 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2691 dest = blockaddr + (DX + i) * 32;
2692 memcpyb(0xA000, dest, ES, src, BH);
2694 release_font_access();
2701 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2703 Bit16u blockaddr,dest,i,src;
2706 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2707 for(i=0;i<0x100;i++)
2710 dest = blockaddr + i * 32;
2711 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2713 release_font_access();
2720 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2722 Bit16u blockaddr,dest,i,src;
2725 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2726 for(i=0;i<0x100;i++)
2729 dest = blockaddr + i * 32;
2730 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2732 release_font_access();
2739 // --------------------------------------------------------------------------------------------
2741 biosfn_set_text_block_specifier:
2744 mov dx, # VGAREG_SEQU_ADDRESS
2753 // --------------------------------------------------------------------------------------------
2754 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2756 Bit16u blockaddr,dest,i,src;
2759 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2760 for(i=0;i<0x100;i++)
2763 dest = blockaddr + i * 32;
2764 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2766 release_font_access();
2773 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2779 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2785 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2791 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2797 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2803 // --------------------------------------------------------------------------------------------
2804 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2805 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2806 {Bit16u ss=get_SS();
2810 write_word(ss,ES,read_word(0x00,0x1f*4));
2811 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2814 write_word(ss,ES,read_word(0x00,0x43*4));
2815 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2818 write_word(ss,ES,0xC000);
2819 write_word(ss,BP,vgafont14);
2822 write_word(ss,ES,0xC000);
2823 write_word(ss,BP,vgafont8);
2826 write_word(ss,ES,0xC000);
2827 write_word(ss,BP,vgafont8+128*8);
2830 write_word(ss,ES,0xC000);
2831 write_word(ss,BP,vgafont14alt);
2834 write_word(ss,ES,0xC000);
2835 write_word(ss,BP,vgafont16);
2838 write_word(ss,ES,0xC000);
2839 write_word(ss,BP,vgafont16alt);
2843 printf("Get font info BH(%02x) was discarded\n",BH);
2847 // Set byte/char of on screen font
2848 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2850 // Set Highest char row
2851 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2854 // --------------------------------------------------------------------------------------------
2856 biosfn_get_ega_info:
2859 mov ax, # BIOSMEM_SEG
2862 mov bx, # BIOSMEM_SWITCHES
2865 mov bx, # BIOSMEM_CRTC_ADDRESS
2868 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2877 // --------------------------------------------------------------------------------------------
2878 static void biosfn_alternate_prtsc()
2885 // --------------------------------------------------------------------------------------------
2887 biosfn_select_vert_res:
2889 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2895 mov ax, # BIOSMEM_SEG
2897 mov bx, # BIOSMEM_MODESET_CTL
2899 mov bx, # BIOSMEM_SWITCHES
2910 mov bx, #msg_vert_res
2918 ; reset modeset ctl bit 7 and set bit 4
2919 ; set switches bit 3-0 to 0x09
2928 ; reset modeset ctl bit 7 and bit 4
2929 ; set switches bit 3-0 to 0x09
2937 ; set modeset ctl bit 7 and reset bit 4
2938 ; set switches bit 3-0 to 0x08
2945 mov bx, # BIOSMEM_MODESET_CTL
2947 mov bx, # BIOSMEM_SWITCHES
2958 .ascii "Select vert res (%02x) was discarded"
2959 .byte 0x0d,0x0a,0x00
2963 biosfn_enable_default_palette_loading:
2970 mov ax, # BIOSMEM_SEG
2972 mov bx, # BIOSMEM_MODESET_CTL
2984 biosfn_enable_video_addressing:
2991 mov dx, # VGAREG_READ_MISC_OUTPUT
2995 mov dx, # VGAREG_WRITE_MISC_OUTPUT
3003 biosfn_enable_grayscale_summing:
3011 mov ax, # BIOSMEM_SEG
3013 mov bx, # BIOSMEM_MODESET_CTL
3025 biosfn_enable_cursor_emulation:
3032 mov ax, # BIOSMEM_SEG
3034 mov bx, # BIOSMEM_MODESET_CTL
3046 // --------------------------------------------------------------------------------------------
3047 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3053 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3060 // --------------------------------------------------------------------------------------------
3061 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3062 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3064 Bit16u newcurs,oldcurs,dummy;
3067 // Read curs info for the page
3068 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3070 // if row=0xff special case : use current cursor position
3072 {col=oldcurs&0x00ff;
3073 row=(oldcurs&0xff00)>>8;
3076 newcurs=row; newcurs<<=8; newcurs+=col;
3077 biosfn_set_cursor_pos(page,newcurs);
3081 car=read_byte(seg,offset++);
3083 attr=read_byte(seg,offset++);
3085 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3088 // Set back curs pos
3090 biosfn_set_cursor_pos(page,oldcurs);
3093 // --------------------------------------------------------------------------------------------
3097 je biosfn_read_display_code
3099 je biosfn_set_display_code
3104 biosfn_read_display_code:
3107 mov ax, # BIOSMEM_SEG
3109 mov bx, # BIOSMEM_DCC_INDEX
3117 biosfn_set_display_code:
3121 mov ax, # BIOSMEM_SEG
3124 mov bx, # BIOSMEM_DCC_INDEX
3130 mov bx, #msg_alt_dcc
3143 .ascii "Alternate Display code (%02x) was discarded"
3144 .byte 0x0d,0x0a,0x00
3148 // --------------------------------------------------------------------------------------------
3149 static void biosfn_read_state_info (BX,ES,DI)
3150 Bit16u BX;Bit16u ES;Bit16u DI;
3152 // Address of static functionality table
3153 write_word(ES,DI+0x00,&static_functionality);
3154 write_word(ES,DI+0x02,0xC000);
3156 // Hard coded copy from BIOS area. Should it be cleaner ?
3157 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3158 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3160 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3161 write_byte(ES,DI+0x26,0);
3162 write_byte(ES,DI+0x27,16);
3163 write_byte(ES,DI+0x28,0);
3164 write_byte(ES,DI+0x29,8);
3165 write_byte(ES,DI+0x2a,2);
3166 write_byte(ES,DI+0x2b,0);
3167 write_byte(ES,DI+0x2c,0);
3168 write_byte(ES,DI+0x31,3);
3169 write_byte(ES,DI+0x32,0);
3171 memsetb(ES,DI+0x33,0,13);
3174 // --------------------------------------------------------------------------------------------
3175 // --------------------------------------------------------------------------------------------
3176 static Bit16u biosfn_read_video_state_size2 (CX)
3185 size += (5 + 8 + 5) * 2 + 6;
3188 size += 3 + 256 * 3 + 1;
3193 static void biosfn_read_video_state_size (CX, BX)
3194 Bit16u CX; Bit16u *BX;
3197 write_word(ss, BX, biosfn_read_video_state_size2(CX));
3200 static Bit16u biosfn_save_video_state (CX,ES,BX)
3201 Bit16u CX;Bit16u ES;Bit16u BX;
3203 Bit16u i, v, crtc_addr, ar_index;
3205 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3207 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3208 write_byte(ES, BX, inb(crtc_addr)); BX++;
3209 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3210 inb(VGAREG_ACTL_RESET);
3211 ar_index = inb(VGAREG_ACTL_ADDRESS);
3212 write_byte(ES, BX, ar_index); BX++;
3213 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3216 outb(VGAREG_SEQU_ADDRESS, i);
3217 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3219 outb(VGAREG_SEQU_ADDRESS, 0);
3220 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3222 for(i=0;i<=0x18;i++) {
3224 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3227 for(i=0;i<=0x13;i++) {
3228 inb(VGAREG_ACTL_RESET);
3229 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3230 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3232 inb(VGAREG_ACTL_RESET);
3235 outb(VGAREG_GRDC_ADDRESS,i);
3236 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3239 write_word(ES, BX, crtc_addr); BX+= 2;
3241 /* XXX: read plane latches */
3242 write_byte(ES, BX, 0); BX++;
3243 write_byte(ES, BX, 0); BX++;
3244 write_byte(ES, BX, 0); BX++;
3245 write_byte(ES, BX, 0); BX++;
3248 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3249 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3250 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3251 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3252 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3253 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3254 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3255 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3256 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3257 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3259 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3262 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3263 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3265 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3266 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3267 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3268 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3271 /* XXX: check this */
3272 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3273 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3274 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3275 // Set the whole dac always, from 0
3276 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3277 for(i=0;i<256*3;i++) {
3278 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3280 write_byte(ES, BX, 0); BX++; /* color select register */
3285 static Bit16u biosfn_restore_video_state (CX,ES,BX)
3286 Bit16u CX;Bit16u ES;Bit16u BX;
3288 Bit16u i, crtc_addr, v, addr1, ar_index;
3291 // Reset Attribute Ctl flip-flop
3292 inb(VGAREG_ACTL_RESET);
3294 crtc_addr = read_word(ES, BX + 0x40);
3299 outb(VGAREG_SEQU_ADDRESS, i);
3300 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3302 outb(VGAREG_SEQU_ADDRESS, 0);
3303 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3305 // Disable CRTC write protection
3306 outw(crtc_addr,0x0011);
3308 for(i=0;i<=0x18;i++) {
3311 outb(crtc_addr+1, read_byte(ES, BX));
3315 // select crtc base address
3316 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3317 if (crtc_addr = 0x3d4)
3319 outb(VGAREG_WRITE_MISC_OUTPUT, v);
3321 // enable write protection if needed
3322 outb(crtc_addr, 0x11);
3323 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3325 // Set Attribute Ctl
3326 ar_index = read_byte(ES, addr1 + 0x03);
3327 inb(VGAREG_ACTL_RESET);
3328 for(i=0;i<=0x13;i++) {
3329 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3330 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3332 outb(VGAREG_ACTL_ADDRESS, ar_index);
3333 inb(VGAREG_ACTL_RESET);
3336 outb(VGAREG_GRDC_ADDRESS,i);
3337 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3339 BX += 2; /* crtc_addr */
3340 BX += 4; /* plane latches */
3342 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3343 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3344 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3346 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3349 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3350 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3351 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3352 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3353 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3354 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3355 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3356 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3357 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3358 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3360 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3363 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3364 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3366 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3367 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3368 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3369 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3373 v = read_byte(ES, BX); BX++;
3374 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3375 // Set the whole dac always, from 0
3376 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3377 for(i=0;i<256*3;i++) {
3378 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3381 outb(VGAREG_DAC_WRITE_ADDRESS, v);
3386 // ============================================================================================
3390 // ============================================================================================
3392 // --------------------------------------------------------------------------------------------
3393 static Bit8u find_vga_entry(mode)
3397 for(i=0;i<=MODE_MAX;i++)
3398 if(vga_modes[i].svgamode==mode)
3405 /* =========================================================== */
3409 /* =========================================================== */
3411 // --------------------------------------------------------------------------------------------
3412 static void memsetb(seg,offset,value,count)
3427 mov cx, 10[bp] ; count
3430 mov ax, 4[bp] ; segment
3432 mov ax, 6[bp] ; offset
3434 mov al, 8[bp] ; value
3449 // --------------------------------------------------------------------------------------------
3450 static void memsetw(seg,offset,value,count)
3465 mov cx, 10[bp] ; count
3468 mov ax, 4[bp] ; segment
3470 mov ax, 6[bp] ; offset
3472 mov ax, 8[bp] ; value
3487 // --------------------------------------------------------------------------------------------
3488 static void memcpyb(dseg,doffset,sseg,soffset,count)
3506 mov cx, 12[bp] ; count
3509 mov ax, 4[bp] ; dsegment
3511 mov ax, 6[bp] ; doffset
3513 mov ax, 8[bp] ; ssegment
3515 mov ax, 10[bp] ; soffset
3533 // --------------------------------------------------------------------------------------------
3534 static void memcpyw(dseg,doffset,sseg,soffset,count)
3552 mov cx, 12[bp] ; count
3555 mov ax, 4[bp] ; dsegment
3557 mov ax, 6[bp] ; doffset
3559 mov ax, 8[bp] ; ssegment
3561 mov ax, 10[bp] ; soffset
3579 /* =========================================================== */
3581 * These functions where ripped from Kevin's rombios.c
3583 /* =========================================================== */
3585 // --------------------------------------------------------------------------------------------
3587 read_byte(seg, offset)
3597 mov ax, 4[bp] ; segment
3599 mov bx, 6[bp] ; offset
3601 ;; al = return value (byte)
3609 // --------------------------------------------------------------------------------------------
3611 read_word(seg, offset)
3621 mov ax, 4[bp] ; segment
3623 mov bx, 6[bp] ; offset
3625 ;; ax = return value (word)
3633 // --------------------------------------------------------------------------------------------
3635 write_byte(seg, offset, data)
3647 mov ax, 4[bp] ; segment
3649 mov bx, 6[bp] ; offset
3650 mov al, 8[bp] ; data byte
3651 mov [bx], al ; write data byte
3660 // --------------------------------------------------------------------------------------------
3662 write_word(seg, offset, data)
3674 mov ax, 4[bp] ; segment
3676 mov bx, 6[bp] ; offset
3677 mov ax, 8[bp] ; data word
3678 mov [bx], ax ; write data word
3687 // --------------------------------------------------------------------------------------------
3722 // --------------------------------------------------------------------------------------------
3744 // --------------------------------------------------------------------------------------------
3774 void unimplemented()
3776 printf("--> Unimplemented\n");
3781 printf("--> Unknown int10\n");
3785 // --------------------------------------------------------------------------------------------
3786 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3790 Bit8u c, format_char;
3792 unsigned format_width, i;
3794 Bit16u arg_seg, arg, digit, nibble, shift_count;
3802 while (c = read_byte(0xc000, s)) {
3807 else if (in_format) {
3808 if ( (c>='0') && (c<='9') ) {
3809 format_width = (format_width * 10) + (c - '0');
3811 else if (c == 'x') {
3812 arg_ptr++; // increment to next arg
3813 arg = read_word(arg_seg, arg_ptr);
3814 if (format_width == 0)
3817 digit = format_width - 1;
3818 for (i=0; i<format_width; i++) {
3819 nibble = (arg >> (4 * digit)) & 0x000f;
3821 outb(0x0500, nibble + '0');
3823 outb(0x0500, (nibble - 10) + 'A');
3828 //else if (c == 'd') {
3841 ; get LFB address from PCI
3842 ; in - ax: PCI device vendor
3843 ; out - ax: LFB address (high 16 bit)
3844 ;; NOTE - may be called in protected mode
3855 jz pci_get_lfb_addr_fail
3856 pci_get_lfb_addr_next_dev:
3859 cmp ax, bx ;; check vendor
3860 jz pci_get_lfb_addr_found
3862 cmp cx, #0x200 ;; search bus #0 and #1
3863 jb pci_get_lfb_addr_next_dev
3864 pci_get_lfb_addr_fail:
3865 xor dx, dx ;; no LFB
3866 jmp pci_get_lfb_addr_return
3867 pci_get_lfb_addr_found:
3868 mov dl, #0x10 ;; I/O space #0
3871 jz pci_get_lfb_addr_success
3872 mov dl, #0x14 ;; I/O space #1
3875 jnz pci_get_lfb_addr_fail
3876 pci_get_lfb_addr_success:
3878 mov dx, ax ;; LFB address
3879 pci_get_lfb_addr_return:
3888 ; in - cx: device/function
3892 mov eax, #0x00800000
3911 // --------------------------------------------------------------------------------------------
3914 ;; DATA_SEG_DEFS_HERE
3918 .ascii "vgabios ends here"
3922 ;; BLOCK_STRINGS_BEGIN