- added DPMS support to cirrus vgabios (patch from Gleb Natapov)
[vgabios.git] / vgabios.c
blobe6fe2a0d03a2a61dcbe09cf885839d6c9d9f0b68
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001-2008 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 #ifdef PCIBIOS
153 .org 0x18
154 .word vgabios_pci_data
155 #endif
157 // Info from Bart Oldeman
158 .org 0x1e
159 .ascii "IBM"
160 .byte 0x00
162 vgabios_name:
163 .ascii "Plex86/Bochs VGABios"
164 #ifdef PCIBIOS
165 .ascii " (PCI)"
166 #endif
167 .ascii " "
168 .byte 0x00
170 vgabios_version:
171 #ifndef VGABIOS_VERS
172 .ascii "current-cvs"
173 #else
174 .ascii VGABIOS_VERS
175 #endif
176 .ascii " "
178 vgabios_date:
179 .ascii VGABIOS_DATE
180 .byte 0x0a,0x0d
181 .byte 0x00
183 vgabios_copyright:
184 .ascii "(C) 2008 the LGPL VGABios developers Team"
185 .byte 0x0a,0x0d
186 .byte 0x00
188 vgabios_license:
189 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
190 .byte 0x0a,0x0d
191 .byte 0x0a,0x0d
192 .byte 0x00
194 vgabios_website:
195 .ascii "Please visit :"
196 .byte 0x0a,0x0d
197 ;;.ascii " . http://www.plex86.org"
198 ;;.byte 0x0a,0x0d
199 .ascii " . http://bochs.sourceforge.net"
200 .byte 0x0a,0x0d
201 .ascii " . http://www.nongnu.org/vgabios"
202 .byte 0x0a,0x0d
203 .byte 0x0a,0x0d
204 .byte 0x00
206 #ifdef PCIBIOS
207 vgabios_pci_data:
208 .ascii "PCIR"
209 #ifdef CIRRUS
210 .word 0x1013
211 .word 0x00b8 // CLGD5446
212 #else
213 #error "Unknown PCI vendor and device id"
214 #endif
215 .word 0 // reserved
216 .word 0x18 // dlen
217 .byte 0 // revision
218 .byte 0x0 // class,hi: vga display
219 .word 0x300 // class,lo: vga display
220 .word 0x40 // bios size
221 .word 1 // revision
222 .byte 0 // intel x86 data
223 .byte 0x80 // last image
224 .word 0 // reserved
225 #endif
228 ;; ============================================================================================
230 ;; Init Entry point
232 ;; ============================================================================================
233 vgabios_init_func:
235 ;; init vga card
236 call init_vga_card
238 ;; init basic bios vars
239 call init_bios_area
241 #ifdef VBE
242 ;; init vbe functions
243 call vbe_init
244 #endif
246 ;; set int10 vect
247 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
249 #ifdef CIRRUS
250 call cirrus_init
251 #endif
253 ;; display splash screen
254 call _display_splash_screen
256 ;; init video mode and clear the screen
257 mov ax,#0x0003
258 int #0x10
260 ;; show info
261 call _display_info
263 #ifdef VBE
264 ;; show vbe info
265 call vbe_display_info
266 #endif
268 #ifdef CIRRUS
269 ;; show cirrus info
270 call cirrus_display_info
271 #endif
273 retf
274 ASM_END
277 * int10 handled here
279 ASM_START
280 vgabios_int10_handler:
281 pushf
282 #ifdef DEBUG
283 push es
284 push ds
285 pusha
286 mov bx, #0xc000
287 mov ds, bx
288 call _int10_debugmsg
289 popa
290 pop ds
291 pop es
292 #endif
293 cmp ah, #0x0f
294 jne int10_test_1A
295 call biosfn_get_video_mode
296 jmp int10_end
297 int10_test_1A:
298 cmp ah, #0x1a
299 jne int10_test_0B
300 call biosfn_group_1A
301 jmp int10_end
302 int10_test_0B:
303 cmp ah, #0x0b
304 jne int10_test_1103
305 call biosfn_group_0B
306 jmp int10_end
307 int10_test_1103:
308 cmp ax, #0x1103
309 jne int10_test_12
310 call biosfn_set_text_block_specifier
311 jmp int10_end
312 int10_test_12:
313 cmp ah, #0x12
314 jne int10_test_101B
315 cmp bl, #0x10
316 jne int10_test_BL30
317 call biosfn_get_ega_info
318 jmp int10_end
319 int10_test_BL30:
320 cmp bl, #0x30
321 jne int10_test_BL31
322 call biosfn_select_vert_res
323 jmp int10_end
324 int10_test_BL31:
325 cmp bl, #0x31
326 jne int10_test_BL32
327 call biosfn_enable_default_palette_loading
328 jmp int10_end
329 int10_test_BL32:
330 cmp bl, #0x32
331 jne int10_test_BL33
332 call biosfn_enable_video_addressing
333 jmp int10_end
334 int10_test_BL33:
335 cmp bl, #0x33
336 jne int10_test_BL34
337 call biosfn_enable_grayscale_summing
338 jmp int10_end
339 int10_test_BL34:
340 cmp bl, #0x34
341 jne int10_normal
342 call biosfn_enable_cursor_emulation
343 jmp int10_end
344 int10_test_101B:
345 cmp ax, #0x101b
346 je int10_normal
347 cmp ah, #0x10
348 #ifndef VBE
349 jne int10_normal
350 #else
351 jne int10_test_4F
352 #endif
353 call biosfn_group_10
354 jmp int10_end
355 #ifdef VBE
356 int10_test_4F:
357 cmp ah, #0x4f
358 jne int10_normal
359 cmp al, #0x03
360 jne int10_test_vbe_05
361 call vbe_biosfn_return_current_mode
362 jmp int10_end
363 int10_test_vbe_05:
364 cmp al, #0x05
365 jne int10_test_vbe_06
366 call vbe_biosfn_display_window_control
367 jmp int10_end
368 int10_test_vbe_06:
369 cmp al, #0x06
370 jne int10_test_vbe_07
371 call vbe_biosfn_set_get_logical_scan_line_length
372 jmp int10_end
373 int10_test_vbe_07:
374 cmp al, #0x07
375 jne int10_test_vbe_08
376 call vbe_biosfn_set_get_display_start
377 jmp int10_end
378 int10_test_vbe_08:
379 cmp al, #0x08
380 jne int10_test_vbe_0A
381 call vbe_biosfn_set_get_dac_palette_format
382 jmp int10_end
383 int10_test_vbe_0A:
384 cmp al, #0x0A
385 jne int10_normal
386 call vbe_biosfn_return_protected_mode_interface
387 jmp int10_end
388 #endif
390 int10_normal:
391 push es
392 push ds
393 pusha
395 ;; We have to set ds to access the right data segment
396 mov bx, #0xc000
397 mov ds, bx
398 call _int10_func
400 popa
401 pop ds
402 pop es
403 int10_end:
404 popf
405 iret
406 ASM_END
408 #include "vgatables.h"
409 #include "vgafonts.h"
412 * Boot time harware inits
414 ASM_START
415 init_vga_card:
416 ;; switch to color mode and enable CPU access 480 lines
417 mov dx, #0x3C2
418 mov al, #0xC3
419 outb dx,al
421 ;; more than 64k 3C4/04
422 mov dx, #0x3C4
423 mov al, #0x04
424 outb dx,al
425 mov dx, #0x3C5
426 mov al, #0x02
427 outb dx,al
429 #if defined(USE_BX_INFO) || defined(DEBUG)
430 mov bx, #msg_vga_init
431 push bx
432 call _printf
433 #endif
434 inc sp
435 inc sp
438 #if defined(USE_BX_INFO) || defined(DEBUG)
439 msg_vga_init:
440 .ascii "VGABios $Id$"
441 .byte 0x0d,0x0a,0x00
442 #endif
443 ASM_END
445 // --------------------------------------------------------------------------------------------
447 * Boot time bios area inits
449 ASM_START
450 init_bios_area:
451 push ds
452 mov ax, # BIOSMEM_SEG
453 mov ds, ax
455 ;; init detected hardware BIOS Area
456 mov bx, # BIOSMEM_INITIAL_MODE
457 mov ax, [bx]
458 and ax, #0xffcf
459 ;; set 80x25 color (not clear from RBIL but usual)
460 or ax, #0x0020
461 mov [bx], ax
463 ;; Just for the first int10 find its children
465 ;; the default char height
466 mov bx, # BIOSMEM_CHAR_HEIGHT
467 mov al, #0x10
468 mov [bx], al
470 ;; Clear the screen
471 mov bx, # BIOSMEM_VIDEO_CTL
472 mov al, #0x60
473 mov [bx], al
475 ;; Set the basic screen we have
476 mov bx, # BIOSMEM_SWITCHES
477 mov al, #0xf9
478 mov [bx], al
480 ;; Set the basic modeset options
481 mov bx, # BIOSMEM_MODESET_CTL
482 mov al, #0x51
483 mov [bx], al
485 ;; Set the default MSR
486 mov bx, # BIOSMEM_CURRENT_MSR
487 mov al, #0x09
488 mov [bx], al
490 pop ds
493 _video_save_pointer_table:
494 .word _video_param_table
495 .word 0xc000
497 .word 0 /* XXX: fill it */
498 .word 0
500 .word 0 /* XXX: fill it */
501 .word 0
503 .word 0 /* XXX: fill it */
504 .word 0
506 .word 0 /* XXX: fill it */
507 .word 0
509 .word 0 /* XXX: fill it */
510 .word 0
512 .word 0 /* XXX: fill it */
513 .word 0
515 ASM_END
517 // --------------------------------------------------------------------------------------------
519 * Boot time Splash screen
521 static void display_splash_screen()
525 // --------------------------------------------------------------------------------------------
527 * Tell who we are
530 static void display_info()
532 ASM_START
533 mov ax,#0xc000
534 mov ds,ax
535 mov si,#vgabios_name
536 call _display_string
537 mov si,#vgabios_version
538 call _display_string
540 ;;mov si,#vgabios_copyright
541 ;;call _display_string
542 ;;mov si,#crlf
543 ;;call _display_string
545 mov si,#vgabios_license
546 call _display_string
547 mov si,#vgabios_website
548 call _display_string
549 ASM_END
552 static void display_string()
554 // Get length of string
555 ASM_START
556 mov ax,ds
557 mov es,ax
558 mov di,si
559 xor cx,cx
560 not cx
561 xor al,al
563 repne
564 scasb
565 not cx
566 dec cx
567 push cx
569 mov ax,#0x0300
570 mov bx,#0x0000
571 int #0x10
573 pop cx
574 mov ax,#0x1301
575 mov bx,#0x000b
576 mov bp,si
577 int #0x10
578 ASM_END
581 // --------------------------------------------------------------------------------------------
582 #ifdef DEBUG
583 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
584 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
586 // 0E is write char...
587 if(GET_AH()!=0x0E)
588 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
590 #endif
592 // --------------------------------------------------------------------------------------------
594 * int10 main dispatcher
596 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
597 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
600 // BIOS functions
601 switch(GET_AH())
603 case 0x00:
604 biosfn_set_video_mode(GET_AL());
605 switch(GET_AL()&0x7F)
606 {case 6:
607 SET_AL(0x3F);
608 break;
609 case 0:
610 case 1:
611 case 2:
612 case 3:
613 case 4:
614 case 5:
615 case 7:
616 SET_AL(0x30);
617 break;
618 default:
619 SET_AL(0x20);
621 break;
622 case 0x01:
623 biosfn_set_cursor_shape(GET_CH(),GET_CL());
624 break;
625 case 0x02:
626 biosfn_set_cursor_pos(GET_BH(),DX);
627 break;
628 case 0x03:
629 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
630 break;
631 case 0x04:
632 // Read light pen pos (unimplemented)
633 #ifdef DEBUG
634 unimplemented();
635 #endif
636 AX=0x00;
637 BX=0x00;
638 CX=0x00;
639 DX=0x00;
640 break;
641 case 0x05:
642 biosfn_set_active_page(GET_AL());
643 break;
644 case 0x06:
645 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
646 break;
647 case 0x07:
648 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
649 break;
650 case 0x08:
651 biosfn_read_char_attr(GET_BH(),&AX);
652 break;
653 case 0x09:
654 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
655 break;
656 case 0x0A:
657 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
658 break;
659 case 0x0C:
660 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
661 break;
662 case 0x0D:
663 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
664 break;
665 case 0x0E:
666 // Ralf Brown Interrupt list is WRONG on bh(page)
667 // We do output only on the current page !
668 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
669 break;
670 case 0x10:
671 // All other functions of group AH=0x10 rewritten in assembler
672 biosfn_perform_gray_scale_summing(BX,CX);
673 break;
674 case 0x11:
675 switch(GET_AL())
677 case 0x00:
678 case 0x10:
679 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
680 break;
681 case 0x01:
682 case 0x11:
683 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
684 break;
685 case 0x02:
686 case 0x12:
687 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
688 break;
689 case 0x04:
690 case 0x14:
691 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
692 break;
693 case 0x20:
694 biosfn_load_gfx_8_8_chars(ES,BP);
695 break;
696 case 0x21:
697 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
698 break;
699 case 0x22:
700 biosfn_load_gfx_8_14_chars(GET_BL());
701 break;
702 case 0x23:
703 biosfn_load_gfx_8_8_dd_chars(GET_BL());
704 break;
705 case 0x24:
706 biosfn_load_gfx_8_16_chars(GET_BL());
707 break;
708 case 0x30:
709 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
710 break;
711 #ifdef DEBUG
712 default:
713 unknown();
714 #endif
717 break;
718 case 0x12:
719 switch(GET_BL())
721 case 0x20:
722 biosfn_alternate_prtsc();
723 break;
724 case 0x35:
725 biosfn_switch_video_interface(GET_AL(),ES,DX);
726 SET_AL(0x12);
727 break;
728 case 0x36:
729 biosfn_enable_video_refresh_control(GET_AL());
730 SET_AL(0x12);
731 break;
732 #ifdef DEBUG
733 default:
734 unknown();
735 #endif
737 break;
738 case 0x13:
739 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
740 break;
741 case 0x1B:
742 biosfn_read_state_info(BX,ES,DI);
743 SET_AL(0x1B);
744 break;
745 case 0x1C:
746 switch(GET_AL())
748 case 0x00:
749 biosfn_read_video_state_size(CX,&BX);
750 break;
751 case 0x01:
752 biosfn_save_video_state(CX,ES,BX);
753 break;
754 case 0x02:
755 biosfn_restore_video_state(CX,ES,BX);
756 break;
757 #ifdef DEBUG
758 default:
759 unknown();
760 #endif
762 SET_AL(0x1C);
763 break;
765 #ifdef VBE
766 case 0x4f:
767 if (vbe_has_vbe_display()) {
768 switch(GET_AL())
770 case 0x00:
771 vbe_biosfn_return_controller_information(&AX,ES,DI);
772 break;
773 case 0x01:
774 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
775 break;
776 case 0x02:
777 vbe_biosfn_set_mode(&AX,BX,ES,DI);
778 break;
779 case 0x04:
780 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
781 break;
782 case 0x09:
783 //FIXME
784 #ifdef DEBUG
785 unimplemented();
786 #endif
787 // function failed
788 AX=0x100;
789 break;
790 case 0x0A:
791 //FIXME
792 #ifdef DEBUG
793 unimplemented();
794 #endif
795 // function failed
796 AX=0x100;
797 break;
798 default:
799 #ifdef DEBUG
800 unknown();
801 #endif
802 // function failed
803 AX=0x100;
806 else {
807 // No VBE display
808 AX=0x0100;
810 break;
811 #endif
813 #ifdef DEBUG
814 default:
815 unknown();
816 #endif
820 // ============================================================================================
822 // BIOS functions
824 // ============================================================================================
826 static void biosfn_set_video_mode(mode) Bit8u mode;
827 {// mode: Bit 7 is 1 if no clear screen
829 // Should we clear the screen ?
830 Bit8u noclearmem=mode&0x80;
831 Bit8u line,mmask,*palette,vpti;
832 Bit16u i,twidth,theightm1,cheight;
833 Bit8u modeset_ctl,video_ctl,vga_switches;
834 Bit16u crtc_addr;
836 #ifdef VBE
837 if (vbe_has_vbe_display()) {
838 dispi_set_enable(VBE_DISPI_DISABLED);
840 #endif // def VBE
842 // The real mode
843 mode=mode&0x7f;
845 // find the entry in the video modes
846 line=find_vga_entry(mode);
848 #ifdef DEBUG
849 printf("mode search %02x found line %02x\n",mode,line);
850 #endif
852 if(line==0xFF)
853 return;
855 vpti=line_to_vpti[line];
856 twidth=video_param_table[vpti].twidth;
857 theightm1=video_param_table[vpti].theightm1;
858 cheight=video_param_table[vpti].cheight;
860 // Read the bios vga control
861 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
863 // Read the bios vga switches
864 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
866 // Read the bios mode set control
867 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
869 // Then we know the number of lines
870 // FIXME
872 // if palette loading (bit 3 of modeset ctl = 0)
873 if((modeset_ctl&0x08)==0)
874 {// Set the PEL mask
875 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
877 // Set the whole dac always, from 0
878 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
880 // From which palette
881 switch(vga_modes[line].dacmodel)
882 {case 0:
883 palette=&palette0;
884 break;
885 case 1:
886 palette=&palette1;
887 break;
888 case 2:
889 palette=&palette2;
890 break;
891 case 3:
892 palette=&palette3;
893 break;
895 // Always 256*3 values
896 for(i=0;i<0x0100;i++)
897 {if(i<=dac_regs[vga_modes[line].dacmodel])
898 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
899 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
900 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
902 else
903 {outb(VGAREG_DAC_DATA,0);
904 outb(VGAREG_DAC_DATA,0);
905 outb(VGAREG_DAC_DATA,0);
908 if((modeset_ctl&0x02)==0x02)
910 biosfn_perform_gray_scale_summing(0x00, 0x100);
914 // Reset Attribute Ctl flip-flop
915 inb(VGAREG_ACTL_RESET);
917 // Set Attribute Ctl
918 for(i=0;i<=0x13;i++)
919 {outb(VGAREG_ACTL_ADDRESS,i);
920 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
922 outb(VGAREG_ACTL_ADDRESS,0x14);
923 outb(VGAREG_ACTL_WRITE_DATA,0x00);
925 // Set Sequencer Ctl
926 outb(VGAREG_SEQU_ADDRESS,0);
927 outb(VGAREG_SEQU_DATA,0x03);
928 for(i=1;i<=4;i++)
929 {outb(VGAREG_SEQU_ADDRESS,i);
930 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
933 // Set Grafx Ctl
934 for(i=0;i<=8;i++)
935 {outb(VGAREG_GRDC_ADDRESS,i);
936 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
939 // Set CRTC address VGA or MDA
940 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
942 // Disable CRTC write protection
943 outw(crtc_addr,0x0011);
944 // Set CRTC regs
945 for(i=0;i<=0x18;i++)
946 {outb(crtc_addr,i);
947 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
950 // Set the misc register
951 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
953 // Enable video
954 outb(VGAREG_ACTL_ADDRESS,0x20);
955 inb(VGAREG_ACTL_RESET);
957 if(noclearmem==0x00)
959 if(vga_modes[line].class==TEXT)
961 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
963 else
965 if(mode<0x0d)
967 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
969 else
971 outb( VGAREG_SEQU_ADDRESS, 0x02 );
972 mmask = inb( VGAREG_SEQU_DATA );
973 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
974 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
975 outb( VGAREG_SEQU_DATA, mmask );
980 // Set the BIOS mem
981 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
982 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
983 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
984 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
985 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
986 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
987 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
988 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
989 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
991 // FIXME We nearly have the good tables. to be reworked
992 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
993 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
994 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
996 // FIXME
997 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
998 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
1000 // Set cursor shape
1001 if(vga_modes[line].class==TEXT)
1003 biosfn_set_cursor_shape(0x06,0x07);
1006 // Set cursor pos for page 0..7
1007 for(i=0;i<8;i++)
1008 biosfn_set_cursor_pos(i,0x0000);
1010 // Set active page 0
1011 biosfn_set_active_page(0x00);
1013 // Write the fonts in memory
1014 if(vga_modes[line].class==TEXT)
1016 ASM_START
1017 ;; copy and activate 8x16 font
1018 mov ax, #0x1104
1019 mov bl, #0x00
1020 int #0x10
1021 mov ax, #0x1103
1022 mov bl, #0x00
1023 int #0x10
1024 ASM_END
1027 // Set the ints 0x1F and 0x43
1028 ASM_START
1029 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1030 ASM_END
1032 switch(cheight)
1033 {case 8:
1034 ASM_START
1035 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1036 ASM_END
1037 break;
1038 case 14:
1039 ASM_START
1040 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1041 ASM_END
1042 break;
1043 case 16:
1044 ASM_START
1045 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1046 ASM_END
1047 break;
1051 // --------------------------------------------------------------------------------------------
1052 static void biosfn_set_cursor_shape (CH,CL)
1053 Bit8u CH;Bit8u CL;
1054 {Bit16u cheight,curs,crtc_addr;
1055 Bit8u modeset_ctl;
1057 CH&=0x3f;
1058 CL&=0x1f;
1060 curs=(CH<<8)+CL;
1061 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1063 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1064 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1065 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1067 if(CL!=(CH+1))
1069 CH = ((CH+1) * cheight / 8) -1;
1071 else
1073 CH = ((CL+1) * cheight / 8) - 2;
1075 CL = ((CL+1) * cheight / 8) - 1;
1078 // CTRC regs 0x0a and 0x0b
1079 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1080 outb(crtc_addr,0x0a);
1081 outb(crtc_addr+1,CH);
1082 outb(crtc_addr,0x0b);
1083 outb(crtc_addr+1,CL);
1086 // --------------------------------------------------------------------------------------------
1087 static void biosfn_set_cursor_pos (page, cursor)
1088 Bit8u page;Bit16u cursor;
1090 Bit8u xcurs,ycurs,current;
1091 Bit16u nbcols,nbrows,address,crtc_addr;
1093 // Should not happen...
1094 if(page>7)return;
1096 // Bios cursor pos
1097 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1099 // Set the hardware cursor
1100 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1101 if(page==current)
1103 // Get the dimensions
1104 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1105 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1107 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1109 // Calculate the address knowing nbcols nbrows and page num
1110 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1112 // CRTC regs 0x0e and 0x0f
1113 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1114 outb(crtc_addr,0x0e);
1115 outb(crtc_addr+1,(address&0xff00)>>8);
1116 outb(crtc_addr,0x0f);
1117 outb(crtc_addr+1,address&0x00ff);
1121 // --------------------------------------------------------------------------------------------
1122 static void biosfn_get_cursor_pos (page,shape, pos)
1123 Bit8u page;Bit16u *shape;Bit16u *pos;
1125 Bit16u ss=get_SS();
1127 // Default
1128 write_word(ss, shape, 0);
1129 write_word(ss, pos, 0);
1131 if(page>7)return;
1132 // FIXME should handle VGA 14/16 lines
1133 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1134 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1137 // --------------------------------------------------------------------------------------------
1138 static void biosfn_set_active_page (page)
1139 Bit8u page;
1141 Bit16u cursor,dummy,crtc_addr;
1142 Bit16u nbcols,nbrows,address;
1143 Bit8u mode,line;
1145 if(page>7)return;
1147 // Get the mode
1148 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1149 line=find_vga_entry(mode);
1150 if(line==0xFF)return;
1152 // Get pos curs pos for the right page
1153 biosfn_get_cursor_pos(page,&dummy,&cursor);
1155 if(vga_modes[line].class==TEXT)
1157 // Get the dimensions
1158 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1159 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1161 // Calculate the address knowing nbcols nbrows and page num
1162 address=SCREEN_MEM_START(nbcols,nbrows,page);
1163 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1165 // Start address
1166 address=SCREEN_IO_START(nbcols,nbrows,page);
1168 else
1170 address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
1173 // CRTC regs 0x0c and 0x0d
1174 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1175 outb(crtc_addr,0x0c);
1176 outb(crtc_addr+1,(address&0xff00)>>8);
1177 outb(crtc_addr,0x0d);
1178 outb(crtc_addr+1,address&0x00ff);
1180 // And change the BIOS page
1181 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1183 #ifdef DEBUG
1184 printf("Set active page %02x address %04x\n",page,address);
1185 #endif
1187 // Display the cursor, now the page is active
1188 biosfn_set_cursor_pos(page,cursor);
1191 // --------------------------------------------------------------------------------------------
1192 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1193 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1195 Bit16u src,dest;
1196 Bit8u i;
1198 src=ysrc*cheight*nbcols+xstart;
1199 dest=ydest*cheight*nbcols+xstart;
1200 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1201 for(i=0;i<cheight;i++)
1203 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1205 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1208 // --------------------------------------------------------------------------------------------
1209 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1210 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1212 Bit16u dest;
1213 Bit8u i;
1215 dest=ystart*cheight*nbcols+xstart;
1216 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1217 for(i=0;i<cheight;i++)
1219 memsetb(0xa000,dest+i*nbcols,attr,cols);
1221 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1224 // --------------------------------------------------------------------------------------------
1225 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1226 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1228 Bit16u src,dest;
1229 Bit8u i;
1231 src=((ysrc*cheight*nbcols)>>1)+xstart;
1232 dest=((ydest*cheight*nbcols)>>1)+xstart;
1233 for(i=0;i<cheight;i++)
1235 if (i & 1)
1236 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1237 else
1238 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1242 // --------------------------------------------------------------------------------------------
1243 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1244 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1246 Bit16u dest;
1247 Bit8u i;
1249 dest=((ystart*cheight*nbcols)>>1)+xstart;
1250 for(i=0;i<cheight;i++)
1252 if (i & 1)
1253 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1254 else
1255 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1259 // --------------------------------------------------------------------------------------------
1260 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1261 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1263 // page == 0xFF if current
1265 Bit8u mode,line,cheight,bpp,cols;
1266 Bit16u nbcols,nbrows,i;
1267 Bit16u address;
1269 if(rul>rlr)return;
1270 if(cul>clr)return;
1272 // Get the mode
1273 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1274 line=find_vga_entry(mode);
1275 if(line==0xFF)return;
1277 // Get the dimensions
1278 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1279 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1281 // Get the current page
1282 if(page==0xFF)
1283 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1285 if(rlr>=nbrows)rlr=nbrows-1;
1286 if(clr>=nbcols)clr=nbcols-1;
1287 if(nblines>nbrows)nblines=0;
1288 cols=clr-cul+1;
1290 if(vga_modes[line].class==TEXT)
1292 // Compute the address
1293 address=SCREEN_MEM_START(nbcols,nbrows,page);
1294 #ifdef DEBUG
1295 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1296 #endif
1298 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1300 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1302 else
1303 {// if Scroll up
1304 if(dir==SCROLL_UP)
1305 {for(i=rul;i<=rlr;i++)
1307 if((i+nblines>rlr)||(nblines==0))
1308 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1309 else
1310 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1313 else
1314 {for(i=rlr;i>=rul;i--)
1316 if((i<rul+nblines)||(nblines==0))
1317 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1318 else
1319 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1320 if (i>rlr) break;
1325 else
1327 // FIXME gfx mode not complete
1328 cheight=video_param_table[line_to_vpti[line]].cheight;
1329 switch(vga_modes[line].memmodel)
1331 case PLANAR4:
1332 case PLANAR1:
1333 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1335 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1336 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1337 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1339 else
1340 {// if Scroll up
1341 if(dir==SCROLL_UP)
1342 {for(i=rul;i<=rlr;i++)
1344 if((i+nblines>rlr)||(nblines==0))
1345 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1346 else
1347 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1350 else
1351 {for(i=rlr;i>=rul;i--)
1353 if((i<rul+nblines)||(nblines==0))
1354 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1355 else
1356 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1357 if (i>rlr) break;
1361 break;
1362 case CGA:
1363 bpp=vga_modes[line].pixbits;
1364 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1366 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1368 else
1370 if(bpp==2)
1372 cul<<=1;
1373 cols<<=1;
1374 nbcols<<=1;
1376 // if Scroll up
1377 if(dir==SCROLL_UP)
1378 {for(i=rul;i<=rlr;i++)
1380 if((i+nblines>rlr)||(nblines==0))
1381 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1382 else
1383 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1386 else
1387 {for(i=rlr;i>=rul;i--)
1389 if((i<rul+nblines)||(nblines==0))
1390 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1391 else
1392 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1393 if (i>rlr) break;
1397 break;
1398 #ifdef DEBUG
1399 default:
1400 printf("Scroll in graphics mode ");
1401 unimplemented();
1402 #endif
1407 // --------------------------------------------------------------------------------------------
1408 static void biosfn_read_char_attr (page,car)
1409 Bit8u page;Bit16u *car;
1410 {Bit16u ss=get_SS();
1411 Bit8u xcurs,ycurs,mode,line;
1412 Bit16u nbcols,nbrows,address;
1413 Bit16u cursor,dummy;
1415 // Get the mode
1416 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1417 line=find_vga_entry(mode);
1418 if(line==0xFF)return;
1420 // Get the cursor pos for the page
1421 biosfn_get_cursor_pos(page,&dummy,&cursor);
1422 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1424 // Get the dimensions
1425 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1426 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1428 if(vga_modes[line].class==TEXT)
1430 // Compute the address
1431 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1433 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1435 else
1437 // FIXME gfx mode
1438 #ifdef DEBUG
1439 unimplemented();
1440 #endif
1444 // --------------------------------------------------------------------------------------------
1445 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1446 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1448 Bit8u i,j,mask;
1449 Bit8u *fdata;
1450 Bit16u addr,dest,src;
1452 switch(cheight)
1453 {case 14:
1454 fdata = &vgafont14;
1455 break;
1456 case 16:
1457 fdata = &vgafont16;
1458 break;
1459 default:
1460 fdata = &vgafont8;
1462 addr=xcurs+ycurs*cheight*nbcols;
1463 src = car * cheight;
1464 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1465 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1466 if(attr&0x80)
1468 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1470 else
1472 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1474 for(i=0;i<cheight;i++)
1476 dest=addr+i*nbcols;
1477 for(j=0;j<8;j++)
1479 mask=0x80>>j;
1480 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1481 read_byte(0xa000,dest);
1482 if(fdata[src+i]&mask)
1484 write_byte(0xa000,dest,attr&0x0f);
1486 else
1488 write_byte(0xa000,dest,0x00);
1492 ASM_START
1493 mov dx, # VGAREG_GRDC_ADDRESS
1494 mov ax, #0xff08
1495 out dx, ax
1496 mov ax, #0x0005
1497 out dx, ax
1498 mov ax, #0x0003
1499 out dx, ax
1500 ASM_END
1503 // --------------------------------------------------------------------------------------------
1504 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1505 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1507 Bit8u i,j,mask,data;
1508 Bit8u *fdata;
1509 Bit16u addr,dest,src;
1511 fdata = &vgafont8;
1512 addr=(xcurs*bpp)+ycurs*320;
1513 src = car * 8;
1514 for(i=0;i<8;i++)
1516 dest=addr+(i>>1)*80;
1517 if (i & 1) dest += 0x2000;
1518 mask = 0x80;
1519 if (bpp == 1)
1521 if (attr & 0x80)
1523 data = read_byte(0xb800,dest);
1525 else
1527 data = 0x00;
1529 for(j=0;j<8;j++)
1531 if (fdata[src+i] & mask)
1533 if (attr & 0x80)
1535 data ^= (attr & 0x01) << (7-j);
1537 else
1539 data |= (attr & 0x01) << (7-j);
1542 mask >>= 1;
1544 write_byte(0xb800,dest,data);
1546 else
1548 while (mask > 0)
1550 if (attr & 0x80)
1552 data = read_byte(0xb800,dest);
1554 else
1556 data = 0x00;
1558 for(j=0;j<4;j++)
1560 if (fdata[src+i] & mask)
1562 if (attr & 0x80)
1564 data ^= (attr & 0x03) << ((3-j)*2);
1566 else
1568 data |= (attr & 0x03) << ((3-j)*2);
1571 mask >>= 1;
1573 write_byte(0xb800,dest,data);
1574 dest += 1;
1580 // --------------------------------------------------------------------------------------------
1581 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1582 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1584 Bit8u i,j,mask,data;
1585 Bit8u *fdata;
1586 Bit16u addr,dest,src;
1588 fdata = &vgafont8;
1589 addr=xcurs*8+ycurs*nbcols*64;
1590 src = car * 8;
1591 for(i=0;i<8;i++)
1593 dest=addr+i*nbcols*8;
1594 mask = 0x80;
1595 for(j=0;j<8;j++)
1597 data = 0x00;
1598 if (fdata[src+i] & mask)
1600 data = attr;
1602 write_byte(0xa000,dest+j,data);
1603 mask >>= 1;
1608 // --------------------------------------------------------------------------------------------
1609 static void biosfn_write_char_attr (car,page,attr,count)
1610 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1612 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1613 Bit16u nbcols,nbrows,address;
1614 Bit16u cursor,dummy;
1616 // Get the mode
1617 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1618 line=find_vga_entry(mode);
1619 if(line==0xFF)return;
1621 // Get the cursor pos for the page
1622 biosfn_get_cursor_pos(page,&dummy,&cursor);
1623 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1625 // Get the dimensions
1626 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1627 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1629 if(vga_modes[line].class==TEXT)
1631 // Compute the address
1632 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1634 dummy=((Bit16u)attr<<8)+car;
1635 memsetw(vga_modes[line].sstart,address,dummy,count);
1637 else
1639 // FIXME gfx mode not complete
1640 cheight=video_param_table[line_to_vpti[line]].cheight;
1641 bpp=vga_modes[line].pixbits;
1642 while((count-->0) && (xcurs<nbcols))
1644 switch(vga_modes[line].memmodel)
1646 case PLANAR4:
1647 case PLANAR1:
1648 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1649 break;
1650 case CGA:
1651 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1652 break;
1653 case LINEAR8:
1654 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1655 break;
1656 #ifdef DEBUG
1657 default:
1658 unimplemented();
1659 #endif
1661 xcurs++;
1666 // --------------------------------------------------------------------------------------------
1667 static void biosfn_write_char_only (car,page,attr,count)
1668 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1670 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1671 Bit16u nbcols,nbrows,address;
1672 Bit16u cursor,dummy;
1674 // Get the mode
1675 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1676 line=find_vga_entry(mode);
1677 if(line==0xFF)return;
1679 // Get the cursor pos for the page
1680 biosfn_get_cursor_pos(page,&dummy,&cursor);
1681 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1683 // Get the dimensions
1684 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1685 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1687 if(vga_modes[line].class==TEXT)
1689 // Compute the address
1690 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1692 while(count-->0)
1693 {write_byte(vga_modes[line].sstart,address,car);
1694 address+=2;
1697 else
1699 // FIXME gfx mode not complete
1700 cheight=video_param_table[line_to_vpti[line]].cheight;
1701 bpp=vga_modes[line].pixbits;
1702 while((count-->0) && (xcurs<nbcols))
1704 switch(vga_modes[line].memmodel)
1706 case PLANAR4:
1707 case PLANAR1:
1708 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1709 break;
1710 case CGA:
1711 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1712 break;
1713 case LINEAR8:
1714 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1715 break;
1716 #ifdef DEBUG
1717 default:
1718 unimplemented();
1719 #endif
1721 xcurs++;
1726 // --------------------------------------------------------------------------------------------
1727 ASM_START
1728 biosfn_group_0B:
1729 cmp bh, #0x00
1730 je biosfn_set_border_color
1731 cmp bh, #0x01
1732 je biosfn_set_palette
1733 #ifdef DEBUG
1734 call _unknown
1735 #endif
1737 biosfn_set_border_color:
1738 push ax
1739 push bx
1740 push cx
1741 push dx
1742 mov dx, # VGAREG_ACTL_RESET
1743 in al, dx
1744 mov dx, # VGAREG_ACTL_ADDRESS
1745 mov al, #0x00
1746 out dx, al
1747 mov al, bl
1748 and al, #0x0f
1749 test al, #0x08
1750 jz set_low_border
1751 add al, #0x08
1752 set_low_border:
1753 out dx, al
1754 mov cl, #0x01
1755 and bl, #0x10
1756 set_intensity_loop:
1757 mov dx, # VGAREG_ACTL_ADDRESS
1758 mov al, cl
1759 out dx, al
1760 mov dx, # VGAREG_ACTL_READ_DATA
1761 in al, dx
1762 and al, #0xef
1763 or al, bl
1764 mov dx, # VGAREG_ACTL_ADDRESS
1765 out dx, al
1766 inc cl
1767 cmp cl, #0x04
1768 jne set_intensity_loop
1769 mov al, #0x20
1770 out dx, al
1771 pop dx
1772 pop cx
1773 pop bx
1774 pop ax
1776 biosfn_set_palette:
1777 push ax
1778 push bx
1779 push cx
1780 push dx
1781 mov dx, # VGAREG_ACTL_RESET
1782 in al, dx
1783 mov cl, #0x01
1784 and bl, #0x01
1785 set_cga_palette_loop:
1786 mov dx, # VGAREG_ACTL_ADDRESS
1787 mov al, cl
1788 out dx, al
1789 mov dx, # VGAREG_ACTL_READ_DATA
1790 in al, dx
1791 and al, #0xfe
1792 or al, bl
1793 mov dx, # VGAREG_ACTL_ADDRESS
1794 out dx, al
1795 inc cl
1796 cmp cl, #0x04
1797 jne set_cga_palette_loop
1798 mov al, #0x20
1799 out dx, al
1800 pop dx
1801 pop cx
1802 pop bx
1803 pop ax
1805 ASM_END
1807 // --------------------------------------------------------------------------------------------
1808 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1810 Bit8u mode,line,mask,attr,data;
1811 Bit16u addr;
1813 // Get the mode
1814 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1815 line=find_vga_entry(mode);
1816 if(line==0xFF)return;
1817 if(vga_modes[line].class==TEXT)return;
1819 switch(vga_modes[line].memmodel)
1821 case PLANAR4:
1822 case PLANAR1:
1823 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1824 mask = 0x80 >> (CX & 0x07);
1825 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1826 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1827 data = read_byte(0xa000,addr);
1828 if (AL & 0x80)
1830 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1832 write_byte(0xa000,addr,AL);
1833 ASM_START
1834 mov dx, # VGAREG_GRDC_ADDRESS
1835 mov ax, #0xff08
1836 out dx, ax
1837 mov ax, #0x0005
1838 out dx, ax
1839 mov ax, #0x0003
1840 out dx, ax
1841 ASM_END
1842 break;
1843 case CGA:
1844 if(vga_modes[line].pixbits==2)
1846 addr=(CX>>2)+(DX>>1)*80;
1848 else
1850 addr=(CX>>3)+(DX>>1)*80;
1852 if (DX & 1) addr += 0x2000;
1853 data = read_byte(0xb800,addr);
1854 if(vga_modes[line].pixbits==2)
1856 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1857 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1859 else
1861 attr = (AL & 0x01) << (7 - (CX & 0x07));
1862 mask = 0x01 << (7 - (CX & 0x07));
1864 if (AL & 0x80)
1866 data ^= attr;
1868 else
1870 data &= ~mask;
1871 data |= attr;
1873 write_byte(0xb800,addr,data);
1874 break;
1875 case LINEAR8:
1876 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1877 write_byte(0xa000,addr,AL);
1878 break;
1879 #ifdef DEBUG
1880 default:
1881 unimplemented();
1882 #endif
1886 // --------------------------------------------------------------------------------------------
1887 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1889 Bit8u mode,line,mask,attr,data,i;
1890 Bit16u addr;
1891 Bit16u ss=get_SS();
1893 // Get the mode
1894 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1895 line=find_vga_entry(mode);
1896 if(line==0xFF)return;
1897 if(vga_modes[line].class==TEXT)return;
1899 switch(vga_modes[line].memmodel)
1901 case PLANAR4:
1902 case PLANAR1:
1903 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1904 mask = 0x80 >> (CX & 0x07);
1905 attr = 0x00;
1906 for(i=0;i<4;i++)
1908 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1909 data = read_byte(0xa000,addr) & mask;
1910 if (data > 0) attr |= (0x01 << i);
1912 break;
1913 case CGA:
1914 addr=(CX>>2)+(DX>>1)*80;
1915 if (DX & 1) addr += 0x2000;
1916 data = read_byte(0xb800,addr);
1917 if(vga_modes[line].pixbits==2)
1919 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1921 else
1923 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1925 break;
1926 case LINEAR8:
1927 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1928 attr=read_byte(0xa000,addr);
1929 break;
1930 default:
1931 #ifdef DEBUG
1932 unimplemented();
1933 #endif
1934 attr = 0;
1936 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1939 // --------------------------------------------------------------------------------------------
1940 static void biosfn_write_teletype (car, page, attr, flag)
1941 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1942 {// flag = WITH_ATTR / NO_ATTR
1944 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1945 Bit16u nbcols,nbrows,address;
1946 Bit16u cursor,dummy;
1948 // special case if page is 0xff, use current page
1949 if(page==0xff)
1950 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1952 // Get the mode
1953 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1954 line=find_vga_entry(mode);
1955 if(line==0xFF)return;
1957 // Get the cursor pos for the page
1958 biosfn_get_cursor_pos(page,&dummy,&cursor);
1959 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1961 // Get the dimensions
1962 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1963 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1965 switch(car)
1967 case 7:
1968 //FIXME should beep
1969 break;
1971 case 8:
1972 if(xcurs>0)xcurs--;
1973 break;
1975 case '\r':
1976 xcurs=0;
1977 break;
1979 case '\n':
1980 ycurs++;
1981 break;
1983 case '\t':
1986 biosfn_write_teletype(' ',page,attr,flag);
1987 biosfn_get_cursor_pos(page,&dummy,&cursor);
1988 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1989 }while(xcurs%8==0);
1990 break;
1992 default:
1994 if(vga_modes[line].class==TEXT)
1996 // Compute the address
1997 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1999 // Write the char
2000 write_byte(vga_modes[line].sstart,address,car);
2002 if(flag==WITH_ATTR)
2003 write_byte(vga_modes[line].sstart,address+1,attr);
2005 else
2007 // FIXME gfx mode not complete
2008 cheight=video_param_table[line_to_vpti[line]].cheight;
2009 bpp=vga_modes[line].pixbits;
2010 switch(vga_modes[line].memmodel)
2012 case PLANAR4:
2013 case PLANAR1:
2014 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
2015 break;
2016 case CGA:
2017 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
2018 break;
2019 case LINEAR8:
2020 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
2021 break;
2022 #ifdef DEBUG
2023 default:
2024 unimplemented();
2025 #endif
2028 xcurs++;
2031 // Do we need to wrap ?
2032 if(xcurs==nbcols)
2033 {xcurs=0;
2034 ycurs++;
2037 // Do we need to scroll ?
2038 if(ycurs==nbrows)
2040 if(vga_modes[line].class==TEXT)
2042 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2044 else
2046 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2048 ycurs-=1;
2051 // Set the cursor for the page
2052 cursor=ycurs; cursor<<=8; cursor+=xcurs;
2053 biosfn_set_cursor_pos(page,cursor);
2056 // --------------------------------------------------------------------------------------------
2057 ASM_START
2058 biosfn_get_video_mode:
2059 push ds
2060 mov ax, # BIOSMEM_SEG
2061 mov ds, ax
2062 push bx
2063 mov bx, # BIOSMEM_CURRENT_PAGE
2064 mov al, [bx]
2065 pop bx
2066 mov bh, al
2067 push bx
2068 mov bx, # BIOSMEM_VIDEO_CTL
2069 mov ah, [bx]
2070 and ah, #0x80
2071 mov bx, # BIOSMEM_CURRENT_MODE
2072 mov al, [bx]
2073 or al, ah
2074 mov bx, # BIOSMEM_NB_COLS
2075 mov ah, [bx]
2076 pop bx
2077 pop ds
2079 ASM_END
2081 // --------------------------------------------------------------------------------------------
2082 ASM_START
2083 biosfn_group_10:
2084 cmp al, #0x00
2085 jne int10_test_1001
2086 jmp biosfn_set_single_palette_reg
2087 int10_test_1001:
2088 cmp al, #0x01
2089 jne int10_test_1002
2090 jmp biosfn_set_overscan_border_color
2091 int10_test_1002:
2092 cmp al, #0x02
2093 jne int10_test_1003
2094 jmp biosfn_set_all_palette_reg
2095 int10_test_1003:
2096 cmp al, #0x03
2097 jne int10_test_1007
2098 jmp biosfn_toggle_intensity
2099 int10_test_1007:
2100 cmp al, #0x07
2101 jne int10_test_1008
2102 jmp biosfn_get_single_palette_reg
2103 int10_test_1008:
2104 cmp al, #0x08
2105 jne int10_test_1009
2106 jmp biosfn_read_overscan_border_color
2107 int10_test_1009:
2108 cmp al, #0x09
2109 jne int10_test_1010
2110 jmp biosfn_get_all_palette_reg
2111 int10_test_1010:
2112 cmp al, #0x10
2113 jne int10_test_1012
2114 jmp biosfn_set_single_dac_reg
2115 int10_test_1012:
2116 cmp al, #0x12
2117 jne int10_test_1013
2118 jmp biosfn_set_all_dac_reg
2119 int10_test_1013:
2120 cmp al, #0x13
2121 jne int10_test_1015
2122 jmp biosfn_select_video_dac_color_page
2123 int10_test_1015:
2124 cmp al, #0x15
2125 jne int10_test_1017
2126 jmp biosfn_read_single_dac_reg
2127 int10_test_1017:
2128 cmp al, #0x17
2129 jne int10_test_1018
2130 jmp biosfn_read_all_dac_reg
2131 int10_test_1018:
2132 cmp al, #0x18
2133 jne int10_test_1019
2134 jmp biosfn_set_pel_mask
2135 int10_test_1019:
2136 cmp al, #0x19
2137 jne int10_test_101A
2138 jmp biosfn_read_pel_mask
2139 int10_test_101A:
2140 cmp al, #0x1a
2141 jne int10_group_10_unknown
2142 jmp biosfn_read_video_dac_state
2143 int10_group_10_unknown:
2144 #ifdef DEBUG
2145 call _unknown
2146 #endif
2149 biosfn_set_single_palette_reg:
2150 cmp bl, #0x14
2151 ja no_actl_reg1
2152 push ax
2153 push dx
2154 mov dx, # VGAREG_ACTL_RESET
2155 in al, dx
2156 mov dx, # VGAREG_ACTL_ADDRESS
2157 mov al, bl
2158 out dx, al
2159 mov al, bh
2160 out dx, al
2161 mov al, #0x20
2162 out dx, al
2163 pop dx
2164 pop ax
2165 no_actl_reg1:
2167 ASM_END
2169 // --------------------------------------------------------------------------------------------
2170 ASM_START
2171 biosfn_set_overscan_border_color:
2172 push bx
2173 mov bl, #0x11
2174 call biosfn_set_single_palette_reg
2175 pop bx
2177 ASM_END
2179 // --------------------------------------------------------------------------------------------
2180 ASM_START
2181 biosfn_set_all_palette_reg:
2182 push ax
2183 push bx
2184 push cx
2185 push dx
2186 mov bx, dx
2187 mov dx, # VGAREG_ACTL_RESET
2188 in al, dx
2189 mov cl, #0x00
2190 mov dx, # VGAREG_ACTL_ADDRESS
2191 set_palette_loop:
2192 mov al, cl
2193 out dx, al
2194 seg es
2195 mov al, [bx]
2196 out dx, al
2197 inc bx
2198 inc cl
2199 cmp cl, #0x10
2200 jne set_palette_loop
2201 mov al, #0x11
2202 out dx, al
2203 seg es
2204 mov al, [bx]
2205 out dx, al
2206 mov al, #0x20
2207 out dx, al
2208 pop dx
2209 pop cx
2210 pop bx
2211 pop ax
2213 ASM_END
2215 // --------------------------------------------------------------------------------------------
2216 ASM_START
2217 biosfn_toggle_intensity:
2218 push ax
2219 push bx
2220 push dx
2221 mov dx, # VGAREG_ACTL_RESET
2222 in al, dx
2223 mov dx, # VGAREG_ACTL_ADDRESS
2224 mov al, #0x10
2225 out dx, al
2226 mov dx, # VGAREG_ACTL_READ_DATA
2227 in al, dx
2228 and al, #0xf7
2229 and bl, #0x01
2230 shl bl, 3
2231 or al, bl
2232 mov dx, # VGAREG_ACTL_ADDRESS
2233 out dx, al
2234 mov al, #0x20
2235 out dx, al
2236 pop dx
2237 pop bx
2238 pop ax
2240 ASM_END
2242 // --------------------------------------------------------------------------------------------
2243 ASM_START
2244 biosfn_get_single_palette_reg:
2245 cmp bl, #0x14
2246 ja no_actl_reg2
2247 push ax
2248 push dx
2249 mov dx, # VGAREG_ACTL_RESET
2250 in al, dx
2251 mov dx, # VGAREG_ACTL_ADDRESS
2252 mov al, bl
2253 out dx, al
2254 mov dx, # VGAREG_ACTL_READ_DATA
2255 in al, dx
2256 mov bh, al
2257 mov dx, # VGAREG_ACTL_RESET
2258 in al, dx
2259 mov dx, # VGAREG_ACTL_ADDRESS
2260 mov al, #0x20
2261 out dx, al
2262 pop dx
2263 pop ax
2264 no_actl_reg2:
2266 ASM_END
2268 // --------------------------------------------------------------------------------------------
2269 ASM_START
2270 biosfn_read_overscan_border_color:
2271 push ax
2272 push bx
2273 mov bl, #0x11
2274 call biosfn_get_single_palette_reg
2275 mov al, bh
2276 pop bx
2277 mov bh, al
2278 pop ax
2280 ASM_END
2282 // --------------------------------------------------------------------------------------------
2283 ASM_START
2284 biosfn_get_all_palette_reg:
2285 push ax
2286 push bx
2287 push cx
2288 push dx
2289 mov bx, dx
2290 mov cl, #0x00
2291 get_palette_loop:
2292 mov dx, # VGAREG_ACTL_RESET
2293 in al, dx
2294 mov dx, # VGAREG_ACTL_ADDRESS
2295 mov al, cl
2296 out dx, al
2297 mov dx, # VGAREG_ACTL_READ_DATA
2298 in al, dx
2299 seg es
2300 mov [bx], al
2301 inc bx
2302 inc cl
2303 cmp cl, #0x10
2304 jne get_palette_loop
2305 mov dx, # VGAREG_ACTL_RESET
2306 in al, dx
2307 mov dx, # VGAREG_ACTL_ADDRESS
2308 mov al, #0x11
2309 out dx, al
2310 mov dx, # VGAREG_ACTL_READ_DATA
2311 in al, dx
2312 seg es
2313 mov [bx], al
2314 mov dx, # VGAREG_ACTL_RESET
2315 in al, dx
2316 mov dx, # VGAREG_ACTL_ADDRESS
2317 mov al, #0x20
2318 out dx, al
2319 pop dx
2320 pop cx
2321 pop bx
2322 pop ax
2324 ASM_END
2326 // --------------------------------------------------------------------------------------------
2327 ASM_START
2328 biosfn_set_single_dac_reg:
2329 push ax
2330 push dx
2331 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2332 mov al, bl
2333 out dx, al
2334 mov dx, # VGAREG_DAC_DATA
2335 pop ax
2336 push ax
2337 mov al, ah
2338 out dx, al
2339 mov al, ch
2340 out dx, al
2341 mov al, cl
2342 out dx, al
2343 pop dx
2344 pop ax
2346 ASM_END
2348 // --------------------------------------------------------------------------------------------
2349 ASM_START
2350 biosfn_set_all_dac_reg:
2351 push ax
2352 push bx
2353 push cx
2354 push dx
2355 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2356 mov al, bl
2357 out dx, al
2358 pop dx
2359 push dx
2360 mov bx, dx
2361 mov dx, # VGAREG_DAC_DATA
2362 set_dac_loop:
2363 seg es
2364 mov al, [bx]
2365 out dx, al
2366 inc bx
2367 seg es
2368 mov al, [bx]
2369 out dx, al
2370 inc bx
2371 seg es
2372 mov al, [bx]
2373 out dx, al
2374 inc bx
2375 dec cx
2376 jnz set_dac_loop
2377 pop dx
2378 pop cx
2379 pop bx
2380 pop ax
2382 ASM_END
2384 // --------------------------------------------------------------------------------------------
2385 ASM_START
2386 biosfn_select_video_dac_color_page:
2387 push ax
2388 push bx
2389 push dx
2390 mov dx, # VGAREG_ACTL_RESET
2391 in al, dx
2392 mov dx, # VGAREG_ACTL_ADDRESS
2393 mov al, #0x10
2394 out dx, al
2395 mov dx, # VGAREG_ACTL_READ_DATA
2396 in al, dx
2397 and bl, #0x01
2398 jnz set_dac_page
2399 and al, #0x7f
2400 shl bh, 7
2401 or al, bh
2402 mov dx, # VGAREG_ACTL_ADDRESS
2403 out dx, al
2404 jmp set_actl_normal
2405 set_dac_page:
2406 push ax
2407 mov dx, # VGAREG_ACTL_RESET
2408 in al, dx
2409 mov dx, # VGAREG_ACTL_ADDRESS
2410 mov al, #0x14
2411 out dx, al
2412 pop ax
2413 and al, #0x80
2414 jnz set_dac_16_page
2415 shl bh, 2
2416 set_dac_16_page:
2417 and bh, #0x0f
2418 mov al, bh
2419 out dx, al
2420 set_actl_normal:
2421 mov al, #0x20
2422 out dx, al
2423 pop dx
2424 pop bx
2425 pop ax
2427 ASM_END
2429 // --------------------------------------------------------------------------------------------
2430 ASM_START
2431 biosfn_read_single_dac_reg:
2432 push ax
2433 push dx
2434 mov dx, # VGAREG_DAC_READ_ADDRESS
2435 mov al, bl
2436 out dx, al
2437 pop ax
2438 mov ah, al
2439 mov dx, # VGAREG_DAC_DATA
2440 in al, dx
2441 xchg al, ah
2442 push ax
2443 in al, dx
2444 mov ch, al
2445 in al, dx
2446 mov cl, al
2447 pop dx
2448 pop ax
2450 ASM_END
2452 // --------------------------------------------------------------------------------------------
2453 ASM_START
2454 biosfn_read_all_dac_reg:
2455 push ax
2456 push bx
2457 push cx
2458 push dx
2459 mov dx, # VGAREG_DAC_READ_ADDRESS
2460 mov al, bl
2461 out dx, al
2462 pop dx
2463 push dx
2464 mov bx, dx
2465 mov dx, # VGAREG_DAC_DATA
2466 read_dac_loop:
2467 in al, dx
2468 seg es
2469 mov [bx], al
2470 inc bx
2471 in al, dx
2472 seg es
2473 mov [bx], al
2474 inc bx
2475 in al, dx
2476 seg es
2477 mov [bx], al
2478 inc bx
2479 dec cx
2480 jnz read_dac_loop
2481 pop dx
2482 pop cx
2483 pop bx
2484 pop ax
2486 ASM_END
2488 // --------------------------------------------------------------------------------------------
2489 ASM_START
2490 biosfn_set_pel_mask:
2491 push ax
2492 push dx
2493 mov dx, # VGAREG_PEL_MASK
2494 mov al, bl
2495 out dx, al
2496 pop dx
2497 pop ax
2499 ASM_END
2501 // --------------------------------------------------------------------------------------------
2502 ASM_START
2503 biosfn_read_pel_mask:
2504 push ax
2505 push dx
2506 mov dx, # VGAREG_PEL_MASK
2507 in al, dx
2508 mov bl, al
2509 pop dx
2510 pop ax
2512 ASM_END
2514 // --------------------------------------------------------------------------------------------
2515 ASM_START
2516 biosfn_read_video_dac_state:
2517 push ax
2518 push dx
2519 mov dx, # VGAREG_ACTL_RESET
2520 in al, dx
2521 mov dx, # VGAREG_ACTL_ADDRESS
2522 mov al, #0x10
2523 out dx, al
2524 mov dx, # VGAREG_ACTL_READ_DATA
2525 in al, dx
2526 mov bl, al
2527 shr bl, 7
2528 mov dx, # VGAREG_ACTL_RESET
2529 in al, dx
2530 mov dx, # VGAREG_ACTL_ADDRESS
2531 mov al, #0x14
2532 out dx, al
2533 mov dx, # VGAREG_ACTL_READ_DATA
2534 in al, dx
2535 mov bh, al
2536 and bh, #0x0f
2537 test bl, #0x01
2538 jnz get_dac_16_page
2539 shr bh, 2
2540 get_dac_16_page:
2541 mov dx, # VGAREG_ACTL_RESET
2542 in al, dx
2543 mov dx, # VGAREG_ACTL_ADDRESS
2544 mov al, #0x20
2545 out dx, al
2546 pop dx
2547 pop ax
2549 ASM_END
2551 // --------------------------------------------------------------------------------------------
2552 static void biosfn_perform_gray_scale_summing (start,count)
2553 Bit16u start;Bit16u count;
2554 {Bit8u r,g,b;
2555 Bit16u i;
2556 Bit16u index;
2558 inb(VGAREG_ACTL_RESET);
2559 outb(VGAREG_ACTL_ADDRESS,0x00);
2561 for( index = 0; index < count; index++ )
2563 // set read address and switch to read mode
2564 outb(VGAREG_DAC_READ_ADDRESS,start);
2565 // get 6-bit wide RGB data values
2566 r=inb( VGAREG_DAC_DATA );
2567 g=inb( VGAREG_DAC_DATA );
2568 b=inb( VGAREG_DAC_DATA );
2570 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2571 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2573 if(i>0x3f)i=0x3f;
2575 // set write address and switch to write mode
2576 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2577 // write new intensity value
2578 outb( VGAREG_DAC_DATA, i&0xff );
2579 outb( VGAREG_DAC_DATA, i&0xff );
2580 outb( VGAREG_DAC_DATA, i&0xff );
2581 start++;
2583 inb(VGAREG_ACTL_RESET);
2584 outb(VGAREG_ACTL_ADDRESS,0x20);
2587 // --------------------------------------------------------------------------------------------
2588 static void get_font_access()
2590 ASM_START
2591 mov dx, # VGAREG_SEQU_ADDRESS
2592 mov ax, #0x0100
2593 out dx, ax
2594 mov ax, #0x0402
2595 out dx, ax
2596 mov ax, #0x0704
2597 out dx, ax
2598 mov ax, #0x0300
2599 out dx, ax
2600 mov dx, # VGAREG_GRDC_ADDRESS
2601 mov ax, #0x0204
2602 out dx, ax
2603 mov ax, #0x0005
2604 out dx, ax
2605 mov ax, #0x0406
2606 out dx, ax
2607 ASM_END
2610 static void release_font_access()
2612 ASM_START
2613 mov dx, # VGAREG_SEQU_ADDRESS
2614 mov ax, #0x0100
2615 out dx, ax
2616 mov ax, #0x0302
2617 out dx, ax
2618 mov ax, #0x0304
2619 out dx, ax
2620 mov ax, #0x0300
2621 out dx, ax
2622 mov dx, # VGAREG_READ_MISC_OUTPUT
2623 in al, dx
2624 and al, #0x01
2625 shl al, 2
2626 or al, #0x0a
2627 mov ah, al
2628 mov al, #0x06
2629 mov dx, # VGAREG_GRDC_ADDRESS
2630 out dx, ax
2631 mov ax, #0x0004
2632 out dx, ax
2633 mov ax, #0x1005
2634 out dx, ax
2635 ASM_END
2638 ASM_START
2639 idiv_u:
2640 xor dx,dx
2641 div bx
2643 ASM_END
2645 static void set_scan_lines(lines) Bit8u lines;
2647 Bit16u crtc_addr,cols,page,vde;
2648 Bit8u crtc_r9,ovl,rows;
2650 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2651 outb(crtc_addr, 0x09);
2652 crtc_r9 = inb(crtc_addr+1);
2653 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2654 outb(crtc_addr+1, crtc_r9);
2655 if(lines==8)
2657 biosfn_set_cursor_shape(0x06,0x07);
2659 else
2661 biosfn_set_cursor_shape(lines-4,lines-3);
2663 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2664 outb(crtc_addr, 0x12);
2665 vde = inb(crtc_addr+1);
2666 outb(crtc_addr, 0x07);
2667 ovl = inb(crtc_addr+1);
2668 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2669 rows = vde / lines;
2670 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2671 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2672 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2675 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;
2677 Bit16u blockaddr,dest,i,src;
2679 get_font_access();
2680 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2681 for(i=0;i<CX;i++)
2683 src = BP + i * BH;
2684 dest = blockaddr + (DX + i) * 32;
2685 memcpyb(0xA000, dest, ES, src, BH);
2687 release_font_access();
2688 if(AL>=0x10)
2690 set_scan_lines(BH);
2694 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2696 Bit16u blockaddr,dest,i,src;
2698 get_font_access();
2699 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2700 for(i=0;i<0x100;i++)
2702 src = i * 14;
2703 dest = blockaddr + i * 32;
2704 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2706 release_font_access();
2707 if(AL>=0x10)
2709 set_scan_lines(14);
2713 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2715 Bit16u blockaddr,dest,i,src;
2717 get_font_access();
2718 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2719 for(i=0;i<0x100;i++)
2721 src = i * 8;
2722 dest = blockaddr + i * 32;
2723 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2725 release_font_access();
2726 if(AL>=0x10)
2728 set_scan_lines(8);
2732 // --------------------------------------------------------------------------------------------
2733 ASM_START
2734 biosfn_set_text_block_specifier:
2735 push ax
2736 push dx
2737 mov dx, # VGAREG_SEQU_ADDRESS
2738 mov ah, bl
2739 mov al, #0x03
2740 out dx, ax
2741 pop dx
2742 pop ax
2744 ASM_END
2746 // --------------------------------------------------------------------------------------------
2747 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2749 Bit16u blockaddr,dest,i,src;
2751 get_font_access();
2752 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2753 for(i=0;i<0x100;i++)
2755 src = i * 16;
2756 dest = blockaddr + i * 32;
2757 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2759 release_font_access();
2760 if(AL>=0x10)
2762 set_scan_lines(16);
2766 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2768 #ifdef DEBUG
2769 unimplemented();
2770 #endif
2772 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2774 #ifdef DEBUG
2775 unimplemented();
2776 #endif
2778 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2780 #ifdef DEBUG
2781 unimplemented();
2782 #endif
2784 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2786 #ifdef DEBUG
2787 unimplemented();
2788 #endif
2790 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2792 #ifdef DEBUG
2793 unimplemented();
2794 #endif
2796 // --------------------------------------------------------------------------------------------
2797 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2798 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2799 {Bit16u ss=get_SS();
2801 switch(BH)
2802 {case 0x00:
2803 write_word(ss,ES,read_word(0x00,0x1f*4));
2804 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2805 break;
2806 case 0x01:
2807 write_word(ss,ES,read_word(0x00,0x43*4));
2808 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2809 break;
2810 case 0x02:
2811 write_word(ss,ES,0xC000);
2812 write_word(ss,BP,vgafont14);
2813 break;
2814 case 0x03:
2815 write_word(ss,ES,0xC000);
2816 write_word(ss,BP,vgafont8);
2817 break;
2818 case 0x04:
2819 write_word(ss,ES,0xC000);
2820 write_word(ss,BP,vgafont8+128*8);
2821 break;
2822 case 0x05:
2823 write_word(ss,ES,0xC000);
2824 write_word(ss,BP,vgafont14alt);
2825 break;
2826 case 0x06:
2827 write_word(ss,ES,0xC000);
2828 write_word(ss,BP,vgafont16);
2829 break;
2830 case 0x07:
2831 write_word(ss,ES,0xC000);
2832 write_word(ss,BP,vgafont16alt);
2833 break;
2834 default:
2835 #ifdef DEBUG
2836 printf("Get font info BH(%02x) was discarded\n",BH);
2837 #endif
2838 return;
2840 // Set byte/char of on screen font
2841 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2843 // Set Highest char row
2844 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2847 // --------------------------------------------------------------------------------------------
2848 ASM_START
2849 biosfn_get_ega_info:
2850 push ds
2851 push ax
2852 mov ax, # BIOSMEM_SEG
2853 mov ds, ax
2854 xor ch, ch
2855 mov bx, # BIOSMEM_SWITCHES
2856 mov cl, [bx]
2857 and cl, #0x0f
2858 mov bx, # BIOSMEM_CRTC_ADDRESS
2859 mov ax, [bx]
2860 mov bx, #0x0003
2861 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2862 jne mode_ega_color
2863 mov bh, #0x01
2864 mode_ega_color:
2865 pop ax
2866 pop ds
2868 ASM_END
2870 // --------------------------------------------------------------------------------------------
2871 static void biosfn_alternate_prtsc()
2873 #ifdef DEBUG
2874 unimplemented();
2875 #endif
2878 // --------------------------------------------------------------------------------------------
2879 ASM_START
2880 biosfn_select_vert_res:
2882 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2884 push ds
2885 push bx
2886 push dx
2887 mov dl, al
2888 mov ax, # BIOSMEM_SEG
2889 mov ds, ax
2890 mov bx, # BIOSMEM_MODESET_CTL
2891 mov al, [bx]
2892 mov bx, # BIOSMEM_SWITCHES
2893 mov ah, [bx]
2894 cmp dl, #0x01
2895 je vert_res_350
2896 jb vert_res_200
2897 cmp dl, #0x02
2898 je vert_res_400
2899 #ifdef DEBUG
2900 mov al, dl
2901 xor ah, ah
2902 push ax
2903 mov bx, #msg_vert_res
2904 push bx
2905 call _printf
2906 add sp, #4
2907 #endif
2908 jmp set_retcode
2909 vert_res_400:
2911 ; reset modeset ctl bit 7 and set bit 4
2912 ; set switches bit 3-0 to 0x09
2914 and al, #0x7f
2915 or al, #0x10
2916 and ah, #0xf0
2917 or ah, #0x09
2918 jnz set_vert_res
2919 vert_res_350:
2921 ; reset modeset ctl bit 7 and bit 4
2922 ; set switches bit 3-0 to 0x09
2924 and al, #0x6f
2925 and ah, #0xf0
2926 or ah, #0x09
2927 jnz set_vert_res
2928 vert_res_200:
2930 ; set modeset ctl bit 7 and reset bit 4
2931 ; set switches bit 3-0 to 0x08
2933 and al, #0xef
2934 or al, #0x80
2935 and ah, #0xf0
2936 or ah, #0x08
2937 set_vert_res:
2938 mov bx, # BIOSMEM_MODESET_CTL
2939 mov [bx], al
2940 mov bx, # BIOSMEM_SWITCHES
2941 mov [bx], ah
2942 set_retcode:
2943 mov ax, #0x1212
2944 pop dx
2945 pop bx
2946 pop ds
2949 #ifdef DEBUG
2950 msg_vert_res:
2951 .ascii "Select vert res (%02x) was discarded"
2952 .byte 0x0d,0x0a,0x00
2953 #endif
2956 biosfn_enable_default_palette_loading:
2957 push ds
2958 push bx
2959 push dx
2960 mov dl, al
2961 and dl, #0x01
2962 shl dl, 3
2963 mov ax, # BIOSMEM_SEG
2964 mov ds, ax
2965 mov bx, # BIOSMEM_MODESET_CTL
2966 mov al, [bx]
2967 and al, #0xf7
2968 or al, dl
2969 mov [bx], al
2970 mov ax, #0x1212
2971 pop dx
2972 pop bx
2973 pop ds
2977 biosfn_enable_video_addressing:
2978 push bx
2979 push dx
2980 mov bl, al
2981 and bl, #0x01
2982 xor bl, #0x01
2983 shl bl, 1
2984 mov dx, # VGAREG_READ_MISC_OUTPUT
2985 in al, dx
2986 and al, #0xfd
2987 or al, bl
2988 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2989 out dx, al
2990 mov ax, #0x1212
2991 pop dx
2992 pop bx
2996 biosfn_enable_grayscale_summing:
2997 push ds
2998 push bx
2999 push dx
3000 mov dl, al
3001 and dl, #0x01
3002 xor dl, #0x01
3003 shl dl, 1
3004 mov ax, # BIOSMEM_SEG
3005 mov ds, ax
3006 mov bx, # BIOSMEM_MODESET_CTL
3007 mov al, [bx]
3008 and al, #0xfd
3009 or al, dl
3010 mov [bx], al
3011 mov ax, #0x1212
3012 pop dx
3013 pop bx
3014 pop ds
3018 biosfn_enable_cursor_emulation:
3019 push ds
3020 push bx
3021 push dx
3022 mov dl, al
3023 and dl, #0x01
3024 xor dl, #0x01
3025 mov ax, # BIOSMEM_SEG
3026 mov ds, ax
3027 mov bx, # BIOSMEM_MODESET_CTL
3028 mov al, [bx]
3029 and al, #0xfe
3030 or al, dl
3031 mov [bx], al
3032 mov ax, #0x1212
3033 pop dx
3034 pop bx
3035 pop ds
3037 ASM_END
3039 // --------------------------------------------------------------------------------------------
3040 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3042 #ifdef DEBUG
3043 unimplemented();
3044 #endif
3046 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3048 #ifdef DEBUG
3049 unimplemented();
3050 #endif
3053 // --------------------------------------------------------------------------------------------
3054 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3055 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3057 Bit16u newcurs,oldcurs,dummy;
3058 Bit8u car,carattr;
3060 // Read curs info for the page
3061 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3063 // if row=0xff special case : use current cursor position
3064 if(row==0xff)
3065 {col=oldcurs&0x00ff;
3066 row=(oldcurs&0xff00)>>8;
3069 newcurs=row; newcurs<<=8; newcurs+=col;
3070 biosfn_set_cursor_pos(page,newcurs);
3072 while(count--!=0)
3074 car=read_byte(seg,offset++);
3075 if((flag&0x02)!=0)
3076 attr=read_byte(seg,offset++);
3078 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3081 // Set back curs pos
3082 if((flag&0x01)==0)
3083 biosfn_set_cursor_pos(page,oldcurs);
3086 // --------------------------------------------------------------------------------------------
3087 ASM_START
3088 biosfn_group_1A:
3089 cmp al, #0x00
3090 je biosfn_read_display_code
3091 cmp al, #0x01
3092 je biosfn_set_display_code
3093 #ifdef DEBUG
3094 call _unknown
3095 #endif
3097 biosfn_read_display_code:
3098 push ds
3099 push ax
3100 mov ax, # BIOSMEM_SEG
3101 mov ds, ax
3102 mov bx, # BIOSMEM_DCC_INDEX
3103 mov al, [bx]
3104 mov bl, al
3105 xor bh, bh
3106 pop ax
3107 mov al, ah
3108 pop ds
3110 biosfn_set_display_code:
3111 push ds
3112 push ax
3113 push bx
3114 mov ax, # BIOSMEM_SEG
3115 mov ds, ax
3116 mov ax, bx
3117 mov bx, # BIOSMEM_DCC_INDEX
3118 mov [bx], al
3119 #ifdef DEBUG
3120 mov al, ah
3121 xor ah, ah
3122 push ax
3123 mov bx, #msg_alt_dcc
3124 push bx
3125 call _printf
3126 add sp, #4
3127 #endif
3128 pop bx
3129 pop ax
3130 mov al, ah
3131 pop ds
3134 #ifdef DEBUG
3135 msg_alt_dcc:
3136 .ascii "Alternate Display code (%02x) was discarded"
3137 .byte 0x0d,0x0a,0x00
3138 #endif
3139 ASM_END
3141 // --------------------------------------------------------------------------------------------
3142 static void biosfn_read_state_info (BX,ES,DI)
3143 Bit16u BX;Bit16u ES;Bit16u DI;
3145 // Address of static functionality table
3146 write_word(ES,DI+0x00,&static_functionality);
3147 write_word(ES,DI+0x02,0xC000);
3149 // Hard coded copy from BIOS area. Should it be cleaner ?
3150 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3151 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3153 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3154 write_byte(ES,DI+0x26,0);
3155 write_byte(ES,DI+0x27,16);
3156 write_byte(ES,DI+0x28,0);
3157 write_byte(ES,DI+0x29,8);
3158 write_byte(ES,DI+0x2a,2);
3159 write_byte(ES,DI+0x2b,0);
3160 write_byte(ES,DI+0x2c,0);
3161 write_byte(ES,DI+0x31,3);
3162 write_byte(ES,DI+0x32,0);
3164 memsetb(ES,DI+0x33,0,13);
3167 // --------------------------------------------------------------------------------------------
3168 // --------------------------------------------------------------------------------------------
3169 static Bit16u biosfn_read_video_state_size2 (CX)
3170 Bit16u CX;
3172 Bit16u size;
3173 size = 0;
3174 if (CX & 1) {
3175 size += 0x46;
3177 if (CX & 2) {
3178 size += (5 + 8 + 5) * 2 + 6;
3180 if (CX & 4) {
3181 size += 3 + 256 * 3 + 1;
3183 return size;
3186 static void biosfn_read_video_state_size (CX, BX)
3187 Bit16u CX; Bit16u *BX;
3189 Bit16u ss=get_SS();
3190 write_word(ss, BX, biosfn_read_video_state_size2(CX));
3193 static Bit16u biosfn_save_video_state (CX,ES,BX)
3194 Bit16u CX;Bit16u ES;Bit16u BX;
3196 Bit16u i, v, crtc_addr, ar_index;
3198 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3199 if (CX & 1) {
3200 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3201 write_byte(ES, BX, inb(crtc_addr)); BX++;
3202 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3203 inb(VGAREG_ACTL_RESET);
3204 ar_index = inb(VGAREG_ACTL_ADDRESS);
3205 write_byte(ES, BX, ar_index); BX++;
3206 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3208 for(i=1;i<=4;i++){
3209 outb(VGAREG_SEQU_ADDRESS, i);
3210 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3212 outb(VGAREG_SEQU_ADDRESS, 0);
3213 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3215 for(i=0;i<=0x18;i++) {
3216 outb(crtc_addr,i);
3217 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3220 for(i=0;i<=0x13;i++) {
3221 inb(VGAREG_ACTL_RESET);
3222 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3223 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3225 inb(VGAREG_ACTL_RESET);
3227 for(i=0;i<=8;i++) {
3228 outb(VGAREG_GRDC_ADDRESS,i);
3229 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3232 write_word(ES, BX, crtc_addr); BX+= 2;
3234 /* XXX: read plane latches */
3235 write_byte(ES, BX, 0); BX++;
3236 write_byte(ES, BX, 0); BX++;
3237 write_byte(ES, BX, 0); BX++;
3238 write_byte(ES, BX, 0); BX++;
3240 if (CX & 2) {
3241 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3242 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3243 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3244 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3245 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3246 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3247 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3248 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3249 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3250 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3251 for(i=0;i<8;i++) {
3252 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3253 BX += 2;
3255 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3256 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3257 /* current font */
3258 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3259 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3260 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3261 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3263 if (CX & 4) {
3264 /* XXX: check this */
3265 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3266 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3267 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3268 // Set the whole dac always, from 0
3269 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3270 for(i=0;i<256*3;i++) {
3271 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3273 write_byte(ES, BX, 0); BX++; /* color select register */
3275 return BX;
3278 static Bit16u biosfn_restore_video_state (CX,ES,BX)
3279 Bit16u CX;Bit16u ES;Bit16u BX;
3281 Bit16u i, crtc_addr, v, addr1, ar_index;
3283 if (CX & 1) {
3284 // Reset Attribute Ctl flip-flop
3285 inb(VGAREG_ACTL_RESET);
3287 crtc_addr = read_word(ES, BX + 0x40);
3288 addr1 = BX;
3289 BX += 5;
3291 for(i=1;i<=4;i++){
3292 outb(VGAREG_SEQU_ADDRESS, i);
3293 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3295 outb(VGAREG_SEQU_ADDRESS, 0);
3296 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3298 // Disable CRTC write protection
3299 outw(crtc_addr,0x0011);
3300 // Set CRTC regs
3301 for(i=0;i<=0x18;i++) {
3302 if (i != 0x11) {
3303 outb(crtc_addr,i);
3304 outb(crtc_addr+1, read_byte(ES, BX));
3306 BX++;
3308 // select crtc base address
3309 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3310 if (crtc_addr = 0x3d4)
3311 v |= 0x01;
3312 outb(VGAREG_WRITE_MISC_OUTPUT, v);
3314 // enable write protection if needed
3315 outb(crtc_addr, 0x11);
3316 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3318 // Set Attribute Ctl
3319 ar_index = read_byte(ES, addr1 + 0x03);
3320 inb(VGAREG_ACTL_RESET);
3321 for(i=0;i<=0x13;i++) {
3322 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3323 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3325 outb(VGAREG_ACTL_ADDRESS, ar_index);
3326 inb(VGAREG_ACTL_RESET);
3328 for(i=0;i<=8;i++) {
3329 outb(VGAREG_GRDC_ADDRESS,i);
3330 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3332 BX += 2; /* crtc_addr */
3333 BX += 4; /* plane latches */
3335 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3336 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3337 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3338 addr1++;
3339 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3341 if (CX & 2) {
3342 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3343 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3344 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3345 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3346 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3347 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3348 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3349 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3350 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3351 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3352 for(i=0;i<8;i++) {
3353 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3354 BX += 2;
3356 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3357 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3358 /* current font */
3359 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3360 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3361 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3362 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3364 if (CX & 4) {
3365 BX++;
3366 v = read_byte(ES, BX); BX++;
3367 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3368 // Set the whole dac always, from 0
3369 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3370 for(i=0;i<256*3;i++) {
3371 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3373 BX++;
3374 outb(VGAREG_DAC_WRITE_ADDRESS, v);
3376 return BX;
3379 // ============================================================================================
3381 // Video Utils
3383 // ============================================================================================
3385 // --------------------------------------------------------------------------------------------
3386 static Bit8u find_vga_entry(mode)
3387 Bit8u mode;
3389 Bit8u i,line=0xFF;
3390 for(i=0;i<=MODE_MAX;i++)
3391 if(vga_modes[i].svgamode==mode)
3392 {line=i;
3393 break;
3395 return line;
3398 /* =========================================================== */
3400 * Misc Utils
3402 /* =========================================================== */
3404 // --------------------------------------------------------------------------------------------
3405 static void memsetb(seg,offset,value,count)
3406 Bit16u seg;
3407 Bit16u offset;
3408 Bit16u value;
3409 Bit16u count;
3411 ASM_START
3412 push bp
3413 mov bp, sp
3415 push ax
3416 push cx
3417 push es
3418 push di
3420 mov cx, 10[bp] ; count
3421 cmp cx, #0x00
3422 je memsetb_end
3423 mov ax, 4[bp] ; segment
3424 mov es, ax
3425 mov ax, 6[bp] ; offset
3426 mov di, ax
3427 mov al, 8[bp] ; value
3430 stosb
3432 memsetb_end:
3433 pop di
3434 pop es
3435 pop cx
3436 pop ax
3438 pop bp
3439 ASM_END
3442 // --------------------------------------------------------------------------------------------
3443 static void memsetw(seg,offset,value,count)
3444 Bit16u seg;
3445 Bit16u offset;
3446 Bit16u value;
3447 Bit16u count;
3449 ASM_START
3450 push bp
3451 mov bp, sp
3453 push ax
3454 push cx
3455 push es
3456 push di
3458 mov cx, 10[bp] ; count
3459 cmp cx, #0x00
3460 je memsetw_end
3461 mov ax, 4[bp] ; segment
3462 mov es, ax
3463 mov ax, 6[bp] ; offset
3464 mov di, ax
3465 mov ax, 8[bp] ; value
3468 stosw
3470 memsetw_end:
3471 pop di
3472 pop es
3473 pop cx
3474 pop ax
3476 pop bp
3477 ASM_END
3480 // --------------------------------------------------------------------------------------------
3481 static void memcpyb(dseg,doffset,sseg,soffset,count)
3482 Bit16u dseg;
3483 Bit16u doffset;
3484 Bit16u sseg;
3485 Bit16u soffset;
3486 Bit16u count;
3488 ASM_START
3489 push bp
3490 mov bp, sp
3492 push ax
3493 push cx
3494 push es
3495 push di
3496 push ds
3497 push si
3499 mov cx, 12[bp] ; count
3500 cmp cx, #0x0000
3501 je memcpyb_end
3502 mov ax, 4[bp] ; dsegment
3503 mov es, ax
3504 mov ax, 6[bp] ; doffset
3505 mov di, ax
3506 mov ax, 8[bp] ; ssegment
3507 mov ds, ax
3508 mov ax, 10[bp] ; soffset
3509 mov si, ax
3512 movsb
3514 memcpyb_end:
3515 pop si
3516 pop ds
3517 pop di
3518 pop es
3519 pop cx
3520 pop ax
3522 pop bp
3523 ASM_END
3526 // --------------------------------------------------------------------------------------------
3527 static void memcpyw(dseg,doffset,sseg,soffset,count)
3528 Bit16u dseg;
3529 Bit16u doffset;
3530 Bit16u sseg;
3531 Bit16u soffset;
3532 Bit16u count;
3534 ASM_START
3535 push bp
3536 mov bp, sp
3538 push ax
3539 push cx
3540 push es
3541 push di
3542 push ds
3543 push si
3545 mov cx, 12[bp] ; count
3546 cmp cx, #0x0000
3547 je memcpyw_end
3548 mov ax, 4[bp] ; dsegment
3549 mov es, ax
3550 mov ax, 6[bp] ; doffset
3551 mov di, ax
3552 mov ax, 8[bp] ; ssegment
3553 mov ds, ax
3554 mov ax, 10[bp] ; soffset
3555 mov si, ax
3558 movsw
3560 memcpyw_end:
3561 pop si
3562 pop ds
3563 pop di
3564 pop es
3565 pop cx
3566 pop ax
3568 pop bp
3569 ASM_END
3572 /* =========================================================== */
3574 * These functions where ripped from Kevin's rombios.c
3576 /* =========================================================== */
3578 // --------------------------------------------------------------------------------------------
3579 static Bit8u
3580 read_byte(seg, offset)
3581 Bit16u seg;
3582 Bit16u offset;
3584 ASM_START
3585 push bp
3586 mov bp, sp
3588 push bx
3589 push ds
3590 mov ax, 4[bp] ; segment
3591 mov ds, ax
3592 mov bx, 6[bp] ; offset
3593 mov al, [bx]
3594 ;; al = return value (byte)
3595 pop ds
3596 pop bx
3598 pop bp
3599 ASM_END
3602 // --------------------------------------------------------------------------------------------
3603 static Bit16u
3604 read_word(seg, offset)
3605 Bit16u seg;
3606 Bit16u offset;
3608 ASM_START
3609 push bp
3610 mov bp, sp
3612 push bx
3613 push ds
3614 mov ax, 4[bp] ; segment
3615 mov ds, ax
3616 mov bx, 6[bp] ; offset
3617 mov ax, [bx]
3618 ;; ax = return value (word)
3619 pop ds
3620 pop bx
3622 pop bp
3623 ASM_END
3626 // --------------------------------------------------------------------------------------------
3627 static void
3628 write_byte(seg, offset, data)
3629 Bit16u seg;
3630 Bit16u offset;
3631 Bit8u data;
3633 ASM_START
3634 push bp
3635 mov bp, sp
3637 push ax
3638 push bx
3639 push ds
3640 mov ax, 4[bp] ; segment
3641 mov ds, ax
3642 mov bx, 6[bp] ; offset
3643 mov al, 8[bp] ; data byte
3644 mov [bx], al ; write data byte
3645 pop ds
3646 pop bx
3647 pop ax
3649 pop bp
3650 ASM_END
3653 // --------------------------------------------------------------------------------------------
3654 static void
3655 write_word(seg, offset, data)
3656 Bit16u seg;
3657 Bit16u offset;
3658 Bit16u data;
3660 ASM_START
3661 push bp
3662 mov bp, sp
3664 push ax
3665 push bx
3666 push ds
3667 mov ax, 4[bp] ; segment
3668 mov ds, ax
3669 mov bx, 6[bp] ; offset
3670 mov ax, 8[bp] ; data word
3671 mov [bx], ax ; write data word
3672 pop ds
3673 pop bx
3674 pop ax
3676 pop bp
3677 ASM_END
3680 // --------------------------------------------------------------------------------------------
3681 Bit8u
3682 inb(port)
3683 Bit16u port;
3685 ASM_START
3686 push bp
3687 mov bp, sp
3689 push dx
3690 mov dx, 4[bp]
3691 in al, dx
3692 pop dx
3694 pop bp
3695 ASM_END
3698 Bit16u
3699 inw(port)
3700 Bit16u port;
3702 ASM_START
3703 push bp
3704 mov bp, sp
3706 push dx
3707 mov dx, 4[bp]
3708 in ax, dx
3709 pop dx
3711 pop bp
3712 ASM_END
3715 // --------------------------------------------------------------------------------------------
3716 void
3717 outb(port, val)
3718 Bit16u port;
3719 Bit8u val;
3721 ASM_START
3722 push bp
3723 mov bp, sp
3725 push ax
3726 push dx
3727 mov dx, 4[bp]
3728 mov al, 6[bp]
3729 out dx, al
3730 pop dx
3731 pop ax
3733 pop bp
3734 ASM_END
3737 // --------------------------------------------------------------------------------------------
3738 void
3739 outw(port, val)
3740 Bit16u port;
3741 Bit16u val;
3743 ASM_START
3744 push bp
3745 mov bp, sp
3747 push ax
3748 push dx
3749 mov dx, 4[bp]
3750 mov ax, 6[bp]
3751 out dx, ax
3752 pop dx
3753 pop ax
3755 pop bp
3756 ASM_END
3759 Bit16u get_SS()
3761 ASM_START
3762 mov ax, ss
3763 ASM_END
3766 #ifdef DEBUG
3767 void unimplemented()
3769 printf("--> Unimplemented\n");
3772 void unknown()
3774 printf("--> Unknown int10\n");
3776 #endif
3778 // --------------------------------------------------------------------------------------------
3779 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3780 void printf(s)
3781 Bit8u *s;
3783 Bit8u c, format_char;
3784 Boolean in_format;
3785 unsigned format_width, i;
3786 Bit16u *arg_ptr;
3787 Bit16u arg_seg, arg, digit, nibble, shift_count;
3789 arg_ptr = &s;
3790 arg_seg = get_SS();
3792 in_format = 0;
3793 format_width = 0;
3795 while (c = read_byte(0xc000, s)) {
3796 if ( c == '%' ) {
3797 in_format = 1;
3798 format_width = 0;
3800 else if (in_format) {
3801 if ( (c>='0') && (c<='9') ) {
3802 format_width = (format_width * 10) + (c - '0');
3804 else if (c == 'x') {
3805 arg_ptr++; // increment to next arg
3806 arg = read_word(arg_seg, arg_ptr);
3807 if (format_width == 0)
3808 format_width = 4;
3809 i = 0;
3810 digit = format_width - 1;
3811 for (i=0; i<format_width; i++) {
3812 nibble = (arg >> (4 * digit)) & 0x000f;
3813 if (nibble <= 9)
3814 outb(0x0500, nibble + '0');
3815 else
3816 outb(0x0500, (nibble - 10) + 'A');
3817 digit--;
3819 in_format = 0;
3821 //else if (c == 'd') {
3822 // in_format = 0;
3823 // }
3825 else {
3826 outb(0x0500, c);
3828 s ++;
3831 #endif
3833 #ifdef VBE
3834 #include "vbe.c"
3835 #endif
3837 #ifdef CIRRUS
3838 #include "clext.c"
3839 #endif
3841 // --------------------------------------------------------------------------------------------
3843 ASM_START
3844 ;; DATA_SEG_DEFS_HERE
3845 ASM_END
3847 ASM_START
3848 .ascii "vgabios ends here"
3849 .byte 0x00
3850 vgabios_end:
3851 .byte 0xCB
3852 ;; BLOCK_STRINGS_BEGIN
3853 ASM_END