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.
13 //
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.
18 //
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
32 //
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
37 //
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
45 //
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
48 //
49 // ============================================================================================
50
51 #include "vgabios.h"
52
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
56
57 #define USE_BX_INFO
58
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();
68
69 static Bit16u get_SS();
70
71 // Output
72 static void printf();
73 static void unimplemented();
74 static void unknown();
75
76 static Bit8u find_vga_entry();
77
78 static void memsetb();
79 static void memsetw();
80 static void memcpyb();
81 static void memcpyw();
82
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[];
115
116 // This is for compiling with gcc2 and gcc3
117 #define ASM_START #asm
118 #define ASM_END #endasm
119
120 ASM_START
121
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
132
133 ASM_END
134
135 ASM_START
136 .text
137 .rom
138 .org 0
139
140 use16 386
141
142 vgabios_start:
143 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
144
145 .byte 0x40 /* BIOS extension length in units of 512 bytes */
146
147
148 vgabios_entry_point:
149
150 jmp vgabios_init_func
151
152 #ifdef PCIBIOS
153 .org 0x18
154 .word vgabios_pci_data
155 #endif
156
157 // Info from Bart Oldeman
158 .org 0x1e
159 .ascii "IBM"
160 .byte 0x00
161
162 vgabios_name:
163 .ascii "Plex86/Bochs VGABios"
164 #ifdef PCIBIOS
165 .ascii " (PCI)"
166 #endif
167 .ascii " "
168 .byte 0x00
169
170 vgabios_version:
171 #ifndef VGABIOS_VERS
172 .ascii "current-cvs"
173 #else
174 .ascii VGABIOS_VERS
175 #endif
176 .ascii " "
177
178 vgabios_date:
179 .ascii VGABIOS_DATE
180 .byte 0x0a,0x0d
181 .byte 0x00
182
183 vgabios_copyright:
184 .ascii "(C) 2008 the LGPL VGABios developers Team"
185 .byte 0x0a,0x0d
186 .byte 0x00
187
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
193
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
205
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
226
227
228 ;; ============================================================================================
229 ;;
230 ;; Init Entry point
231 ;;
232 ;; ============================================================================================
233 vgabios_init_func:
234
235 ;; init vga card
236 call init_vga_card
237
238 ;; init basic bios vars
239 call init_bios_area
240
241 #ifdef VBE
242 ;; init vbe functions
243 call vbe_init
244 #endif
245
246 ;; set int10 vect
247 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
248
249 #ifdef CIRRUS
250 call cirrus_init
251 #endif
252
253 ;; display splash screen
254 call _display_splash_screen
255
256 ;; init video mode and clear the screen
257 mov ax,#0x0003
258 int #0x10
259
260 ;; show info
261 call _display_info
262
263 #ifdef VBE
264 ;; show vbe info
265 call vbe_display_info
266 #endif
267
268 #ifdef CIRRUS
269 ;; show cirrus info
270 call cirrus_display_info
271 #endif
272
273 retf
274 ASM_END
275
276 /*
277 * int10 handled here
278 */
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
389
390 int10_normal:
391 push es
392 push ds
393 pusha
394
395 ;; We have to set ds to access the right data segment
396 mov bx, #0xc000
397 mov ds, bx
398 call _int10_func
399
400 popa
401 pop ds
402 pop es
403 int10_end:
404 popf
405 iret
406 ASM_END
407
408 #include "vgatables.h"
409 #include "vgafonts.h"
410
411 /*
412 * Boot time harware inits
413 */
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
420
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
428
429 #if defined(USE_BX_INFO) || defined(DEBUG)
430 mov bx, #msg_vga_init
431 push bx
432 call _printf
433 inc sp
434 inc sp
435 #endif
436 ret
437
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
444
445 // --------------------------------------------------------------------------------------------
446 /*
447 * Boot time bios area inits
448 */
449 ASM_START
450 init_bios_area:
451 push ds
452 mov ax, # BIOSMEM_SEG
453 mov ds, ax
454
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
462
463 ;; Just for the first int10 find its children
464
465 ;; the default char height
466 mov bx, # BIOSMEM_CHAR_HEIGHT
467 mov al, #0x10
468 mov [bx], al
469
470 ;; Clear the screen
471 mov bx, # BIOSMEM_VIDEO_CTL
472 mov al, #0x60
473 mov [bx], al
474
475 ;; Set the basic screen we have
476 mov bx, # BIOSMEM_SWITCHES
477 mov al, #0xf9
478 mov [bx], al
479
480 ;; Set the basic modeset options
481 mov bx, # BIOSMEM_MODESET_CTL
482 mov al, #0x51
483 mov [bx], al
484
485 ;; Set the default MSR
486 mov bx, # BIOSMEM_CURRENT_MSR
487 mov al, #0x09
488 mov [bx], al
489
490 pop ds
491 ret
492
493 _video_save_pointer_table:
494 .word _video_param_table
495 .word 0xc000
496
497 .word 0 /* XXX: fill it */
498 .word 0
499
500 .word 0 /* XXX: fill it */
501 .word 0
502
503 .word 0 /* XXX: fill it */
504 .word 0
505
506 .word 0 /* XXX: fill it */
507 .word 0
508
509 .word 0 /* XXX: fill it */
510 .word 0
511
512 .word 0 /* XXX: fill it */
513 .word 0
514
515 ASM_END
516
517 // --------------------------------------------------------------------------------------------
518 /*
519 * Boot time Splash screen
520 */
521 static void display_splash_screen()
522 {
523 }
524
525 // --------------------------------------------------------------------------------------------
526 /*
527 * Tell who we are
528 */
529
display_info()530 static void display_info()
531 {
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
539
540 ;;mov si,#vgabios_copyright
541 ;;call _display_string
542 ;;mov si,#crlf
543 ;;call _display_string
544
545 mov si,#vgabios_license
546 call _display_string
547 mov si,#vgabios_website
548 call _display_string
549 ASM_END
550 }
551
display_string()552 static void display_string()
553 {
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
562 cld
563 repne
564 scasb
565 not cx
566 dec cx
567 push cx
568
569 mov ax,#0x0300
570 mov bx,#0x0000
571 int #0x10
572
573 pop cx
574 mov ax,#0x1301
575 mov bx,#0x000b
576 mov bp,si
577 int #0x10
578 ASM_END
579 }
580
581 // --------------------------------------------------------------------------------------------
582 #ifdef DEBUG
int10_debugmsg(DI,SI,BP,SP,BX,DX,CX,AX,DS,ES,FLAGS)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;
585 {
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);
589 }
590 #endif
591
592 // --------------------------------------------------------------------------------------------
593 /*
594 * int10 main dispatcher
595 */
int10_func(DI,SI,BP,SP,BX,DX,CX,AX,DS,ES,FLAGS)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;
598 {
599
600 // BIOS functions
601 switch(GET_AH())
602 {
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);
620 }
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())
676 {
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
715 }
716
717 break;
718 case 0x12:
719 switch(GET_BL())
720 {
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
736 }
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())
747 {
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
761 }
762 SET_AL(0x1C);
763 break;
764
765 #ifdef VBE
766 case 0x4f:
767 if (vbe_has_vbe_display()) {
768 switch(GET_AL())
769 {
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;
804 }
805 }
806 else {
807 // No VBE display
808 AX=0x0100;
809 }
810 break;
811 #endif
812
813 #ifdef DEBUG
814 default:
815 unknown();
816 #endif
817 }
818 }
819
820 // ============================================================================================
821 //
822 // BIOS functions
823 //
824 // ============================================================================================
825
biosfn_set_video_mode(mode)826 static void biosfn_set_video_mode(mode) Bit8u mode;
827 {// mode: Bit 7 is 1 if no clear screen
828
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;
835
836 #ifdef VBE
837 if (vbe_has_vbe_display()) {
838 dispi_set_enable(VBE_DISPI_DISABLED);
839 }
840 #endif // def VBE
841
842 // The real mode
843 mode=mode&0x7f;
844
845 // find the entry in the video modes
846 line=find_vga_entry(mode);
847
848 #ifdef DEBUG
849 printf("mode search %02x found line %02x\n",mode,line);
850 #endif
851
852 if(line==0xFF)
853 return;
854
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;
859
860 // Read the bios vga control
861 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
862
863 // Read the bios vga switches
864 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
865
866 // Read the bios mode set control
867 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
868
869 // Then we know the number of lines
870 // FIXME
871
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);
876
877 // Set the whole dac always, from 0
878 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
879
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;
894 }
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]);
901 }
902 else
903 {outb(VGAREG_DAC_DATA,0);
904 outb(VGAREG_DAC_DATA,0);
905 outb(VGAREG_DAC_DATA,0);
906 }
907 }
908 if((modeset_ctl&0x02)==0x02)
909 {
910 biosfn_perform_gray_scale_summing(0x00, 0x100);
911 }
912 }
913
914 // Reset Attribute Ctl flip-flop
915 inb(VGAREG_ACTL_RESET);
916
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]);
921 }
922 outb(VGAREG_ACTL_ADDRESS,0x14);
923 outb(VGAREG_ACTL_WRITE_DATA,0x00);
924
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]);
931 }
932
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]);
937 }
938
939 // Set CRTC address VGA or MDA
940 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
941
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]);
948 }
949
950 // Set the misc register
951 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
952
953 // Enable video
954 outb(VGAREG_ACTL_ADDRESS,0x20);
955 inb(VGAREG_ACTL_RESET);
956
957 if(noclearmem==0x00)
958 {
959 if(vga_modes[line].class==TEXT)
960 {
961 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
962 }
963 else
964 {
965 if(mode<0x0d)
966 {
967 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
968 }
969 else
970 {
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 );
976 }
977 }
978 }
979
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);
990
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);
995
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...
999
1000 // Set cursor shape
1001 if(vga_modes[line].class==TEXT)
1002 {
1003 biosfn_set_cursor_shape(0x06,0x07);
1004 }
1005
1006 // Set cursor pos for page 0..7
1007 for(i=0;i<8;i++)
1008 biosfn_set_cursor_pos(i,0x0000);
1009
1010 // Set active page 0
1011 biosfn_set_active_page(0x00);
1012
1013 // Write the fonts in memory
1014 if(vga_modes[line].class==TEXT)
1015 {
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
1025 }
1026
1027 // Set the ints 0x1F and 0x43
1028 ASM_START
1029 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1030 ASM_END
1031
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;
1048 }
1049 }
1050
1051 // --------------------------------------------------------------------------------------------
biosfn_set_cursor_shape(CH,CL)1052 static void biosfn_set_cursor_shape (CH,CL)
1053 Bit8u CH;Bit8u CL;
1054 {Bit16u cheight,curs,crtc_addr;
1055 Bit8u modeset_ctl;
1056
1057 CH&=0x3f;
1058 CL&=0x1f;
1059
1060 curs=(CH<<8)+CL;
1061 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1062
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))
1066 {
1067 if(CL!=(CH+1))
1068 {
1069 CH = ((CH+1) * cheight / 8) -1;
1070 }
1071 else
1072 {
1073 CH = ((CL+1) * cheight / 8) - 2;
1074 }
1075 CL = ((CL+1) * cheight / 8) - 1;
1076 }
1077
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);
1084 }
1085
1086 // --------------------------------------------------------------------------------------------
biosfn_set_cursor_pos(page,cursor)1087 static void biosfn_set_cursor_pos (page, cursor)
1088 Bit8u page;Bit16u cursor;
1089 {
1090 Bit8u xcurs,ycurs,current;
1091 Bit16u nbcols,nbrows,address,crtc_addr;
1092
1093 // Should not happen...
1094 if(page>7)return;
1095
1096 // Bios cursor pos
1097 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1098
1099 // Set the hardware cursor
1100 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1101 if(page==current)
1102 {
1103 // Get the dimensions
1104 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1105 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1106
1107 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1108
1109 // Calculate the address knowing nbcols nbrows and page num
1110 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1111
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);
1118 }
1119 }
1120
1121 // --------------------------------------------------------------------------------------------
biosfn_get_cursor_pos(page,shape,pos)1122 static void biosfn_get_cursor_pos (page,shape, pos)
1123 Bit8u page;Bit16u *shape;Bit16u *pos;
1124 {
1125 Bit16u ss=get_SS();
1126
1127 // Default
1128 write_word(ss, shape, 0);
1129 write_word(ss, pos, 0);
1130
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));
1135 }
1136
1137 // --------------------------------------------------------------------------------------------
biosfn_set_active_page(page)1138 static void biosfn_set_active_page (page)
1139 Bit8u page;
1140 {
1141 Bit16u cursor,dummy,crtc_addr;
1142 Bit16u nbcols,nbrows,address;
1143 Bit8u mode,line;
1144
1145 if(page>7)return;
1146
1147 // Get the mode
1148 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1149 line=find_vga_entry(mode);
1150 if(line==0xFF)return;
1151
1152 // Get pos curs pos for the right page
1153 biosfn_get_cursor_pos(page,&dummy,&cursor);
1154
1155 if(vga_modes[line].class==TEXT)
1156 {
1157 // Get the dimensions
1158 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1159 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1160
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);
1164
1165 // Start address
1166 address=SCREEN_IO_START(nbcols,nbrows,page);
1167 }
1168 else
1169 {
1170 address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
1171 }
1172
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);
1179
1180 // And change the BIOS page
1181 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1182
1183 #ifdef DEBUG
1184 printf("Set active page %02x address %04x\n",page,address);
1185 #endif
1186
1187 // Display the cursor, now the page is active
1188 biosfn_set_cursor_pos(page,cursor);
1189 }
1190
1191 // --------------------------------------------------------------------------------------------
vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)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;
1194 {
1195 Bit16u src,dest;
1196 Bit8u i;
1197
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++)
1202 {
1203 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1204 }
1205 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1206 }
1207
1208 // --------------------------------------------------------------------------------------------
vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)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;
1211 {
1212 Bit16u dest;
1213 Bit8u i;
1214
1215 dest=ystart*cheight*nbcols+xstart;
1216 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1217 for(i=0;i<cheight;i++)
1218 {
1219 memsetb(0xa000,dest+i*nbcols,attr,cols);
1220 }
1221 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1222 }
1223
1224 // --------------------------------------------------------------------------------------------
vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)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;
1227 {
1228 Bit16u src,dest;
1229 Bit8u i;
1230
1231 src=((ysrc*cheight*nbcols)>>1)+xstart;
1232 dest=((ydest*cheight*nbcols)>>1)+xstart;
1233 for(i=0;i<cheight;i++)
1234 {
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);
1239 }
1240 }
1241
1242 // --------------------------------------------------------------------------------------------
vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)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;
1245 {
1246 Bit16u dest;
1247 Bit8u i;
1248
1249 dest=((ystart*cheight*nbcols)>>1)+xstart;
1250 for(i=0;i<cheight;i++)
1251 {
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);
1256 }
1257 }
1258
1259 // --------------------------------------------------------------------------------------------
biosfn_scroll(nblines,attr,rul,cul,rlr,clr,page,dir)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;
1262 {
1263 // page == 0xFF if current
1264
1265 Bit8u mode,line,cheight,bpp,cols;
1266 Bit16u nbcols,nbrows,i;
1267 Bit16u address;
1268
1269 if(rul>rlr)return;
1270 if(cul>clr)return;
1271
1272 // Get the mode
1273 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1274 line=find_vga_entry(mode);
1275 if(line==0xFF)return;
1276
1277 // Get the dimensions
1278 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1279 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1280
1281 // Get the current page
1282 if(page==0xFF)
1283 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1284
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;
1289
1290 if(vga_modes[line].class==TEXT)
1291 {
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
1297
1298 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1299 {
1300 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1301 }
1302 else
1303 {// if Scroll up
1304 if(dir==SCROLL_UP)
1305 {for(i=rul;i<=rlr;i++)
1306 {
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);
1311 }
1312 }
1313 else
1314 {for(i=rlr;i>=rul;i--)
1315 {
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;
1321 }
1322 }
1323 }
1324 }
1325 else
1326 {
1327 // FIXME gfx mode not complete
1328 cheight=video_param_table[line_to_vpti[line]].cheight;
1329 switch(vga_modes[line].memmodel)
1330 {
1331 case PLANAR4:
1332 case PLANAR1:
1333 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1334 {
1335 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1336 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1337 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1338 }
1339 else
1340 {// if Scroll up
1341 if(dir==SCROLL_UP)
1342 {for(i=rul;i<=rlr;i++)
1343 {
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);
1348 }
1349 }
1350 else
1351 {for(i=rlr;i>=rul;i--)
1352 {
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;
1358 }
1359 }
1360 }
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)
1365 {
1366 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1367 }
1368 else
1369 {
1370 if(bpp==2)
1371 {
1372 cul<<=1;
1373 cols<<=1;
1374 nbcols<<=1;
1375 }
1376 // if Scroll up
1377 if(dir==SCROLL_UP)
1378 {for(i=rul;i<=rlr;i++)
1379 {
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);
1384 }
1385 }
1386 else
1387 {for(i=rlr;i>=rul;i--)
1388 {
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;
1394 }
1395 }
1396 }
1397 break;
1398 #ifdef DEBUG
1399 default:
1400 printf("Scroll in graphics mode ");
1401 unimplemented();
1402 #endif
1403 }
1404 }
1405 }
1406
1407 // --------------------------------------------------------------------------------------------
biosfn_read_char_attr(page,car)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;
1414
1415 // Get the mode
1416 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1417 line=find_vga_entry(mode);
1418 if(line==0xFF)return;
1419
1420 // Get the cursor pos for the page
1421 biosfn_get_cursor_pos(page,&dummy,&cursor);
1422 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1423
1424 // Get the dimensions
1425 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1426 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1427
1428 if(vga_modes[line].class==TEXT)
1429 {
1430 // Compute the address
1431 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1432
1433 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1434 }
1435 else
1436 {
1437 // FIXME gfx mode
1438 #ifdef DEBUG
1439 unimplemented();
1440 #endif
1441 }
1442 }
1443
1444 // --------------------------------------------------------------------------------------------
write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)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;
1447 {
1448 Bit8u i,j,mask;
1449 Bit8u *fdata;
1450 Bit16u addr,dest,src;
1451
1452 switch(cheight)
1453 {case 14:
1454 fdata = &vgafont14;
1455 break;
1456 case 16:
1457 fdata = &vgafont16;
1458 break;
1459 default:
1460 fdata = &vgafont8;
1461 }
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)
1467 {
1468 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1469 }
1470 else
1471 {
1472 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1473 }
1474 for(i=0;i<cheight;i++)
1475 {
1476 dest=addr+i*nbcols;
1477 for(j=0;j<8;j++)
1478 {
1479 mask=0x80>>j;
1480 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1481 read_byte(0xa000,dest);
1482 if(fdata[src+i]&mask)
1483 {
1484 write_byte(0xa000,dest,attr&0x0f);
1485 }
1486 else
1487 {
1488 write_byte(0xa000,dest,0x00);
1489 }
1490 }
1491 }
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
1501 }
1502
1503 // --------------------------------------------------------------------------------------------
write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)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;
1506 {
1507 Bit8u i,j,mask,data;
1508 Bit8u *fdata;
1509 Bit16u addr,dest,src;
1510
1511 fdata = &vgafont8;
1512 addr=(xcurs*bpp)+ycurs*320;
1513 src = car * 8;
1514 for(i=0;i<8;i++)
1515 {
1516 dest=addr+(i>>1)*80;
1517 if (i & 1) dest += 0x2000;
1518 mask = 0x80;
1519 if (bpp == 1)
1520 {
1521 if (attr & 0x80)
1522 {
1523 data = read_byte(0xb800,dest);
1524 }
1525 else
1526 {
1527 data = 0x00;
1528 }
1529 for(j=0;j<8;j++)
1530 {
1531 if (fdata[src+i] & mask)
1532 {
1533 if (attr & 0x80)
1534 {
1535 data ^= (attr & 0x01) << (7-j);
1536 }
1537 else
1538 {
1539 data |= (attr & 0x01) << (7-j);
1540 }
1541 }
1542 mask >>= 1;
1543 }
1544 write_byte(0xb800,dest,data);
1545 }
1546 else
1547 {
1548 while (mask > 0)
1549 {
1550 if (attr & 0x80)
1551 {
1552 data = read_byte(0xb800,dest);
1553 }
1554 else
1555 {
1556 data = 0x00;
1557 }
1558 for(j=0;j<4;j++)
1559 {
1560 if (fdata[src+i] & mask)
1561 {
1562 if (attr & 0x80)
1563 {
1564 data ^= (attr & 0x03) << ((3-j)*2);
1565 }
1566 else
1567 {
1568 data |= (attr & 0x03) << ((3-j)*2);
1569 }
1570 }
1571 mask >>= 1;
1572 }
1573 write_byte(0xb800,dest,data);
1574 dest += 1;
1575 }
1576 }
1577 }
1578 }
1579
1580 // --------------------------------------------------------------------------------------------
write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)1581 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1582 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1583 {
1584 Bit8u i,j,mask,data;
1585 Bit8u *fdata;
1586 Bit16u addr,dest,src;
1587
1588 fdata = &vgafont8;
1589 addr=xcurs*8+ycurs*nbcols*64;
1590 src = car * 8;
1591 for(i=0;i<8;i++)
1592 {
1593 dest=addr+i*nbcols*8;
1594 mask = 0x80;
1595 for(j=0;j<8;j++)
1596 {
1597 data = 0x00;
1598 if (fdata[src+i] & mask)
1599 {
1600 data = attr;
1601 }
1602 write_byte(0xa000,dest+j,data);
1603 mask >>= 1;
1604 }
1605 }
1606 }
1607
1608 // --------------------------------------------------------------------------------------------
biosfn_write_char_attr(car,page,attr,count)1609 static void biosfn_write_char_attr (car,page,attr,count)
1610 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1611 {
1612 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1613 Bit16u nbcols,nbrows,address;
1614 Bit16u cursor,dummy;
1615
1616 // Get the mode
1617 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1618 line=find_vga_entry(mode);
1619 if(line==0xFF)return;
1620
1621 // Get the cursor pos for the page
1622 biosfn_get_cursor_pos(page,&dummy,&cursor);
1623 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1624
1625 // Get the dimensions
1626 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1627 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1628
1629 if(vga_modes[line].class==TEXT)
1630 {
1631 // Compute the address
1632 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1633
1634 dummy=((Bit16u)attr<<8)+car;
1635 memsetw(vga_modes[line].sstart,address,dummy,count);
1636 }
1637 else
1638 {
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))
1643 {
1644 switch(vga_modes[line].memmodel)
1645 {
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
1660 }
1661 xcurs++;
1662 }
1663 }
1664 }
1665
1666 // --------------------------------------------------------------------------------------------
biosfn_write_char_only(car,page,attr,count)1667 static void biosfn_write_char_only (car,page,attr,count)
1668 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1669 {
1670 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1671 Bit16u nbcols,nbrows,address;
1672 Bit16u cursor,dummy;
1673
1674 // Get the mode
1675 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1676 line=find_vga_entry(mode);
1677 if(line==0xFF)return;
1678
1679 // Get the cursor pos for the page
1680 biosfn_get_cursor_pos(page,&dummy,&cursor);
1681 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1682
1683 // Get the dimensions
1684 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1685 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1686
1687 if(vga_modes[line].class==TEXT)
1688 {
1689 // Compute the address
1690 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1691
1692 while(count-->0)
1693 {write_byte(vga_modes[line].sstart,address,car);
1694 address+=2;
1695 }
1696 }
1697 else
1698 {
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))
1703 {
1704 switch(vga_modes[line].memmodel)
1705 {
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
1720 }
1721 xcurs++;
1722 }
1723 }
1724 }
1725
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
1736 ret
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
1775 ret
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
1804 ret
1805 ASM_END
1806
1807 // --------------------------------------------------------------------------------------------
biosfn_write_pixel(BH,AL,CX,DX)1808 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1809 {
1810 Bit8u mode,line,mask,attr,data;
1811 Bit16u addr;
1812
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;
1818
1819 switch(vga_modes[line].memmodel)
1820 {
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)
1829 {
1830 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1831 }
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)
1845 {
1846 addr=(CX>>2)+(DX>>1)*80;
1847 }
1848 else
1849 {
1850 addr=(CX>>3)+(DX>>1)*80;
1851 }
1852 if (DX & 1) addr += 0x2000;
1853 data = read_byte(0xb800,addr);
1854 if(vga_modes[line].pixbits==2)
1855 {
1856 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1857 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1858 }
1859 else
1860 {
1861 attr = (AL & 0x01) << (7 - (CX & 0x07));
1862 mask = 0x01 << (7 - (CX & 0x07));
1863 }
1864 if (AL & 0x80)
1865 {
1866 data ^= attr;
1867 }
1868 else
1869 {
1870 data &= ~mask;
1871 data |= attr;
1872 }
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
1883 }
1884 }
1885
1886 // --------------------------------------------------------------------------------------------
biosfn_read_pixel(BH,CX,DX,AX)1887 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1888 {
1889 Bit8u mode,line,mask,attr,data,i;
1890 Bit16u addr;
1891 Bit16u ss=get_SS();
1892
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;
1898
1899 switch(vga_modes[line].memmodel)
1900 {
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++)
1907 {
1908 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1909 data = read_byte(0xa000,addr) & mask;
1910 if (data > 0) attr |= (0x01 << i);
1911 }
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)
1918 {
1919 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1920 }
1921 else
1922 {
1923 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1924 }
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;
1935 }
1936 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1937 }
1938
1939 // --------------------------------------------------------------------------------------------
biosfn_write_teletype(car,page,attr,flag)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
1943
1944 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1945 Bit16u nbcols,nbrows,address;
1946 Bit16u cursor,dummy;
1947
1948 // special case if page is 0xff, use current page
1949 if(page==0xff)
1950 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1951
1952 // Get the mode
1953 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1954 line=find_vga_entry(mode);
1955 if(line==0xFF)return;
1956
1957 // Get the cursor pos for the page
1958 biosfn_get_cursor_pos(page,&dummy,&cursor);
1959 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1960
1961 // Get the dimensions
1962 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1963 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1964
1965 switch(car)
1966 {
1967 case 7:
1968 //FIXME should beep
1969 break;
1970
1971 case 8:
1972 if(xcurs>0)xcurs--;
1973 break;
1974
1975 case '\r':
1976 xcurs=0;
1977 break;
1978
1979 case '\n':
1980 ycurs++;
1981 break;
1982
1983 case '\t':
1984 do
1985 {
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;
1991
1992 default:
1993
1994 if(vga_modes[line].class==TEXT)
1995 {
1996 // Compute the address
1997 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1998
1999 // Write the char
2000 write_byte(vga_modes[line].sstart,address,car);
2001
2002 if(flag==WITH_ATTR)
2003 write_byte(vga_modes[line].sstart,address+1,attr);
2004 }
2005 else
2006 {
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)
2011 {
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
2026 }
2027 }
2028 xcurs++;
2029 }
2030
2031 // Do we need to wrap ?
2032 if(xcurs==nbcols)
2033 {xcurs=0;
2034 ycurs++;
2035 }
2036
2037 // Do we need to scroll ?
2038 if(ycurs==nbrows)
2039 {
2040 if(vga_modes[line].class==TEXT)
2041 {
2042 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
2043 attr=read_byte(vga_modes[line].sstart,address+1);
2044 biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2045 }
2046 else
2047 {
2048 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2049 }
2050 ycurs-=1;
2051 }
2052
2053 // Set the cursor for the page
2054 cursor=ycurs; cursor<<=8; cursor+=xcurs;
2055 biosfn_set_cursor_pos(page,cursor);
2056 }
2057
2058 // --------------------------------------------------------------------------------------------
2059 ASM_START
2060 biosfn_get_video_mode:
2061 push ds
2062 mov ax, # BIOSMEM_SEG
2063 mov ds, ax
2064 push bx
2065 mov bx, # BIOSMEM_CURRENT_PAGE
2066 mov al, [bx]
2067 pop bx
2068 mov bh, al
2069 push bx
2070 mov bx, # BIOSMEM_VIDEO_CTL
2071 mov ah, [bx]
2072 and ah, #0x80
2073 mov bx, # BIOSMEM_CURRENT_MODE
2074 mov al, [bx]
2075 or al, ah
2076 mov bx, # BIOSMEM_NB_COLS
2077 mov ah, [bx]
2078 pop bx
2079 pop ds
2080 ret
2081 ASM_END
2082
2083 // --------------------------------------------------------------------------------------------
2084 ASM_START
2085 biosfn_group_10:
2086 cmp al, #0x00
2087 jne int10_test_1001
2088 jmp biosfn_set_single_palette_reg
2089 int10_test_1001:
2090 cmp al, #0x01
2091 jne int10_test_1002
2092 jmp biosfn_set_overscan_border_color
2093 int10_test_1002:
2094 cmp al, #0x02
2095 jne int10_test_1003
2096 jmp biosfn_set_all_palette_reg
2097 int10_test_1003:
2098 cmp al, #0x03
2099 jne int10_test_1007
2100 jmp biosfn_toggle_intensity
2101 int10_test_1007:
2102 cmp al, #0x07
2103 jne int10_test_1008
2104 jmp biosfn_get_single_palette_reg
2105 int10_test_1008:
2106 cmp al, #0x08
2107 jne int10_test_1009
2108 jmp biosfn_read_overscan_border_color
2109 int10_test_1009:
2110 cmp al, #0x09
2111 jne int10_test_1010
2112 jmp biosfn_get_all_palette_reg
2113 int10_test_1010:
2114 cmp al, #0x10
2115 jne int10_test_1012
2116 jmp biosfn_set_single_dac_reg
2117 int10_test_1012:
2118 cmp al, #0x12
2119 jne int10_test_1013
2120 jmp biosfn_set_all_dac_reg
2121 int10_test_1013:
2122 cmp al, #0x13
2123 jne int10_test_1015
2124 jmp biosfn_select_video_dac_color_page
2125 int10_test_1015:
2126 cmp al, #0x15
2127 jne int10_test_1017
2128 jmp biosfn_read_single_dac_reg
2129 int10_test_1017:
2130 cmp al, #0x17
2131 jne int10_test_1018
2132 jmp biosfn_read_all_dac_reg
2133 int10_test_1018:
2134 cmp al, #0x18
2135 jne int10_test_1019
2136 jmp biosfn_set_pel_mask
2137 int10_test_1019:
2138 cmp al, #0x19
2139 jne int10_test_101A
2140 jmp biosfn_read_pel_mask
2141 int10_test_101A:
2142 cmp al, #0x1a
2143 jne int10_group_10_unknown
2144 jmp biosfn_read_video_dac_state
2145 int10_group_10_unknown:
2146 #ifdef DEBUG
2147 call _unknown
2148 #endif
2149 ret
2150
2151 biosfn_set_single_palette_reg:
2152 cmp bl, #0x14
2153 ja no_actl_reg1
2154 push ax
2155 push dx
2156 mov dx, # VGAREG_ACTL_RESET
2157 in al, dx
2158 mov dx, # VGAREG_ACTL_ADDRESS
2159 mov al, bl
2160 out dx, al
2161 mov al, bh
2162 out dx, al
2163 mov al, #0x20
2164 out dx, al
2165 pop dx
2166 pop ax
2167 no_actl_reg1:
2168 ret
2169 ASM_END
2170
2171 // --------------------------------------------------------------------------------------------
2172 ASM_START
2173 biosfn_set_overscan_border_color:
2174 push bx
2175 mov bl, #0x11
2176 call biosfn_set_single_palette_reg
2177 pop bx
2178 ret
2179 ASM_END
2180
2181 // --------------------------------------------------------------------------------------------
2182 ASM_START
2183 biosfn_set_all_palette_reg:
2184 push ax
2185 push bx
2186 push cx
2187 push dx
2188 mov bx, dx
2189 mov dx, # VGAREG_ACTL_RESET
2190 in al, dx
2191 mov cl, #0x00
2192 mov dx, # VGAREG_ACTL_ADDRESS
2193 set_palette_loop:
2194 mov al, cl
2195 out dx, al
2196 seg es
2197 mov al, [bx]
2198 out dx, al
2199 inc bx
2200 inc cl
2201 cmp cl, #0x10
2202 jne set_palette_loop
2203 mov al, #0x11
2204 out dx, al
2205 seg es
2206 mov al, [bx]
2207 out dx, al
2208 mov al, #0x20
2209 out dx, al
2210 pop dx
2211 pop cx
2212 pop bx
2213 pop ax
2214 ret
2215 ASM_END
2216
2217 // --------------------------------------------------------------------------------------------
2218 ASM_START
2219 biosfn_toggle_intensity:
2220 push ax
2221 push bx
2222 push dx
2223 mov dx, # VGAREG_ACTL_RESET
2224 in al, dx
2225 mov dx, # VGAREG_ACTL_ADDRESS
2226 mov al, #0x10
2227 out dx, al
2228 mov dx, # VGAREG_ACTL_READ_DATA
2229 in al, dx
2230 and al, #0xf7
2231 and bl, #0x01
2232 shl bl, 3
2233 or al, bl
2234 mov dx, # VGAREG_ACTL_ADDRESS
2235 out dx, al
2236 mov al, #0x20
2237 out dx, al
2238 pop dx
2239 pop bx
2240 pop ax
2241 ret
2242 ASM_END
2243
2244 // --------------------------------------------------------------------------------------------
2245 ASM_START
2246 biosfn_get_single_palette_reg:
2247 cmp bl, #0x14
2248 ja no_actl_reg2
2249 push ax
2250 push dx
2251 mov dx, # VGAREG_ACTL_RESET
2252 in al, dx
2253 mov dx, # VGAREG_ACTL_ADDRESS
2254 mov al, bl
2255 out dx, al
2256 mov dx, # VGAREG_ACTL_READ_DATA
2257 in al, dx
2258 mov bh, al
2259 mov dx, # VGAREG_ACTL_RESET
2260 in al, dx
2261 mov dx, # VGAREG_ACTL_ADDRESS
2262 mov al, #0x20
2263 out dx, al
2264 pop dx
2265 pop ax
2266 no_actl_reg2:
2267 ret
2268 ASM_END
2269
2270 // --------------------------------------------------------------------------------------------
2271 ASM_START
2272 biosfn_read_overscan_border_color:
2273 push ax
2274 push bx
2275 mov bl, #0x11
2276 call biosfn_get_single_palette_reg
2277 mov al, bh
2278 pop bx
2279 mov bh, al
2280 pop ax
2281 ret
2282 ASM_END
2283
2284 // --------------------------------------------------------------------------------------------
2285 ASM_START
2286 biosfn_get_all_palette_reg:
2287 push ax
2288 push bx
2289 push cx
2290 push dx
2291 mov bx, dx
2292 mov cl, #0x00
2293 get_palette_loop:
2294 mov dx, # VGAREG_ACTL_RESET
2295 in al, dx
2296 mov dx, # VGAREG_ACTL_ADDRESS
2297 mov al, cl
2298 out dx, al
2299 mov dx, # VGAREG_ACTL_READ_DATA
2300 in al, dx
2301 seg es
2302 mov [bx], al
2303 inc bx
2304 inc cl
2305 cmp cl, #0x10
2306 jne get_palette_loop
2307 mov dx, # VGAREG_ACTL_RESET
2308 in al, dx
2309 mov dx, # VGAREG_ACTL_ADDRESS
2310 mov al, #0x11
2311 out dx, al
2312 mov dx, # VGAREG_ACTL_READ_DATA
2313 in al, dx
2314 seg es
2315 mov [bx], al
2316 mov dx, # VGAREG_ACTL_RESET
2317 in al, dx
2318 mov dx, # VGAREG_ACTL_ADDRESS
2319 mov al, #0x20
2320 out dx, al
2321 pop dx
2322 pop cx
2323 pop bx
2324 pop ax
2325 ret
2326 ASM_END
2327
2328 // --------------------------------------------------------------------------------------------
2329 ASM_START
2330 biosfn_set_single_dac_reg:
2331 push ax
2332 push dx
2333 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2334 mov al, bl
2335 out dx, al
2336 mov dx, # VGAREG_DAC_DATA
2337 pop ax
2338 push ax
2339 mov al, ah
2340 out dx, al
2341 mov al, ch
2342 out dx, al
2343 mov al, cl
2344 out dx, al
2345 pop dx
2346 pop ax
2347 ret
2348 ASM_END
2349
2350 // --------------------------------------------------------------------------------------------
2351 ASM_START
2352 biosfn_set_all_dac_reg:
2353 push ax
2354 push bx
2355 push cx
2356 push dx
2357 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2358 mov al, bl
2359 out dx, al
2360 pop dx
2361 push dx
2362 mov bx, dx
2363 mov dx, # VGAREG_DAC_DATA
2364 set_dac_loop:
2365 seg es
2366 mov al, [bx]
2367 out dx, al
2368 inc bx
2369 seg es
2370 mov al, [bx]
2371 out dx, al
2372 inc bx
2373 seg es
2374 mov al, [bx]
2375 out dx, al
2376 inc bx
2377 dec cx
2378 jnz set_dac_loop
2379 pop dx
2380 pop cx
2381 pop bx
2382 pop ax
2383 ret
2384 ASM_END
2385
2386 // --------------------------------------------------------------------------------------------
2387 ASM_START
2388 biosfn_select_video_dac_color_page:
2389 push ax
2390 push bx
2391 push dx
2392 mov dx, # VGAREG_ACTL_RESET
2393 in al, dx
2394 mov dx, # VGAREG_ACTL_ADDRESS
2395 mov al, #0x10
2396 out dx, al
2397 mov dx, # VGAREG_ACTL_READ_DATA
2398 in al, dx
2399 and bl, #0x01
2400 jnz set_dac_page
2401 and al, #0x7f
2402 shl bh, 7
2403 or al, bh
2404 mov dx, # VGAREG_ACTL_ADDRESS
2405 out dx, al
2406 jmp set_actl_normal
2407 set_dac_page:
2408 push ax
2409 mov dx, # VGAREG_ACTL_RESET
2410 in al, dx
2411 mov dx, # VGAREG_ACTL_ADDRESS
2412 mov al, #0x14
2413 out dx, al
2414 pop ax
2415 and al, #0x80
2416 jnz set_dac_16_page
2417 shl bh, 2
2418 set_dac_16_page:
2419 and bh, #0x0f
2420 mov al, bh
2421 out dx, al
2422 set_actl_normal:
2423 mov al, #0x20
2424 out dx, al
2425 pop dx
2426 pop bx
2427 pop ax
2428 ret
2429 ASM_END
2430
2431 // --------------------------------------------------------------------------------------------
2432 ASM_START
2433 biosfn_read_single_dac_reg:
2434 push ax
2435 push dx
2436 mov dx, # VGAREG_DAC_READ_ADDRESS
2437 mov al, bl
2438 out dx, al
2439 pop ax
2440 mov ah, al
2441 mov dx, # VGAREG_DAC_DATA
2442 in al, dx
2443 xchg al, ah
2444 push ax
2445 in al, dx
2446 mov ch, al
2447 in al, dx
2448 mov cl, al
2449 pop dx
2450 pop ax
2451 ret
2452 ASM_END
2453
2454 // --------------------------------------------------------------------------------------------
2455 ASM_START
2456 biosfn_read_all_dac_reg:
2457 push ax
2458 push bx
2459 push cx
2460 push dx
2461 mov dx, # VGAREG_DAC_READ_ADDRESS
2462 mov al, bl
2463 out dx, al
2464 pop dx
2465 push dx
2466 mov bx, dx
2467 mov dx, # VGAREG_DAC_DATA
2468 read_dac_loop:
2469 in al, dx
2470 seg es
2471 mov [bx], al
2472 inc bx
2473 in al, dx
2474 seg es
2475 mov [bx], al
2476 inc bx
2477 in al, dx
2478 seg es
2479 mov [bx], al
2480 inc bx
2481 dec cx
2482 jnz read_dac_loop
2483 pop dx
2484 pop cx
2485 pop bx
2486 pop ax
2487 ret
2488 ASM_END
2489
2490 // --------------------------------------------------------------------------------------------
2491 ASM_START
2492 biosfn_set_pel_mask:
2493 push ax
2494 push dx
2495 mov dx, # VGAREG_PEL_MASK
2496 mov al, bl
2497 out dx, al
2498 pop dx
2499 pop ax
2500 ret
2501 ASM_END
2502
2503 // --------------------------------------------------------------------------------------------
2504 ASM_START
2505 biosfn_read_pel_mask:
2506 push ax
2507 push dx
2508 mov dx, # VGAREG_PEL_MASK
2509 in al, dx
2510 mov bl, al
2511 pop dx
2512 pop ax
2513 ret
2514 ASM_END
2515
2516 // --------------------------------------------------------------------------------------------
2517 ASM_START
2518 biosfn_read_video_dac_state:
2519 push ax
2520 push dx
2521 mov dx, # VGAREG_ACTL_RESET
2522 in al, dx
2523 mov dx, # VGAREG_ACTL_ADDRESS
2524 mov al, #0x10
2525 out dx, al
2526 mov dx, # VGAREG_ACTL_READ_DATA
2527 in al, dx
2528 mov bl, al
2529 shr bl, 7
2530 mov dx, # VGAREG_ACTL_RESET
2531 in al, dx
2532 mov dx, # VGAREG_ACTL_ADDRESS
2533 mov al, #0x14
2534 out dx, al
2535 mov dx, # VGAREG_ACTL_READ_DATA
2536 in al, dx
2537 mov bh, al
2538 and bh, #0x0f
2539 test bl, #0x01
2540 jnz get_dac_16_page
2541 shr bh, 2
2542 get_dac_16_page:
2543 mov dx, # VGAREG_ACTL_RESET
2544 in al, dx
2545 mov dx, # VGAREG_ACTL_ADDRESS
2546 mov al, #0x20
2547 out dx, al
2548 pop dx
2549 pop ax
2550 ret
2551 ASM_END
2552
2553 // --------------------------------------------------------------------------------------------
biosfn_perform_gray_scale_summing(start,count)2554 static void biosfn_perform_gray_scale_summing (start,count)
2555 Bit16u start;Bit16u count;
2556 {Bit8u r,g,b;
2557 Bit16u i;
2558 Bit16u index;
2559
2560 inb(VGAREG_ACTL_RESET);
2561 outb(VGAREG_ACTL_ADDRESS,0x00);
2562
2563 for( index = 0; index < count; index++ )
2564 {
2565 // set read address and switch to read mode
2566 outb(VGAREG_DAC_READ_ADDRESS,start);
2567 // get 6-bit wide RGB data values
2568 r=inb( VGAREG_DAC_DATA );
2569 g=inb( VGAREG_DAC_DATA );
2570 b=inb( VGAREG_DAC_DATA );
2571
2572 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2573 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2574
2575 if(i>0x3f)i=0x3f;
2576
2577 // set write address and switch to write mode
2578 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2579 // write new intensity value
2580 outb( VGAREG_DAC_DATA, i&0xff );
2581 outb( VGAREG_DAC_DATA, i&0xff );
2582 outb( VGAREG_DAC_DATA, i&0xff );
2583 start++;
2584 }
2585 inb(VGAREG_ACTL_RESET);
2586 outb(VGAREG_ACTL_ADDRESS,0x20);
2587 }
2588
2589 // --------------------------------------------------------------------------------------------
get_font_access()2590 static void get_font_access()
2591 {
2592 ASM_START
2593 mov dx, # VGAREG_SEQU_ADDRESS
2594 mov ax, #0x0100
2595 out dx, ax
2596 mov ax, #0x0402
2597 out dx, ax
2598 mov ax, #0x0704
2599 out dx, ax
2600 mov ax, #0x0300
2601 out dx, ax
2602 mov dx, # VGAREG_GRDC_ADDRESS
2603 mov ax, #0x0204
2604 out dx, ax
2605 mov ax, #0x0005
2606 out dx, ax
2607 mov ax, #0x0406
2608 out dx, ax
2609 ASM_END
2610 }
2611
release_font_access()2612 static void release_font_access()
2613 {
2614 ASM_START
2615 mov dx, # VGAREG_SEQU_ADDRESS
2616 mov ax, #0x0100
2617 out dx, ax
2618 mov ax, #0x0302
2619 out dx, ax
2620 mov ax, #0x0304
2621 out dx, ax
2622 mov ax, #0x0300
2623 out dx, ax
2624 mov dx, # VGAREG_READ_MISC_OUTPUT
2625 in al, dx
2626 and al, #0x01
2627 shl al, 2
2628 or al, #0x0a
2629 mov ah, al
2630 mov al, #0x06
2631 mov dx, # VGAREG_GRDC_ADDRESS
2632 out dx, ax
2633 mov ax, #0x0004
2634 out dx, ax
2635 mov ax, #0x1005
2636 out dx, ax
2637 ASM_END
2638 }
2639
2640 ASM_START
2641 idiv_u:
2642 xor dx,dx
2643 div bx
2644 ret
2645 ASM_END
2646
set_scan_lines(lines)2647 static void set_scan_lines(lines) Bit8u lines;
2648 {
2649 Bit16u crtc_addr,cols,page,vde;
2650 Bit8u crtc_r9,ovl,rows;
2651
2652 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2653 outb(crtc_addr, 0x09);
2654 crtc_r9 = inb(crtc_addr+1);
2655 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2656 outb(crtc_addr+1, crtc_r9);
2657 if(lines==8)
2658 {
2659 biosfn_set_cursor_shape(0x06,0x07);
2660 }
2661 else
2662 {
2663 biosfn_set_cursor_shape(lines-4,lines-3);
2664 }
2665 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2666 outb(crtc_addr, 0x12);
2667 vde = inb(crtc_addr+1);
2668 outb(crtc_addr, 0x07);
2669 ovl = inb(crtc_addr+1);
2670 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2671 rows = vde / lines;
2672 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2673 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2674 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2675 }
2676
biosfn_load_text_user_pat(AL,ES,BP,CX,DX,BL,BH)2677 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;
2678 {
2679 Bit16u blockaddr,dest,i,src;
2680
2681 get_font_access();
2682 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2683 for(i=0;i<CX;i++)
2684 {
2685 src = BP + i * BH;
2686 dest = blockaddr + (DX + i) * 32;
2687 memcpyb(0xA000, dest, ES, src, BH);
2688 }
2689 release_font_access();
2690 if(AL>=0x10)
2691 {
2692 set_scan_lines(BH);
2693 }
2694 }
2695
biosfn_load_text_8_14_pat(AL,BL)2696 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2697 {
2698 Bit16u blockaddr,dest,i,src;
2699
2700 get_font_access();
2701 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2702 for(i=0;i<0x100;i++)
2703 {
2704 src = i * 14;
2705 dest = blockaddr + i * 32;
2706 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2707 }
2708 release_font_access();
2709 if(AL>=0x10)
2710 {
2711 set_scan_lines(14);
2712 }
2713 }
2714
biosfn_load_text_8_8_pat(AL,BL)2715 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2716 {
2717 Bit16u blockaddr,dest,i,src;
2718
2719 get_font_access();
2720 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2721 for(i=0;i<0x100;i++)
2722 {
2723 src = i * 8;
2724 dest = blockaddr + i * 32;
2725 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2726 }
2727 release_font_access();
2728 if(AL>=0x10)
2729 {
2730 set_scan_lines(8);
2731 }
2732 }
2733
2734 // --------------------------------------------------------------------------------------------
2735 ASM_START
2736 biosfn_set_text_block_specifier:
2737 push ax
2738 push dx
2739 mov dx, # VGAREG_SEQU_ADDRESS
2740 mov ah, bl
2741 mov al, #0x03
2742 out dx, ax
2743 pop dx
2744 pop ax
2745 ret
2746 ASM_END
2747
2748 // --------------------------------------------------------------------------------------------
biosfn_load_text_8_16_pat(AL,BL)2749 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2750 {
2751 Bit16u blockaddr,dest,i,src;
2752
2753 get_font_access();
2754 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2755 for(i=0;i<0x100;i++)
2756 {
2757 src = i * 16;
2758 dest = blockaddr + i * 32;
2759 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2760 }
2761 release_font_access();
2762 if(AL>=0x10)
2763 {
2764 set_scan_lines(16);
2765 }
2766 }
2767
biosfn_load_gfx_8_8_chars(ES,BP)2768 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2769 {
2770 #ifdef DEBUG
2771 unimplemented();
2772 #endif
2773 }
biosfn_load_gfx_user_chars(ES,BP,CX,BL,DL)2774 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2775 {
2776 #ifdef DEBUG
2777 unimplemented();
2778 #endif
2779 }
biosfn_load_gfx_8_14_chars(BL)2780 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2781 {
2782 #ifdef DEBUG
2783 unimplemented();
2784 #endif
2785 }
biosfn_load_gfx_8_8_dd_chars(BL)2786 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2787 {
2788 #ifdef DEBUG
2789 unimplemented();
2790 #endif
2791 }
biosfn_load_gfx_8_16_chars(BL)2792 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2793 {
2794 #ifdef DEBUG
2795 unimplemented();
2796 #endif
2797 }
2798 // --------------------------------------------------------------------------------------------
biosfn_get_font_info(BH,ES,BP,CX,DX)2799 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2800 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2801 {Bit16u ss=get_SS();
2802
2803 switch(BH)
2804 {case 0x00:
2805 write_word(ss,ES,read_word(0x00,0x1f*4));
2806 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2807 break;
2808 case 0x01:
2809 write_word(ss,ES,read_word(0x00,0x43*4));
2810 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2811 break;
2812 case 0x02:
2813 write_word(ss,ES,0xC000);
2814 write_word(ss,BP,vgafont14);
2815 break;
2816 case 0x03:
2817 write_word(ss,ES,0xC000);
2818 write_word(ss,BP,vgafont8);
2819 break;
2820 case 0x04:
2821 write_word(ss,ES,0xC000);
2822 write_word(ss,BP,vgafont8+128*8);
2823 break;
2824 case 0x05:
2825 write_word(ss,ES,0xC000);
2826 write_word(ss,BP,vgafont14alt);
2827 break;
2828 case 0x06:
2829 write_word(ss,ES,0xC000);
2830 write_word(ss,BP,vgafont16);
2831 break;
2832 case 0x07:
2833 write_word(ss,ES,0xC000);
2834 write_word(ss,BP,vgafont16alt);
2835 break;
2836 default:
2837 #ifdef DEBUG
2838 printf("Get font info BH(%02x) was discarded\n",BH);
2839 #endif
2840 return;
2841 }
2842 // Set byte/char of on screen font
2843 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2844
2845 // Set Highest char row
2846 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2847 }
2848
2849 // --------------------------------------------------------------------------------------------
2850 ASM_START
2851 biosfn_get_ega_info:
2852 push ds
2853 push ax
2854 mov ax, # BIOSMEM_SEG
2855 mov ds, ax
2856 xor ch, ch
2857 mov bx, # BIOSMEM_SWITCHES
2858 mov cl, [bx]
2859 and cl, #0x0f
2860 mov bx, # BIOSMEM_CRTC_ADDRESS
2861 mov ax, [bx]
2862 mov bx, #0x0003
2863 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2864 jne mode_ega_color
2865 mov bh, #0x01
2866 mode_ega_color:
2867 pop ax
2868 pop ds
2869 ret
2870 ASM_END
2871
2872 // --------------------------------------------------------------------------------------------
2873 static void biosfn_alternate_prtsc()
2874 {
2875 #ifdef DEBUG
2876 unimplemented();
2877 #endif
2878 }
2879
2880 // --------------------------------------------------------------------------------------------
2881 ASM_START
2882 biosfn_select_vert_res:
2883
2884 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2885
2886 push ds
2887 push bx
2888 push dx
2889 mov dl, al
2890 mov ax, # BIOSMEM_SEG
2891 mov ds, ax
2892 mov bx, # BIOSMEM_MODESET_CTL
2893 mov al, [bx]
2894 mov bx, # BIOSMEM_SWITCHES
2895 mov ah, [bx]
2896 cmp dl, #0x01
2897 je vert_res_350
2898 jb vert_res_200
2899 cmp dl, #0x02
2900 je vert_res_400
2901 #ifdef DEBUG
2902 mov al, dl
2903 xor ah, ah
2904 push ax
2905 mov bx, #msg_vert_res
2906 push bx
2907 call _printf
2908 add sp, #4
2909 #endif
2910 jmp set_retcode
2911 vert_res_400:
2912
2913 ; reset modeset ctl bit 7 and set bit 4
2914 ; set switches bit 3-0 to 0x09
2915
2916 and al, #0x7f
2917 or al, #0x10
2918 and ah, #0xf0
2919 or ah, #0x09
2920 jnz set_vert_res
2921 vert_res_350:
2922
2923 ; reset modeset ctl bit 7 and bit 4
2924 ; set switches bit 3-0 to 0x09
2925
2926 and al, #0x6f
2927 and ah, #0xf0
2928 or ah, #0x09
2929 jnz set_vert_res
2930 vert_res_200:
2931
2932 ; set modeset ctl bit 7 and reset bit 4
2933 ; set switches bit 3-0 to 0x08
2934
2935 and al, #0xef
2936 or al, #0x80
2937 and ah, #0xf0
2938 or ah, #0x08
2939 set_vert_res:
2940 mov bx, # BIOSMEM_MODESET_CTL
2941 mov [bx], al
2942 mov bx, # BIOSMEM_SWITCHES
2943 mov [bx], ah
2944 set_retcode:
2945 mov ax, #0x1212
2946 pop dx
2947 pop bx
2948 pop ds
2949 ret
2950
2951 #ifdef DEBUG
2952 msg_vert_res:
2953 .ascii "Select vert res (%02x) was discarded"
2954 .byte 0x0d,0x0a,0x00
2955 #endif
2956
2957
2958 biosfn_enable_default_palette_loading:
2959 push ds
2960 push bx
2961 push dx
2962 mov dl, al
2963 and dl, #0x01
2964 shl dl, 3
2965 mov ax, # BIOSMEM_SEG
2966 mov ds, ax
2967 mov bx, # BIOSMEM_MODESET_CTL
2968 mov al, [bx]
2969 and al, #0xf7
2970 or al, dl
2971 mov [bx], al
2972 mov ax, #0x1212
2973 pop dx
2974 pop bx
2975 pop ds
2976 ret
2977
2978
2979 biosfn_enable_video_addressing:
2980 push bx
2981 push dx
2982 mov bl, al
2983 and bl, #0x01
2984 xor bl, #0x01
2985 shl bl, 1
2986 mov dx, # VGAREG_READ_MISC_OUTPUT
2987 in al, dx
2988 and al, #0xfd
2989 or al, bl
2990 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2991 out dx, al
2992 mov ax, #0x1212
2993 pop dx
2994 pop bx
2995 ret
2996
2997
2998 biosfn_enable_grayscale_summing:
2999 push ds
3000 push bx
3001 push dx
3002 mov dl, al
3003 and dl, #0x01
3004 xor dl, #0x01
3005 shl dl, 1
3006 mov ax, # BIOSMEM_SEG
3007 mov ds, ax
3008 mov bx, # BIOSMEM_MODESET_CTL
3009 mov al, [bx]
3010 and al, #0xfd
3011 or al, dl
3012 mov [bx], al
3013 mov ax, #0x1212
3014 pop dx
3015 pop bx
3016 pop ds
3017 ret
3018
3019
3020 biosfn_enable_cursor_emulation:
3021 push ds
3022 push bx
3023 push dx
3024 mov dl, al
3025 and dl, #0x01
3026 xor dl, #0x01
3027 mov ax, # BIOSMEM_SEG
3028 mov ds, ax
3029 mov bx, # BIOSMEM_MODESET_CTL
3030 mov al, [bx]
3031 and al, #0xfe
3032 or al, dl
3033 mov [bx], al
3034 mov ax, #0x1212
3035 pop dx
3036 pop bx
3037 pop ds
3038 ret
3039 ASM_END
3040
3041 // --------------------------------------------------------------------------------------------
biosfn_switch_video_interface(AL,ES,DX)3042 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3043 {
3044 #ifdef DEBUG
3045 unimplemented();
3046 #endif
3047 }
biosfn_enable_video_refresh_control(AL)3048 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3049 {
3050 #ifdef DEBUG
3051 unimplemented();
3052 #endif
3053 }
3054
3055 // --------------------------------------------------------------------------------------------
biosfn_write_string(flag,page,attr,count,row,col,seg,offset)3056 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3057 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3058 {
3059 Bit16u newcurs,oldcurs,dummy;
3060 Bit8u car,carattr;
3061
3062 // Read curs info for the page
3063 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3064
3065 // if row=0xff special case : use current cursor position
3066 if(row==0xff)
3067 {col=oldcurs&0x00ff;
3068 row=(oldcurs&0xff00)>>8;
3069 }
3070
3071 newcurs=row; newcurs<<=8; newcurs+=col;
3072 biosfn_set_cursor_pos(page,newcurs);
3073
3074 while(count--!=0)
3075 {
3076 car=read_byte(seg,offset++);
3077 if((flag&0x02)!=0)
3078 attr=read_byte(seg,offset++);
3079
3080 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3081 }
3082
3083 // Set back curs pos
3084 if((flag&0x01)==0)
3085 biosfn_set_cursor_pos(page,oldcurs);
3086 }
3087
3088 // --------------------------------------------------------------------------------------------
3089 ASM_START
3090 biosfn_group_1A:
3091 cmp al, #0x00
3092 je biosfn_read_display_code
3093 cmp al, #0x01
3094 je biosfn_set_display_code
3095 #ifdef DEBUG
3096 call _unknown
3097 #endif
3098 ret
3099 biosfn_read_display_code:
3100 push ds
3101 push ax
3102 mov ax, # BIOSMEM_SEG
3103 mov ds, ax
3104 mov bx, # BIOSMEM_DCC_INDEX
3105 mov al, [bx]
3106 mov bl, al
3107 xor bh, bh
3108 pop ax
3109 mov al, ah
3110 pop ds
3111 ret
3112 biosfn_set_display_code:
3113 push ds
3114 push ax
3115 push bx
3116 mov ax, # BIOSMEM_SEG
3117 mov ds, ax
3118 mov ax, bx
3119 mov bx, # BIOSMEM_DCC_INDEX
3120 mov [bx], al
3121 #ifdef DEBUG
3122 mov al, ah
3123 xor ah, ah
3124 push ax
3125 mov bx, #msg_alt_dcc
3126 push bx
3127 call _printf
3128 add sp, #4
3129 #endif
3130 pop bx
3131 pop ax
3132 mov al, ah
3133 pop ds
3134 ret
3135
3136 #ifdef DEBUG
3137 msg_alt_dcc:
3138 .ascii "Alternate Display code (%02x) was discarded"
3139 .byte 0x0d,0x0a,0x00
3140 #endif
3141 ASM_END
3142
3143 // --------------------------------------------------------------------------------------------
biosfn_read_state_info(BX,ES,DI)3144 static void biosfn_read_state_info (BX,ES,DI)
3145 Bit16u BX;Bit16u ES;Bit16u DI;
3146 {
3147 // Address of static functionality table
3148 write_word(ES,DI+0x00,&static_functionality);
3149 write_word(ES,DI+0x02,0xC000);
3150
3151 // Hard coded copy from BIOS area. Should it be cleaner ?
3152 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3153 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3154
3155 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3156 write_byte(ES,DI+0x26,0);
3157 write_byte(ES,DI+0x27,16);
3158 write_byte(ES,DI+0x28,0);
3159 write_byte(ES,DI+0x29,8);
3160 write_byte(ES,DI+0x2a,2);
3161 write_byte(ES,DI+0x2b,0);
3162 write_byte(ES,DI+0x2c,0);
3163 write_byte(ES,DI+0x31,3);
3164 write_byte(ES,DI+0x32,0);
3165
3166 memsetb(ES,DI+0x33,0,13);
3167 }
3168
3169 // --------------------------------------------------------------------------------------------
3170 // --------------------------------------------------------------------------------------------
biosfn_read_video_state_size2(CX)3171 static Bit16u biosfn_read_video_state_size2 (CX)
3172 Bit16u CX;
3173 {
3174 Bit16u size;
3175 size = 0;
3176 if (CX & 1) {
3177 size += 0x46;
3178 }
3179 if (CX & 2) {
3180 size += (5 + 8 + 5) * 2 + 6;
3181 }
3182 if (CX & 4) {
3183 size += 3 + 256 * 3 + 1;
3184 }
3185 return size;
3186 }
3187
biosfn_read_video_state_size(CX,BX)3188 static void biosfn_read_video_state_size (CX, BX)
3189 Bit16u CX; Bit16u *BX;
3190 {
3191 Bit16u ss=get_SS();
3192 write_word(ss, BX, biosfn_read_video_state_size2(CX));
3193 }
3194
biosfn_save_video_state(CX,ES,BX)3195 static Bit16u biosfn_save_video_state (CX,ES,BX)
3196 Bit16u CX;Bit16u ES;Bit16u BX;
3197 {
3198 Bit16u i, v, crtc_addr, ar_index;
3199
3200 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3201 if (CX & 1) {
3202 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3203 write_byte(ES, BX, inb(crtc_addr)); BX++;
3204 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3205 inb(VGAREG_ACTL_RESET);
3206 ar_index = inb(VGAREG_ACTL_ADDRESS);
3207 write_byte(ES, BX, ar_index); BX++;
3208 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3209
3210 for(i=1;i<=4;i++){
3211 outb(VGAREG_SEQU_ADDRESS, i);
3212 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3213 }
3214 outb(VGAREG_SEQU_ADDRESS, 0);
3215 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3216
3217 for(i=0;i<=0x18;i++) {
3218 outb(crtc_addr,i);
3219 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3220 }
3221
3222 for(i=0;i<=0x13;i++) {
3223 inb(VGAREG_ACTL_RESET);
3224 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3225 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3226 }
3227 inb(VGAREG_ACTL_RESET);
3228
3229 for(i=0;i<=8;i++) {
3230 outb(VGAREG_GRDC_ADDRESS,i);
3231 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3232 }
3233
3234 write_word(ES, BX, crtc_addr); BX+= 2;
3235
3236 /* XXX: read plane latches */
3237 write_byte(ES, BX, 0); BX++;
3238 write_byte(ES, BX, 0); BX++;
3239 write_byte(ES, BX, 0); BX++;
3240 write_byte(ES, BX, 0); BX++;
3241 }
3242 if (CX & 2) {
3243 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3244 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3245 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3246 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3247 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3248 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3249 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3250 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3251 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3252 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3253 for(i=0;i<8;i++) {
3254 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3255 BX += 2;
3256 }
3257 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3258 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3259 /* current font */
3260 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3261 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3262 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3263 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3264 }
3265 if (CX & 4) {
3266 /* XXX: check this */
3267 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3268 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3269 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3270 // Set the whole dac always, from 0
3271 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3272 for(i=0;i<256*3;i++) {
3273 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3274 }
3275 write_byte(ES, BX, 0); BX++; /* color select register */
3276 }
3277 return BX;
3278 }
3279
biosfn_restore_video_state(CX,ES,BX)3280 static Bit16u biosfn_restore_video_state (CX,ES,BX)
3281 Bit16u CX;Bit16u ES;Bit16u BX;
3282 {
3283 Bit16u i, crtc_addr, v, addr1, ar_index;
3284
3285 if (CX & 1) {
3286 // Reset Attribute Ctl flip-flop
3287 inb(VGAREG_ACTL_RESET);
3288
3289 crtc_addr = read_word(ES, BX + 0x40);
3290 addr1 = BX;
3291 BX += 5;
3292
3293 for(i=1;i<=4;i++){
3294 outb(VGAREG_SEQU_ADDRESS, i);
3295 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3296 }
3297 outb(VGAREG_SEQU_ADDRESS, 0);
3298 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3299
3300 // Disable CRTC write protection
3301 outw(crtc_addr,0x0011);
3302 // Set CRTC regs
3303 for(i=0;i<=0x18;i++) {
3304 if (i != 0x11) {
3305 outb(crtc_addr,i);
3306 outb(crtc_addr+1, read_byte(ES, BX));
3307 }
3308 BX++;
3309 }
3310 // select crtc base address
3311 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3312 if (crtc_addr = 0x3d4)
3313 v |= 0x01;
3314 outb(VGAREG_WRITE_MISC_OUTPUT, v);
3315
3316 // enable write protection if needed
3317 outb(crtc_addr, 0x11);
3318 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3319
3320 // Set Attribute Ctl
3321 ar_index = read_byte(ES, addr1 + 0x03);
3322 inb(VGAREG_ACTL_RESET);
3323 for(i=0;i<=0x13;i++) {
3324 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3325 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3326 }
3327 outb(VGAREG_ACTL_ADDRESS, ar_index);
3328 inb(VGAREG_ACTL_RESET);
3329
3330 for(i=0;i<=8;i++) {
3331 outb(VGAREG_GRDC_ADDRESS,i);
3332 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3333 }
3334 BX += 2; /* crtc_addr */
3335 BX += 4; /* plane latches */
3336
3337 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3338 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3339 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3340 addr1++;
3341 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3342 }
3343 if (CX & 2) {
3344 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3345 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3346 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3347 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3348 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3349 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3350 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3351 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3352 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3353 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3354 for(i=0;i<8;i++) {
3355 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3356 BX += 2;
3357 }
3358 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3359 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3360 /* current font */
3361 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3362 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3363 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3364 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3365 }
3366 if (CX & 4) {
3367 BX++;
3368 v = read_byte(ES, BX); BX++;
3369 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3370 // Set the whole dac always, from 0
3371 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3372 for(i=0;i<256*3;i++) {
3373 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3374 }
3375 BX++;
3376 outb(VGAREG_DAC_WRITE_ADDRESS, v);
3377 }
3378 return BX;
3379 }
3380
3381 // ============================================================================================
3382 //
3383 // Video Utils
3384 //
3385 // ============================================================================================
3386
3387 // --------------------------------------------------------------------------------------------
find_vga_entry(mode)3388 static Bit8u find_vga_entry(mode)
3389 Bit8u mode;
3390 {
3391 Bit8u i,line=0xFF;
3392 for(i=0;i<=MODE_MAX;i++)
3393 if(vga_modes[i].svgamode==mode)
3394 {line=i;
3395 break;
3396 }
3397 return line;
3398 }
3399
3400 /* =========================================================== */
3401 /*
3402 * Misc Utils
3403 */
3404 /* =========================================================== */
3405
3406 // --------------------------------------------------------------------------------------------
memsetb(seg,offset,value,count)3407 static void memsetb(seg,offset,value,count)
3408 Bit16u seg;
3409 Bit16u offset;
3410 Bit16u value;
3411 Bit16u count;
3412 {
3413 ASM_START
3414 push bp
3415 mov bp, sp
3416
3417 push ax
3418 push cx
3419 push es
3420 push di
3421
3422 mov cx, 10[bp] ; count
3423 cmp cx, #0x00
3424 je memsetb_end
3425 mov ax, 4[bp] ; segment
3426 mov es, ax
3427 mov ax, 6[bp] ; offset
3428 mov di, ax
3429 mov al, 8[bp] ; value
3430 cld
3431 rep
3432 stosb
3433
3434 memsetb_end:
3435 pop di
3436 pop es
3437 pop cx
3438 pop ax
3439
3440 pop bp
3441 ASM_END
3442 }
3443
3444 // --------------------------------------------------------------------------------------------
memsetw(seg,offset,value,count)3445 static void memsetw(seg,offset,value,count)
3446 Bit16u seg;
3447 Bit16u offset;
3448 Bit16u value;
3449 Bit16u count;
3450 {
3451 ASM_START
3452 push bp
3453 mov bp, sp
3454
3455 push ax
3456 push cx
3457 push es
3458 push di
3459
3460 mov cx, 10[bp] ; count
3461 cmp cx, #0x00
3462 je memsetw_end
3463 mov ax, 4[bp] ; segment
3464 mov es, ax
3465 mov ax, 6[bp] ; offset
3466 mov di, ax
3467 mov ax, 8[bp] ; value
3468 cld
3469 rep
3470 stosw
3471
3472 memsetw_end:
3473 pop di
3474 pop es
3475 pop cx
3476 pop ax
3477
3478 pop bp
3479 ASM_END
3480 }
3481
3482 // --------------------------------------------------------------------------------------------
memcpyb(dseg,doffset,sseg,soffset,count)3483 static void memcpyb(dseg,doffset,sseg,soffset,count)
3484 Bit16u dseg;
3485 Bit16u doffset;
3486 Bit16u sseg;
3487 Bit16u soffset;
3488 Bit16u count;
3489 {
3490 ASM_START
3491 push bp
3492 mov bp, sp
3493
3494 push ax
3495 push cx
3496 push es
3497 push di
3498 push ds
3499 push si
3500
3501 mov cx, 12[bp] ; count
3502 cmp cx, #0x0000
3503 je memcpyb_end
3504 mov ax, 4[bp] ; dsegment
3505 mov es, ax
3506 mov ax, 6[bp] ; doffset
3507 mov di, ax
3508 mov ax, 8[bp] ; ssegment
3509 mov ds, ax
3510 mov ax, 10[bp] ; soffset
3511 mov si, ax
3512 cld
3513 rep
3514 movsb
3515
3516 memcpyb_end:
3517 pop si
3518 pop ds
3519 pop di
3520 pop es
3521 pop cx
3522 pop ax
3523
3524 pop bp
3525 ASM_END
3526 }
3527
3528 // --------------------------------------------------------------------------------------------
memcpyw(dseg,doffset,sseg,soffset,count)3529 static void memcpyw(dseg,doffset,sseg,soffset,count)
3530 Bit16u dseg;
3531 Bit16u doffset;
3532 Bit16u sseg;
3533 Bit16u soffset;
3534 Bit16u count;
3535 {
3536 ASM_START
3537 push bp
3538 mov bp, sp
3539
3540 push ax
3541 push cx
3542 push es
3543 push di
3544 push ds
3545 push si
3546
3547 mov cx, 12[bp] ; count
3548 cmp cx, #0x0000
3549 je memcpyw_end
3550 mov ax, 4[bp] ; dsegment
3551 mov es, ax
3552 mov ax, 6[bp] ; doffset
3553 mov di, ax
3554 mov ax, 8[bp] ; ssegment
3555 mov ds, ax
3556 mov ax, 10[bp] ; soffset
3557 mov si, ax
3558 cld
3559 rep
3560 movsw
3561
3562 memcpyw_end:
3563 pop si
3564 pop ds
3565 pop di
3566 pop es
3567 pop cx
3568 pop ax
3569
3570 pop bp
3571 ASM_END
3572 }
3573
3574 /* =========================================================== */
3575 /*
3576 * These functions where ripped from Kevin's rombios.c
3577 */
3578 /* =========================================================== */
3579
3580 // --------------------------------------------------------------------------------------------
3581 static Bit8u
read_byte(seg,offset)3582 read_byte(seg, offset)
3583 Bit16u seg;
3584 Bit16u offset;
3585 {
3586 ASM_START
3587 push bp
3588 mov bp, sp
3589
3590 push bx
3591 push ds
3592 mov ax, 4[bp] ; segment
3593 mov ds, ax
3594 mov bx, 6[bp] ; offset
3595 mov al, [bx]
3596 ;; al = return value (byte)
3597 pop ds
3598 pop bx
3599
3600 pop bp
3601 ASM_END
3602 }
3603
3604 // --------------------------------------------------------------------------------------------
3605 static Bit16u
3606 read_word(seg, offset)
3607 Bit16u seg;
3608 Bit16u offset;
3609 {
3610 ASM_START
3611 push bp
3612 mov bp, sp
3613
3614 push bx
3615 push ds
3616 mov ax, 4[bp] ; segment
3617 mov ds, ax
3618 mov bx, 6[bp] ; offset
3619 mov ax, [bx]
3620 ;; ax = return value (word)
3621 pop ds
3622 pop bx
3623
3624 pop bp
3625 ASM_END
3626 }
3627
3628 // --------------------------------------------------------------------------------------------
3629 static void
3630 write_byte(seg, offset, data)
3631 Bit16u seg;
3632 Bit16u offset;
3633 Bit8u data;
3634 {
3635 ASM_START
3636 push bp
3637 mov bp, sp
3638
3639 push ax
3640 push bx
3641 push ds
3642 mov ax, 4[bp] ; segment
3643 mov ds, ax
3644 mov bx, 6[bp] ; offset
3645 mov al, 8[bp] ; data byte
3646 mov [bx], al ; write data byte
3647 pop ds
3648 pop bx
3649 pop ax
3650
3651 pop bp
3652 ASM_END
3653 }
3654
3655 // --------------------------------------------------------------------------------------------
3656 static void
3657 write_word(seg, offset, data)
3658 Bit16u seg;
3659 Bit16u offset;
3660 Bit16u data;
3661 {
3662 ASM_START
3663 push bp
3664 mov bp, sp
3665
3666 push ax
3667 push bx
3668 push ds
3669 mov ax, 4[bp] ; segment
3670 mov ds, ax
3671 mov bx, 6[bp] ; offset
3672 mov ax, 8[bp] ; data word
3673 mov [bx], ax ; write data word
3674 pop ds
3675 pop bx
3676 pop ax
3677
3678 pop bp
3679 ASM_END
3680 }
3681
3682 // --------------------------------------------------------------------------------------------
3683 Bit8u
3684 inb(port)
3685 Bit16u port;
3686 {
3687 ASM_START
3688 push bp
3689 mov bp, sp
3690
3691 push dx
3692 mov dx, 4[bp]
3693 in al, dx
3694 pop dx
3695
3696 pop bp
3697 ASM_END
3698 }
3699
3700 Bit16u
3701 inw(port)
3702 Bit16u port;
3703 {
3704 ASM_START
3705 push bp
3706 mov bp, sp
3707
3708 push dx
3709 mov dx, 4[bp]
3710 in ax, dx
3711 pop dx
3712
3713 pop bp
3714 ASM_END
3715 }
3716
3717 // --------------------------------------------------------------------------------------------
3718 void
3719 outb(port, val)
3720 Bit16u port;
3721 Bit8u val;
3722 {
3723 ASM_START
3724 push bp
3725 mov bp, sp
3726
3727 push ax
3728 push dx
3729 mov dx, 4[bp]
3730 mov al, 6[bp]
3731 out dx, al
3732 pop dx
3733 pop ax
3734
3735 pop bp
3736 ASM_END
3737 }
3738
3739 // --------------------------------------------------------------------------------------------
3740 void
3741 outw(port, val)
3742 Bit16u port;
3743 Bit16u val;
3744 {
3745 ASM_START
3746 push bp
3747 mov bp, sp
3748
3749 push ax
3750 push dx
3751 mov dx, 4[bp]
3752 mov ax, 6[bp]
3753 out dx, ax
3754 pop dx
3755 pop ax
3756
3757 pop bp
3758 ASM_END
3759 }
3760
3761 Bit16u get_SS()
3762 {
3763 ASM_START
3764 mov ax, ss
3765 ASM_END
3766 }
3767
3768 #ifdef DEBUG
3769 void unimplemented()
3770 {
3771 printf("--> Unimplemented\n");
3772 }
3773
3774 void unknown()
3775 {
3776 printf("--> Unknown int10\n");
3777 }
3778 #endif
3779
3780 // --------------------------------------------------------------------------------------------
3781 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3782 void printf(s)
3783 Bit8u *s;
3784 {
3785 Bit8u c, format_char;
3786 Boolean in_format;
3787 unsigned format_width, i;
3788 Bit16u *arg_ptr;
3789 Bit16u arg_seg, arg, digit, nibble, shift_count;
3790
3791 arg_ptr = &s;
3792 arg_seg = get_SS();
3793
3794 in_format = 0;
3795 format_width = 0;
3796
3797 while (c = read_byte(0xc000, s)) {
3798 if ( c == '%' ) {
3799 in_format = 1;
3800 format_width = 0;
3801 }
3802 else if (in_format) {
3803 if ( (c>='0') && (c<='9') ) {
3804 format_width = (format_width * 10) + (c - '0');
3805 }
3806 else if (c == 'x') {
3807 arg_ptr++; // increment to next arg
3808 arg = read_word(arg_seg, arg_ptr);
3809 if (format_width == 0)
3810 format_width = 4;
3811 i = 0;
3812 digit = format_width - 1;
3813 for (i=0; i<format_width; i++) {
3814 nibble = (arg >> (4 * digit)) & 0x000f;
3815 if (nibble <= 9)
3816 outb(0x0500, nibble + '0');
3817 else
3818 outb(0x0500, (nibble - 10) + 'A');
3819 digit--;
3820 }
3821 in_format = 0;
3822 }
3823 //else if (c == 'd') {
3824 // in_format = 0;
3825 // }
3826 }
3827 else {
3828 outb(0x0500, c);
3829 }
3830 s ++;
3831 }
3832 }
3833 #endif
3834
3835 ASM_START
3836 ; get LFB address from PCI
3837 ; in - ax: PCI device vendor
3838 ; out - ax: LFB address (high 16 bit)
3839 ;; NOTE - may be called in protected mode
3840 _pci_get_lfb_addr:
3841 push bx
3842 push cx
3843 push dx
3844 push eax
3845 mov bx, ax
3846 xor cx, cx
3847 mov dl, #0x00
3848 call pci_read_reg
3849 cmp ax, #0xffff
3850 jz pci_get_lfb_addr_5
3851 pci_get_lfb_addr_3:
3852 mov dl, #0x00
3853 call pci_read_reg
3854 cmp ax, bx ;; check vendor
3855 jz pci_get_lfb_addr_4
3856 add cx, #0x8
3857 cmp cx, #0x200 ;; search bus #0 and #1
3858 jb pci_get_lfb_addr_3
3859 pci_get_lfb_addr_5:
3860 xor dx, dx ;; no LFB
3861 jmp pci_get_lfb_addr_6
3862 pci_get_lfb_addr_4:
3863 mov dl, #0x10 ;; I/O space #0
3864 call pci_read_reg
3865 test ax, #0xfff1
3866 jnz pci_get_lfb_addr_5
3867 shr eax, #16
3868 mov dx, ax ;; LFB address
3869 pci_get_lfb_addr_6:
3870 pop eax
3871 mov ax, dx
3872 pop dx
3873 pop cx
3874 pop bx
3875 ret
3876
3877 ; read PCI register
3878 ; in - cx: device/function
3879 ; in - dl: register
3880 ; out - eax: value
3881 pci_read_reg:
3882 mov eax, #0x00800000
3883 mov ax, cx
3884 shl eax, #8
3885 mov al, dl
3886 mov dx, #0xcf8
3887 out dx, eax
3888 add dl, #4
3889 in eax, dx
3890 ret
3891 ASM_END
3892
3893 #ifdef VBE
3894 #include "vbe.c"
3895 #endif
3896
3897 #ifdef CIRRUS
3898 #include "clext.c"
3899 #endif
3900
3901 // --------------------------------------------------------------------------------------------
3902
3903 ASM_START
3904 ;; DATA_SEG_DEFS_HERE
3905 ASM_END
3906
3907 ASM_START
3908 .ascii "vgabios ends here"
3909 .byte 0x00
3910 vgabios_end:
3911 .byte 0xCB
3912 ;; BLOCK_STRINGS_BEGIN
3913 ASM_END
3914