- applied patch from the qemu project (Fabrice Bellard)
[vgabios.git] / vgabios.c
blob7190c0e95e638ef600bd6f4549475aa47d52b97f
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // ============================================================================================
24 //
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
27 //
28 // ============================================================================================
29 //
30 // This file contains code ripped from :
31 // - rombios.c of plex86
33 // This VGA Bios contains fonts from :
34 // - fntcol16.zip (c) by Joseph Gil avalable at :
35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36 // These fonts are public domain
38 // This VGA Bios is based on information taken from :
39 // - Kevin Lawton's vga card emulation for bochs/plex86
40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42 // - Michael Abrash's Graphics Programming Black Book
43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44 // - DOSEMU 1.0.1 source code for several tables values and formulas
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
49 // ============================================================================================
51 #include "vgabios.h"
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
57 #define USE_BX_INFO
59 /* Declares */
60 static Bit8u read_byte();
61 static Bit16u read_word();
62 static void write_byte();
63 static void write_word();
64 static Bit8u inb();
65 static Bit16u inw();
66 static void outb();
67 static void outw();
69 static Bit16u get_SS();
71 // Output
72 static void printf();
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
120 ASM_START
122 MACRO SET_INT_VECTOR
123 push ds
124 xor ax, ax
125 mov ds, ax
126 mov ax, ?3
127 mov ?1*4, ax
128 mov ax, ?2
129 mov ?1*4+2, ax
130 pop ds
131 MEND
133 ASM_END
135 ASM_START
136 .text
137 .rom
138 .org 0
140 use16 386
142 vgabios_start:
143 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
145 .byte 0x40 /* BIOS extension length in units of 512 bytes */
148 vgabios_entry_point:
150 jmp vgabios_init_func
152 vgabios_name:
153 .ascii "Plex86/Bochs VGABios"
154 .ascii " "
155 .byte 0x00
157 // Info from Bart Oldeman
158 .org 0x1e
159 .ascii "IBM"
160 .byte 0x00
162 vgabios_version:
163 #ifndef VGABIOS_VERS
164 .ascii "current-cvs"
165 #else
166 .ascii VGABIOS_VERS
167 #endif
168 .ascii " "
170 vgabios_date:
171 .ascii VGABIOS_DATE
172 .byte 0x0a,0x0d
173 .byte 0x00
175 vgabios_copyright:
176 .ascii "(C) 2003 the LGPL VGABios developers Team"
177 .byte 0x0a,0x0d
178 .byte 0x00
180 vgabios_license:
181 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
182 .byte 0x0a,0x0d
183 .byte 0x0a,0x0d
184 .byte 0x00
186 vgabios_website:
187 .ascii "Please visit :"
188 .byte 0x0a,0x0d
189 ;;.ascii " . http://www.plex86.org"
190 ;;.byte 0x0a,0x0d
191 .ascii " . http://bochs.sourceforge.net"
192 .byte 0x0a,0x0d
193 .ascii " . http://www.nongnu.org/vgabios"
194 .byte 0x0a,0x0d
195 .byte 0x0a,0x0d
196 .byte 0x00
199 ;; ============================================================================================
201 ;; Init Entry point
203 ;; ============================================================================================
204 vgabios_init_func:
206 ;; init vga card
207 call init_vga_card
209 ;; init basic bios vars
210 call init_bios_area
212 #ifdef VBE
213 ;; init vbe functions
214 call vbe_init
215 #endif
217 ;; set int10 vect
218 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
220 #ifdef CIRRUS
221 call cirrus_init
222 #endif
224 ;; display splash screen
225 call _display_splash_screen
227 ;; init video mode and clear the screen
228 mov ax,#0x0003
229 int #0x10
231 ;; show info
232 call _display_info
234 #ifdef VBE
235 ;; show vbe info
236 call vbe_display_info
237 #endif
239 #ifdef CIRRUS
240 ;; show cirrus info
241 call cirrus_display_info
242 #endif
244 retf
245 ASM_END
248 * int10 handled here
250 ASM_START
251 vgabios_int10_handler:
252 pushf
253 #ifdef DEBUG
254 push es
255 push ds
256 pusha
257 mov bx, #0xc000
258 mov ds, bx
259 call _int10_debugmsg
260 popa
261 pop ds
262 pop es
263 #endif
264 cmp ah, #0x0f
265 jne int10_test_1A
266 call biosfn_get_video_mode
267 jmp int10_end
268 int10_test_1A:
269 cmp ah, #0x1a
270 jne int10_test_0B
271 call biosfn_group_1A
272 jmp int10_end
273 int10_test_0B:
274 cmp ah, #0x0b
275 jne int10_test_1103
276 call biosfn_group_0B
277 jmp int10_end
278 int10_test_1103:
279 cmp ax, #0x1103
280 jne int10_test_12
281 call biosfn_set_text_block_specifier
282 jmp int10_end
283 int10_test_12:
284 cmp ah, #0x12
285 jne int10_test_101B
286 cmp bl, #0x10
287 jne int10_test_BL30
288 call biosfn_get_ega_info
289 jmp int10_end
290 int10_test_BL30:
291 cmp bl, #0x30
292 jne int10_test_BL31
293 call biosfn_select_vert_res
294 jmp int10_end
295 int10_test_BL31:
296 cmp bl, #0x31
297 jne int10_test_BL32
298 call biosfn_enable_default_palette_loading
299 jmp int10_end
300 int10_test_BL32:
301 cmp bl, #0x32
302 jne int10_test_BL33
303 call biosfn_enable_video_addressing
304 jmp int10_end
305 int10_test_BL33:
306 cmp bl, #0x33
307 jne int10_test_BL34
308 call biosfn_enable_grayscale_summing
309 jmp int10_end
310 int10_test_BL34:
311 cmp bl, #0x34
312 jne int10_normal
313 call biosfn_enable_cursor_emulation
314 jmp int10_end
315 int10_test_101B:
316 cmp ax, #0x101b
317 je int10_normal
318 cmp ah, #0x10
319 #ifndef VBE
320 jne int10_normal
321 #else
322 jne int10_test_4F
323 #endif
324 call biosfn_group_10
325 jmp int10_end
326 #ifdef VBE
327 int10_test_4F:
328 cmp ah, #0x4f
329 jne int10_normal
330 cmp al, #0x03
331 jne int10_test_vbe_05
332 call vbe_biosfn_return_current_mode
333 jmp int10_end
334 int10_test_vbe_05:
335 cmp al, #0x05
336 jne int10_test_vbe_06
337 call vbe_biosfn_display_window_control
338 jmp int10_end
339 int10_test_vbe_06:
340 cmp al, #0x06
341 jne int10_test_vbe_07
342 call vbe_biosfn_set_get_logical_scan_line_length
343 jmp int10_end
344 int10_test_vbe_07:
345 cmp al, #0x07
346 jne int10_test_vbe_08
347 call vbe_biosfn_set_get_display_start
348 jmp int10_end
349 int10_test_vbe_08:
350 cmp al, #0x08
351 jne int10_test_vbe_0A
352 call vbe_biosfn_set_get_dac_palette_format
353 jmp int10_end
354 int10_test_vbe_0A:
355 cmp al, #0x0A
356 jne int10_normal
357 call vbe_biosfn_return_protected_mode_interface
358 jmp int10_end
359 #endif
361 int10_normal:
362 push es
363 push ds
364 pusha
366 ;; We have to set ds to access the right data segment
367 mov bx, #0xc000
368 mov ds, bx
369 call _int10_func
371 popa
372 pop ds
373 pop es
374 int10_end:
375 popf
376 iret
377 ASM_END
379 #include "vgatables.h"
380 #include "vgafonts.h"
383 * Boot time harware inits
385 ASM_START
386 init_vga_card:
387 ;; switch to color mode and enable CPU access 480 lines
388 mov dx, #0x3C2
389 mov al, #0xC3
390 outb dx,al
392 ;; more than 64k 3C4/04
393 mov dx, #0x3C4
394 mov al, #0x04
395 outb dx,al
396 mov dx, #0x3C5
397 mov al, #0x02
398 outb dx,al
400 #if defined(USE_BX_INFO) || defined(DEBUG)
401 mov bx, #msg_vga_init
402 push bx
403 call _printf
404 #endif
405 inc sp
406 inc sp
409 #if defined(USE_BX_INFO) || defined(DEBUG)
410 msg_vga_init:
411 .ascii "VGABios $Id$"
412 .byte 0x0d,0x0a,0x00
413 #endif
414 ASM_END
416 // --------------------------------------------------------------------------------------------
418 * Boot time bios area inits
420 ASM_START
421 init_bios_area:
422 push ds
423 mov ax, # BIOSMEM_SEG
424 mov ds, ax
426 ;; init detected hardware BIOS Area
427 mov bx, # BIOSMEM_INITIAL_MODE
428 mov ax, [bx]
429 and ax, #0xffcf
430 ;; set 80x25 color (not clear from RBIL but usual)
431 or ax, #0x0020
432 mov [bx], ax
434 ;; Just for the first int10 find its children
436 ;; the default char height
437 mov bx, # BIOSMEM_CHAR_HEIGHT
438 mov al, #0x10
439 mov [bx], al
441 ;; Clear the screen
442 mov bx, # BIOSMEM_VIDEO_CTL
443 mov al, #0x60
444 mov [bx], al
446 ;; Set the basic screen we have
447 mov bx, # BIOSMEM_SWITCHES
448 mov al, #0xf9
449 mov [bx], al
451 ;; Set the basic modeset options
452 mov bx, # BIOSMEM_MODESET_CTL
453 mov al, #0x51
454 mov [bx], al
456 ;; Set the default MSR
457 mov bx, # BIOSMEM_CURRENT_MSR
458 mov al, #0x09
459 mov [bx], al
461 pop ds
464 _video_save_pointer_table:
465 .word _video_param_table
466 .word 0xc000
468 .word 0 /* XXX: fill it */
469 .word 0
471 .word 0 /* XXX: fill it */
472 .word 0
474 .word 0 /* XXX: fill it */
475 .word 0
477 .word 0 /* XXX: fill it */
478 .word 0
480 .word 0 /* XXX: fill it */
481 .word 0
483 .word 0 /* XXX: fill it */
484 .word 0
486 ASM_END
488 // --------------------------------------------------------------------------------------------
490 * Boot time Splash screen
492 static void display_splash_screen()
496 // --------------------------------------------------------------------------------------------
498 * Tell who we are
501 static void display_info()
503 ASM_START
504 mov ax,#0xc000
505 mov ds,ax
506 mov si,#vgabios_name
507 call _display_string
508 mov si,#vgabios_version
509 call _display_string
511 ;;mov si,#vgabios_copyright
512 ;;call _display_string
513 ;;mov si,#crlf
514 ;;call _display_string
516 mov si,#vgabios_license
517 call _display_string
518 mov si,#vgabios_website
519 call _display_string
520 ASM_END
523 static void display_string()
525 // Get length of string
526 ASM_START
527 mov ax,ds
528 mov es,ax
529 mov di,si
530 xor cx,cx
531 not cx
532 xor al,al
534 repne
535 scasb
536 not cx
537 dec cx
538 push cx
540 mov ax,#0x0300
541 mov bx,#0x0000
542 int #0x10
544 pop cx
545 mov ax,#0x1301
546 mov bx,#0x000b
547 mov bp,si
548 int #0x10
549 ASM_END
552 // --------------------------------------------------------------------------------------------
553 #ifdef DEBUG
554 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
555 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
557 // 0E is write char...
558 if(GET_AH()!=0x0E)
559 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
561 #endif
563 // --------------------------------------------------------------------------------------------
565 * int10 main dispatcher
567 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
568 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
571 // BIOS functions
572 switch(GET_AH())
574 case 0x00:
575 biosfn_set_video_mode(GET_AL());
576 switch(GET_AL()&0x7F)
577 {case 6:
578 SET_AL(0x3F);
579 break;
580 case 0:
581 case 1:
582 case 2:
583 case 3:
584 case 4:
585 case 5:
586 case 7:
587 SET_AL(0x30);
588 break;
589 default:
590 SET_AL(0x20);
592 break;
593 case 0x01:
594 biosfn_set_cursor_shape(GET_CH(),GET_CL());
595 break;
596 case 0x02:
597 biosfn_set_cursor_pos(GET_BH(),DX);
598 break;
599 case 0x03:
600 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
601 break;
602 case 0x04:
603 // Read light pen pos (unimplemented)
604 #ifdef DEBUG
605 unimplemented();
606 #endif
607 AX=0x00;
608 BX=0x00;
609 CX=0x00;
610 DX=0x00;
611 break;
612 case 0x05:
613 biosfn_set_active_page(GET_AL());
614 break;
615 case 0x06:
616 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
617 break;
618 case 0x07:
619 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
620 break;
621 case 0x08:
622 biosfn_read_char_attr(GET_BH(),&AX);
623 break;
624 case 0x09:
625 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
626 break;
627 case 0x0A:
628 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
629 break;
630 case 0x0C:
631 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
632 break;
633 case 0x0D:
634 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
635 break;
636 case 0x0E:
637 // Ralf Brown Interrupt list is WRONG on bh(page)
638 // We do output only on the current page !
639 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
640 break;
641 case 0x10:
642 // All other functions of group AH=0x10 rewritten in assembler
643 biosfn_perform_gray_scale_summing(BX,CX);
644 break;
645 case 0x11:
646 switch(GET_AL())
648 case 0x00:
649 case 0x10:
650 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
651 break;
652 case 0x01:
653 case 0x11:
654 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
655 break;
656 case 0x02:
657 case 0x12:
658 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
659 break;
660 case 0x04:
661 case 0x14:
662 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
663 break;
664 case 0x20:
665 biosfn_load_gfx_8_8_chars(ES,BP);
666 break;
667 case 0x21:
668 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
669 break;
670 case 0x22:
671 biosfn_load_gfx_8_14_chars(GET_BL());
672 break;
673 case 0x23:
674 biosfn_load_gfx_8_8_dd_chars(GET_BL());
675 break;
676 case 0x24:
677 biosfn_load_gfx_8_16_chars(GET_BL());
678 break;
679 case 0x30:
680 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
681 break;
682 #ifdef DEBUG
683 default:
684 unknown();
685 #endif
688 break;
689 case 0x12:
690 switch(GET_BL())
692 case 0x20:
693 biosfn_alternate_prtsc();
694 break;
695 case 0x35:
696 biosfn_switch_video_interface(GET_AL(),ES,DX);
697 SET_AL(0x12);
698 break;
699 case 0x36:
700 biosfn_enable_video_refresh_control(GET_AL());
701 SET_AL(0x12);
702 break;
703 #ifdef DEBUG
704 default:
705 unknown();
706 #endif
708 break;
709 case 0x13:
710 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
711 break;
712 case 0x1B:
713 biosfn_read_state_info(BX,ES,DI);
714 SET_AL(0x1B);
715 break;
716 case 0x1C:
717 switch(GET_AL())
719 case 0x00:
720 biosfn_read_video_state_size(CX,&BX);
721 break;
722 case 0x01:
723 biosfn_save_video_state(CX,ES,BX);
724 break;
725 case 0x02:
726 biosfn_restore_video_state(CX,ES,BX);
727 break;
728 #ifdef DEBUG
729 default:
730 unknown();
731 #endif
733 SET_AL(0x1C);
734 break;
736 #ifdef VBE
737 case 0x4f:
738 if (vbe_has_vbe_display()) {
739 switch(GET_AL())
741 case 0x00:
742 vbe_biosfn_return_controller_information(&AX,ES,DI);
743 break;
744 case 0x01:
745 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
746 break;
747 case 0x02:
748 vbe_biosfn_set_mode(&AX,BX,ES,DI);
749 break;
750 case 0x04:
751 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
752 break;
753 case 0x09:
754 //FIXME
755 #ifdef DEBUG
756 unimplemented();
757 #endif
758 // function failed
759 AX=0x100;
760 break;
761 case 0x0A:
762 //FIXME
763 #ifdef DEBUG
764 unimplemented();
765 #endif
766 // function failed
767 AX=0x100;
768 break;
769 default:
770 #ifdef DEBUG
771 unknown();
772 #endif
773 // function failed
774 AX=0x100;
777 else {
778 // No VBE display
779 AX=0x0100;
781 break;
782 #endif
784 #ifdef DEBUG
785 default:
786 unknown();
787 #endif
791 // ============================================================================================
793 // BIOS functions
795 // ============================================================================================
797 static void biosfn_set_video_mode(mode) Bit8u mode;
798 {// mode: Bit 7 is 1 if no clear screen
800 // Should we clear the screen ?
801 Bit8u noclearmem=mode&0x80;
802 Bit8u line,mmask,*palette,vpti;
803 Bit16u i,twidth,theightm1,cheight;
804 Bit8u modeset_ctl,video_ctl,vga_switches;
805 Bit16u crtc_addr;
807 #ifdef VBE
808 if (vbe_has_vbe_display()) {
809 dispi_set_enable(VBE_DISPI_DISABLED);
811 #endif // def VBE
813 // The real mode
814 mode=mode&0x7f;
816 // find the entry in the video modes
817 line=find_vga_entry(mode);
819 #ifdef DEBUG
820 printf("mode search %02x found line %02x\n",mode,line);
821 #endif
823 if(line==0xFF)
824 return;
826 vpti=line_to_vpti[line];
827 twidth=video_param_table[vpti].twidth;
828 theightm1=video_param_table[vpti].theightm1;
829 cheight=video_param_table[vpti].cheight;
831 // Read the bios vga control
832 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
834 // Read the bios vga switches
835 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
837 // Read the bios mode set control
838 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
840 // Then we know the number of lines
841 // FIXME
843 // if palette loading (bit 3 of modeset ctl = 0)
844 if((modeset_ctl&0x08)==0)
845 {// Set the PEL mask
846 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
848 // Set the whole dac always, from 0
849 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
851 // From which palette
852 switch(vga_modes[line].dacmodel)
853 {case 0:
854 palette=&palette0;
855 break;
856 case 1:
857 palette=&palette1;
858 break;
859 case 2:
860 palette=&palette2;
861 break;
862 case 3:
863 palette=&palette3;
864 break;
866 // Always 256*3 values
867 for(i=0;i<0x0100;i++)
868 {if(i<=dac_regs[vga_modes[line].dacmodel])
869 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
870 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
871 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
873 else
874 {outb(VGAREG_DAC_DATA,0);
875 outb(VGAREG_DAC_DATA,0);
876 outb(VGAREG_DAC_DATA,0);
879 if((modeset_ctl&0x02)==0x02)
881 biosfn_perform_gray_scale_summing(0x00, 0x100);
885 // Reset Attribute Ctl flip-flop
886 inb(VGAREG_ACTL_RESET);
888 // Set Attribute Ctl
889 for(i=0;i<=0x13;i++)
890 {outb(VGAREG_ACTL_ADDRESS,i);
891 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
893 outb(VGAREG_ACTL_ADDRESS,0x14);
894 outb(VGAREG_ACTL_WRITE_DATA,0x00);
896 // Set Sequencer Ctl
897 outb(VGAREG_SEQU_ADDRESS,0);
898 outb(VGAREG_SEQU_DATA,0x03);
899 for(i=1;i<=4;i++)
900 {outb(VGAREG_SEQU_ADDRESS,i);
901 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
904 // Set Grafx Ctl
905 for(i=0;i<=8;i++)
906 {outb(VGAREG_GRDC_ADDRESS,i);
907 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
910 // Set CRTC address VGA or MDA
911 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
913 // Disable CRTC write protection
914 outw(crtc_addr,0x0011);
915 // Set CRTC regs
916 for(i=0;i<=0x18;i++)
917 {outb(crtc_addr,i);
918 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
921 // Set the misc register
922 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
924 // Enable video
925 outb(VGAREG_ACTL_ADDRESS,0x20);
926 inb(VGAREG_ACTL_RESET);
928 if(noclearmem==0x00)
930 if(vga_modes[line].class==TEXT)
932 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
934 else
936 if(mode<0x0d)
938 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
940 else
942 outb( VGAREG_SEQU_ADDRESS, 0x02 );
943 mmask = inb( VGAREG_SEQU_DATA );
944 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
945 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
946 outb( VGAREG_SEQU_DATA, mmask );
951 // Set the BIOS mem
952 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
953 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
954 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
955 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
956 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
957 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
958 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
959 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
960 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
962 // FIXME We nearly have the good tables. to be reworked
963 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
964 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
965 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
967 // FIXME
968 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
969 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
971 // Set cursor shape
972 if(vga_modes[line].class==TEXT)
974 biosfn_set_cursor_shape(0x06,0x07);
977 // Set cursor pos for page 0..7
978 for(i=0;i<8;i++)
979 biosfn_set_cursor_pos(i,0x0000);
981 // Set active page 0
982 biosfn_set_active_page(0x00);
984 // Write the fonts in memory
985 if(vga_modes[line].class==TEXT)
987 ASM_START
988 ;; copy and activate 8x16 font
989 mov ax, #0x1104
990 mov bl, #0x00
991 int #0x10
992 mov ax, #0x1103
993 mov bl, #0x00
994 int #0x10
995 ASM_END
998 // Set the ints 0x1F and 0x43
999 ASM_START
1000 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1001 ASM_END
1003 switch(cheight)
1004 {case 8:
1005 ASM_START
1006 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1007 ASM_END
1008 break;
1009 case 14:
1010 ASM_START
1011 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1012 ASM_END
1013 break;
1014 case 16:
1015 ASM_START
1016 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1017 ASM_END
1018 break;
1022 // --------------------------------------------------------------------------------------------
1023 static void biosfn_set_cursor_shape (CH,CL)
1024 Bit8u CH;Bit8u CL;
1025 {Bit16u cheight,curs,crtc_addr;
1026 Bit8u modeset_ctl;
1028 CH&=0x3f;
1029 CL&=0x1f;
1031 curs=(CH<<8)+CL;
1032 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1034 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1035 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1036 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1038 if(CL!=(CH+1))
1040 CH = ((CH+1) * cheight / 8) -1;
1042 else
1044 CH = ((CL+1) * cheight / 8) - 2;
1046 CL = ((CL+1) * cheight / 8) - 1;
1049 // CTRC regs 0x0a and 0x0b
1050 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1051 outb(crtc_addr,0x0a);
1052 outb(crtc_addr+1,CH);
1053 outb(crtc_addr,0x0b);
1054 outb(crtc_addr+1,CL);
1057 // --------------------------------------------------------------------------------------------
1058 static void biosfn_set_cursor_pos (page, cursor)
1059 Bit8u page;Bit16u cursor;
1061 Bit8u xcurs,ycurs,current;
1062 Bit16u nbcols,nbrows,address,crtc_addr;
1064 // Should not happen...
1065 if(page>7)return;
1067 // Bios cursor pos
1068 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1070 // Set the hardware cursor
1071 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1072 if(page==current)
1074 // Get the dimensions
1075 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1076 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1078 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1080 // Calculate the address knowing nbcols nbrows and page num
1081 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1083 // CRTC regs 0x0e and 0x0f
1084 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1085 outb(crtc_addr,0x0e);
1086 outb(crtc_addr+1,(address&0xff00)>>8);
1087 outb(crtc_addr,0x0f);
1088 outb(crtc_addr+1,address&0x00ff);
1092 // --------------------------------------------------------------------------------------------
1093 static void biosfn_get_cursor_pos (page,shape, pos)
1094 Bit8u page;Bit16u *shape;Bit16u *pos;
1096 Bit16u ss=get_SS();
1098 // Default
1099 write_word(ss, shape, 0);
1100 write_word(ss, pos, 0);
1102 if(page>7)return;
1103 // FIXME should handle VGA 14/16 lines
1104 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1105 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1108 // --------------------------------------------------------------------------------------------
1109 static void biosfn_set_active_page (page)
1110 Bit8u page;
1112 Bit16u cursor,dummy,crtc_addr;
1113 Bit16u nbcols,nbrows,address;
1114 Bit8u mode,line;
1116 if(page>7)return;
1118 // Get the mode
1119 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1120 line=find_vga_entry(mode);
1121 if(line==0xFF)return;
1123 // Get pos curs pos for the right page
1124 biosfn_get_cursor_pos(page,&dummy,&cursor);
1126 if(vga_modes[line].class==TEXT)
1128 // Get the dimensions
1129 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1130 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1132 // Calculate the address knowing nbcols nbrows and page num
1133 address=SCREEN_MEM_START(nbcols,nbrows,page);
1134 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1136 // Start address
1137 address=SCREEN_IO_START(nbcols,nbrows,page);
1139 else
1141 address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
1144 // CRTC regs 0x0c and 0x0d
1145 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1146 outb(crtc_addr,0x0c);
1147 outb(crtc_addr+1,(address&0xff00)>>8);
1148 outb(crtc_addr,0x0d);
1149 outb(crtc_addr+1,address&0x00ff);
1151 // And change the BIOS page
1152 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1154 #ifdef DEBUG
1155 printf("Set active page %02x address %04x\n",page,address);
1156 #endif
1158 // Display the cursor, now the page is active
1159 biosfn_set_cursor_pos(page,cursor);
1162 // --------------------------------------------------------------------------------------------
1163 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1164 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1166 Bit16u src,dest;
1167 Bit8u i;
1169 src=ysrc*cheight*nbcols+xstart;
1170 dest=ydest*cheight*nbcols+xstart;
1171 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1172 for(i=0;i<cheight;i++)
1174 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1176 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1179 // --------------------------------------------------------------------------------------------
1180 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1181 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1183 Bit16u dest;
1184 Bit8u i;
1186 dest=ystart*cheight*nbcols+xstart;
1187 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1188 for(i=0;i<cheight;i++)
1190 memsetb(0xa000,dest+i*nbcols,attr,cols);
1192 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1195 // --------------------------------------------------------------------------------------------
1196 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1197 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1199 Bit16u src,dest;
1200 Bit8u i;
1202 src=((ysrc*cheight*nbcols)>>1)+xstart;
1203 dest=((ydest*cheight*nbcols)>>1)+xstart;
1204 for(i=0;i<cheight;i++)
1206 if (i & 1)
1207 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1208 else
1209 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1213 // --------------------------------------------------------------------------------------------
1214 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1215 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1217 Bit16u dest;
1218 Bit8u i;
1220 dest=((ystart*cheight*nbcols)>>1)+xstart;
1221 for(i=0;i<cheight;i++)
1223 if (i & 1)
1224 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1225 else
1226 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1230 // --------------------------------------------------------------------------------------------
1231 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1232 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1234 // page == 0xFF if current
1236 Bit8u mode,line,cheight,bpp,cols;
1237 Bit16u nbcols,nbrows,i;
1238 Bit16u address;
1240 if(rul>rlr)return;
1241 if(cul>clr)return;
1243 // Get the mode
1244 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1245 line=find_vga_entry(mode);
1246 if(line==0xFF)return;
1248 // Get the dimensions
1249 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1250 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1252 // Get the current page
1253 if(page==0xFF)
1254 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1256 if(rlr>=nbrows)rlr=nbrows-1;
1257 if(clr>=nbcols)clr=nbcols-1;
1258 if(nblines>nbrows)nblines=0;
1259 cols=clr-cul+1;
1261 if(vga_modes[line].class==TEXT)
1263 // Compute the address
1264 address=SCREEN_MEM_START(nbcols,nbrows,page);
1265 #ifdef DEBUG
1266 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1267 #endif
1269 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1271 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1273 else
1274 {// if Scroll up
1275 if(dir==SCROLL_UP)
1276 {for(i=rul;i<=rlr;i++)
1278 if((i+nblines>rlr)||(nblines==0))
1279 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1280 else
1281 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1284 else
1285 {for(i=rlr;i>=rul;i--)
1287 if((i<rul+nblines)||(nblines==0))
1288 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1289 else
1290 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1295 else
1297 // FIXME gfx mode not complete
1298 cheight=video_param_table[line_to_vpti[line]].cheight;
1299 switch(vga_modes[line].memmodel)
1301 case PLANAR4:
1302 case PLANAR1:
1303 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1305 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1306 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1307 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1309 else
1310 {// if Scroll up
1311 if(dir==SCROLL_UP)
1312 {for(i=rul;i<=rlr;i++)
1314 if((i+nblines>rlr)||(nblines==0))
1315 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1316 else
1317 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1320 else
1321 {for(i=rlr;i>=rul;i--)
1323 if((i<rul+nblines)||(nblines==0))
1324 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1325 else
1326 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1330 break;
1331 case CGA:
1332 bpp=vga_modes[line].pixbits;
1333 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1335 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1337 else
1339 if(bpp==2)
1341 cul<<=1;
1342 cols<<=1;
1343 nbcols<<=1;
1345 // if Scroll up
1346 if(dir==SCROLL_UP)
1347 {for(i=rul;i<=rlr;i++)
1349 if((i+nblines>rlr)||(nblines==0))
1350 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1351 else
1352 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1355 else
1356 {for(i=rlr;i>=rul;i--)
1358 if((i<rul+nblines)||(nblines==0))
1359 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1360 else
1361 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1365 break;
1366 #ifdef DEBUG
1367 default:
1368 printf("Scroll in graphics mode ");
1369 unimplemented();
1370 #endif
1375 // --------------------------------------------------------------------------------------------
1376 static void biosfn_read_char_attr (page,car)
1377 Bit8u page;Bit16u *car;
1378 {Bit16u ss=get_SS();
1379 Bit8u xcurs,ycurs,mode,line;
1380 Bit16u nbcols,nbrows,address;
1381 Bit16u cursor,dummy;
1383 // Get the mode
1384 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1385 line=find_vga_entry(mode);
1386 if(line==0xFF)return;
1388 // Get the cursor pos for the page
1389 biosfn_get_cursor_pos(page,&dummy,&cursor);
1390 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1392 // Get the dimensions
1393 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1394 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1396 if(vga_modes[line].class==TEXT)
1398 // Compute the address
1399 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1401 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1403 else
1405 // FIXME gfx mode
1406 #ifdef DEBUG
1407 unimplemented();
1408 #endif
1412 // --------------------------------------------------------------------------------------------
1413 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1414 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1416 Bit8u i,j,mask;
1417 Bit8u *fdata;
1418 Bit16u addr,dest,src;
1420 switch(cheight)
1421 {case 14:
1422 fdata = &vgafont14;
1423 break;
1424 case 16:
1425 fdata = &vgafont16;
1426 break;
1427 default:
1428 fdata = &vgafont8;
1430 addr=xcurs+ycurs*cheight*nbcols;
1431 src = car * cheight;
1432 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1433 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1434 if(attr&0x80)
1436 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1438 else
1440 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1442 for(i=0;i<cheight;i++)
1444 dest=addr+i*nbcols;
1445 for(j=0;j<8;j++)
1447 mask=0x80>>j;
1448 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1449 read_byte(0xa000,dest);
1450 if(fdata[src+i]&mask)
1452 write_byte(0xa000,dest,attr&0x0f);
1454 else
1456 write_byte(0xa000,dest,0x00);
1460 ASM_START
1461 mov dx, # VGAREG_GRDC_ADDRESS
1462 mov ax, #0xff08
1463 out dx, ax
1464 mov ax, #0x0005
1465 out dx, ax
1466 mov ax, #0x0003
1467 out dx, ax
1468 ASM_END
1471 // --------------------------------------------------------------------------------------------
1472 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1473 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1475 Bit8u i,j,mask,data;
1476 Bit8u *fdata;
1477 Bit16u addr,dest,src;
1479 fdata = &vgafont8;
1480 addr=(xcurs*bpp)+ycurs*320;
1481 src = car * 8;
1482 for(i=0;i<8;i++)
1484 dest=addr+(i>>1)*80;
1485 if (i & 1) dest += 0x2000;
1486 mask = 0x80;
1487 if (bpp == 1)
1489 if (attr & 0x80)
1491 data = read_byte(0xb800,dest);
1493 else
1495 data = 0x00;
1497 for(j=0;j<8;j++)
1499 if (fdata[src+i] & mask)
1501 if (attr & 0x80)
1503 data ^= (attr & 0x01) << (7-j);
1505 else
1507 data |= (attr & 0x01) << (7-j);
1510 mask >>= 1;
1512 write_byte(0xb800,dest,data);
1514 else
1516 while (mask > 0)
1518 if (attr & 0x80)
1520 data = read_byte(0xb800,dest);
1522 else
1524 data = 0x00;
1526 for(j=0;j<4;j++)
1528 if (fdata[src+i] & mask)
1530 if (attr & 0x80)
1532 data ^= (attr & 0x03) << ((3-j)*2);
1534 else
1536 data |= (attr & 0x03) << ((3-j)*2);
1539 mask >>= 1;
1541 write_byte(0xb800,dest,data);
1542 dest += 1;
1548 // --------------------------------------------------------------------------------------------
1549 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1550 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1552 Bit8u i,j,mask,data;
1553 Bit8u *fdata;
1554 Bit16u addr,dest,src;
1556 fdata = &vgafont8;
1557 addr=xcurs*8+ycurs*nbcols*64;
1558 src = car * 8;
1559 for(i=0;i<8;i++)
1561 dest=addr+i*nbcols*8;
1562 mask = 0x80;
1563 for(j=0;j<8;j++)
1565 data = 0x00;
1566 if (fdata[src+i] & mask)
1568 data = attr;
1570 write_byte(0xa000,dest+j,data);
1571 mask >>= 1;
1576 // --------------------------------------------------------------------------------------------
1577 static void biosfn_write_char_attr (car,page,attr,count)
1578 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1580 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1581 Bit16u nbcols,nbrows,address;
1582 Bit16u cursor,dummy;
1584 // Get the mode
1585 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1586 line=find_vga_entry(mode);
1587 if(line==0xFF)return;
1589 // Get the cursor pos for the page
1590 biosfn_get_cursor_pos(page,&dummy,&cursor);
1591 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1593 // Get the dimensions
1594 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1595 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1597 if(vga_modes[line].class==TEXT)
1599 // Compute the address
1600 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1602 dummy=((Bit16u)attr<<8)+car;
1603 memsetw(vga_modes[line].sstart,address,dummy,count);
1605 else
1607 // FIXME gfx mode not complete
1608 cheight=video_param_table[line_to_vpti[line]].cheight;
1609 bpp=vga_modes[line].pixbits;
1610 while((count-->0) && (xcurs<nbcols))
1612 switch(vga_modes[line].memmodel)
1614 case PLANAR4:
1615 case PLANAR1:
1616 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1617 break;
1618 case CGA:
1619 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1620 break;
1621 case LINEAR8:
1622 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1623 break;
1624 #ifdef DEBUG
1625 default:
1626 unimplemented();
1627 #endif
1629 xcurs++;
1634 // --------------------------------------------------------------------------------------------
1635 static void biosfn_write_char_only (car,page,attr,count)
1636 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1638 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1639 Bit16u nbcols,nbrows,address;
1640 Bit16u cursor,dummy;
1642 // Get the mode
1643 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1644 line=find_vga_entry(mode);
1645 if(line==0xFF)return;
1647 // Get the cursor pos for the page
1648 biosfn_get_cursor_pos(page,&dummy,&cursor);
1649 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1651 // Get the dimensions
1652 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1653 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1655 if(vga_modes[line].class==TEXT)
1657 // Compute the address
1658 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1660 while(count-->0)
1661 {write_byte(vga_modes[line].sstart,address,car);
1662 address+=2;
1665 else
1667 // FIXME gfx mode not complete
1668 cheight=video_param_table[line_to_vpti[line]].cheight;
1669 bpp=vga_modes[line].pixbits;
1670 while((count-->0) && (xcurs<nbcols))
1672 switch(vga_modes[line].memmodel)
1674 case PLANAR4:
1675 case PLANAR1:
1676 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1677 break;
1678 case CGA:
1679 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1680 break;
1681 case LINEAR8:
1682 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1683 break;
1684 #ifdef DEBUG
1685 default:
1686 unimplemented();
1687 #endif
1689 xcurs++;
1694 // --------------------------------------------------------------------------------------------
1695 ASM_START
1696 biosfn_group_0B:
1697 cmp bh, #0x00
1698 je biosfn_set_border_color
1699 cmp bh, #0x01
1700 je biosfn_set_palette
1701 #ifdef DEBUG
1702 call _unknown
1703 #endif
1705 biosfn_set_border_color:
1706 push ax
1707 push bx
1708 push cx
1709 push dx
1710 mov dx, # VGAREG_ACTL_RESET
1711 in al, dx
1712 mov dx, # VGAREG_ACTL_ADDRESS
1713 mov al, #0x00
1714 out dx, al
1715 mov al, bl
1716 and al, #0x0f
1717 test al, #0x08
1718 jz set_low_border
1719 add al, #0x08
1720 set_low_border:
1721 out dx, al
1722 mov cl, #0x01
1723 and bl, #0x10
1724 set_intensity_loop:
1725 mov dx, # VGAREG_ACTL_ADDRESS
1726 mov al, cl
1727 out dx, al
1728 mov dx, # VGAREG_ACTL_READ_DATA
1729 in al, dx
1730 and al, #0xef
1731 or al, bl
1732 mov dx, # VGAREG_ACTL_ADDRESS
1733 out dx, al
1734 inc cl
1735 cmp cl, #0x04
1736 jne set_intensity_loop
1737 mov al, #0x20
1738 out dx, al
1739 pop dx
1740 pop cx
1741 pop bx
1742 pop ax
1744 biosfn_set_palette:
1745 push ax
1746 push bx
1747 push cx
1748 push dx
1749 mov dx, # VGAREG_ACTL_RESET
1750 in al, dx
1751 mov cl, #0x01
1752 and bl, #0x01
1753 set_cga_palette_loop:
1754 mov dx, # VGAREG_ACTL_ADDRESS
1755 mov al, cl
1756 out dx, al
1757 mov dx, # VGAREG_ACTL_READ_DATA
1758 in al, dx
1759 and al, #0xfe
1760 or al, bl
1761 mov dx, # VGAREG_ACTL_ADDRESS
1762 out dx, al
1763 inc cl
1764 cmp cl, #0x04
1765 jne set_cga_palette_loop
1766 mov al, #0x20
1767 out dx, al
1768 pop dx
1769 pop cx
1770 pop bx
1771 pop ax
1773 ASM_END
1775 // --------------------------------------------------------------------------------------------
1776 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1778 Bit8u mode,line,mask,attr,data;
1779 Bit16u addr;
1781 // Get the mode
1782 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1783 line=find_vga_entry(mode);
1784 if(line==0xFF)return;
1785 if(vga_modes[line].class==TEXT)return;
1787 switch(vga_modes[line].memmodel)
1789 case PLANAR4:
1790 case PLANAR1:
1791 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1792 mask = 0x80 >> (CX & 0x07);
1793 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1794 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1795 data = read_byte(0xa000,addr);
1796 if (AL & 0x80)
1798 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1800 write_byte(0xa000,addr,AL);
1801 ASM_START
1802 mov dx, # VGAREG_GRDC_ADDRESS
1803 mov ax, #0xff08
1804 out dx, ax
1805 mov ax, #0x0005
1806 out dx, ax
1807 mov ax, #0x0003
1808 out dx, ax
1809 ASM_END
1810 break;
1811 case CGA:
1812 if(vga_modes[line].pixbits==2)
1814 addr=(CX>>2)+(DX>>1)*80;
1816 else
1818 addr=(CX>>3)+(DX>>1)*80;
1820 if (DX & 1) addr += 0x2000;
1821 data = read_byte(0xb800,addr);
1822 if(vga_modes[line].pixbits==2)
1824 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1825 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1827 else
1829 attr = (AL & 0x01) << (7 - (CX & 0x07));
1830 mask = 0x01 << (7 - (CX & 0x07));
1832 if (AL & 0x80)
1834 data ^= attr;
1836 else
1838 data &= ~mask;
1839 data |= attr;
1841 write_byte(0xb800,addr,data);
1842 break;
1843 case LINEAR8:
1844 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1845 write_byte(0xa000,addr,AL);
1846 break;
1847 #ifdef DEBUG
1848 default:
1849 unimplemented();
1850 #endif
1854 // --------------------------------------------------------------------------------------------
1855 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1857 Bit8u mode,line,mask,attr,data,i;
1858 Bit16u addr;
1859 Bit16u ss=get_SS();
1861 // Get the mode
1862 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1863 line=find_vga_entry(mode);
1864 if(line==0xFF)return;
1865 if(vga_modes[line].class==TEXT)return;
1867 switch(vga_modes[line].memmodel)
1869 case PLANAR4:
1870 case PLANAR1:
1871 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1872 mask = 0x80 >> (CX & 0x07);
1873 attr = 0x00;
1874 for(i=0;i<4;i++)
1876 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1877 data = read_byte(0xa000,addr) & mask;
1878 if (data > 0) attr |= (0x01 << i);
1880 break;
1881 case CGA:
1882 addr=(CX>>2)+(DX>>1)*80;
1883 if (DX & 1) addr += 0x2000;
1884 data = read_byte(0xb800,addr);
1885 if(vga_modes[line].pixbits==2)
1887 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1889 else
1891 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1893 break;
1894 case LINEAR8:
1895 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1896 attr=read_byte(0xa000,addr);
1897 break;
1898 default:
1899 #ifdef DEBUG
1900 unimplemented();
1901 #endif
1902 attr = 0;
1904 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1907 // --------------------------------------------------------------------------------------------
1908 static void biosfn_write_teletype (car, page, attr, flag)
1909 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1910 {// flag = WITH_ATTR / NO_ATTR
1912 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1913 Bit16u nbcols,nbrows,address;
1914 Bit16u cursor,dummy;
1916 // special case if page is 0xff, use current page
1917 if(page==0xff)
1918 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1920 // Get the mode
1921 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1922 line=find_vga_entry(mode);
1923 if(line==0xFF)return;
1925 // Get the cursor pos for the page
1926 biosfn_get_cursor_pos(page,&dummy,&cursor);
1927 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1929 // Get the dimensions
1930 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1931 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1933 switch(car)
1935 case 7:
1936 //FIXME should beep
1937 break;
1939 case 8:
1940 if(xcurs>0)xcurs--;
1941 break;
1943 case '\r':
1944 xcurs=0;
1945 break;
1947 case '\n':
1948 ycurs++;
1949 break;
1951 case '\t':
1954 biosfn_write_teletype(' ',page,attr,flag);
1955 biosfn_get_cursor_pos(page,&dummy,&cursor);
1956 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1957 }while(xcurs%8==0);
1958 break;
1960 default:
1962 if(vga_modes[line].class==TEXT)
1964 // Compute the address
1965 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1967 // Write the char
1968 write_byte(vga_modes[line].sstart,address,car);
1970 if(flag==WITH_ATTR)
1971 write_byte(vga_modes[line].sstart,address+1,attr);
1973 else
1975 // FIXME gfx mode not complete
1976 cheight=video_param_table[line_to_vpti[line]].cheight;
1977 bpp=vga_modes[line].pixbits;
1978 switch(vga_modes[line].memmodel)
1980 case PLANAR4:
1981 case PLANAR1:
1982 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1983 break;
1984 case CGA:
1985 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1986 break;
1987 case LINEAR8:
1988 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1989 break;
1990 #ifdef DEBUG
1991 default:
1992 unimplemented();
1993 #endif
1996 xcurs++;
1999 // Do we need to wrap ?
2000 if(xcurs==nbcols)
2001 {xcurs=0;
2002 ycurs++;
2005 // Do we need to scroll ?
2006 if(ycurs==nbrows)
2008 if(vga_modes[line].class==TEXT)
2010 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2012 else
2014 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2016 ycurs-=1;
2019 // Set the cursor for the page
2020 cursor=ycurs; cursor<<=8; cursor+=xcurs;
2021 biosfn_set_cursor_pos(page,cursor);
2024 // --------------------------------------------------------------------------------------------
2025 ASM_START
2026 biosfn_get_video_mode:
2027 push ds
2028 mov ax, # BIOSMEM_SEG
2029 mov ds, ax
2030 push bx
2031 mov bx, # BIOSMEM_CURRENT_PAGE
2032 mov al, [bx]
2033 pop bx
2034 mov bh, al
2035 push bx
2036 mov bx, # BIOSMEM_VIDEO_CTL
2037 mov ah, [bx]
2038 and ah, #0x80
2039 mov bx, # BIOSMEM_CURRENT_MODE
2040 mov al, [bx]
2041 or al, ah
2042 mov bx, # BIOSMEM_NB_COLS
2043 mov ah, [bx]
2044 pop bx
2045 pop ds
2047 ASM_END
2049 // --------------------------------------------------------------------------------------------
2050 ASM_START
2051 biosfn_group_10:
2052 cmp al, #0x00
2053 jne int10_test_1001
2054 jmp biosfn_set_single_palette_reg
2055 int10_test_1001:
2056 cmp al, #0x01
2057 jne int10_test_1002
2058 jmp biosfn_set_overscan_border_color
2059 int10_test_1002:
2060 cmp al, #0x02
2061 jne int10_test_1003
2062 jmp biosfn_set_all_palette_reg
2063 int10_test_1003:
2064 cmp al, #0x03
2065 jne int10_test_1007
2066 jmp biosfn_toggle_intensity
2067 int10_test_1007:
2068 cmp al, #0x07
2069 jne int10_test_1008
2070 jmp biosfn_get_single_palette_reg
2071 int10_test_1008:
2072 cmp al, #0x08
2073 jne int10_test_1009
2074 jmp biosfn_read_overscan_border_color
2075 int10_test_1009:
2076 cmp al, #0x09
2077 jne int10_test_1010
2078 jmp biosfn_get_all_palette_reg
2079 int10_test_1010:
2080 cmp al, #0x10
2081 jne int10_test_1012
2082 jmp biosfn_set_single_dac_reg
2083 int10_test_1012:
2084 cmp al, #0x12
2085 jne int10_test_1013
2086 jmp biosfn_set_all_dac_reg
2087 int10_test_1013:
2088 cmp al, #0x13
2089 jne int10_test_1015
2090 jmp biosfn_select_video_dac_color_page
2091 int10_test_1015:
2092 cmp al, #0x15
2093 jne int10_test_1017
2094 jmp biosfn_read_single_dac_reg
2095 int10_test_1017:
2096 cmp al, #0x17
2097 jne int10_test_1018
2098 jmp biosfn_read_all_dac_reg
2099 int10_test_1018:
2100 cmp al, #0x18
2101 jne int10_test_1019
2102 jmp biosfn_set_pel_mask
2103 int10_test_1019:
2104 cmp al, #0x19
2105 jne int10_test_101A
2106 jmp biosfn_read_pel_mask
2107 int10_test_101A:
2108 cmp al, #0x1a
2109 jne int10_group_10_unknown
2110 jmp biosfn_read_video_dac_state
2111 int10_group_10_unknown:
2112 #ifdef DEBUG
2113 call _unknown
2114 #endif
2117 biosfn_set_single_palette_reg:
2118 cmp bl, #0x14
2119 ja no_actl_reg1
2120 push ax
2121 push dx
2122 mov dx, # VGAREG_ACTL_RESET
2123 in al, dx
2124 mov dx, # VGAREG_ACTL_ADDRESS
2125 mov al, bl
2126 out dx, al
2127 mov al, bh
2128 out dx, al
2129 mov al, #0x20
2130 out dx, al
2131 pop dx
2132 pop ax
2133 no_actl_reg1:
2135 ASM_END
2137 // --------------------------------------------------------------------------------------------
2138 ASM_START
2139 biosfn_set_overscan_border_color:
2140 push bx
2141 mov bl, #0x11
2142 call biosfn_set_single_palette_reg
2143 pop bx
2145 ASM_END
2147 // --------------------------------------------------------------------------------------------
2148 ASM_START
2149 biosfn_set_all_palette_reg:
2150 push ax
2151 push bx
2152 push cx
2153 push dx
2154 mov bx, dx
2155 mov dx, # VGAREG_ACTL_RESET
2156 in al, dx
2157 mov cl, #0x00
2158 mov dx, # VGAREG_ACTL_ADDRESS
2159 set_palette_loop:
2160 mov al, cl
2161 out dx, al
2162 seg es
2163 mov al, [bx]
2164 out dx, al
2165 inc bx
2166 inc cl
2167 cmp cl, #0x10
2168 jne set_palette_loop
2169 mov al, #0x11
2170 out dx, al
2171 seg es
2172 mov al, [bx]
2173 out dx, al
2174 mov al, #0x20
2175 out dx, al
2176 pop dx
2177 pop cx
2178 pop bx
2179 pop ax
2181 ASM_END
2183 // --------------------------------------------------------------------------------------------
2184 ASM_START
2185 biosfn_toggle_intensity:
2186 push ax
2187 push bx
2188 push dx
2189 mov dx, # VGAREG_ACTL_RESET
2190 in al, dx
2191 mov dx, # VGAREG_ACTL_ADDRESS
2192 mov al, #0x10
2193 out dx, al
2194 mov dx, # VGAREG_ACTL_READ_DATA
2195 in al, dx
2196 and al, #0xf7
2197 and bl, #0x01
2198 shl bl, 3
2199 or al, bl
2200 mov dx, # VGAREG_ACTL_ADDRESS
2201 out dx, al
2202 mov al, #0x20
2203 out dx, al
2204 pop dx
2205 pop bx
2206 pop ax
2208 ASM_END
2210 // --------------------------------------------------------------------------------------------
2211 ASM_START
2212 biosfn_get_single_palette_reg:
2213 cmp bl, #0x14
2214 ja no_actl_reg2
2215 push ax
2216 push dx
2217 mov dx, # VGAREG_ACTL_RESET
2218 in al, dx
2219 mov dx, # VGAREG_ACTL_ADDRESS
2220 mov al, bl
2221 out dx, al
2222 mov dx, # VGAREG_ACTL_READ_DATA
2223 in al, dx
2224 mov bh, al
2225 mov dx, # VGAREG_ACTL_RESET
2226 in al, dx
2227 mov dx, # VGAREG_ACTL_ADDRESS
2228 mov al, #0x20
2229 out dx, al
2230 pop dx
2231 pop ax
2232 no_actl_reg2:
2234 ASM_END
2236 // --------------------------------------------------------------------------------------------
2237 ASM_START
2238 biosfn_read_overscan_border_color:
2239 push ax
2240 push bx
2241 mov bl, #0x11
2242 call biosfn_get_single_palette_reg
2243 mov al, bh
2244 pop bx
2245 mov bh, al
2246 pop ax
2248 ASM_END
2250 // --------------------------------------------------------------------------------------------
2251 ASM_START
2252 biosfn_get_all_palette_reg:
2253 push ax
2254 push bx
2255 push cx
2256 push dx
2257 mov bx, dx
2258 mov cl, #0x00
2259 get_palette_loop:
2260 mov dx, # VGAREG_ACTL_RESET
2261 in al, dx
2262 mov dx, # VGAREG_ACTL_ADDRESS
2263 mov al, cl
2264 out dx, al
2265 mov dx, # VGAREG_ACTL_READ_DATA
2266 in al, dx
2267 seg es
2268 mov [bx], al
2269 inc bx
2270 inc cl
2271 cmp cl, #0x10
2272 jne get_palette_loop
2273 mov dx, # VGAREG_ACTL_RESET
2274 in al, dx
2275 mov dx, # VGAREG_ACTL_ADDRESS
2276 mov al, #0x11
2277 out dx, al
2278 mov dx, # VGAREG_ACTL_READ_DATA
2279 in al, dx
2280 seg es
2281 mov [bx], al
2282 mov dx, # VGAREG_ACTL_RESET
2283 in al, dx
2284 mov dx, # VGAREG_ACTL_ADDRESS
2285 mov al, #0x20
2286 out dx, al
2287 pop dx
2288 pop cx
2289 pop bx
2290 pop ax
2292 ASM_END
2294 // --------------------------------------------------------------------------------------------
2295 ASM_START
2296 biosfn_set_single_dac_reg:
2297 push ax
2298 push dx
2299 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2300 mov al, bl
2301 out dx, al
2302 mov dx, # VGAREG_DAC_DATA
2303 pop ax
2304 push ax
2305 mov al, ah
2306 out dx, al
2307 mov al, ch
2308 out dx, al
2309 mov al, cl
2310 out dx, al
2311 pop dx
2312 pop ax
2314 ASM_END
2316 // --------------------------------------------------------------------------------------------
2317 ASM_START
2318 biosfn_set_all_dac_reg:
2319 push ax
2320 push bx
2321 push cx
2322 push dx
2323 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2324 mov al, bl
2325 out dx, al
2326 pop dx
2327 push dx
2328 mov bx, dx
2329 mov dx, # VGAREG_DAC_DATA
2330 set_dac_loop:
2331 seg es
2332 mov al, [bx]
2333 out dx, al
2334 inc bx
2335 seg es
2336 mov al, [bx]
2337 out dx, al
2338 inc bx
2339 seg es
2340 mov al, [bx]
2341 out dx, al
2342 inc bx
2343 dec cx
2344 jnz set_dac_loop
2345 pop dx
2346 pop cx
2347 pop bx
2348 pop ax
2350 ASM_END
2352 // --------------------------------------------------------------------------------------------
2353 ASM_START
2354 biosfn_select_video_dac_color_page:
2355 push ax
2356 push bx
2357 push dx
2358 mov dx, # VGAREG_ACTL_RESET
2359 in al, dx
2360 mov dx, # VGAREG_ACTL_ADDRESS
2361 mov al, #0x10
2362 out dx, al
2363 mov dx, # VGAREG_ACTL_READ_DATA
2364 in al, dx
2365 and bl, #0x01
2366 jnz set_dac_page
2367 and al, #0x7f
2368 shl bh, 7
2369 or al, bh
2370 mov dx, # VGAREG_ACTL_ADDRESS
2371 out dx, al
2372 jmp set_actl_normal
2373 set_dac_page:
2374 push ax
2375 mov dx, # VGAREG_ACTL_RESET
2376 in al, dx
2377 mov dx, # VGAREG_ACTL_ADDRESS
2378 mov al, #0x14
2379 out dx, al
2380 pop ax
2381 and al, #0x80
2382 jnz set_dac_16_page
2383 shl bh, 2
2384 set_dac_16_page:
2385 and bh, #0x0f
2386 mov al, bh
2387 out dx, al
2388 set_actl_normal:
2389 mov al, #0x20
2390 out dx, al
2391 pop dx
2392 pop bx
2393 pop ax
2395 ASM_END
2397 // --------------------------------------------------------------------------------------------
2398 ASM_START
2399 biosfn_read_single_dac_reg:
2400 push ax
2401 push dx
2402 mov dx, # VGAREG_DAC_READ_ADDRESS
2403 mov al, bl
2404 out dx, al
2405 pop ax
2406 mov ah, al
2407 mov dx, # VGAREG_DAC_DATA
2408 in al, dx
2409 xchg al, ah
2410 push ax
2411 in al, dx
2412 mov ch, al
2413 in al, dx
2414 mov cl, al
2415 pop dx
2416 pop ax
2418 ASM_END
2420 // --------------------------------------------------------------------------------------------
2421 ASM_START
2422 biosfn_read_all_dac_reg:
2423 push ax
2424 push bx
2425 push cx
2426 push dx
2427 mov dx, # VGAREG_DAC_READ_ADDRESS
2428 mov al, bl
2429 out dx, al
2430 pop dx
2431 push dx
2432 mov bx, dx
2433 mov dx, # VGAREG_DAC_DATA
2434 read_dac_loop:
2435 in al, dx
2436 seg es
2437 mov [bx], al
2438 inc bx
2439 in al, dx
2440 seg es
2441 mov [bx], al
2442 inc bx
2443 in al, dx
2444 seg es
2445 mov [bx], al
2446 inc bx
2447 dec cx
2448 jnz read_dac_loop
2449 pop dx
2450 pop cx
2451 pop bx
2452 pop ax
2454 ASM_END
2456 // --------------------------------------------------------------------------------------------
2457 ASM_START
2458 biosfn_set_pel_mask:
2459 push ax
2460 push dx
2461 mov dx, # VGAREG_PEL_MASK
2462 mov al, bl
2463 out dx, al
2464 pop dx
2465 pop ax
2467 ASM_END
2469 // --------------------------------------------------------------------------------------------
2470 ASM_START
2471 biosfn_read_pel_mask:
2472 push ax
2473 push dx
2474 mov dx, # VGAREG_PEL_MASK
2475 in al, dx
2476 mov bl, al
2477 pop dx
2478 pop ax
2480 ASM_END
2482 // --------------------------------------------------------------------------------------------
2483 ASM_START
2484 biosfn_read_video_dac_state:
2485 push ax
2486 push dx
2487 mov dx, # VGAREG_ACTL_RESET
2488 in al, dx
2489 mov dx, # VGAREG_ACTL_ADDRESS
2490 mov al, #0x10
2491 out dx, al
2492 mov dx, # VGAREG_ACTL_READ_DATA
2493 in al, dx
2494 mov bl, al
2495 shr bl, 7
2496 mov dx, # VGAREG_ACTL_RESET
2497 in al, dx
2498 mov dx, # VGAREG_ACTL_ADDRESS
2499 mov al, #0x14
2500 out dx, al
2501 mov dx, # VGAREG_ACTL_READ_DATA
2502 in al, dx
2503 mov bh, al
2504 and bh, #0x0f
2505 test bl, #0x01
2506 jnz get_dac_16_page
2507 shr bh, 2
2508 get_dac_16_page:
2509 mov dx, # VGAREG_ACTL_RESET
2510 in al, dx
2511 mov dx, # VGAREG_ACTL_ADDRESS
2512 mov al, #0x20
2513 out dx, al
2514 pop dx
2515 pop ax
2517 ASM_END
2519 // --------------------------------------------------------------------------------------------
2520 static void biosfn_perform_gray_scale_summing (start,count)
2521 Bit16u start;Bit16u count;
2522 {Bit8u r,g,b;
2523 Bit16u i;
2524 Bit16u index;
2526 inb(VGAREG_ACTL_RESET);
2527 outb(VGAREG_ACTL_ADDRESS,0x00);
2529 for( index = 0; index < count; index++ )
2531 // set read address and switch to read mode
2532 outb(VGAREG_DAC_READ_ADDRESS,start);
2533 // get 6-bit wide RGB data values
2534 r=inb( VGAREG_DAC_DATA );
2535 g=inb( VGAREG_DAC_DATA );
2536 b=inb( VGAREG_DAC_DATA );
2538 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2539 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2541 if(i>0x3f)i=0x3f;
2543 // set write address and switch to write mode
2544 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2545 // write new intensity value
2546 outb( VGAREG_DAC_DATA, i&0xff );
2547 outb( VGAREG_DAC_DATA, i&0xff );
2548 outb( VGAREG_DAC_DATA, i&0xff );
2549 start++;
2551 inb(VGAREG_ACTL_RESET);
2552 outb(VGAREG_ACTL_ADDRESS,0x20);
2555 // --------------------------------------------------------------------------------------------
2556 static void get_font_access()
2558 ASM_START
2559 mov dx, # VGAREG_SEQU_ADDRESS
2560 mov ax, #0x0100
2561 out dx, ax
2562 mov ax, #0x0402
2563 out dx, ax
2564 mov ax, #0x0704
2565 out dx, ax
2566 mov ax, #0x0300
2567 out dx, ax
2568 mov dx, # VGAREG_GRDC_ADDRESS
2569 mov ax, #0x0204
2570 out dx, ax
2571 mov ax, #0x0005
2572 out dx, ax
2573 mov ax, #0x0406
2574 out dx, ax
2575 ASM_END
2578 static void release_font_access()
2580 ASM_START
2581 mov dx, # VGAREG_SEQU_ADDRESS
2582 mov ax, #0x0100
2583 out dx, ax
2584 mov ax, #0x0302
2585 out dx, ax
2586 mov ax, #0x0304
2587 out dx, ax
2588 mov ax, #0x0300
2589 out dx, ax
2590 mov dx, # VGAREG_READ_MISC_OUTPUT
2591 in al, dx
2592 and al, #0x01
2593 shl al, 2
2594 or al, #0x0a
2595 mov ah, al
2596 mov al, #0x06
2597 mov dx, # VGAREG_GRDC_ADDRESS
2598 out dx, ax
2599 mov ax, #0x0004
2600 out dx, ax
2601 mov ax, #0x1005
2602 out dx, ax
2603 ASM_END
2606 ASM_START
2607 idiv_u:
2608 xor dx,dx
2609 div bx
2611 ASM_END
2613 static void set_scan_lines(lines) Bit8u lines;
2615 Bit16u crtc_addr,cols,page,vde;
2616 Bit8u crtc_r9,ovl,rows;
2618 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2619 outb(crtc_addr, 0x09);
2620 crtc_r9 = inb(crtc_addr+1);
2621 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2622 outb(crtc_addr+1, crtc_r9);
2623 if(lines==8)
2625 biosfn_set_cursor_shape(0x06,0x07);
2627 else
2629 biosfn_set_cursor_shape(lines-4,lines-3);
2631 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2632 outb(crtc_addr, 0x12);
2633 vde = inb(crtc_addr+1);
2634 outb(crtc_addr, 0x07);
2635 ovl = inb(crtc_addr+1);
2636 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2637 rows = vde / lines;
2638 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2639 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2640 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2643 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;
2645 Bit16u blockaddr,dest,i,src;
2647 get_font_access();
2648 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2649 for(i=0;i<CX;i++)
2651 src = BP + i * BH;
2652 dest = blockaddr + (DX + i) * 32;
2653 memcpyb(0xA000, dest, ES, src, BH);
2655 release_font_access();
2656 if(AL>=0x10)
2658 set_scan_lines(BH);
2662 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2664 Bit16u blockaddr,dest,i,src;
2666 get_font_access();
2667 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2668 for(i=0;i<0x100;i++)
2670 src = i * 14;
2671 dest = blockaddr + i * 32;
2672 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2674 release_font_access();
2675 if(AL>=0x10)
2677 set_scan_lines(14);
2681 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2683 Bit16u blockaddr,dest,i,src;
2685 get_font_access();
2686 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2687 for(i=0;i<0x100;i++)
2689 src = i * 8;
2690 dest = blockaddr + i * 32;
2691 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2693 release_font_access();
2694 if(AL>=0x10)
2696 set_scan_lines(8);
2700 // --------------------------------------------------------------------------------------------
2701 ASM_START
2702 biosfn_set_text_block_specifier:
2703 push ax
2704 push dx
2705 mov dx, # VGAREG_SEQU_ADDRESS
2706 mov ah, bl
2707 mov al, #0x03
2708 out dx, ax
2709 pop dx
2710 pop ax
2712 ASM_END
2714 // --------------------------------------------------------------------------------------------
2715 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2717 Bit16u blockaddr,dest,i,src;
2719 get_font_access();
2720 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2721 for(i=0;i<0x100;i++)
2723 src = i * 16;
2724 dest = blockaddr + i * 32;
2725 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2727 release_font_access();
2728 if(AL>=0x10)
2730 set_scan_lines(16);
2734 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2736 #ifdef DEBUG
2737 unimplemented();
2738 #endif
2740 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2742 #ifdef DEBUG
2743 unimplemented();
2744 #endif
2746 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2748 #ifdef DEBUG
2749 unimplemented();
2750 #endif
2752 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2754 #ifdef DEBUG
2755 unimplemented();
2756 #endif
2758 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2760 #ifdef DEBUG
2761 unimplemented();
2762 #endif
2764 // --------------------------------------------------------------------------------------------
2765 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2766 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2767 {Bit16u ss=get_SS();
2769 switch(BH)
2770 {case 0x00:
2771 write_word(ss,ES,read_word(0x00,0x1f*4));
2772 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2773 break;
2774 case 0x01:
2775 write_word(ss,ES,read_word(0x00,0x43*4));
2776 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2777 break;
2778 case 0x02:
2779 write_word(ss,ES,0xC000);
2780 write_word(ss,BP,vgafont14);
2781 break;
2782 case 0x03:
2783 write_word(ss,ES,0xC000);
2784 write_word(ss,BP,vgafont8);
2785 break;
2786 case 0x04:
2787 write_word(ss,ES,0xC000);
2788 write_word(ss,BP,vgafont8+128*8);
2789 break;
2790 case 0x05:
2791 write_word(ss,ES,0xC000);
2792 write_word(ss,BP,vgafont14alt);
2793 break;
2794 case 0x06:
2795 write_word(ss,ES,0xC000);
2796 write_word(ss,BP,vgafont16);
2797 break;
2798 case 0x07:
2799 write_word(ss,ES,0xC000);
2800 write_word(ss,BP,vgafont16alt);
2801 break;
2802 default:
2803 #ifdef DEBUG
2804 printf("Get font info BH(%02x) was discarded\n",BH);
2805 #endif
2806 return;
2808 // Set byte/char of on screen font
2809 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2811 // Set Highest char row
2812 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2815 // --------------------------------------------------------------------------------------------
2816 ASM_START
2817 biosfn_get_ega_info:
2818 push ds
2819 push ax
2820 mov ax, # BIOSMEM_SEG
2821 mov ds, ax
2822 xor ch, ch
2823 mov bx, # BIOSMEM_SWITCHES
2824 mov cl, [bx]
2825 and cl, #0x0f
2826 mov bx, # BIOSMEM_CRTC_ADDRESS
2827 mov ax, [bx]
2828 mov bx, #0x0003
2829 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2830 jne mode_ega_color
2831 mov bh, #0x01
2832 mode_ega_color:
2833 pop ax
2834 pop ds
2836 ASM_END
2838 // --------------------------------------------------------------------------------------------
2839 static void biosfn_alternate_prtsc()
2841 #ifdef DEBUG
2842 unimplemented();
2843 #endif
2846 // --------------------------------------------------------------------------------------------
2847 ASM_START
2848 biosfn_select_vert_res:
2850 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2852 push ds
2853 push bx
2854 push dx
2855 mov dl, al
2856 mov ax, # BIOSMEM_SEG
2857 mov ds, ax
2858 mov bx, # BIOSMEM_MODESET_CTL
2859 mov al, [bx]
2860 mov bx, # BIOSMEM_SWITCHES
2861 mov ah, [bx]
2862 cmp dl, #0x01
2863 je vert_res_350
2864 jb vert_res_200
2865 cmp dl, #0x02
2866 je vert_res_400
2867 #ifdef DEBUG
2868 mov al, dl
2869 xor ah, ah
2870 push ax
2871 mov bx, #msg_vert_res
2872 push bx
2873 call _printf
2874 add sp, #4
2875 #endif
2876 jmp set_retcode
2877 vert_res_400:
2879 ; reset modeset ctl bit 7 and set bit 4
2880 ; set switches bit 3-0 to 0x09
2882 and al, #0x7f
2883 or al, #0x10
2884 and ah, #0xf0
2885 or ah, #0x09
2886 jnz set_vert_res
2887 vert_res_350:
2889 ; reset modeset ctl bit 7 and bit 4
2890 ; set switches bit 3-0 to 0x09
2892 and al, #0x6f
2893 and ah, #0xf0
2894 or ah, #0x09
2895 jnz set_vert_res
2896 vert_res_200:
2898 ; set modeset ctl bit 7 and reset bit 4
2899 ; set switches bit 3-0 to 0x08
2901 and al, #0xef
2902 or al, #0x80
2903 and ah, #0xf0
2904 or ah, #0x08
2905 set_vert_res:
2906 mov bx, # BIOSMEM_MODESET_CTL
2907 mov [bx], al
2908 mov bx, # BIOSMEM_SWITCHES
2909 mov [bx], ah
2910 set_retcode:
2911 mov ax, #0x1212
2912 pop dx
2913 pop bx
2914 pop ds
2917 #ifdef DEBUG
2918 msg_vert_res:
2919 .ascii "Select vert res (%02x) was discarded"
2920 .byte 0x0d,0x0a,0x00
2921 #endif
2924 biosfn_enable_default_palette_loading:
2925 push ds
2926 push bx
2927 push dx
2928 mov dl, al
2929 and dl, #0x01
2930 shl dl, 3
2931 mov ax, # BIOSMEM_SEG
2932 mov ds, ax
2933 mov bx, # BIOSMEM_MODESET_CTL
2934 mov al, [bx]
2935 and al, #0xf7
2936 or al, dl
2937 mov [bx], al
2938 mov ax, #0x1212
2939 pop dx
2940 pop bx
2941 pop ds
2945 biosfn_enable_video_addressing:
2946 push bx
2947 push dx
2948 mov bl, al
2949 and bl, #0x01
2950 xor bl, #0x01
2951 shl bl, 1
2952 mov dx, # VGAREG_READ_MISC_OUTPUT
2953 in al, dx
2954 and al, #0xfd
2955 or al, bl
2956 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2957 out dx, al
2958 mov ax, #0x1212
2959 pop dx
2960 pop bx
2964 biosfn_enable_grayscale_summing:
2965 push ds
2966 push bx
2967 push dx
2968 mov dl, al
2969 and dl, #0x01
2970 xor dl, #0x01
2971 shl dl, 1
2972 mov ax, # BIOSMEM_SEG
2973 mov ds, ax
2974 mov bx, # BIOSMEM_MODESET_CTL
2975 mov al, [bx]
2976 and al, #0xfd
2977 or al, dl
2978 mov [bx], al
2979 mov ax, #0x1212
2980 pop dx
2981 pop bx
2982 pop ds
2986 biosfn_enable_cursor_emulation:
2987 push ds
2988 push bx
2989 push dx
2990 mov dl, al
2991 and dl, #0x01
2992 xor dl, #0x01
2993 mov ax, # BIOSMEM_SEG
2994 mov ds, ax
2995 mov bx, # BIOSMEM_MODESET_CTL
2996 mov al, [bx]
2997 and al, #0xfe
2998 or al, dl
2999 mov [bx], al
3000 mov ax, #0x1212
3001 pop dx
3002 pop bx
3003 pop ds
3005 ASM_END
3007 // --------------------------------------------------------------------------------------------
3008 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3010 #ifdef DEBUG
3011 unimplemented();
3012 #endif
3014 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3016 #ifdef DEBUG
3017 unimplemented();
3018 #endif
3021 // --------------------------------------------------------------------------------------------
3022 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3023 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3025 Bit16u newcurs,oldcurs,dummy;
3026 Bit8u car,carattr;
3028 // Read curs info for the page
3029 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3031 // if row=0xff special case : use current cursor position
3032 if(row==0xff)
3033 {col=oldcurs&0x00ff;
3034 row=(oldcurs&0xff00)>>8;
3037 newcurs=row; newcurs<<=8; newcurs+=col;
3038 biosfn_set_cursor_pos(page,newcurs);
3040 while(count--!=0)
3042 car=read_byte(seg,offset++);
3043 if((flag&0x02)!=0)
3044 attr=read_byte(seg,offset++);
3046 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3049 // Set back curs pos
3050 if((flag&0x01)==0)
3051 biosfn_set_cursor_pos(page,oldcurs);
3054 // --------------------------------------------------------------------------------------------
3055 ASM_START
3056 biosfn_group_1A:
3057 cmp al, #0x00
3058 je biosfn_read_display_code
3059 cmp al, #0x01
3060 je biosfn_set_display_code
3061 #ifdef DEBUG
3062 call _unknown
3063 #endif
3065 biosfn_read_display_code:
3066 push ds
3067 push ax
3068 mov ax, # BIOSMEM_SEG
3069 mov ds, ax
3070 mov bx, # BIOSMEM_DCC_INDEX
3071 mov al, [bx]
3072 mov bl, al
3073 xor bh, bh
3074 pop ax
3075 mov al, ah
3076 pop ds
3078 biosfn_set_display_code:
3079 push ds
3080 push ax
3081 push bx
3082 mov ax, # BIOSMEM_SEG
3083 mov ds, ax
3084 mov ax, bx
3085 mov bx, # BIOSMEM_DCC_INDEX
3086 mov [bx], al
3087 #ifdef DEBUG
3088 mov al, ah
3089 xor ah, ah
3090 push ax
3091 mov bx, #msg_alt_dcc
3092 push bx
3093 call _printf
3094 add sp, #4
3095 #endif
3096 pop bx
3097 pop ax
3098 mov al, ah
3099 pop ds
3102 #ifdef DEBUG
3103 msg_alt_dcc:
3104 .ascii "Alternate Display code (%02x) was discarded"
3105 .byte 0x0d,0x0a,0x00
3106 #endif
3107 ASM_END
3109 // --------------------------------------------------------------------------------------------
3110 static void biosfn_read_state_info (BX,ES,DI)
3111 Bit16u BX;Bit16u ES;Bit16u DI;
3113 // Address of static functionality table
3114 write_word(ES,DI+0x00,&static_functionality);
3115 write_word(ES,DI+0x02,0xC000);
3117 // Hard coded copy from BIOS area. Should it be cleaner ?
3118 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3119 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3121 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3122 write_byte(ES,DI+0x26,0);
3123 write_byte(ES,DI+0x27,16);
3124 write_byte(ES,DI+0x28,0);
3125 write_byte(ES,DI+0x29,8);
3126 write_byte(ES,DI+0x2a,2);
3127 write_byte(ES,DI+0x2b,0);
3128 write_byte(ES,DI+0x2c,0);
3129 write_byte(ES,DI+0x31,3);
3130 write_byte(ES,DI+0x32,0);
3132 memsetb(ES,DI+0x33,0,13);
3135 // --------------------------------------------------------------------------------------------
3136 // --------------------------------------------------------------------------------------------
3137 static Bit16u biosfn_read_video_state_size2 (CX)
3138 Bit16u CX;
3140 Bit16u size;
3141 size = 0;
3142 if (CX & 1) {
3143 size += 0x46;
3145 if (CX & 2) {
3146 size += (5 + 8 + 5) * 2 + 6;
3148 if (CX & 4) {
3149 size += 3 + 256 * 3 + 1;
3151 return size;
3154 static void biosfn_read_video_state_size (CX, BX)
3155 Bit16u CX; Bit16u *BX;
3157 Bit16u ss=get_SS();
3158 write_word(ss, BX, biosfn_read_video_state_size2(CX));
3161 static Bit16u biosfn_save_video_state (CX,ES,BX)
3162 Bit16u CX;Bit16u ES;Bit16u BX;
3164 Bit16u i, v, crtc_addr, ar_index;
3166 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3167 if (CX & 1) {
3168 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3169 write_byte(ES, BX, inb(crtc_addr)); BX++;
3170 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3171 inb(VGAREG_ACTL_RESET);
3172 ar_index = inb(VGAREG_ACTL_ADDRESS);
3173 write_byte(ES, BX, ar_index); BX++;
3174 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3176 for(i=1;i<=4;i++){
3177 outb(VGAREG_SEQU_ADDRESS, i);
3178 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3180 outb(VGAREG_SEQU_ADDRESS, 0);
3181 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3183 for(i=0;i<=0x18;i++) {
3184 outb(crtc_addr,i);
3185 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3188 for(i=0;i<=0x13;i++) {
3189 inb(VGAREG_ACTL_RESET);
3190 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3191 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3193 inb(VGAREG_ACTL_RESET);
3195 for(i=0;i<=8;i++) {
3196 outb(VGAREG_GRDC_ADDRESS,i);
3197 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3200 write_word(ES, BX, crtc_addr); BX+= 2;
3202 /* XXX: read plane latches */
3203 write_byte(ES, BX, 0); BX++;
3204 write_byte(ES, BX, 0); BX++;
3205 write_byte(ES, BX, 0); BX++;
3206 write_byte(ES, BX, 0); BX++;
3208 if (CX & 2) {
3209 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3210 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3211 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3212 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3213 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3214 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3215 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3216 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3217 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3218 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3219 for(i=0;i<8;i++) {
3220 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3221 BX += 2;
3223 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3224 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3225 /* current font */
3226 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3227 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3228 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3229 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3231 if (CX & 4) {
3232 /* XXX: check this */
3233 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3234 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3235 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3236 // Set the whole dac always, from 0
3237 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3238 for(i=0;i<256*3;i++) {
3239 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3241 write_byte(ES, BX, 0); BX++; /* color select register */
3243 return BX;
3246 static Bit16u biosfn_restore_video_state (CX,ES,BX)
3247 Bit16u CX;Bit16u ES;Bit16u BX;
3249 Bit16u i, crtc_addr, v, addr1, ar_index;
3251 if (CX & 1) {
3252 // Reset Attribute Ctl flip-flop
3253 inb(VGAREG_ACTL_RESET);
3255 crtc_addr = read_word(ES, BX + 0x40);
3256 addr1 = BX;
3257 BX += 5;
3259 for(i=1;i<=4;i++){
3260 outb(VGAREG_SEQU_ADDRESS, i);
3261 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3263 outb(VGAREG_SEQU_ADDRESS, 0);
3264 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3266 // Disable CRTC write protection
3267 outw(crtc_addr,0x0011);
3268 // Set CRTC regs
3269 for(i=0;i<=0x18;i++) {
3270 if (i != 0x11) {
3271 outb(crtc_addr,i);
3272 outb(crtc_addr+1, read_byte(ES, BX));
3274 BX++;
3276 // select crtc base address
3277 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3278 if (crtc_addr = 0x3d4)
3279 v |= 0x01;
3280 outb(VGAREG_WRITE_MISC_OUTPUT, v);
3282 // enable write protection if needed
3283 outb(crtc_addr, 0x11);
3284 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3286 // Set Attribute Ctl
3287 ar_index = read_byte(ES, addr1 + 0x03);
3288 inb(VGAREG_ACTL_RESET);
3289 for(i=0;i<=0x13;i++) {
3290 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3291 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3293 outb(VGAREG_ACTL_ADDRESS, ar_index);
3294 inb(VGAREG_ACTL_RESET);
3296 for(i=0;i<=8;i++) {
3297 outb(VGAREG_GRDC_ADDRESS,i);
3298 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3300 BX += 2; /* crtc_addr */
3301 BX += 4; /* plane latches */
3303 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3304 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3305 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3306 addr1++;
3307 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3309 if (CX & 2) {
3310 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3311 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3312 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3313 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3314 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3315 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3316 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3317 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3318 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3319 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3320 for(i=0;i<8;i++) {
3321 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3322 BX += 2;
3324 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3325 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3326 /* current font */
3327 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3328 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3329 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3330 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3332 if (CX & 4) {
3333 BX++;
3334 v = read_byte(ES, BX); BX++;
3335 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3336 // Set the whole dac always, from 0
3337 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3338 for(i=0;i<256*3;i++) {
3339 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3341 BX++;
3342 outb(VGAREG_DAC_WRITE_ADDRESS, v);
3344 return BX;
3347 // ============================================================================================
3349 // Video Utils
3351 // ============================================================================================
3353 // --------------------------------------------------------------------------------------------
3354 static Bit8u find_vga_entry(mode)
3355 Bit8u mode;
3357 Bit8u i,line=0xFF;
3358 for(i=0;i<=MODE_MAX;i++)
3359 if(vga_modes[i].svgamode==mode)
3360 {line=i;
3361 break;
3363 return line;
3366 /* =========================================================== */
3368 * Misc Utils
3370 /* =========================================================== */
3372 // --------------------------------------------------------------------------------------------
3373 static void memsetb(seg,offset,value,count)
3374 Bit16u seg;
3375 Bit16u offset;
3376 Bit16u value;
3377 Bit16u count;
3379 ASM_START
3380 push bp
3381 mov bp, sp
3383 push ax
3384 push cx
3385 push es
3386 push di
3388 mov cx, 10[bp] ; count
3389 cmp cx, #0x00
3390 je memsetb_end
3391 mov ax, 4[bp] ; segment
3392 mov es, ax
3393 mov ax, 6[bp] ; offset
3394 mov di, ax
3395 mov al, 8[bp] ; value
3398 stosb
3400 memsetb_end:
3401 pop di
3402 pop es
3403 pop cx
3404 pop ax
3406 pop bp
3407 ASM_END
3410 // --------------------------------------------------------------------------------------------
3411 static void memsetw(seg,offset,value,count)
3412 Bit16u seg;
3413 Bit16u offset;
3414 Bit16u value;
3415 Bit16u count;
3417 ASM_START
3418 push bp
3419 mov bp, sp
3421 push ax
3422 push cx
3423 push es
3424 push di
3426 mov cx, 10[bp] ; count
3427 cmp cx, #0x00
3428 je memsetw_end
3429 mov ax, 4[bp] ; segment
3430 mov es, ax
3431 mov ax, 6[bp] ; offset
3432 mov di, ax
3433 mov ax, 8[bp] ; value
3436 stosw
3438 memsetw_end:
3439 pop di
3440 pop es
3441 pop cx
3442 pop ax
3444 pop bp
3445 ASM_END
3448 // --------------------------------------------------------------------------------------------
3449 static void memcpyb(dseg,doffset,sseg,soffset,count)
3450 Bit16u dseg;
3451 Bit16u doffset;
3452 Bit16u sseg;
3453 Bit16u soffset;
3454 Bit16u count;
3456 ASM_START
3457 push bp
3458 mov bp, sp
3460 push ax
3461 push cx
3462 push es
3463 push di
3464 push ds
3465 push si
3467 mov cx, 12[bp] ; count
3468 cmp cx, #0x0000
3469 je memcpyb_end
3470 mov ax, 4[bp] ; dsegment
3471 mov es, ax
3472 mov ax, 6[bp] ; doffset
3473 mov di, ax
3474 mov ax, 8[bp] ; ssegment
3475 mov ds, ax
3476 mov ax, 10[bp] ; soffset
3477 mov si, ax
3480 movsb
3482 memcpyb_end:
3483 pop si
3484 pop ds
3485 pop di
3486 pop es
3487 pop cx
3488 pop ax
3490 pop bp
3491 ASM_END
3494 // --------------------------------------------------------------------------------------------
3495 static void memcpyw(dseg,doffset,sseg,soffset,count)
3496 Bit16u dseg;
3497 Bit16u doffset;
3498 Bit16u sseg;
3499 Bit16u soffset;
3500 Bit16u count;
3502 ASM_START
3503 push bp
3504 mov bp, sp
3506 push ax
3507 push cx
3508 push es
3509 push di
3510 push ds
3511 push si
3513 mov cx, 12[bp] ; count
3514 cmp cx, #0x0000
3515 je memcpyw_end
3516 mov ax, 4[bp] ; dsegment
3517 mov es, ax
3518 mov ax, 6[bp] ; doffset
3519 mov di, ax
3520 mov ax, 8[bp] ; ssegment
3521 mov ds, ax
3522 mov ax, 10[bp] ; soffset
3523 mov si, ax
3526 movsw
3528 memcpyw_end:
3529 pop si
3530 pop ds
3531 pop di
3532 pop es
3533 pop cx
3534 pop ax
3536 pop bp
3537 ASM_END
3540 /* =========================================================== */
3542 * These functions where ripped from Kevin's rombios.c
3544 /* =========================================================== */
3546 // --------------------------------------------------------------------------------------------
3547 static Bit8u
3548 read_byte(seg, offset)
3549 Bit16u seg;
3550 Bit16u offset;
3552 ASM_START
3553 push bp
3554 mov bp, sp
3556 push bx
3557 push ds
3558 mov ax, 4[bp] ; segment
3559 mov ds, ax
3560 mov bx, 6[bp] ; offset
3561 mov al, [bx]
3562 ;; al = return value (byte)
3563 pop ds
3564 pop bx
3566 pop bp
3567 ASM_END
3570 // --------------------------------------------------------------------------------------------
3571 static Bit16u
3572 read_word(seg, offset)
3573 Bit16u seg;
3574 Bit16u offset;
3576 ASM_START
3577 push bp
3578 mov bp, sp
3580 push bx
3581 push ds
3582 mov ax, 4[bp] ; segment
3583 mov ds, ax
3584 mov bx, 6[bp] ; offset
3585 mov ax, [bx]
3586 ;; ax = return value (word)
3587 pop ds
3588 pop bx
3590 pop bp
3591 ASM_END
3594 // --------------------------------------------------------------------------------------------
3595 static void
3596 write_byte(seg, offset, data)
3597 Bit16u seg;
3598 Bit16u offset;
3599 Bit8u data;
3601 ASM_START
3602 push bp
3603 mov bp, sp
3605 push ax
3606 push bx
3607 push ds
3608 mov ax, 4[bp] ; segment
3609 mov ds, ax
3610 mov bx, 6[bp] ; offset
3611 mov al, 8[bp] ; data byte
3612 mov [bx], al ; write data byte
3613 pop ds
3614 pop bx
3615 pop ax
3617 pop bp
3618 ASM_END
3621 // --------------------------------------------------------------------------------------------
3622 static void
3623 write_word(seg, offset, data)
3624 Bit16u seg;
3625 Bit16u offset;
3626 Bit16u data;
3628 ASM_START
3629 push bp
3630 mov bp, sp
3632 push ax
3633 push bx
3634 push ds
3635 mov ax, 4[bp] ; segment
3636 mov ds, ax
3637 mov bx, 6[bp] ; offset
3638 mov ax, 8[bp] ; data word
3639 mov [bx], ax ; write data word
3640 pop ds
3641 pop bx
3642 pop ax
3644 pop bp
3645 ASM_END
3648 // --------------------------------------------------------------------------------------------
3649 Bit8u
3650 inb(port)
3651 Bit16u port;
3653 ASM_START
3654 push bp
3655 mov bp, sp
3657 push dx
3658 mov dx, 4[bp]
3659 in al, dx
3660 pop dx
3662 pop bp
3663 ASM_END
3666 Bit16u
3667 inw(port)
3668 Bit16u port;
3670 ASM_START
3671 push bp
3672 mov bp, sp
3674 push dx
3675 mov dx, 4[bp]
3676 in ax, dx
3677 pop dx
3679 pop bp
3680 ASM_END
3683 // --------------------------------------------------------------------------------------------
3684 void
3685 outb(port, val)
3686 Bit16u port;
3687 Bit8u val;
3689 ASM_START
3690 push bp
3691 mov bp, sp
3693 push ax
3694 push dx
3695 mov dx, 4[bp]
3696 mov al, 6[bp]
3697 out dx, al
3698 pop dx
3699 pop ax
3701 pop bp
3702 ASM_END
3705 // --------------------------------------------------------------------------------------------
3706 void
3707 outw(port, val)
3708 Bit16u port;
3709 Bit16u val;
3711 ASM_START
3712 push bp
3713 mov bp, sp
3715 push ax
3716 push dx
3717 mov dx, 4[bp]
3718 mov ax, 6[bp]
3719 out dx, ax
3720 pop dx
3721 pop ax
3723 pop bp
3724 ASM_END
3727 Bit16u get_SS()
3729 ASM_START
3730 mov ax, ss
3731 ASM_END
3734 #ifdef DEBUG
3735 void unimplemented()
3737 printf("--> Unimplemented\n");
3740 void unknown()
3742 printf("--> Unknown int10\n");
3744 #endif
3746 // --------------------------------------------------------------------------------------------
3747 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3748 void printf(s)
3749 Bit8u *s;
3751 Bit8u c, format_char;
3752 Boolean in_format;
3753 unsigned format_width, i;
3754 Bit16u *arg_ptr;
3755 Bit16u arg_seg, arg, digit, nibble, shift_count;
3757 arg_ptr = &s;
3758 arg_seg = get_SS();
3760 in_format = 0;
3761 format_width = 0;
3763 while (c = read_byte(0xc000, s)) {
3764 if ( c == '%' ) {
3765 in_format = 1;
3766 format_width = 0;
3768 else if (in_format) {
3769 if ( (c>='0') && (c<='9') ) {
3770 format_width = (format_width * 10) + (c - '0');
3772 else if (c == 'x') {
3773 arg_ptr++; // increment to next arg
3774 arg = read_word(arg_seg, arg_ptr);
3775 if (format_width == 0)
3776 format_width = 4;
3777 i = 0;
3778 digit = format_width - 1;
3779 for (i=0; i<format_width; i++) {
3780 nibble = (arg >> (4 * digit)) & 0x000f;
3781 if (nibble <= 9)
3782 outb(0x0500, nibble + '0');
3783 else
3784 outb(0x0500, (nibble - 10) + 'A');
3785 digit--;
3787 in_format = 0;
3789 //else if (c == 'd') {
3790 // in_format = 0;
3791 // }
3793 else {
3794 outb(0x0500, c);
3796 s ++;
3799 #endif
3801 #ifdef VBE
3802 #include "vbe.c"
3803 #endif
3805 #ifdef CIRRUS
3806 #include "clext.c"
3807 #endif
3809 // --------------------------------------------------------------------------------------------
3811 ASM_START
3812 ;; DATA_SEG_DEFS_HERE
3813 ASM_END
3815 ASM_START
3816 .ascii "vgabios ends here"
3817 .byte 0x00
3818 vgabios_end:
3819 .byte 0xCB
3820 ;; BLOCK_STRINGS_BEGIN
3821 ASM_END