|
|
1.1 root 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: // - [email protected]
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
1.1.1.2 ! root 213: #ifdef PCI_VID
! 214: .word PCI_VID
! 215: .word PCI_DID
! 216: #else
1.1 root 217: #error "Unknown PCI vendor and device id"
218: #endif
1.1.1.2 ! root 219: #endif
1.1 root 220: .word 0 // reserved
221: .word 0x18 // dlen
222: .byte 0 // revision
223: .byte 0x0 // class,hi: vga display
224: .word 0x300 // class,lo: vga display
225: .word 0x40 // bios size
226: .word 1 // revision
227: .byte 0 // intel x86 data
228: .byte 0x80 // last image
229: .word 0 // reserved
230: #endif
231:
232:
233: ;; ============================================================================================
234: ;;
235: ;; Init Entry point
236: ;;
237: ;; ============================================================================================
238: vgabios_init_func:
239:
240: ;; init vga card
241: call init_vga_card
242:
243: ;; init basic bios vars
244: call init_bios_area
245:
246: #ifdef VBE
247: ;; init vbe functions
248: call vbe_init
249: #endif
250:
251: ;; set int10 vect
252: SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
253:
254: #ifdef CIRRUS
255: call cirrus_init
256: #endif
257:
258: ;; display splash screen
259: call _display_splash_screen
260:
261: ;; init video mode and clear the screen
262: mov ax,#0x0003
263: int #0x10
264:
265: ;; show info
266: call _display_info
267:
268: #ifdef VBE
269: ;; show vbe info
270: call vbe_display_info
271: #endif
272:
273: #ifdef CIRRUS
274: ;; show cirrus info
275: call cirrus_display_info
276: #endif
277:
278: retf
279: ASM_END
280:
281: /*
282: * int10 handled here
283: */
284: ASM_START
285: vgabios_int10_handler:
286: pushf
287: #ifdef DEBUG
288: push es
289: push ds
290: pusha
291: mov bx, #0xc000
292: mov ds, bx
293: call _int10_debugmsg
294: popa
295: pop ds
296: pop es
297: #endif
298: cmp ah, #0x0f
299: jne int10_test_1A
300: call biosfn_get_video_mode
301: jmp int10_end
302: int10_test_1A:
303: cmp ah, #0x1a
304: jne int10_test_0B
305: call biosfn_group_1A
306: jmp int10_end
307: int10_test_0B:
308: cmp ah, #0x0b
309: jne int10_test_1103
310: call biosfn_group_0B
311: jmp int10_end
312: int10_test_1103:
313: cmp ax, #0x1103
314: jne int10_test_12
315: call biosfn_set_text_block_specifier
316: jmp int10_end
317: int10_test_12:
318: cmp ah, #0x12
319: jne int10_test_101B
320: cmp bl, #0x10
321: jne int10_test_BL30
322: call biosfn_get_ega_info
323: jmp int10_end
324: int10_test_BL30:
325: cmp bl, #0x30
326: jne int10_test_BL31
327: call biosfn_select_vert_res
328: jmp int10_end
329: int10_test_BL31:
330: cmp bl, #0x31
331: jne int10_test_BL32
332: call biosfn_enable_default_palette_loading
333: jmp int10_end
334: int10_test_BL32:
335: cmp bl, #0x32
336: jne int10_test_BL33
337: call biosfn_enable_video_addressing
338: jmp int10_end
339: int10_test_BL33:
340: cmp bl, #0x33
341: jne int10_test_BL34
342: call biosfn_enable_grayscale_summing
343: jmp int10_end
344: int10_test_BL34:
345: cmp bl, #0x34
346: jne int10_normal
347: call biosfn_enable_cursor_emulation
348: jmp int10_end
349: int10_test_101B:
350: cmp ax, #0x101b
351: je int10_normal
352: cmp ah, #0x10
353: #ifndef VBE
354: jne int10_normal
355: #else
356: jne int10_test_4F
357: #endif
358: call biosfn_group_10
359: jmp int10_end
360: #ifdef VBE
361: int10_test_4F:
362: cmp ah, #0x4f
363: jne int10_normal
364: cmp al, #0x03
365: jne int10_test_vbe_05
366: call vbe_biosfn_return_current_mode
367: jmp int10_end
368: int10_test_vbe_05:
369: cmp al, #0x05
370: jne int10_test_vbe_06
371: call vbe_biosfn_display_window_control
372: jmp int10_end
373: int10_test_vbe_06:
374: cmp al, #0x06
375: jne int10_test_vbe_07
376: call vbe_biosfn_set_get_logical_scan_line_length
377: jmp int10_end
378: int10_test_vbe_07:
379: cmp al, #0x07
380: jne int10_test_vbe_08
381: call vbe_biosfn_set_get_display_start
382: jmp int10_end
383: int10_test_vbe_08:
384: cmp al, #0x08
385: jne int10_test_vbe_0A
386: call vbe_biosfn_set_get_dac_palette_format
387: jmp int10_end
388: int10_test_vbe_0A:
389: cmp al, #0x0A
390: jne int10_normal
391: call vbe_biosfn_return_protected_mode_interface
392: jmp int10_end
393: #endif
394:
395: int10_normal:
396: push es
397: push ds
398: pusha
399:
400: ;; We have to set ds to access the right data segment
401: mov bx, #0xc000
402: mov ds, bx
403: call _int10_func
404:
405: popa
406: pop ds
407: pop es
408: int10_end:
409: popf
410: iret
411: ASM_END
412:
413: #include "vgatables.h"
414: #include "vgafonts.h"
415:
416: /*
417: * Boot time harware inits
418: */
419: ASM_START
420: init_vga_card:
421: ;; switch to color mode and enable CPU access 480 lines
422: mov dx, #0x3C2
423: mov al, #0xC3
424: outb dx,al
425:
426: ;; more than 64k 3C4/04
427: mov dx, #0x3C4
428: mov al, #0x04
429: outb dx,al
430: mov dx, #0x3C5
431: mov al, #0x02
432: outb dx,al
433:
434: #if defined(USE_BX_INFO) || defined(DEBUG)
435: mov bx, #msg_vga_init
436: push bx
437: call _printf
438: #endif
439: inc sp
440: inc sp
441: ret
442:
443: #if defined(USE_BX_INFO) || defined(DEBUG)
444: msg_vga_init:
445: .ascii "VGABios $Id$"
446: .byte 0x0d,0x0a,0x00
447: #endif
448: ASM_END
449:
450: // --------------------------------------------------------------------------------------------
451: /*
452: * Boot time bios area inits
453: */
454: ASM_START
455: init_bios_area:
456: push ds
457: mov ax, # BIOSMEM_SEG
458: mov ds, ax
459:
460: ;; init detected hardware BIOS Area
461: mov bx, # BIOSMEM_INITIAL_MODE
462: mov ax, [bx]
463: and ax, #0xffcf
464: ;; set 80x25 color (not clear from RBIL but usual)
465: or ax, #0x0020
466: mov [bx], ax
467:
468: ;; Just for the first int10 find its children
469:
470: ;; the default char height
471: mov bx, # BIOSMEM_CHAR_HEIGHT
472: mov al, #0x10
473: mov [bx], al
474:
475: ;; Clear the screen
476: mov bx, # BIOSMEM_VIDEO_CTL
477: mov al, #0x60
478: mov [bx], al
479:
480: ;; Set the basic screen we have
481: mov bx, # BIOSMEM_SWITCHES
482: mov al, #0xf9
483: mov [bx], al
484:
485: ;; Set the basic modeset options
486: mov bx, # BIOSMEM_MODESET_CTL
487: mov al, #0x51
488: mov [bx], al
489:
490: ;; Set the default MSR
491: mov bx, # BIOSMEM_CURRENT_MSR
492: mov al, #0x09
493: mov [bx], al
494:
495: pop ds
496: ret
497:
498: _video_save_pointer_table:
499: .word _video_param_table
500: .word 0xc000
501:
502: .word 0 /* XXX: fill it */
503: .word 0
504:
505: .word 0 /* XXX: fill it */
506: .word 0
507:
508: .word 0 /* XXX: fill it */
509: .word 0
510:
511: .word 0 /* XXX: fill it */
512: .word 0
513:
514: .word 0 /* XXX: fill it */
515: .word 0
516:
517: .word 0 /* XXX: fill it */
518: .word 0
519:
520: ASM_END
521:
522: // --------------------------------------------------------------------------------------------
523: /*
524: * Boot time Splash screen
525: */
526: static void display_splash_screen()
527: {
528: }
529:
530: // --------------------------------------------------------------------------------------------
531: /*
532: * Tell who we are
533: */
534:
535: static void display_info()
536: {
537: ASM_START
538: mov ax,#0xc000
539: mov ds,ax
540: mov si,#vgabios_name
541: call _display_string
542: mov si,#vgabios_version
543: call _display_string
544:
545: ;;mov si,#vgabios_copyright
546: ;;call _display_string
547: ;;mov si,#crlf
548: ;;call _display_string
549:
550: mov si,#vgabios_license
551: call _display_string
552: mov si,#vgabios_website
553: call _display_string
554: ASM_END
555: }
556:
557: static void display_string()
558: {
559: // Get length of string
560: ASM_START
561: mov ax,ds
562: mov es,ax
563: mov di,si
564: xor cx,cx
565: not cx
566: xor al,al
567: cld
568: repne
569: scasb
570: not cx
571: dec cx
572: push cx
573:
574: mov ax,#0x0300
575: mov bx,#0x0000
576: int #0x10
577:
578: pop cx
579: mov ax,#0x1301
580: mov bx,#0x000b
581: mov bp,si
582: int #0x10
583: ASM_END
584: }
585:
586: // --------------------------------------------------------------------------------------------
587: #ifdef DEBUG
588: static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
589: Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
590: {
591: // 0E is write char...
592: if(GET_AH()!=0x0E)
593: printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
594: }
595: #endif
596:
597: // --------------------------------------------------------------------------------------------
598: /*
599: * int10 main dispatcher
600: */
601: static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
602: Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
603: {
604:
605: // BIOS functions
606: switch(GET_AH())
607: {
608: case 0x00:
609: biosfn_set_video_mode(GET_AL());
610: switch(GET_AL()&0x7F)
611: {case 6:
612: SET_AL(0x3F);
613: break;
614: case 0:
615: case 1:
616: case 2:
617: case 3:
618: case 4:
619: case 5:
620: case 7:
621: SET_AL(0x30);
622: break;
623: default:
624: SET_AL(0x20);
625: }
626: break;
627: case 0x01:
628: biosfn_set_cursor_shape(GET_CH(),GET_CL());
629: break;
630: case 0x02:
631: biosfn_set_cursor_pos(GET_BH(),DX);
632: break;
633: case 0x03:
634: biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
635: break;
636: case 0x04:
637: // Read light pen pos (unimplemented)
638: #ifdef DEBUG
639: unimplemented();
640: #endif
641: AX=0x00;
642: BX=0x00;
643: CX=0x00;
644: DX=0x00;
645: break;
646: case 0x05:
647: biosfn_set_active_page(GET_AL());
648: break;
649: case 0x06:
650: biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
651: break;
652: case 0x07:
653: biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
654: break;
655: case 0x08:
656: biosfn_read_char_attr(GET_BH(),&AX);
657: break;
658: case 0x09:
659: biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
660: break;
661: case 0x0A:
662: biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
663: break;
664: case 0x0C:
665: biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
666: break;
667: case 0x0D:
668: biosfn_read_pixel(GET_BH(),CX,DX,&AX);
669: break;
670: case 0x0E:
671: // Ralf Brown Interrupt list is WRONG on bh(page)
672: // We do output only on the current page !
673: biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
674: break;
675: case 0x10:
676: // All other functions of group AH=0x10 rewritten in assembler
677: biosfn_perform_gray_scale_summing(BX,CX);
678: break;
679: case 0x11:
680: switch(GET_AL())
681: {
682: case 0x00:
683: case 0x10:
684: biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
685: break;
686: case 0x01:
687: case 0x11:
688: biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
689: break;
690: case 0x02:
691: case 0x12:
692: biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
693: break;
694: case 0x04:
695: case 0x14:
696: biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
697: break;
698: case 0x20:
699: biosfn_load_gfx_8_8_chars(ES,BP);
700: break;
701: case 0x21:
702: biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
703: break;
704: case 0x22:
705: biosfn_load_gfx_8_14_chars(GET_BL());
706: break;
707: case 0x23:
708: biosfn_load_gfx_8_8_dd_chars(GET_BL());
709: break;
710: case 0x24:
711: biosfn_load_gfx_8_16_chars(GET_BL());
712: break;
713: case 0x30:
714: biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
715: break;
716: #ifdef DEBUG
717: default:
718: unknown();
719: #endif
720: }
721:
722: break;
723: case 0x12:
724: switch(GET_BL())
725: {
726: case 0x20:
727: biosfn_alternate_prtsc();
728: break;
729: case 0x35:
730: biosfn_switch_video_interface(GET_AL(),ES,DX);
731: SET_AL(0x12);
732: break;
733: case 0x36:
734: biosfn_enable_video_refresh_control(GET_AL());
735: SET_AL(0x12);
736: break;
737: #ifdef DEBUG
738: default:
739: unknown();
740: #endif
741: }
742: break;
743: case 0x13:
744: biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
745: break;
746: case 0x1B:
747: biosfn_read_state_info(BX,ES,DI);
748: SET_AL(0x1B);
749: break;
750: case 0x1C:
751: switch(GET_AL())
752: {
753: case 0x00:
754: biosfn_read_video_state_size(CX,&BX);
755: break;
756: case 0x01:
757: biosfn_save_video_state(CX,ES,BX);
758: break;
759: case 0x02:
760: biosfn_restore_video_state(CX,ES,BX);
761: break;
762: #ifdef DEBUG
763: default:
764: unknown();
765: #endif
766: }
767: SET_AL(0x1C);
768: break;
769:
770: #ifdef VBE
771: case 0x4f:
772: if (vbe_has_vbe_display()) {
773: switch(GET_AL())
774: {
775: case 0x00:
776: vbe_biosfn_return_controller_information(&AX,ES,DI);
777: break;
778: case 0x01:
779: vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
780: break;
781: case 0x02:
782: vbe_biosfn_set_mode(&AX,BX,ES,DI);
783: break;
784: case 0x04:
785: vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
786: break;
787: case 0x09:
788: //FIXME
789: #ifdef DEBUG
790: unimplemented();
791: #endif
792: // function failed
793: AX=0x100;
794: break;
795: case 0x0A:
796: //FIXME
797: #ifdef DEBUG
798: unimplemented();
799: #endif
800: // function failed
801: AX=0x100;
802: break;
803: default:
804: #ifdef DEBUG
805: unknown();
806: #endif
807: // function failed
808: AX=0x100;
809: }
810: }
811: else {
812: // No VBE display
813: AX=0x0100;
814: }
815: break;
816: #endif
817:
818: #ifdef DEBUG
819: default:
820: unknown();
821: #endif
822: }
823: }
824:
825: // ============================================================================================
826: //
827: // BIOS functions
828: //
829: // ============================================================================================
830:
831: static void biosfn_set_video_mode(mode) Bit8u mode;
832: {// mode: Bit 7 is 1 if no clear screen
833:
834: // Should we clear the screen ?
835: Bit8u noclearmem=mode&0x80;
836: Bit8u line,mmask,*palette,vpti;
837: Bit16u i,twidth,theightm1,cheight;
838: Bit8u modeset_ctl,video_ctl,vga_switches;
839: Bit16u crtc_addr;
840:
841: #ifdef VBE
842: if (vbe_has_vbe_display()) {
843: dispi_set_enable(VBE_DISPI_DISABLED);
844: }
845: #endif // def VBE
846:
847: // The real mode
848: mode=mode&0x7f;
849:
850: // find the entry in the video modes
851: line=find_vga_entry(mode);
852:
853: #ifdef DEBUG
854: printf("mode search %02x found line %02x\n",mode,line);
855: #endif
856:
857: if(line==0xFF)
858: return;
859:
860: vpti=line_to_vpti[line];
861: twidth=video_param_table[vpti].twidth;
862: theightm1=video_param_table[vpti].theightm1;
863: cheight=video_param_table[vpti].cheight;
864:
865: // Read the bios vga control
866: video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
867:
868: // Read the bios vga switches
869: vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
870:
871: // Read the bios mode set control
872: modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
873:
874: // Then we know the number of lines
875: // FIXME
876:
877: // if palette loading (bit 3 of modeset ctl = 0)
878: if((modeset_ctl&0x08)==0)
879: {// Set the PEL mask
880: outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
881:
882: // Set the whole dac always, from 0
883: outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
884:
885: // From which palette
886: switch(vga_modes[line].dacmodel)
887: {case 0:
888: palette=&palette0;
889: break;
890: case 1:
891: palette=&palette1;
892: break;
893: case 2:
894: palette=&palette2;
895: break;
896: case 3:
897: palette=&palette3;
898: break;
899: }
900: // Always 256*3 values
901: for(i=0;i<0x0100;i++)
902: {if(i<=dac_regs[vga_modes[line].dacmodel])
903: {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
904: outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
905: outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
906: }
907: else
908: {outb(VGAREG_DAC_DATA,0);
909: outb(VGAREG_DAC_DATA,0);
910: outb(VGAREG_DAC_DATA,0);
911: }
912: }
913: if((modeset_ctl&0x02)==0x02)
914: {
915: biosfn_perform_gray_scale_summing(0x00, 0x100);
916: }
917: }
918:
919: // Reset Attribute Ctl flip-flop
920: inb(VGAREG_ACTL_RESET);
921:
922: // Set Attribute Ctl
923: for(i=0;i<=0x13;i++)
924: {outb(VGAREG_ACTL_ADDRESS,i);
925: outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
926: }
927: outb(VGAREG_ACTL_ADDRESS,0x14);
928: outb(VGAREG_ACTL_WRITE_DATA,0x00);
929:
930: // Set Sequencer Ctl
931: outb(VGAREG_SEQU_ADDRESS,0);
932: outb(VGAREG_SEQU_DATA,0x03);
933: for(i=1;i<=4;i++)
934: {outb(VGAREG_SEQU_ADDRESS,i);
935: outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
936: }
937:
938: // Set Grafx Ctl
939: for(i=0;i<=8;i++)
940: {outb(VGAREG_GRDC_ADDRESS,i);
941: outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
942: }
943:
944: // Set CRTC address VGA or MDA
945: crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
946:
947: // Disable CRTC write protection
948: outw(crtc_addr,0x0011);
949: // Set CRTC regs
950: for(i=0;i<=0x18;i++)
951: {outb(crtc_addr,i);
952: outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
953: }
954:
955: // Set the misc register
956: outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
957:
958: // Enable video
959: outb(VGAREG_ACTL_ADDRESS,0x20);
960: inb(VGAREG_ACTL_RESET);
961:
962: if(noclearmem==0x00)
963: {
964: if(vga_modes[line].class==TEXT)
965: {
966: memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
967: }
968: else
969: {
970: if(mode<0x0d)
971: {
972: memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
973: }
974: else
975: {
976: outb( VGAREG_SEQU_ADDRESS, 0x02 );
977: mmask = inb( VGAREG_SEQU_DATA );
978: outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
979: memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
980: outb( VGAREG_SEQU_DATA, mmask );
981: }
982: }
983: }
984:
985: // Set the BIOS mem
986: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
987: write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
988: write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l);
989: write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
990: write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
991: write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
992: write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
993: write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
994: write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
995:
996: // FIXME We nearly have the good tables. to be reworked
997: write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
998: write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table);
999: write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000);
1000:
1001: // FIXME
1002: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
1003: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
1004:
1005: // Set cursor shape
1006: if(vga_modes[line].class==TEXT)
1007: {
1008: biosfn_set_cursor_shape(0x06,0x07);
1009: }
1010:
1011: // Set cursor pos for page 0..7
1012: for(i=0;i<8;i++)
1013: biosfn_set_cursor_pos(i,0x0000);
1014:
1015: // Set active page 0
1016: biosfn_set_active_page(0x00);
1017:
1018: // Write the fonts in memory
1019: if(vga_modes[line].class==TEXT)
1020: {
1021: ASM_START
1022: ;; copy and activate 8x16 font
1023: mov ax, #0x1104
1024: mov bl, #0x00
1025: int #0x10
1026: mov ax, #0x1103
1027: mov bl, #0x00
1028: int #0x10
1029: ASM_END
1030: }
1031:
1032: // Set the ints 0x1F and 0x43
1033: ASM_START
1034: SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1035: ASM_END
1036:
1037: switch(cheight)
1038: {case 8:
1039: ASM_START
1040: SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1041: ASM_END
1042: break;
1043: case 14:
1044: ASM_START
1045: SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1046: ASM_END
1047: break;
1048: case 16:
1049: ASM_START
1050: SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1051: ASM_END
1052: break;
1053: }
1054: }
1055:
1056: // --------------------------------------------------------------------------------------------
1057: static void biosfn_set_cursor_shape (CH,CL)
1058: Bit8u CH;Bit8u CL;
1059: {Bit16u cheight,curs,crtc_addr;
1060: Bit8u modeset_ctl;
1061:
1062: CH&=0x3f;
1063: CL&=0x1f;
1064:
1065: curs=(CH<<8)+CL;
1066: write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1067:
1068: modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1069: cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1070: if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1071: {
1072: if(CL!=(CH+1))
1073: {
1074: CH = ((CH+1) * cheight / 8) -1;
1075: }
1076: else
1077: {
1078: CH = ((CL+1) * cheight / 8) - 2;
1079: }
1080: CL = ((CL+1) * cheight / 8) - 1;
1081: }
1082:
1083: // CTRC regs 0x0a and 0x0b
1084: crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1085: outb(crtc_addr,0x0a);
1086: outb(crtc_addr+1,CH);
1087: outb(crtc_addr,0x0b);
1088: outb(crtc_addr+1,CL);
1089: }
1090:
1091: // --------------------------------------------------------------------------------------------
1092: static void biosfn_set_cursor_pos (page, cursor)
1093: Bit8u page;Bit16u cursor;
1094: {
1095: Bit8u xcurs,ycurs,current;
1096: Bit16u nbcols,nbrows,address,crtc_addr;
1097:
1098: // Should not happen...
1099: if(page>7)return;
1100:
1101: // Bios cursor pos
1102: write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1103:
1104: // Set the hardware cursor
1105: current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1106: if(page==current)
1107: {
1108: // Get the dimensions
1109: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1110: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1111:
1112: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1113:
1114: // Calculate the address knowing nbcols nbrows and page num
1115: address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1116:
1117: // CRTC regs 0x0e and 0x0f
1118: crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1119: outb(crtc_addr,0x0e);
1120: outb(crtc_addr+1,(address&0xff00)>>8);
1121: outb(crtc_addr,0x0f);
1122: outb(crtc_addr+1,address&0x00ff);
1123: }
1124: }
1125:
1126: // --------------------------------------------------------------------------------------------
1127: static void biosfn_get_cursor_pos (page,shape, pos)
1128: Bit8u page;Bit16u *shape;Bit16u *pos;
1129: {
1130: Bit16u ss=get_SS();
1131:
1132: // Default
1133: write_word(ss, shape, 0);
1134: write_word(ss, pos, 0);
1135:
1136: if(page>7)return;
1137: // FIXME should handle VGA 14/16 lines
1138: write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1139: write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1140: }
1141:
1142: // --------------------------------------------------------------------------------------------
1143: static void biosfn_set_active_page (page)
1144: Bit8u page;
1145: {
1146: Bit16u cursor,dummy,crtc_addr;
1147: Bit16u nbcols,nbrows,address;
1148: Bit8u mode,line;
1149:
1150: if(page>7)return;
1151:
1152: // Get the mode
1153: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1154: line=find_vga_entry(mode);
1155: if(line==0xFF)return;
1156:
1157: // Get pos curs pos for the right page
1158: biosfn_get_cursor_pos(page,&dummy,&cursor);
1159:
1160: if(vga_modes[line].class==TEXT)
1161: {
1162: // Get the dimensions
1163: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1164: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1165:
1166: // Calculate the address knowing nbcols nbrows and page num
1167: address=SCREEN_MEM_START(nbcols,nbrows,page);
1168: write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1169:
1170: // Start address
1171: address=SCREEN_IO_START(nbcols,nbrows,page);
1172: }
1173: else
1174: {
1175: address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l);
1176: }
1177:
1178: // CRTC regs 0x0c and 0x0d
1179: crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1180: outb(crtc_addr,0x0c);
1181: outb(crtc_addr+1,(address&0xff00)>>8);
1182: outb(crtc_addr,0x0d);
1183: outb(crtc_addr+1,address&0x00ff);
1184:
1185: // And change the BIOS page
1186: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1187:
1188: #ifdef DEBUG
1189: printf("Set active page %02x address %04x\n",page,address);
1190: #endif
1191:
1192: // Display the cursor, now the page is active
1193: biosfn_set_cursor_pos(page,cursor);
1194: }
1195:
1196: // --------------------------------------------------------------------------------------------
1197: static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1198: Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1199: {
1200: Bit16u src,dest;
1201: Bit8u i;
1202:
1203: src=ysrc*cheight*nbcols+xstart;
1204: dest=ydest*cheight*nbcols+xstart;
1205: outw(VGAREG_GRDC_ADDRESS, 0x0105);
1206: for(i=0;i<cheight;i++)
1207: {
1208: memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1209: }
1210: outw(VGAREG_GRDC_ADDRESS, 0x0005);
1211: }
1212:
1213: // --------------------------------------------------------------------------------------------
1214: static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1215: Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1216: {
1217: Bit16u dest;
1218: Bit8u i;
1219:
1220: dest=ystart*cheight*nbcols+xstart;
1221: outw(VGAREG_GRDC_ADDRESS, 0x0205);
1222: for(i=0;i<cheight;i++)
1223: {
1224: memsetb(0xa000,dest+i*nbcols,attr,cols);
1225: }
1226: outw(VGAREG_GRDC_ADDRESS, 0x0005);
1227: }
1228:
1229: // --------------------------------------------------------------------------------------------
1230: static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1231: Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1232: {
1233: Bit16u src,dest;
1234: Bit8u i;
1235:
1236: src=((ysrc*cheight*nbcols)>>1)+xstart;
1237: dest=((ydest*cheight*nbcols)>>1)+xstart;
1238: for(i=0;i<cheight;i++)
1239: {
1240: if (i & 1)
1241: memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1242: else
1243: memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1244: }
1245: }
1246:
1247: // --------------------------------------------------------------------------------------------
1248: static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1249: Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1250: {
1251: Bit16u dest;
1252: Bit8u i;
1253:
1254: dest=((ystart*cheight*nbcols)>>1)+xstart;
1255: for(i=0;i<cheight;i++)
1256: {
1257: if (i & 1)
1258: memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1259: else
1260: memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1261: }
1262: }
1263:
1264: // --------------------------------------------------------------------------------------------
1265: static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1266: Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1267: {
1268: // page == 0xFF if current
1269:
1270: Bit8u mode,line,cheight,bpp,cols;
1271: Bit16u nbcols,nbrows,i;
1272: Bit16u address;
1273:
1274: if(rul>rlr)return;
1275: if(cul>clr)return;
1276:
1277: // Get the mode
1278: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1279: line=find_vga_entry(mode);
1280: if(line==0xFF)return;
1281:
1282: // Get the dimensions
1283: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1284: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1285:
1286: // Get the current page
1287: if(page==0xFF)
1288: page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1289:
1290: if(rlr>=nbrows)rlr=nbrows-1;
1291: if(clr>=nbcols)clr=nbcols-1;
1292: if(nblines>nbrows)nblines=0;
1293: cols=clr-cul+1;
1294:
1295: if(vga_modes[line].class==TEXT)
1296: {
1297: // Compute the address
1298: address=SCREEN_MEM_START(nbcols,nbrows,page);
1299: #ifdef DEBUG
1300: printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1301: #endif
1302:
1303: if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1304: {
1305: memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1306: }
1307: else
1308: {// if Scroll up
1309: if(dir==SCROLL_UP)
1310: {for(i=rul;i<=rlr;i++)
1311: {
1312: if((i+nblines>rlr)||(nblines==0))
1313: memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1314: else
1315: memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1316: }
1317: }
1318: else
1319: {for(i=rlr;i>=rul;i--)
1320: {
1321: if((i<rul+nblines)||(nblines==0))
1322: memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1323: else
1324: memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1325: if (i>rlr) break;
1326: }
1327: }
1328: }
1329: }
1330: else
1331: {
1332: // FIXME gfx mode not complete
1333: cheight=video_param_table[line_to_vpti[line]].cheight;
1334: switch(vga_modes[line].memmodel)
1335: {
1336: case PLANAR4:
1337: case PLANAR1:
1338: if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1339: {
1340: outw(VGAREG_GRDC_ADDRESS, 0x0205);
1341: memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1342: outw(VGAREG_GRDC_ADDRESS, 0x0005);
1343: }
1344: else
1345: {// if Scroll up
1346: if(dir==SCROLL_UP)
1347: {for(i=rul;i<=rlr;i++)
1348: {
1349: if((i+nblines>rlr)||(nblines==0))
1350: vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1351: else
1352: vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1353: }
1354: }
1355: else
1356: {for(i=rlr;i>=rul;i--)
1357: {
1358: if((i<rul+nblines)||(nblines==0))
1359: vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1360: else
1361: vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1362: if (i>rlr) break;
1363: }
1364: }
1365: }
1366: break;
1367: case CGA:
1368: bpp=vga_modes[line].pixbits;
1369: if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1370: {
1371: memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1372: }
1373: else
1374: {
1375: if(bpp==2)
1376: {
1377: cul<<=1;
1378: cols<<=1;
1379: nbcols<<=1;
1380: }
1381: // if Scroll up
1382: if(dir==SCROLL_UP)
1383: {for(i=rul;i<=rlr;i++)
1384: {
1385: if((i+nblines>rlr)||(nblines==0))
1386: vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1387: else
1388: vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1389: }
1390: }
1391: else
1392: {for(i=rlr;i>=rul;i--)
1393: {
1394: if((i<rul+nblines)||(nblines==0))
1395: vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1396: else
1397: vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1398: if (i>rlr) break;
1399: }
1400: }
1401: }
1402: break;
1403: #ifdef DEBUG
1404: default:
1405: printf("Scroll in graphics mode ");
1406: unimplemented();
1407: #endif
1408: }
1409: }
1410: }
1411:
1412: // --------------------------------------------------------------------------------------------
1413: static void biosfn_read_char_attr (page,car)
1414: Bit8u page;Bit16u *car;
1415: {Bit16u ss=get_SS();
1416: Bit8u xcurs,ycurs,mode,line;
1417: Bit16u nbcols,nbrows,address;
1418: Bit16u cursor,dummy;
1419:
1420: // Get the mode
1421: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1422: line=find_vga_entry(mode);
1423: if(line==0xFF)return;
1424:
1425: // Get the cursor pos for the page
1426: biosfn_get_cursor_pos(page,&dummy,&cursor);
1427: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1428:
1429: // Get the dimensions
1430: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1431: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1432:
1433: if(vga_modes[line].class==TEXT)
1434: {
1435: // Compute the address
1436: address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1437:
1438: write_word(ss,car,read_word(vga_modes[line].sstart,address));
1439: }
1440: else
1441: {
1442: // FIXME gfx mode
1443: #ifdef DEBUG
1444: unimplemented();
1445: #endif
1446: }
1447: }
1448:
1449: // --------------------------------------------------------------------------------------------
1450: static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1451: Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1452: {
1453: Bit8u i,j,mask;
1454: Bit8u *fdata;
1455: Bit16u addr,dest,src;
1456:
1457: switch(cheight)
1458: {case 14:
1459: fdata = &vgafont14;
1460: break;
1461: case 16:
1462: fdata = &vgafont16;
1463: break;
1464: default:
1465: fdata = &vgafont8;
1466: }
1467: addr=xcurs+ycurs*cheight*nbcols;
1468: src = car * cheight;
1469: outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1470: outw(VGAREG_GRDC_ADDRESS, 0x0205);
1471: if(attr&0x80)
1472: {
1473: outw(VGAREG_GRDC_ADDRESS, 0x1803);
1474: }
1475: else
1476: {
1477: outw(VGAREG_GRDC_ADDRESS, 0x0003);
1478: }
1479: for(i=0;i<cheight;i++)
1480: {
1481: dest=addr+i*nbcols;
1482: for(j=0;j<8;j++)
1483: {
1484: mask=0x80>>j;
1485: outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1486: read_byte(0xa000,dest);
1487: if(fdata[src+i]&mask)
1488: {
1489: write_byte(0xa000,dest,attr&0x0f);
1490: }
1491: else
1492: {
1493: write_byte(0xa000,dest,0x00);
1494: }
1495: }
1496: }
1497: ASM_START
1498: mov dx, # VGAREG_GRDC_ADDRESS
1499: mov ax, #0xff08
1500: out dx, ax
1501: mov ax, #0x0005
1502: out dx, ax
1503: mov ax, #0x0003
1504: out dx, ax
1505: ASM_END
1506: }
1507:
1508: // --------------------------------------------------------------------------------------------
1509: static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1510: Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1511: {
1512: Bit8u i,j,mask,data;
1513: Bit8u *fdata;
1514: Bit16u addr,dest,src;
1515:
1516: fdata = &vgafont8;
1517: addr=(xcurs*bpp)+ycurs*320;
1518: src = car * 8;
1519: for(i=0;i<8;i++)
1520: {
1521: dest=addr+(i>>1)*80;
1522: if (i & 1) dest += 0x2000;
1523: mask = 0x80;
1524: if (bpp == 1)
1525: {
1526: if (attr & 0x80)
1527: {
1528: data = read_byte(0xb800,dest);
1529: }
1530: else
1531: {
1532: data = 0x00;
1533: }
1534: for(j=0;j<8;j++)
1535: {
1536: if (fdata[src+i] & mask)
1537: {
1538: if (attr & 0x80)
1539: {
1540: data ^= (attr & 0x01) << (7-j);
1541: }
1542: else
1543: {
1544: data |= (attr & 0x01) << (7-j);
1545: }
1546: }
1547: mask >>= 1;
1548: }
1549: write_byte(0xb800,dest,data);
1550: }
1551: else
1552: {
1553: while (mask > 0)
1554: {
1555: if (attr & 0x80)
1556: {
1557: data = read_byte(0xb800,dest);
1558: }
1559: else
1560: {
1561: data = 0x00;
1562: }
1563: for(j=0;j<4;j++)
1564: {
1565: if (fdata[src+i] & mask)
1566: {
1567: if (attr & 0x80)
1568: {
1569: data ^= (attr & 0x03) << ((3-j)*2);
1570: }
1571: else
1572: {
1573: data |= (attr & 0x03) << ((3-j)*2);
1574: }
1575: }
1576: mask >>= 1;
1577: }
1578: write_byte(0xb800,dest,data);
1579: dest += 1;
1580: }
1581: }
1582: }
1583: }
1584:
1585: // --------------------------------------------------------------------------------------------
1586: static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1587: Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1588: {
1589: Bit8u i,j,mask,data;
1590: Bit8u *fdata;
1591: Bit16u addr,dest,src;
1592:
1593: fdata = &vgafont8;
1594: addr=xcurs*8+ycurs*nbcols*64;
1595: src = car * 8;
1596: for(i=0;i<8;i++)
1597: {
1598: dest=addr+i*nbcols*8;
1599: mask = 0x80;
1600: for(j=0;j<8;j++)
1601: {
1602: data = 0x00;
1603: if (fdata[src+i] & mask)
1604: {
1605: data = attr;
1606: }
1607: write_byte(0xa000,dest+j,data);
1608: mask >>= 1;
1609: }
1610: }
1611: }
1612:
1613: // --------------------------------------------------------------------------------------------
1614: static void biosfn_write_char_attr (car,page,attr,count)
1615: Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1616: {
1617: Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1618: Bit16u nbcols,nbrows,address;
1619: Bit16u cursor,dummy;
1620:
1621: // Get the mode
1622: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1623: line=find_vga_entry(mode);
1624: if(line==0xFF)return;
1625:
1626: // Get the cursor pos for the page
1627: biosfn_get_cursor_pos(page,&dummy,&cursor);
1628: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1629:
1630: // Get the dimensions
1631: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1632: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1633:
1634: if(vga_modes[line].class==TEXT)
1635: {
1636: // Compute the address
1637: address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1638:
1639: dummy=((Bit16u)attr<<8)+car;
1640: memsetw(vga_modes[line].sstart,address,dummy,count);
1641: }
1642: else
1643: {
1644: // FIXME gfx mode not complete
1645: cheight=video_param_table[line_to_vpti[line]].cheight;
1646: bpp=vga_modes[line].pixbits;
1647: while((count-->0) && (xcurs<nbcols))
1648: {
1649: switch(vga_modes[line].memmodel)
1650: {
1651: case PLANAR4:
1652: case PLANAR1:
1653: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1654: break;
1655: case CGA:
1656: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1657: break;
1658: case LINEAR8:
1659: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1660: break;
1661: #ifdef DEBUG
1662: default:
1663: unimplemented();
1664: #endif
1665: }
1666: xcurs++;
1667: }
1668: }
1669: }
1670:
1671: // --------------------------------------------------------------------------------------------
1672: static void biosfn_write_char_only (car,page,attr,count)
1673: Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1674: {
1675: Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1676: Bit16u nbcols,nbrows,address;
1677: Bit16u cursor,dummy;
1678:
1679: // Get the mode
1680: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1681: line=find_vga_entry(mode);
1682: if(line==0xFF)return;
1683:
1684: // Get the cursor pos for the page
1685: biosfn_get_cursor_pos(page,&dummy,&cursor);
1686: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1687:
1688: // Get the dimensions
1689: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1690: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1691:
1692: if(vga_modes[line].class==TEXT)
1693: {
1694: // Compute the address
1695: address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1696:
1697: while(count-->0)
1698: {write_byte(vga_modes[line].sstart,address,car);
1699: address+=2;
1700: }
1701: }
1702: else
1703: {
1704: // FIXME gfx mode not complete
1705: cheight=video_param_table[line_to_vpti[line]].cheight;
1706: bpp=vga_modes[line].pixbits;
1707: while((count-->0) && (xcurs<nbcols))
1708: {
1709: switch(vga_modes[line].memmodel)
1710: {
1711: case PLANAR4:
1712: case PLANAR1:
1713: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1714: break;
1715: case CGA:
1716: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1717: break;
1718: case LINEAR8:
1719: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1720: break;
1721: #ifdef DEBUG
1722: default:
1723: unimplemented();
1724: #endif
1725: }
1726: xcurs++;
1727: }
1728: }
1729: }
1730:
1731: // --------------------------------------------------------------------------------------------
1732: ASM_START
1733: biosfn_group_0B:
1734: cmp bh, #0x00
1735: je biosfn_set_border_color
1736: cmp bh, #0x01
1737: je biosfn_set_palette
1738: #ifdef DEBUG
1739: call _unknown
1740: #endif
1741: ret
1742: biosfn_set_border_color:
1743: push ax
1744: push bx
1745: push cx
1746: push dx
1747: mov dx, # VGAREG_ACTL_RESET
1748: in al, dx
1749: mov dx, # VGAREG_ACTL_ADDRESS
1750: mov al, #0x00
1751: out dx, al
1752: mov al, bl
1753: and al, #0x0f
1754: test al, #0x08
1755: jz set_low_border
1756: add al, #0x08
1757: set_low_border:
1758: out dx, al
1759: mov cl, #0x01
1760: and bl, #0x10
1761: set_intensity_loop:
1762: mov dx, # VGAREG_ACTL_ADDRESS
1763: mov al, cl
1764: out dx, al
1765: mov dx, # VGAREG_ACTL_READ_DATA
1766: in al, dx
1767: and al, #0xef
1768: or al, bl
1769: mov dx, # VGAREG_ACTL_ADDRESS
1770: out dx, al
1771: inc cl
1772: cmp cl, #0x04
1773: jne set_intensity_loop
1774: mov al, #0x20
1775: out dx, al
1776: pop dx
1777: pop cx
1778: pop bx
1779: pop ax
1780: ret
1781: biosfn_set_palette:
1782: push ax
1783: push bx
1784: push cx
1785: push dx
1786: mov dx, # VGAREG_ACTL_RESET
1787: in al, dx
1788: mov cl, #0x01
1789: and bl, #0x01
1790: set_cga_palette_loop:
1791: mov dx, # VGAREG_ACTL_ADDRESS
1792: mov al, cl
1793: out dx, al
1794: mov dx, # VGAREG_ACTL_READ_DATA
1795: in al, dx
1796: and al, #0xfe
1797: or al, bl
1798: mov dx, # VGAREG_ACTL_ADDRESS
1799: out dx, al
1800: inc cl
1801: cmp cl, #0x04
1802: jne set_cga_palette_loop
1803: mov al, #0x20
1804: out dx, al
1805: pop dx
1806: pop cx
1807: pop bx
1808: pop ax
1809: ret
1810: ASM_END
1811:
1812: // --------------------------------------------------------------------------------------------
1813: static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1814: {
1815: Bit8u mode,line,mask,attr,data;
1816: Bit16u addr;
1817:
1818: // Get the mode
1819: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1820: line=find_vga_entry(mode);
1821: if(line==0xFF)return;
1822: if(vga_modes[line].class==TEXT)return;
1823:
1824: switch(vga_modes[line].memmodel)
1825: {
1826: case PLANAR4:
1827: case PLANAR1:
1828: addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1829: mask = 0x80 >> (CX & 0x07);
1830: outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1831: outw(VGAREG_GRDC_ADDRESS, 0x0205);
1832: data = read_byte(0xa000,addr);
1833: if (AL & 0x80)
1834: {
1835: outw(VGAREG_GRDC_ADDRESS, 0x1803);
1836: }
1837: write_byte(0xa000,addr,AL);
1838: ASM_START
1839: mov dx, # VGAREG_GRDC_ADDRESS
1840: mov ax, #0xff08
1841: out dx, ax
1842: mov ax, #0x0005
1843: out dx, ax
1844: mov ax, #0x0003
1845: out dx, ax
1846: ASM_END
1847: break;
1848: case CGA:
1849: if(vga_modes[line].pixbits==2)
1850: {
1851: addr=(CX>>2)+(DX>>1)*80;
1852: }
1853: else
1854: {
1855: addr=(CX>>3)+(DX>>1)*80;
1856: }
1857: if (DX & 1) addr += 0x2000;
1858: data = read_byte(0xb800,addr);
1859: if(vga_modes[line].pixbits==2)
1860: {
1861: attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1862: mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1863: }
1864: else
1865: {
1866: attr = (AL & 0x01) << (7 - (CX & 0x07));
1867: mask = 0x01 << (7 - (CX & 0x07));
1868: }
1869: if (AL & 0x80)
1870: {
1871: data ^= attr;
1872: }
1873: else
1874: {
1875: data &= ~mask;
1876: data |= attr;
1877: }
1878: write_byte(0xb800,addr,data);
1879: break;
1880: case LINEAR8:
1881: addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1882: write_byte(0xa000,addr,AL);
1883: break;
1884: #ifdef DEBUG
1885: default:
1886: unimplemented();
1887: #endif
1888: }
1889: }
1890:
1891: // --------------------------------------------------------------------------------------------
1892: static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1893: {
1894: Bit8u mode,line,mask,attr,data,i;
1895: Bit16u addr;
1896: Bit16u ss=get_SS();
1897:
1898: // Get the mode
1899: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1900: line=find_vga_entry(mode);
1901: if(line==0xFF)return;
1902: if(vga_modes[line].class==TEXT)return;
1903:
1904: switch(vga_modes[line].memmodel)
1905: {
1906: case PLANAR4:
1907: case PLANAR1:
1908: addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1909: mask = 0x80 >> (CX & 0x07);
1910: attr = 0x00;
1911: for(i=0;i<4;i++)
1912: {
1913: outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1914: data = read_byte(0xa000,addr) & mask;
1915: if (data > 0) attr |= (0x01 << i);
1916: }
1917: break;
1918: case CGA:
1919: addr=(CX>>2)+(DX>>1)*80;
1920: if (DX & 1) addr += 0x2000;
1921: data = read_byte(0xb800,addr);
1922: if(vga_modes[line].pixbits==2)
1923: {
1924: attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1925: }
1926: else
1927: {
1928: attr = (data >> (7 - (CX & 0x07))) & 0x01;
1929: }
1930: break;
1931: case LINEAR8:
1932: addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1933: attr=read_byte(0xa000,addr);
1934: break;
1935: default:
1936: #ifdef DEBUG
1937: unimplemented();
1938: #endif
1939: attr = 0;
1940: }
1941: write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1942: }
1943:
1944: // --------------------------------------------------------------------------------------------
1945: static void biosfn_write_teletype (car, page, attr, flag)
1946: Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1947: {// flag = WITH_ATTR / NO_ATTR
1948:
1949: Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1950: Bit16u nbcols,nbrows,address;
1951: Bit16u cursor,dummy;
1952:
1953: // special case if page is 0xff, use current page
1954: if(page==0xff)
1955: page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1956:
1957: // Get the mode
1958: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1959: line=find_vga_entry(mode);
1960: if(line==0xFF)return;
1961:
1962: // Get the cursor pos for the page
1963: biosfn_get_cursor_pos(page,&dummy,&cursor);
1964: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1965:
1966: // Get the dimensions
1967: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1968: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1969:
1970: switch(car)
1971: {
1972: case 7:
1973: //FIXME should beep
1974: break;
1975:
1976: case 8:
1977: if(xcurs>0)xcurs--;
1978: break;
1979:
1980: case '\r':
1981: xcurs=0;
1982: break;
1983:
1984: case '\n':
1985: ycurs++;
1986: break;
1987:
1988: case '\t':
1989: do
1990: {
1991: biosfn_write_teletype(' ',page,attr,flag);
1992: biosfn_get_cursor_pos(page,&dummy,&cursor);
1993: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1994: }while(xcurs%8==0);
1995: break;
1996:
1997: default:
1998:
1999: if(vga_modes[line].class==TEXT)
2000: {
2001: // Compute the address
2002: address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
2003:
2004: // Write the char
2005: write_byte(vga_modes[line].sstart,address,car);
2006:
2007: if(flag==WITH_ATTR)
2008: write_byte(vga_modes[line].sstart,address+1,attr);
2009: }
2010: else
2011: {
2012: // FIXME gfx mode not complete
2013: cheight=video_param_table[line_to_vpti[line]].cheight;
2014: bpp=vga_modes[line].pixbits;
2015: switch(vga_modes[line].memmodel)
2016: {
2017: case PLANAR4:
2018: case PLANAR1:
2019: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
2020: break;
2021: case CGA:
2022: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
2023: break;
2024: case LINEAR8:
2025: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
2026: break;
2027: #ifdef DEBUG
2028: default:
2029: unimplemented();
2030: #endif
2031: }
2032: }
2033: xcurs++;
2034: }
2035:
2036: // Do we need to wrap ?
2037: if(xcurs==nbcols)
2038: {xcurs=0;
2039: ycurs++;
2040: }
2041:
2042: // Do we need to scroll ?
2043: if(ycurs==nbrows)
2044: {
2045: if(vga_modes[line].class==TEXT)
2046: {
1.1.1.2 ! root 2047: address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
! 2048: attr=read_byte(vga_modes[line].sstart,address+1);
! 2049: biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1.1 root 2050: }
2051: else
2052: {
2053: biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2054: }
2055: ycurs-=1;
2056: }
1.1.1.2 ! root 2057:
1.1 root 2058: // Set the cursor for the page
2059: cursor=ycurs; cursor<<=8; cursor+=xcurs;
2060: biosfn_set_cursor_pos(page,cursor);
2061: }
2062:
2063: // --------------------------------------------------------------------------------------------
2064: ASM_START
2065: biosfn_get_video_mode:
2066: push ds
2067: mov ax, # BIOSMEM_SEG
2068: mov ds, ax
2069: push bx
2070: mov bx, # BIOSMEM_CURRENT_PAGE
2071: mov al, [bx]
2072: pop bx
2073: mov bh, al
2074: push bx
2075: mov bx, # BIOSMEM_VIDEO_CTL
2076: mov ah, [bx]
2077: and ah, #0x80
2078: mov bx, # BIOSMEM_CURRENT_MODE
2079: mov al, [bx]
2080: or al, ah
2081: mov bx, # BIOSMEM_NB_COLS
2082: mov ah, [bx]
2083: pop bx
2084: pop ds
2085: ret
2086: ASM_END
2087:
2088: // --------------------------------------------------------------------------------------------
2089: ASM_START
2090: biosfn_group_10:
2091: cmp al, #0x00
2092: jne int10_test_1001
2093: jmp biosfn_set_single_palette_reg
2094: int10_test_1001:
2095: cmp al, #0x01
2096: jne int10_test_1002
2097: jmp biosfn_set_overscan_border_color
2098: int10_test_1002:
2099: cmp al, #0x02
2100: jne int10_test_1003
2101: jmp biosfn_set_all_palette_reg
2102: int10_test_1003:
2103: cmp al, #0x03
2104: jne int10_test_1007
2105: jmp biosfn_toggle_intensity
2106: int10_test_1007:
2107: cmp al, #0x07
2108: jne int10_test_1008
2109: jmp biosfn_get_single_palette_reg
2110: int10_test_1008:
2111: cmp al, #0x08
2112: jne int10_test_1009
2113: jmp biosfn_read_overscan_border_color
2114: int10_test_1009:
2115: cmp al, #0x09
2116: jne int10_test_1010
2117: jmp biosfn_get_all_palette_reg
2118: int10_test_1010:
2119: cmp al, #0x10
2120: jne int10_test_1012
2121: jmp biosfn_set_single_dac_reg
2122: int10_test_1012:
2123: cmp al, #0x12
2124: jne int10_test_1013
2125: jmp biosfn_set_all_dac_reg
2126: int10_test_1013:
2127: cmp al, #0x13
2128: jne int10_test_1015
2129: jmp biosfn_select_video_dac_color_page
2130: int10_test_1015:
2131: cmp al, #0x15
2132: jne int10_test_1017
2133: jmp biosfn_read_single_dac_reg
2134: int10_test_1017:
2135: cmp al, #0x17
2136: jne int10_test_1018
2137: jmp biosfn_read_all_dac_reg
2138: int10_test_1018:
2139: cmp al, #0x18
2140: jne int10_test_1019
2141: jmp biosfn_set_pel_mask
2142: int10_test_1019:
2143: cmp al, #0x19
2144: jne int10_test_101A
2145: jmp biosfn_read_pel_mask
2146: int10_test_101A:
2147: cmp al, #0x1a
2148: jne int10_group_10_unknown
2149: jmp biosfn_read_video_dac_state
2150: int10_group_10_unknown:
2151: #ifdef DEBUG
2152: call _unknown
2153: #endif
2154: ret
2155:
2156: biosfn_set_single_palette_reg:
2157: cmp bl, #0x14
2158: ja no_actl_reg1
2159: push ax
2160: push dx
2161: mov dx, # VGAREG_ACTL_RESET
2162: in al, dx
2163: mov dx, # VGAREG_ACTL_ADDRESS
2164: mov al, bl
2165: out dx, al
2166: mov al, bh
2167: out dx, al
2168: mov al, #0x20
2169: out dx, al
2170: pop dx
2171: pop ax
2172: no_actl_reg1:
2173: ret
2174: ASM_END
2175:
2176: // --------------------------------------------------------------------------------------------
2177: ASM_START
2178: biosfn_set_overscan_border_color:
2179: push bx
2180: mov bl, #0x11
2181: call biosfn_set_single_palette_reg
2182: pop bx
2183: ret
2184: ASM_END
2185:
2186: // --------------------------------------------------------------------------------------------
2187: ASM_START
2188: biosfn_set_all_palette_reg:
2189: push ax
2190: push bx
2191: push cx
2192: push dx
2193: mov bx, dx
2194: mov dx, # VGAREG_ACTL_RESET
2195: in al, dx
2196: mov cl, #0x00
2197: mov dx, # VGAREG_ACTL_ADDRESS
2198: set_palette_loop:
2199: mov al, cl
2200: out dx, al
2201: seg es
2202: mov al, [bx]
2203: out dx, al
2204: inc bx
2205: inc cl
2206: cmp cl, #0x10
2207: jne set_palette_loop
2208: mov al, #0x11
2209: out dx, al
2210: seg es
2211: mov al, [bx]
2212: out dx, al
2213: mov al, #0x20
2214: out dx, al
2215: pop dx
2216: pop cx
2217: pop bx
2218: pop ax
2219: ret
2220: ASM_END
2221:
2222: // --------------------------------------------------------------------------------------------
2223: ASM_START
2224: biosfn_toggle_intensity:
2225: push ax
2226: push bx
2227: push dx
2228: mov dx, # VGAREG_ACTL_RESET
2229: in al, dx
2230: mov dx, # VGAREG_ACTL_ADDRESS
2231: mov al, #0x10
2232: out dx, al
2233: mov dx, # VGAREG_ACTL_READ_DATA
2234: in al, dx
2235: and al, #0xf7
2236: and bl, #0x01
2237: shl bl, 3
2238: or al, bl
2239: mov dx, # VGAREG_ACTL_ADDRESS
2240: out dx, al
2241: mov al, #0x20
2242: out dx, al
2243: pop dx
2244: pop bx
2245: pop ax
2246: ret
2247: ASM_END
2248:
2249: // --------------------------------------------------------------------------------------------
2250: ASM_START
2251: biosfn_get_single_palette_reg:
2252: cmp bl, #0x14
2253: ja no_actl_reg2
2254: push ax
2255: push dx
2256: mov dx, # VGAREG_ACTL_RESET
2257: in al, dx
2258: mov dx, # VGAREG_ACTL_ADDRESS
2259: mov al, bl
2260: out dx, al
2261: mov dx, # VGAREG_ACTL_READ_DATA
2262: in al, dx
2263: mov bh, al
2264: mov dx, # VGAREG_ACTL_RESET
2265: in al, dx
2266: mov dx, # VGAREG_ACTL_ADDRESS
2267: mov al, #0x20
2268: out dx, al
2269: pop dx
2270: pop ax
2271: no_actl_reg2:
2272: ret
2273: ASM_END
2274:
2275: // --------------------------------------------------------------------------------------------
2276: ASM_START
2277: biosfn_read_overscan_border_color:
2278: push ax
2279: push bx
2280: mov bl, #0x11
2281: call biosfn_get_single_palette_reg
2282: mov al, bh
2283: pop bx
2284: mov bh, al
2285: pop ax
2286: ret
2287: ASM_END
2288:
2289: // --------------------------------------------------------------------------------------------
2290: ASM_START
2291: biosfn_get_all_palette_reg:
2292: push ax
2293: push bx
2294: push cx
2295: push dx
2296: mov bx, dx
2297: mov cl, #0x00
2298: get_palette_loop:
2299: mov dx, # VGAREG_ACTL_RESET
2300: in al, dx
2301: mov dx, # VGAREG_ACTL_ADDRESS
2302: mov al, cl
2303: out dx, al
2304: mov dx, # VGAREG_ACTL_READ_DATA
2305: in al, dx
2306: seg es
2307: mov [bx], al
2308: inc bx
2309: inc cl
2310: cmp cl, #0x10
2311: jne get_palette_loop
2312: mov dx, # VGAREG_ACTL_RESET
2313: in al, dx
2314: mov dx, # VGAREG_ACTL_ADDRESS
2315: mov al, #0x11
2316: out dx, al
2317: mov dx, # VGAREG_ACTL_READ_DATA
2318: in al, dx
2319: seg es
2320: mov [bx], al
2321: mov dx, # VGAREG_ACTL_RESET
2322: in al, dx
2323: mov dx, # VGAREG_ACTL_ADDRESS
2324: mov al, #0x20
2325: out dx, al
2326: pop dx
2327: pop cx
2328: pop bx
2329: pop ax
2330: ret
2331: ASM_END
2332:
2333: // --------------------------------------------------------------------------------------------
2334: ASM_START
2335: biosfn_set_single_dac_reg:
2336: push ax
2337: push dx
2338: mov dx, # VGAREG_DAC_WRITE_ADDRESS
2339: mov al, bl
2340: out dx, al
2341: mov dx, # VGAREG_DAC_DATA
2342: pop ax
2343: push ax
2344: mov al, ah
2345: out dx, al
2346: mov al, ch
2347: out dx, al
2348: mov al, cl
2349: out dx, al
2350: pop dx
2351: pop ax
2352: ret
2353: ASM_END
2354:
2355: // --------------------------------------------------------------------------------------------
2356: ASM_START
2357: biosfn_set_all_dac_reg:
2358: push ax
2359: push bx
2360: push cx
2361: push dx
2362: mov dx, # VGAREG_DAC_WRITE_ADDRESS
2363: mov al, bl
2364: out dx, al
2365: pop dx
2366: push dx
2367: mov bx, dx
2368: mov dx, # VGAREG_DAC_DATA
2369: set_dac_loop:
2370: seg es
2371: mov al, [bx]
2372: out dx, al
2373: inc bx
2374: seg es
2375: mov al, [bx]
2376: out dx, al
2377: inc bx
2378: seg es
2379: mov al, [bx]
2380: out dx, al
2381: inc bx
2382: dec cx
2383: jnz set_dac_loop
2384: pop dx
2385: pop cx
2386: pop bx
2387: pop ax
2388: ret
2389: ASM_END
2390:
2391: // --------------------------------------------------------------------------------------------
2392: ASM_START
2393: biosfn_select_video_dac_color_page:
2394: push ax
2395: push bx
2396: push dx
2397: mov dx, # VGAREG_ACTL_RESET
2398: in al, dx
2399: mov dx, # VGAREG_ACTL_ADDRESS
2400: mov al, #0x10
2401: out dx, al
2402: mov dx, # VGAREG_ACTL_READ_DATA
2403: in al, dx
2404: and bl, #0x01
2405: jnz set_dac_page
2406: and al, #0x7f
2407: shl bh, 7
2408: or al, bh
2409: mov dx, # VGAREG_ACTL_ADDRESS
2410: out dx, al
2411: jmp set_actl_normal
2412: set_dac_page:
2413: push ax
2414: mov dx, # VGAREG_ACTL_RESET
2415: in al, dx
2416: mov dx, # VGAREG_ACTL_ADDRESS
2417: mov al, #0x14
2418: out dx, al
2419: pop ax
2420: and al, #0x80
2421: jnz set_dac_16_page
2422: shl bh, 2
2423: set_dac_16_page:
2424: and bh, #0x0f
2425: mov al, bh
2426: out dx, al
2427: set_actl_normal:
2428: mov al, #0x20
2429: out dx, al
2430: pop dx
2431: pop bx
2432: pop ax
2433: ret
2434: ASM_END
2435:
2436: // --------------------------------------------------------------------------------------------
2437: ASM_START
2438: biosfn_read_single_dac_reg:
2439: push ax
2440: push dx
2441: mov dx, # VGAREG_DAC_READ_ADDRESS
2442: mov al, bl
2443: out dx, al
2444: pop ax
2445: mov ah, al
2446: mov dx, # VGAREG_DAC_DATA
2447: in al, dx
2448: xchg al, ah
2449: push ax
2450: in al, dx
2451: mov ch, al
2452: in al, dx
2453: mov cl, al
2454: pop dx
2455: pop ax
2456: ret
2457: ASM_END
2458:
2459: // --------------------------------------------------------------------------------------------
2460: ASM_START
2461: biosfn_read_all_dac_reg:
2462: push ax
2463: push bx
2464: push cx
2465: push dx
2466: mov dx, # VGAREG_DAC_READ_ADDRESS
2467: mov al, bl
2468: out dx, al
2469: pop dx
2470: push dx
2471: mov bx, dx
2472: mov dx, # VGAREG_DAC_DATA
2473: read_dac_loop:
2474: in al, dx
2475: seg es
2476: mov [bx], al
2477: inc bx
2478: in al, dx
2479: seg es
2480: mov [bx], al
2481: inc bx
2482: in al, dx
2483: seg es
2484: mov [bx], al
2485: inc bx
2486: dec cx
2487: jnz read_dac_loop
2488: pop dx
2489: pop cx
2490: pop bx
2491: pop ax
2492: ret
2493: ASM_END
2494:
2495: // --------------------------------------------------------------------------------------------
2496: ASM_START
2497: biosfn_set_pel_mask:
2498: push ax
2499: push dx
2500: mov dx, # VGAREG_PEL_MASK
2501: mov al, bl
2502: out dx, al
2503: pop dx
2504: pop ax
2505: ret
2506: ASM_END
2507:
2508: // --------------------------------------------------------------------------------------------
2509: ASM_START
2510: biosfn_read_pel_mask:
2511: push ax
2512: push dx
2513: mov dx, # VGAREG_PEL_MASK
2514: in al, dx
2515: mov bl, al
2516: pop dx
2517: pop ax
2518: ret
2519: ASM_END
2520:
2521: // --------------------------------------------------------------------------------------------
2522: ASM_START
2523: biosfn_read_video_dac_state:
2524: push ax
2525: push dx
2526: mov dx, # VGAREG_ACTL_RESET
2527: in al, dx
2528: mov dx, # VGAREG_ACTL_ADDRESS
2529: mov al, #0x10
2530: out dx, al
2531: mov dx, # VGAREG_ACTL_READ_DATA
2532: in al, dx
2533: mov bl, al
2534: shr bl, 7
2535: mov dx, # VGAREG_ACTL_RESET
2536: in al, dx
2537: mov dx, # VGAREG_ACTL_ADDRESS
2538: mov al, #0x14
2539: out dx, al
2540: mov dx, # VGAREG_ACTL_READ_DATA
2541: in al, dx
2542: mov bh, al
2543: and bh, #0x0f
2544: test bl, #0x01
2545: jnz get_dac_16_page
2546: shr bh, 2
2547: get_dac_16_page:
2548: mov dx, # VGAREG_ACTL_RESET
2549: in al, dx
2550: mov dx, # VGAREG_ACTL_ADDRESS
2551: mov al, #0x20
2552: out dx, al
2553: pop dx
2554: pop ax
2555: ret
2556: ASM_END
2557:
2558: // --------------------------------------------------------------------------------------------
2559: static void biosfn_perform_gray_scale_summing (start,count)
2560: Bit16u start;Bit16u count;
2561: {Bit8u r,g,b;
2562: Bit16u i;
2563: Bit16u index;
2564:
2565: inb(VGAREG_ACTL_RESET);
2566: outb(VGAREG_ACTL_ADDRESS,0x00);
2567:
2568: for( index = 0; index < count; index++ )
2569: {
2570: // set read address and switch to read mode
2571: outb(VGAREG_DAC_READ_ADDRESS,start);
2572: // get 6-bit wide RGB data values
2573: r=inb( VGAREG_DAC_DATA );
2574: g=inb( VGAREG_DAC_DATA );
2575: b=inb( VGAREG_DAC_DATA );
2576:
2577: // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2578: i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2579:
2580: if(i>0x3f)i=0x3f;
2581:
2582: // set write address and switch to write mode
2583: outb(VGAREG_DAC_WRITE_ADDRESS,start);
2584: // write new intensity value
2585: outb( VGAREG_DAC_DATA, i&0xff );
2586: outb( VGAREG_DAC_DATA, i&0xff );
2587: outb( VGAREG_DAC_DATA, i&0xff );
2588: start++;
2589: }
2590: inb(VGAREG_ACTL_RESET);
2591: outb(VGAREG_ACTL_ADDRESS,0x20);
2592: }
2593:
2594: // --------------------------------------------------------------------------------------------
2595: static void get_font_access()
2596: {
2597: ASM_START
2598: mov dx, # VGAREG_SEQU_ADDRESS
2599: mov ax, #0x0100
2600: out dx, ax
2601: mov ax, #0x0402
2602: out dx, ax
2603: mov ax, #0x0704
2604: out dx, ax
2605: mov ax, #0x0300
2606: out dx, ax
2607: mov dx, # VGAREG_GRDC_ADDRESS
2608: mov ax, #0x0204
2609: out dx, ax
2610: mov ax, #0x0005
2611: out dx, ax
2612: mov ax, #0x0406
2613: out dx, ax
2614: ASM_END
2615: }
2616:
2617: static void release_font_access()
2618: {
2619: ASM_START
2620: mov dx, # VGAREG_SEQU_ADDRESS
2621: mov ax, #0x0100
2622: out dx, ax
2623: mov ax, #0x0302
2624: out dx, ax
2625: mov ax, #0x0304
2626: out dx, ax
2627: mov ax, #0x0300
2628: out dx, ax
2629: mov dx, # VGAREG_READ_MISC_OUTPUT
2630: in al, dx
2631: and al, #0x01
2632: shl al, 2
2633: or al, #0x0a
2634: mov ah, al
2635: mov al, #0x06
2636: mov dx, # VGAREG_GRDC_ADDRESS
2637: out dx, ax
2638: mov ax, #0x0004
2639: out dx, ax
2640: mov ax, #0x1005
2641: out dx, ax
2642: ASM_END
2643: }
2644:
2645: ASM_START
2646: idiv_u:
2647: xor dx,dx
2648: div bx
2649: ret
2650: ASM_END
2651:
2652: static void set_scan_lines(lines) Bit8u lines;
2653: {
2654: Bit16u crtc_addr,cols,page,vde;
2655: Bit8u crtc_r9,ovl,rows;
2656:
2657: crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2658: outb(crtc_addr, 0x09);
2659: crtc_r9 = inb(crtc_addr+1);
2660: crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2661: outb(crtc_addr+1, crtc_r9);
2662: if(lines==8)
2663: {
2664: biosfn_set_cursor_shape(0x06,0x07);
2665: }
2666: else
2667: {
2668: biosfn_set_cursor_shape(lines-4,lines-3);
2669: }
2670: write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2671: outb(crtc_addr, 0x12);
2672: vde = inb(crtc_addr+1);
2673: outb(crtc_addr, 0x07);
2674: ovl = inb(crtc_addr+1);
2675: vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2676: rows = vde / lines;
2677: write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2678: cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2679: write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2680: }
2681:
2682: static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH;
2683: {
2684: Bit16u blockaddr,dest,i,src;
2685:
2686: get_font_access();
2687: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2688: for(i=0;i<CX;i++)
2689: {
2690: src = BP + i * BH;
2691: dest = blockaddr + (DX + i) * 32;
2692: memcpyb(0xA000, dest, ES, src, BH);
2693: }
2694: release_font_access();
2695: if(AL>=0x10)
2696: {
2697: set_scan_lines(BH);
2698: }
2699: }
2700:
2701: static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2702: {
2703: Bit16u blockaddr,dest,i,src;
2704:
2705: get_font_access();
2706: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2707: for(i=0;i<0x100;i++)
2708: {
2709: src = i * 14;
2710: dest = blockaddr + i * 32;
2711: memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2712: }
2713: release_font_access();
2714: if(AL>=0x10)
2715: {
2716: set_scan_lines(14);
2717: }
2718: }
2719:
2720: static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2721: {
2722: Bit16u blockaddr,dest,i,src;
2723:
2724: get_font_access();
2725: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2726: for(i=0;i<0x100;i++)
2727: {
2728: src = i * 8;
2729: dest = blockaddr + i * 32;
2730: memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2731: }
2732: release_font_access();
2733: if(AL>=0x10)
2734: {
2735: set_scan_lines(8);
2736: }
2737: }
2738:
2739: // --------------------------------------------------------------------------------------------
2740: ASM_START
2741: biosfn_set_text_block_specifier:
2742: push ax
2743: push dx
2744: mov dx, # VGAREG_SEQU_ADDRESS
2745: mov ah, bl
2746: mov al, #0x03
2747: out dx, ax
2748: pop dx
2749: pop ax
2750: ret
2751: ASM_END
2752:
2753: // --------------------------------------------------------------------------------------------
2754: static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2755: {
2756: Bit16u blockaddr,dest,i,src;
2757:
2758: get_font_access();
2759: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2760: for(i=0;i<0x100;i++)
2761: {
2762: src = i * 16;
2763: dest = blockaddr + i * 32;
2764: memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2765: }
2766: release_font_access();
2767: if(AL>=0x10)
2768: {
2769: set_scan_lines(16);
2770: }
2771: }
2772:
2773: static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2774: {
2775: #ifdef DEBUG
2776: unimplemented();
2777: #endif
2778: }
2779: static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2780: {
2781: #ifdef DEBUG
2782: unimplemented();
2783: #endif
2784: }
2785: static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2786: {
2787: #ifdef DEBUG
2788: unimplemented();
2789: #endif
2790: }
2791: static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2792: {
2793: #ifdef DEBUG
2794: unimplemented();
2795: #endif
2796: }
2797: static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2798: {
2799: #ifdef DEBUG
2800: unimplemented();
2801: #endif
2802: }
2803: // --------------------------------------------------------------------------------------------
2804: static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2805: Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2806: {Bit16u ss=get_SS();
2807:
2808: switch(BH)
2809: {case 0x00:
2810: write_word(ss,ES,read_word(0x00,0x1f*4));
2811: write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2812: break;
2813: case 0x01:
2814: write_word(ss,ES,read_word(0x00,0x43*4));
2815: write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2816: break;
2817: case 0x02:
2818: write_word(ss,ES,0xC000);
2819: write_word(ss,BP,vgafont14);
2820: break;
2821: case 0x03:
2822: write_word(ss,ES,0xC000);
2823: write_word(ss,BP,vgafont8);
2824: break;
2825: case 0x04:
2826: write_word(ss,ES,0xC000);
2827: write_word(ss,BP,vgafont8+128*8);
2828: break;
2829: case 0x05:
2830: write_word(ss,ES,0xC000);
2831: write_word(ss,BP,vgafont14alt);
2832: break;
2833: case 0x06:
2834: write_word(ss,ES,0xC000);
2835: write_word(ss,BP,vgafont16);
2836: break;
2837: case 0x07:
2838: write_word(ss,ES,0xC000);
2839: write_word(ss,BP,vgafont16alt);
2840: break;
2841: default:
2842: #ifdef DEBUG
2843: printf("Get font info BH(%02x) was discarded\n",BH);
2844: #endif
2845: return;
2846: }
2847: // Set byte/char of on screen font
2848: write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2849:
2850: // Set Highest char row
2851: write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2852: }
2853:
2854: // --------------------------------------------------------------------------------------------
2855: ASM_START
2856: biosfn_get_ega_info:
2857: push ds
2858: push ax
2859: mov ax, # BIOSMEM_SEG
2860: mov ds, ax
2861: xor ch, ch
2862: mov bx, # BIOSMEM_SWITCHES
2863: mov cl, [bx]
2864: and cl, #0x0f
2865: mov bx, # BIOSMEM_CRTC_ADDRESS
2866: mov ax, [bx]
2867: mov bx, #0x0003
2868: cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2869: jne mode_ega_color
2870: mov bh, #0x01
2871: mode_ega_color:
2872: pop ax
2873: pop ds
2874: ret
2875: ASM_END
2876:
2877: // --------------------------------------------------------------------------------------------
2878: static void biosfn_alternate_prtsc()
2879: {
2880: #ifdef DEBUG
2881: unimplemented();
2882: #endif
2883: }
2884:
2885: // --------------------------------------------------------------------------------------------
2886: ASM_START
2887: biosfn_select_vert_res:
2888:
2889: ; res : 00 200 lines, 01 350 lines, 02 400 lines
2890:
2891: push ds
2892: push bx
2893: push dx
2894: mov dl, al
2895: mov ax, # BIOSMEM_SEG
2896: mov ds, ax
2897: mov bx, # BIOSMEM_MODESET_CTL
2898: mov al, [bx]
2899: mov bx, # BIOSMEM_SWITCHES
2900: mov ah, [bx]
2901: cmp dl, #0x01
2902: je vert_res_350
2903: jb vert_res_200
2904: cmp dl, #0x02
2905: je vert_res_400
2906: #ifdef DEBUG
2907: mov al, dl
2908: xor ah, ah
2909: push ax
2910: mov bx, #msg_vert_res
2911: push bx
2912: call _printf
2913: add sp, #4
2914: #endif
2915: jmp set_retcode
2916: vert_res_400:
2917:
2918: ; reset modeset ctl bit 7 and set bit 4
2919: ; set switches bit 3-0 to 0x09
2920:
2921: and al, #0x7f
2922: or al, #0x10
2923: and ah, #0xf0
2924: or ah, #0x09
2925: jnz set_vert_res
2926: vert_res_350:
2927:
2928: ; reset modeset ctl bit 7 and bit 4
2929: ; set switches bit 3-0 to 0x09
2930:
2931: and al, #0x6f
2932: and ah, #0xf0
2933: or ah, #0x09
2934: jnz set_vert_res
2935: vert_res_200:
2936:
2937: ; set modeset ctl bit 7 and reset bit 4
2938: ; set switches bit 3-0 to 0x08
2939:
2940: and al, #0xef
2941: or al, #0x80
2942: and ah, #0xf0
2943: or ah, #0x08
2944: set_vert_res:
2945: mov bx, # BIOSMEM_MODESET_CTL
2946: mov [bx], al
2947: mov bx, # BIOSMEM_SWITCHES
2948: mov [bx], ah
2949: set_retcode:
2950: mov ax, #0x1212
2951: pop dx
2952: pop bx
2953: pop ds
2954: ret
2955:
2956: #ifdef DEBUG
2957: msg_vert_res:
2958: .ascii "Select vert res (%02x) was discarded"
2959: .byte 0x0d,0x0a,0x00
2960: #endif
2961:
2962:
2963: biosfn_enable_default_palette_loading:
2964: push ds
2965: push bx
2966: push dx
2967: mov dl, al
2968: and dl, #0x01
2969: shl dl, 3
2970: mov ax, # BIOSMEM_SEG
2971: mov ds, ax
2972: mov bx, # BIOSMEM_MODESET_CTL
2973: mov al, [bx]
2974: and al, #0xf7
2975: or al, dl
2976: mov [bx], al
2977: mov ax, #0x1212
2978: pop dx
2979: pop bx
2980: pop ds
2981: ret
2982:
2983:
2984: biosfn_enable_video_addressing:
2985: push bx
2986: push dx
2987: mov bl, al
2988: and bl, #0x01
2989: xor bl, #0x01
2990: shl bl, 1
2991: mov dx, # VGAREG_READ_MISC_OUTPUT
2992: in al, dx
2993: and al, #0xfd
2994: or al, bl
2995: mov dx, # VGAREG_WRITE_MISC_OUTPUT
2996: out dx, al
2997: mov ax, #0x1212
2998: pop dx
2999: pop bx
3000: ret
3001:
3002:
3003: biosfn_enable_grayscale_summing:
3004: push ds
3005: push bx
3006: push dx
3007: mov dl, al
3008: and dl, #0x01
3009: xor dl, #0x01
3010: shl dl, 1
3011: mov ax, # BIOSMEM_SEG
3012: mov ds, ax
3013: mov bx, # BIOSMEM_MODESET_CTL
3014: mov al, [bx]
3015: and al, #0xfd
3016: or al, dl
3017: mov [bx], al
3018: mov ax, #0x1212
3019: pop dx
3020: pop bx
3021: pop ds
3022: ret
3023:
3024:
3025: biosfn_enable_cursor_emulation:
3026: push ds
3027: push bx
3028: push dx
3029: mov dl, al
3030: and dl, #0x01
3031: xor dl, #0x01
3032: mov ax, # BIOSMEM_SEG
3033: mov ds, ax
3034: mov bx, # BIOSMEM_MODESET_CTL
3035: mov al, [bx]
3036: and al, #0xfe
3037: or al, dl
3038: mov [bx], al
3039: mov ax, #0x1212
3040: pop dx
3041: pop bx
3042: pop ds
3043: ret
3044: ASM_END
3045:
3046: // --------------------------------------------------------------------------------------------
3047: static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3048: {
3049: #ifdef DEBUG
3050: unimplemented();
3051: #endif
3052: }
3053: static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3054: {
3055: #ifdef DEBUG
3056: unimplemented();
3057: #endif
3058: }
3059:
3060: // --------------------------------------------------------------------------------------------
3061: static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3062: Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3063: {
3064: Bit16u newcurs,oldcurs,dummy;
3065: Bit8u car,carattr;
3066:
3067: // Read curs info for the page
3068: biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3069:
3070: // if row=0xff special case : use current cursor position
3071: if(row==0xff)
3072: {col=oldcurs&0x00ff;
3073: row=(oldcurs&0xff00)>>8;
3074: }
3075:
3076: newcurs=row; newcurs<<=8; newcurs+=col;
3077: biosfn_set_cursor_pos(page,newcurs);
3078:
3079: while(count--!=0)
3080: {
3081: car=read_byte(seg,offset++);
3082: if((flag&0x02)!=0)
3083: attr=read_byte(seg,offset++);
3084:
3085: biosfn_write_teletype(car,page,attr,WITH_ATTR);
3086: }
3087:
3088: // Set back curs pos
3089: if((flag&0x01)==0)
3090: biosfn_set_cursor_pos(page,oldcurs);
3091: }
3092:
3093: // --------------------------------------------------------------------------------------------
3094: ASM_START
3095: biosfn_group_1A:
3096: cmp al, #0x00
3097: je biosfn_read_display_code
3098: cmp al, #0x01
3099: je biosfn_set_display_code
3100: #ifdef DEBUG
3101: call _unknown
3102: #endif
3103: ret
3104: biosfn_read_display_code:
3105: push ds
3106: push ax
3107: mov ax, # BIOSMEM_SEG
3108: mov ds, ax
3109: mov bx, # BIOSMEM_DCC_INDEX
3110: mov al, [bx]
3111: mov bl, al
3112: xor bh, bh
3113: pop ax
3114: mov al, ah
3115: pop ds
3116: ret
3117: biosfn_set_display_code:
3118: push ds
3119: push ax
3120: push bx
3121: mov ax, # BIOSMEM_SEG
3122: mov ds, ax
3123: mov ax, bx
3124: mov bx, # BIOSMEM_DCC_INDEX
3125: mov [bx], al
3126: #ifdef DEBUG
3127: mov al, ah
3128: xor ah, ah
3129: push ax
3130: mov bx, #msg_alt_dcc
3131: push bx
3132: call _printf
3133: add sp, #4
3134: #endif
3135: pop bx
3136: pop ax
3137: mov al, ah
3138: pop ds
3139: ret
3140:
3141: #ifdef DEBUG
3142: msg_alt_dcc:
3143: .ascii "Alternate Display code (%02x) was discarded"
3144: .byte 0x0d,0x0a,0x00
3145: #endif
3146: ASM_END
3147:
3148: // --------------------------------------------------------------------------------------------
3149: static void biosfn_read_state_info (BX,ES,DI)
3150: Bit16u BX;Bit16u ES;Bit16u DI;
3151: {
3152: // Address of static functionality table
3153: write_word(ES,DI+0x00,&static_functionality);
3154: write_word(ES,DI+0x02,0xC000);
3155:
3156: // Hard coded copy from BIOS area. Should it be cleaner ?
3157: memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3158: memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3159:
3160: write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3161: write_byte(ES,DI+0x26,0);
3162: write_byte(ES,DI+0x27,16);
3163: write_byte(ES,DI+0x28,0);
3164: write_byte(ES,DI+0x29,8);
3165: write_byte(ES,DI+0x2a,2);
3166: write_byte(ES,DI+0x2b,0);
3167: write_byte(ES,DI+0x2c,0);
3168: write_byte(ES,DI+0x31,3);
3169: write_byte(ES,DI+0x32,0);
3170:
3171: memsetb(ES,DI+0x33,0,13);
3172: }
3173:
3174: // --------------------------------------------------------------------------------------------
3175: // --------------------------------------------------------------------------------------------
3176: static Bit16u biosfn_read_video_state_size2 (CX)
3177: Bit16u CX;
3178: {
3179: Bit16u size;
3180: size = 0;
3181: if (CX & 1) {
3182: size += 0x46;
3183: }
3184: if (CX & 2) {
3185: size += (5 + 8 + 5) * 2 + 6;
3186: }
3187: if (CX & 4) {
3188: size += 3 + 256 * 3 + 1;
3189: }
3190: return size;
3191: }
3192:
3193: static void biosfn_read_video_state_size (CX, BX)
3194: Bit16u CX; Bit16u *BX;
3195: {
3196: Bit16u ss=get_SS();
3197: write_word(ss, BX, biosfn_read_video_state_size2(CX));
3198: }
3199:
3200: static Bit16u biosfn_save_video_state (CX,ES,BX)
3201: Bit16u CX;Bit16u ES;Bit16u BX;
3202: {
3203: Bit16u i, v, crtc_addr, ar_index;
3204:
3205: crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3206: if (CX & 1) {
3207: write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3208: write_byte(ES, BX, inb(crtc_addr)); BX++;
3209: write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3210: inb(VGAREG_ACTL_RESET);
3211: ar_index = inb(VGAREG_ACTL_ADDRESS);
3212: write_byte(ES, BX, ar_index); BX++;
3213: write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3214:
3215: for(i=1;i<=4;i++){
3216: outb(VGAREG_SEQU_ADDRESS, i);
3217: write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3218: }
3219: outb(VGAREG_SEQU_ADDRESS, 0);
3220: write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3221:
3222: for(i=0;i<=0x18;i++) {
3223: outb(crtc_addr,i);
3224: write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3225: }
3226:
3227: for(i=0;i<=0x13;i++) {
3228: inb(VGAREG_ACTL_RESET);
3229: outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3230: write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3231: }
3232: inb(VGAREG_ACTL_RESET);
3233:
3234: for(i=0;i<=8;i++) {
3235: outb(VGAREG_GRDC_ADDRESS,i);
3236: write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3237: }
3238:
3239: write_word(ES, BX, crtc_addr); BX+= 2;
3240:
3241: /* XXX: read plane latches */
3242: write_byte(ES, BX, 0); BX++;
3243: write_byte(ES, BX, 0); BX++;
3244: write_byte(ES, BX, 0); BX++;
3245: write_byte(ES, BX, 0); BX++;
3246: }
3247: if (CX & 2) {
3248: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3249: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3250: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3251: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3252: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3253: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3254: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3255: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3256: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3257: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3258: for(i=0;i<8;i++) {
3259: write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3260: BX += 2;
3261: }
3262: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3263: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3264: /* current font */
3265: write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3266: write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3267: write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3268: write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3269: }
3270: if (CX & 4) {
3271: /* XXX: check this */
3272: write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3273: write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3274: write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3275: // Set the whole dac always, from 0
3276: outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3277: for(i=0;i<256*3;i++) {
3278: write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3279: }
3280: write_byte(ES, BX, 0); BX++; /* color select register */
3281: }
3282: return BX;
3283: }
3284:
3285: static Bit16u biosfn_restore_video_state (CX,ES,BX)
3286: Bit16u CX;Bit16u ES;Bit16u BX;
3287: {
3288: Bit16u i, crtc_addr, v, addr1, ar_index;
3289:
3290: if (CX & 1) {
3291: // Reset Attribute Ctl flip-flop
3292: inb(VGAREG_ACTL_RESET);
3293:
3294: crtc_addr = read_word(ES, BX + 0x40);
3295: addr1 = BX;
3296: BX += 5;
3297:
3298: for(i=1;i<=4;i++){
3299: outb(VGAREG_SEQU_ADDRESS, i);
3300: outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3301: }
3302: outb(VGAREG_SEQU_ADDRESS, 0);
3303: outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3304:
3305: // Disable CRTC write protection
3306: outw(crtc_addr,0x0011);
3307: // Set CRTC regs
3308: for(i=0;i<=0x18;i++) {
3309: if (i != 0x11) {
3310: outb(crtc_addr,i);
3311: outb(crtc_addr+1, read_byte(ES, BX));
3312: }
3313: BX++;
3314: }
3315: // select crtc base address
3316: v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3317: if (crtc_addr = 0x3d4)
3318: v |= 0x01;
3319: outb(VGAREG_WRITE_MISC_OUTPUT, v);
3320:
3321: // enable write protection if needed
3322: outb(crtc_addr, 0x11);
3323: outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3324:
3325: // Set Attribute Ctl
3326: ar_index = read_byte(ES, addr1 + 0x03);
3327: inb(VGAREG_ACTL_RESET);
3328: for(i=0;i<=0x13;i++) {
3329: outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3330: outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3331: }
3332: outb(VGAREG_ACTL_ADDRESS, ar_index);
3333: inb(VGAREG_ACTL_RESET);
3334:
3335: for(i=0;i<=8;i++) {
3336: outb(VGAREG_GRDC_ADDRESS,i);
3337: outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3338: }
3339: BX += 2; /* crtc_addr */
3340: BX += 4; /* plane latches */
3341:
3342: outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3343: outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3344: outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3345: addr1++;
3346: outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3347: }
3348: if (CX & 2) {
3349: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3350: write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3351: write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3352: write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3353: write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3354: write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3355: write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3356: write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3357: write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3358: write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3359: for(i=0;i<8;i++) {
3360: write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3361: BX += 2;
3362: }
3363: write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3364: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3365: /* current font */
3366: write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3367: write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3368: write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3369: write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3370: }
3371: if (CX & 4) {
3372: BX++;
3373: v = read_byte(ES, BX); BX++;
3374: outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3375: // Set the whole dac always, from 0
3376: outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3377: for(i=0;i<256*3;i++) {
3378: outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3379: }
3380: BX++;
3381: outb(VGAREG_DAC_WRITE_ADDRESS, v);
3382: }
3383: return BX;
3384: }
3385:
3386: // ============================================================================================
3387: //
3388: // Video Utils
3389: //
3390: // ============================================================================================
3391:
3392: // --------------------------------------------------------------------------------------------
3393: static Bit8u find_vga_entry(mode)
3394: Bit8u mode;
3395: {
3396: Bit8u i,line=0xFF;
3397: for(i=0;i<=MODE_MAX;i++)
3398: if(vga_modes[i].svgamode==mode)
3399: {line=i;
3400: break;
3401: }
3402: return line;
3403: }
3404:
3405: /* =========================================================== */
3406: /*
3407: * Misc Utils
3408: */
3409: /* =========================================================== */
3410:
3411: // --------------------------------------------------------------------------------------------
3412: static void memsetb(seg,offset,value,count)
3413: Bit16u seg;
3414: Bit16u offset;
3415: Bit16u value;
3416: Bit16u count;
3417: {
3418: ASM_START
3419: push bp
3420: mov bp, sp
3421:
3422: push ax
3423: push cx
3424: push es
3425: push di
3426:
3427: mov cx, 10[bp] ; count
3428: cmp cx, #0x00
3429: je memsetb_end
3430: mov ax, 4[bp] ; segment
3431: mov es, ax
3432: mov ax, 6[bp] ; offset
3433: mov di, ax
3434: mov al, 8[bp] ; value
3435: cld
3436: rep
3437: stosb
3438:
3439: memsetb_end:
3440: pop di
3441: pop es
3442: pop cx
3443: pop ax
3444:
3445: pop bp
3446: ASM_END
3447: }
3448:
3449: // --------------------------------------------------------------------------------------------
3450: static void memsetw(seg,offset,value,count)
3451: Bit16u seg;
3452: Bit16u offset;
3453: Bit16u value;
3454: Bit16u count;
3455: {
3456: ASM_START
3457: push bp
3458: mov bp, sp
3459:
3460: push ax
3461: push cx
3462: push es
3463: push di
3464:
3465: mov cx, 10[bp] ; count
3466: cmp cx, #0x00
3467: je memsetw_end
3468: mov ax, 4[bp] ; segment
3469: mov es, ax
3470: mov ax, 6[bp] ; offset
3471: mov di, ax
3472: mov ax, 8[bp] ; value
3473: cld
3474: rep
3475: stosw
3476:
3477: memsetw_end:
3478: pop di
3479: pop es
3480: pop cx
3481: pop ax
3482:
3483: pop bp
3484: ASM_END
3485: }
3486:
3487: // --------------------------------------------------------------------------------------------
3488: static void memcpyb(dseg,doffset,sseg,soffset,count)
3489: Bit16u dseg;
3490: Bit16u doffset;
3491: Bit16u sseg;
3492: Bit16u soffset;
3493: Bit16u count;
3494: {
3495: ASM_START
3496: push bp
3497: mov bp, sp
3498:
3499: push ax
3500: push cx
3501: push es
3502: push di
3503: push ds
3504: push si
3505:
3506: mov cx, 12[bp] ; count
3507: cmp cx, #0x0000
3508: je memcpyb_end
3509: mov ax, 4[bp] ; dsegment
3510: mov es, ax
3511: mov ax, 6[bp] ; doffset
3512: mov di, ax
3513: mov ax, 8[bp] ; ssegment
3514: mov ds, ax
3515: mov ax, 10[bp] ; soffset
3516: mov si, ax
3517: cld
3518: rep
3519: movsb
3520:
3521: memcpyb_end:
3522: pop si
3523: pop ds
3524: pop di
3525: pop es
3526: pop cx
3527: pop ax
3528:
3529: pop bp
3530: ASM_END
3531: }
3532:
3533: // --------------------------------------------------------------------------------------------
3534: static void memcpyw(dseg,doffset,sseg,soffset,count)
3535: Bit16u dseg;
3536: Bit16u doffset;
3537: Bit16u sseg;
3538: Bit16u soffset;
3539: Bit16u count;
3540: {
3541: ASM_START
3542: push bp
3543: mov bp, sp
3544:
3545: push ax
3546: push cx
3547: push es
3548: push di
3549: push ds
3550: push si
3551:
3552: mov cx, 12[bp] ; count
3553: cmp cx, #0x0000
3554: je memcpyw_end
3555: mov ax, 4[bp] ; dsegment
3556: mov es, ax
3557: mov ax, 6[bp] ; doffset
3558: mov di, ax
3559: mov ax, 8[bp] ; ssegment
3560: mov ds, ax
3561: mov ax, 10[bp] ; soffset
3562: mov si, ax
3563: cld
3564: rep
3565: movsw
3566:
3567: memcpyw_end:
3568: pop si
3569: pop ds
3570: pop di
3571: pop es
3572: pop cx
3573: pop ax
3574:
3575: pop bp
3576: ASM_END
3577: }
3578:
3579: /* =========================================================== */
3580: /*
3581: * These functions where ripped from Kevin's rombios.c
3582: */
3583: /* =========================================================== */
3584:
3585: // --------------------------------------------------------------------------------------------
3586: static Bit8u
3587: read_byte(seg, offset)
3588: Bit16u seg;
3589: Bit16u offset;
3590: {
3591: ASM_START
3592: push bp
3593: mov bp, sp
3594:
3595: push bx
3596: push ds
3597: mov ax, 4[bp] ; segment
3598: mov ds, ax
3599: mov bx, 6[bp] ; offset
3600: mov al, [bx]
3601: ;; al = return value (byte)
3602: pop ds
3603: pop bx
3604:
3605: pop bp
3606: ASM_END
3607: }
3608:
3609: // --------------------------------------------------------------------------------------------
3610: static Bit16u
3611: read_word(seg, offset)
3612: Bit16u seg;
3613: Bit16u offset;
3614: {
3615: ASM_START
3616: push bp
3617: mov bp, sp
3618:
3619: push bx
3620: push ds
3621: mov ax, 4[bp] ; segment
3622: mov ds, ax
3623: mov bx, 6[bp] ; offset
3624: mov ax, [bx]
3625: ;; ax = return value (word)
3626: pop ds
3627: pop bx
3628:
3629: pop bp
3630: ASM_END
3631: }
3632:
3633: // --------------------------------------------------------------------------------------------
3634: static void
3635: write_byte(seg, offset, data)
3636: Bit16u seg;
3637: Bit16u offset;
3638: Bit8u data;
3639: {
3640: ASM_START
3641: push bp
3642: mov bp, sp
3643:
3644: push ax
3645: push bx
3646: push ds
3647: mov ax, 4[bp] ; segment
3648: mov ds, ax
3649: mov bx, 6[bp] ; offset
3650: mov al, 8[bp] ; data byte
3651: mov [bx], al ; write data byte
3652: pop ds
3653: pop bx
3654: pop ax
3655:
3656: pop bp
3657: ASM_END
3658: }
3659:
3660: // --------------------------------------------------------------------------------------------
3661: static void
3662: write_word(seg, offset, data)
3663: Bit16u seg;
3664: Bit16u offset;
3665: Bit16u data;
3666: {
3667: ASM_START
3668: push bp
3669: mov bp, sp
3670:
3671: push ax
3672: push bx
3673: push ds
3674: mov ax, 4[bp] ; segment
3675: mov ds, ax
3676: mov bx, 6[bp] ; offset
3677: mov ax, 8[bp] ; data word
3678: mov [bx], ax ; write data word
3679: pop ds
3680: pop bx
3681: pop ax
3682:
3683: pop bp
3684: ASM_END
3685: }
3686:
3687: // --------------------------------------------------------------------------------------------
3688: Bit8u
3689: inb(port)
3690: Bit16u port;
3691: {
3692: ASM_START
3693: push bp
3694: mov bp, sp
3695:
3696: push dx
3697: mov dx, 4[bp]
3698: in al, dx
3699: pop dx
3700:
3701: pop bp
3702: ASM_END
3703: }
3704:
3705: Bit16u
3706: inw(port)
3707: Bit16u port;
3708: {
3709: ASM_START
3710: push bp
3711: mov bp, sp
3712:
3713: push dx
3714: mov dx, 4[bp]
3715: in ax, dx
3716: pop dx
3717:
3718: pop bp
3719: ASM_END
3720: }
3721:
3722: // --------------------------------------------------------------------------------------------
3723: void
3724: outb(port, val)
3725: Bit16u port;
3726: Bit8u val;
3727: {
3728: ASM_START
3729: push bp
3730: mov bp, sp
3731:
3732: push ax
3733: push dx
3734: mov dx, 4[bp]
3735: mov al, 6[bp]
3736: out dx, al
3737: pop dx
3738: pop ax
3739:
3740: pop bp
3741: ASM_END
3742: }
3743:
3744: // --------------------------------------------------------------------------------------------
3745: void
3746: outw(port, val)
3747: Bit16u port;
3748: Bit16u val;
3749: {
3750: ASM_START
3751: push bp
3752: mov bp, sp
3753:
3754: push ax
3755: push dx
3756: mov dx, 4[bp]
3757: mov ax, 6[bp]
3758: out dx, ax
3759: pop dx
3760: pop ax
3761:
3762: pop bp
3763: ASM_END
3764: }
3765:
3766: Bit16u get_SS()
3767: {
3768: ASM_START
3769: mov ax, ss
3770: ASM_END
3771: }
3772:
3773: #ifdef DEBUG
3774: void unimplemented()
3775: {
3776: printf("--> Unimplemented\n");
3777: }
3778:
3779: void unknown()
3780: {
3781: printf("--> Unknown int10\n");
3782: }
3783: #endif
3784:
3785: // --------------------------------------------------------------------------------------------
3786: #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3787: void printf(s)
3788: Bit8u *s;
3789: {
3790: Bit8u c, format_char;
3791: Boolean in_format;
3792: unsigned format_width, i;
3793: Bit16u *arg_ptr;
3794: Bit16u arg_seg, arg, digit, nibble, shift_count;
3795:
3796: arg_ptr = &s;
3797: arg_seg = get_SS();
3798:
3799: in_format = 0;
3800: format_width = 0;
3801:
3802: while (c = read_byte(0xc000, s)) {
3803: if ( c == '%' ) {
3804: in_format = 1;
3805: format_width = 0;
3806: }
3807: else if (in_format) {
3808: if ( (c>='0') && (c<='9') ) {
3809: format_width = (format_width * 10) + (c - '0');
3810: }
3811: else if (c == 'x') {
3812: arg_ptr++; // increment to next arg
3813: arg = read_word(arg_seg, arg_ptr);
3814: if (format_width == 0)
3815: format_width = 4;
3816: i = 0;
3817: digit = format_width - 1;
3818: for (i=0; i<format_width; i++) {
3819: nibble = (arg >> (4 * digit)) & 0x000f;
3820: if (nibble <= 9)
3821: outb(0x0500, nibble + '0');
3822: else
3823: outb(0x0500, (nibble - 10) + 'A');
3824: digit--;
3825: }
3826: in_format = 0;
3827: }
3828: //else if (c == 'd') {
3829: // in_format = 0;
3830: // }
3831: }
3832: else {
3833: outb(0x0500, c);
3834: }
3835: s ++;
3836: }
3837: }
3838: #endif
3839:
1.1.1.2 ! root 3840: ASM_START
! 3841: ; get LFB address from PCI
! 3842: ; in - ax: PCI device vendor
! 3843: ; out - ax: LFB address (high 16 bit)
! 3844: ;; NOTE - may be called in protected mode
! 3845: _pci_get_lfb_addr:
! 3846: push bx
! 3847: push cx
! 3848: push dx
! 3849: push eax
! 3850: mov bx, ax
! 3851: xor cx, cx
! 3852: mov dl, #0x00
! 3853: call pci_read_reg
! 3854: cmp ax, #0xffff
! 3855: jz pci_get_lfb_addr_fail
! 3856: pci_get_lfb_addr_next_dev:
! 3857: mov dl, #0x00
! 3858: call pci_read_reg
! 3859: cmp ax, bx ;; check vendor
! 3860: jz pci_get_lfb_addr_found
! 3861: add cx, #0x8
! 3862: cmp cx, #0x200 ;; search bus #0 and #1
! 3863: jb pci_get_lfb_addr_next_dev
! 3864: pci_get_lfb_addr_fail:
! 3865: xor dx, dx ;; no LFB
! 3866: jmp pci_get_lfb_addr_return
! 3867: pci_get_lfb_addr_found:
! 3868: mov dl, #0x10 ;; I/O space #0
! 3869: call pci_read_reg
! 3870: test ax, #0xfff1
! 3871: jz pci_get_lfb_addr_success
! 3872: mov dl, #0x14 ;; I/O space #1
! 3873: call pci_read_reg
! 3874: test ax, #0xfff1
! 3875: jnz pci_get_lfb_addr_fail
! 3876: pci_get_lfb_addr_success:
! 3877: shr eax, #16
! 3878: mov dx, ax ;; LFB address
! 3879: pci_get_lfb_addr_return:
! 3880: pop eax
! 3881: mov ax, dx
! 3882: pop dx
! 3883: pop cx
! 3884: pop bx
! 3885: ret
! 3886:
! 3887: ; read PCI register
! 3888: ; in - cx: device/function
! 3889: ; in - dl: register
! 3890: ; out - eax: value
! 3891: pci_read_reg:
! 3892: mov eax, #0x00800000
! 3893: mov ax, cx
! 3894: shl eax, #8
! 3895: mov al, dl
! 3896: mov dx, #0xcf8
! 3897: out dx, eax
! 3898: add dl, #4
! 3899: in eax, dx
! 3900: ret
! 3901: ASM_END
! 3902:
1.1 root 3903: #ifdef VBE
3904: #include "vbe.c"
3905: #endif
3906:
3907: #ifdef CIRRUS
3908: #include "clext.c"
3909: #endif
3910:
3911: // --------------------------------------------------------------------------------------------
3912:
3913: ASM_START
3914: ;; DATA_SEG_DEFS_HERE
3915: ASM_END
3916:
3917: ASM_START
3918: .ascii "vgabios ends here"
3919: .byte 0x00
3920: vgabios_end:
3921: .byte 0xCB
3922: ;; BLOCK_STRINGS_BEGIN
3923: ASM_END
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.