VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/BIOS/vbe.c@ 10485

Last change on this file since 10485 was 8132, checked in by vboxsync, 17 years ago

more rebranding

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.9 KB
Line 
1// ============================================================================================
2//
3// Copyright (C) 2002 Jeroen Janssen
4//
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; either
8// version 2 of the License, or (at your option) any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18//
19// ============================================================================================
20//
21// This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card.
22// You can NOT drive any physical vga card with it.
23//
24// ============================================================================================
25//
26// This VBE Bios is based on information taken from :
27// - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org
28//
29// ============================================================================================
30
31
32// defines available
33
34// disable VESA/VBE2 check in vbe info
35//#define VBE2_NO_VESA_CHECK
36
37// use bytewise i/o by default (Longhorn issue)
38#define VBE_BYTEWISE_IO
39
40// Use VBE new dynamic mode list. Note that without this option, no
41// checks are currently done to make sure that modes fit into the
42// framebuffer!
43#define VBE_NEW_DYN_LIST
44
45
46#include "vbe.h"
47
48
49// The current OEM Software Revision of this VBE Bios
50#define VBE_OEM_SOFTWARE_REV 0x0002;
51
52extern char vbebios_copyright;
53extern char vbebios_vendor_name;
54extern char vbebios_product_name;
55extern char vbebios_product_revision;
56
57ASM_START
58// FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
59_vbebios_copyright:
60.ascii "VirtualBox VBE BIOS http://www.virtualbox.org/"
61.byte 0x00
62
63_vbebios_vendor_name:
64.ascii "Sun Microsystems, Inc."
65.byte 0x00
66
67_vbebios_product_name:
68.ascii "VirtualBox VBE Adapter"
69.byte 0x00
70
71_vbebios_product_revision:
72.ascii "Sun xVM VirtualBox Version "
73.ascii VBOX_VERSION_STRING
74.byte 0x00
75
76_vbebios_info_string:
77//.ascii "Bochs VBE Display Adapter enabled"
78.ascii "VirtualBox VBE Display Adapter enabled"
79.byte 0x0a,0x0d
80.byte 0x0a,0x0d
81.byte 0x00
82
83_no_vbebios_info_string:
84.ascii "No VirtualBox VBE support available!"
85.byte 0x0a,0x0d
86.byte 0x0a,0x0d
87.byte 0x00
88
89msg_vbe_init:
90.ascii "VirtualBox Version "
91.ascii VBOX_VERSION_STRING
92.ascii " VBE Display Adapter"
93.byte 0x0a,0x0d, 0x00
94
95
96 .align 2
97vesa_pm_start:
98 dw vesa_pm_set_window - vesa_pm_start
99 dw vesa_pm_set_display_start - vesa_pm_start
100 dw vesa_pm_unimplemented - vesa_pm_start
101 dw vesa_pm_io_ports_table - vesa_pm_start
102vesa_pm_io_ports_table:
103 dw VBE_DISPI_IOPORT_INDEX
104 dw VBE_DISPI_IOPORT_INDEX + 1
105 dw VBE_DISPI_IOPORT_DATA
106 dw VBE_DISPI_IOPORT_DATA + 1
107 dw 0xffff
108 dw 0xffff
109
110 USE32
111vesa_pm_set_window:
112 cmp bx, #0x00
113 je vesa_pm_set_display_window1
114 mov ax, #0x0100
115 ret
116vesa_pm_set_display_window1:
117 mov ax, dx
118 push dx
119 push ax
120 mov dx, # VBE_DISPI_IOPORT_INDEX
121 mov ax, # VBE_DISPI_INDEX_BANK
122 out dx, ax
123 pop ax
124 mov dx, # VBE_DISPI_IOPORT_DATA
125 out dx, ax
126 in ax, dx
127 pop dx
128 cmp dx, ax
129 jne illegal_window
130 mov ax, #0x004f
131 ret
132illegal_window:
133 mov ax, #0x014f
134 ret
135vesa_pm_set_display_start:
136 cmp bl, #0x80
137 je vesa_pm_set_display_start1
138 cmp bl, #0x00
139 je vesa_pm_set_display_start1
140 mov ax, #0x0100
141 ret
142vesa_pm_set_display_start1:
143; convert offset to (X, Y) coordinate
144; (would be simpler to change Bochs VBE API...)
145 push eax
146 push ecx
147 push edx
148 push esi
149 push edi
150 shl edx, #16
151 and ecx, #0xffff
152 or ecx, edx
153 shl ecx, #2
154 mov eax, ecx
155 push eax
156 mov dx, # VBE_DISPI_IOPORT_INDEX
157 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
158 out dx, ax
159 mov dx, # VBE_DISPI_IOPORT_DATA
160 in ax, dx
161 movzx ecx, ax
162 mov dx, # VBE_DISPI_IOPORT_INDEX
163 mov ax, # VBE_DISPI_INDEX_BPP
164 out dx, ax
165 mov dx, # VBE_DISPI_IOPORT_DATA
166 in ax, dx
167 movzx esi, ax
168 pop eax
169
170 cmp esi, #4
171 jz bpp4_mode
172 add esi, #7
173 shr esi, #3
174 imul ecx, esi
175 xor edx, edx
176 div ecx
177 mov edi, eax
178 mov eax, edx
179 xor edx, edx
180 div esi
181 jmp set_xy_regs
182
183bpp4_mode:
184 shr ecx, #1
185 xor edx, edx
186 div ecx
187 mov edi, eax
188 mov eax, edx
189 shl eax, #1
190
191set_xy_regs:
192 push dx
193 push ax
194 mov dx, # VBE_DISPI_IOPORT_INDEX
195 mov ax, # VBE_DISPI_INDEX_X_OFFSET
196 out dx, ax
197 pop ax
198 mov dx, # VBE_DISPI_IOPORT_DATA
199 out dx, ax
200 pop dx
201
202 mov ax, di
203 push dx
204 push ax
205 mov dx, # VBE_DISPI_IOPORT_INDEX
206 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
207 out dx, ax
208 pop ax
209 mov dx, # VBE_DISPI_IOPORT_DATA
210 out dx, ax
211 pop dx
212
213 pop edi
214 pop esi
215 pop edx
216 pop ecx
217 pop eax
218 mov ax, #0x004f
219 ret
220
221vesa_pm_unimplemented:
222 mov ax, #0x014f
223 ret
224 USE16
225vesa_pm_end:
226
227;; Bytewise in/out
228#ifdef VBE_BYTEWISE_IO
229out_dx_ax:
230 xchg ah, al
231 out dx, al
232 xchg ah, al
233 out dx, al
234 ret
235
236in_ax_dx:
237 in al, dx
238 xchg ah, al
239 in al, dx
240 ret
241#endif
242
243; DISPI ioport functions
244
245dispi_get_id:
246 push dx
247 mov dx, # VBE_DISPI_IOPORT_INDEX
248 mov ax, # VBE_DISPI_INDEX_ID
249#ifdef VBE_BYTEWISE_IO
250 call out_dx_ax
251#else
252 out dx, ax
253#endif
254 mov dx, # VBE_DISPI_IOPORT_DATA
255#ifdef VBE_BYTEWISE_IO
256 call in_ax_dx
257#else
258 in ax, dx
259#endif
260 pop dx
261 ret
262
263dispi_set_id:
264 push dx
265 push ax
266 mov dx, # VBE_DISPI_IOPORT_INDEX
267 mov ax, # VBE_DISPI_INDEX_ID
268#ifdef VBE_BYTEWISE_IO
269 call out_dx_ax
270#else
271 out dx, ax
272#endif
273 pop ax
274 mov dx, # VBE_DISPI_IOPORT_DATA
275#ifdef VBE_BYTEWISE_IO
276 call out_dx_ax
277#else
278 out dx, ax
279#endif
280 pop dx
281 ret
282ASM_END
283
284static void dispi_set_xres(xres)
285 Bit16u xres;
286{
287ASM_START
288 push bp
289 mov bp, sp
290 push ax
291 push dx
292
293 mov dx, # VBE_DISPI_IOPORT_INDEX
294 mov ax, # VBE_DISPI_INDEX_XRES
295#ifdef VBE_BYTEWISE_IO
296 call out_dx_ax
297#else
298 out dx, ax
299#endif
300 mov dx, # VBE_DISPI_IOPORT_DATA
301 mov ax, 4[bp] ; xres
302#ifdef VBE_BYTEWISE_IO
303 call out_dx_ax
304#else
305 out dx, ax
306#endif
307 pop dx
308 pop ax
309 pop bp
310ASM_END
311}
312
313static void dispi_set_yres(yres)
314 Bit16u yres;
315{
316#ifdef VBOX
317ASM_START
318 push bp
319 mov bp, sp
320 push ax
321 push dx
322
323 mov dx, # VBE_DISPI_IOPORT_INDEX
324 mov ax, # VBE_DISPI_INDEX_YRES
325#ifdef VBE_BYTEWISE_IO
326 call out_dx_ax
327#else
328 out dx, ax
329#endif
330 mov dx, # VBE_DISPI_IOPORT_DATA
331 mov ax, 4[bp] ; yres
332#ifdef VBE_BYTEWISE_IO
333 call out_dx_ax
334#else
335 out dx, ax
336#endif
337 pop dx
338 pop ax
339 pop bp
340ASM_END
341#else
342 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_YRES);
343 outw(VBE_DISPI_IOPORT_DATA,yres);
344#endif
345}
346
347static void dispi_set_bpp(bpp)
348 Bit16u bpp;
349{
350#ifdef VBOX
351ASM_START
352 push bp
353 mov bp, sp
354 push ax
355 push dx
356
357 mov dx, # VBE_DISPI_IOPORT_INDEX
358 mov ax, # VBE_DISPI_INDEX_BPP
359#ifdef VBE_BYTEWISE_IO
360 call out_dx_ax
361#else
362 out dx, ax
363#endif
364 mov dx, # VBE_DISPI_IOPORT_DATA
365 mov ax, 4[bp] ; bpp
366#ifdef VBE_BYTEWISE_IO
367 call out_dx_ax
368#else
369 out dx, ax
370#endif
371 pop dx
372 pop ax
373 pop bp
374ASM_END
375#else
376 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_BPP);
377 outw(VBE_DISPI_IOPORT_DATA,bpp);
378#endif
379}
380
381ASM_START
382; AL = bits per pixel / AH = bytes per pixel
383dispi_get_bpp:
384 push dx
385 mov dx, # VBE_DISPI_IOPORT_INDEX
386 mov ax, # VBE_DISPI_INDEX_BPP
387#ifdef VBE_BYTEWISE_IO
388 call out_dx_ax
389#else
390 out dx, ax
391#endif
392 mov dx, # VBE_DISPI_IOPORT_DATA
393#ifdef VBE_BYTEWISE_IO
394 call in_ax_dx
395#else
396 in ax, dx
397#endif
398 mov ah, al
399 shr ah, 3
400 test al, #0x07
401 jz get_bpp_noinc
402 inc ah
403get_bpp_noinc:
404 pop dx
405 ret
406
407; get display capabilities
408
409_dispi_get_max_xres:
410 push dx
411 push bx
412 call dispi_get_enable
413 mov bx, ax
414 or ax, # VBE_DISPI_GETCAPS
415 call _dispi_set_enable
416 mov dx, # VBE_DISPI_IOPORT_INDEX
417 mov ax, # VBE_DISPI_INDEX_XRES
418#ifdef VBE_BYTEWISE_IO
419 call out_dx_ax
420#else
421 out dx, ax
422#endif
423 mov dx, # VBE_DISPI_IOPORT_DATA
424#ifdef VBE_BYTEWISE_IO
425 call in_ax_dx
426#else
427 in ax, dx
428#endif
429 push ax
430 mov ax, bx
431 call _dispi_set_enable
432 pop ax
433 pop bx
434 pop dx
435 ret
436
437_dispi_get_max_bpp:
438 push dx
439 push bx
440 call dispi_get_enable
441 mov bx, ax
442 or ax, # VBE_DISPI_GETCAPS
443 call _dispi_set_enable
444 mov dx, # VBE_DISPI_IOPORT_INDEX
445 mov ax, # VBE_DISPI_INDEX_BPP
446#ifdef VBE_BYTEWISE_IO
447 call out_dx_ax
448#else
449 out dx, ax
450#endif
451 mov dx, # VBE_DISPI_IOPORT_DATA
452#ifdef VBE_BYTEWISE_IO
453 call in_ax_dx
454#else
455 in ax, dx
456#endif
457 push ax
458 mov ax, bx
459 call _dispi_set_enable
460 pop ax
461 pop bx
462 pop dx
463 ret
464
465_dispi_set_enable:
466 push dx
467 push ax
468 mov dx, # VBE_DISPI_IOPORT_INDEX
469 mov ax, # VBE_DISPI_INDEX_ENABLE
470#ifdef VBE_BYTEWISE_IO
471 call out_dx_ax
472#else
473 out dx, ax
474#endif
475 pop ax
476 mov dx, # VBE_DISPI_IOPORT_DATA
477#ifdef VBE_BYTEWISE_IO
478 call out_dx_ax
479#else
480 out dx, ax
481#endif
482 pop dx
483 ret
484
485dispi_get_enable:
486 push dx
487 mov dx, # VBE_DISPI_IOPORT_INDEX
488 mov ax, # VBE_DISPI_INDEX_ENABLE
489#ifdef VBE_BYTEWISE_IO
490 call out_dx_ax
491#else
492 out dx, ax
493#endif
494 mov dx, # VBE_DISPI_IOPORT_DATA
495#ifdef VBE_BYTEWISE_IO
496 call in_ax_dx
497#else
498 in ax, dx
499#endif
500 pop dx
501 ret
502
503_dispi_set_bank:
504 push dx
505 push ax
506 mov dx, # VBE_DISPI_IOPORT_INDEX
507 mov ax, # VBE_DISPI_INDEX_BANK
508#ifdef VBE_BYTEWISE_IO
509 call out_dx_ax
510#else
511 out dx, ax
512#endif
513 pop ax
514 mov dx, # VBE_DISPI_IOPORT_DATA
515#ifdef VBE_BYTEWISE_IO
516 call out_dx_ax
517#else
518 out dx, ax
519#endif
520 pop dx
521 ret
522
523dispi_get_bank:
524 push dx
525 mov dx, # VBE_DISPI_IOPORT_INDEX
526 mov ax, # VBE_DISPI_INDEX_BANK
527#ifdef VBE_BYTEWISE_IO
528 call out_dx_ax
529#else
530 out dx, ax
531#endif
532 mov dx, # VBE_DISPI_IOPORT_DATA
533#ifdef VBE_BYTEWISE_IO
534 call in_ax_dx
535#else
536 in ax, dx
537#endif
538 pop dx
539 ret
540ASM_END
541
542static void dispi_set_bank_farcall()
543{
544ASM_START
545 cmp bx,#0x0100
546 je dispi_set_bank_farcall_get
547 or bx,bx
548 jnz dispi_set_bank_farcall_error
549 mov ax, dx
550 push dx
551 push ax
552 mov ax,# VBE_DISPI_INDEX_BANK
553 mov dx,# VBE_DISPI_IOPORT_INDEX
554#ifdef VBE_BYTEWISE_IO
555 call out_dx_ax
556#else
557 out dx,ax
558#endif
559 pop ax
560 mov dx,# VBE_DISPI_IOPORT_DATA
561#ifdef VBE_BYTEWISE_IO
562 call out_dx_ax
563#else
564 out dx,ax
565#endif
566#ifdef VBE_BYTEWISE_IO
567 call in_ax_dx
568#else
569 in ax,dx
570#endif
571 pop dx
572 cmp dx,ax
573 jne dispi_set_bank_farcall_error
574 mov ax, #0x004f
575 retf
576dispi_set_bank_farcall_get:
577 mov ax,# VBE_DISPI_INDEX_BANK
578 mov dx,# VBE_DISPI_IOPORT_INDEX
579#ifdef VBE_BYTEWISE_IO
580 call out_dx_ax
581#else
582 out dx,ax
583#endif
584 mov dx,# VBE_DISPI_IOPORT_DATA
585#ifdef VBE_BYTEWISE_IO
586 call in_ax_dx
587#else
588 in ax,dx
589#endif
590 mov dx,ax
591 retf
592dispi_set_bank_farcall_error:
593 mov ax,#0x014F
594 retf
595ASM_END
596}
597
598ASM_START
599dispi_set_x_offset:
600 push dx
601 push ax
602 mov dx, # VBE_DISPI_IOPORT_INDEX
603 mov ax, # VBE_DISPI_INDEX_X_OFFSET
604#ifdef VBE_BYTEWISE_IO
605 call out_dx_ax
606#else
607 out dx, ax
608#endif
609 pop ax
610 mov dx, # VBE_DISPI_IOPORT_DATA
611#ifdef VBE_BYTEWISE_IO
612 call out_dx_ax
613#else
614 out dx, ax
615#endif
616 pop dx
617 ret
618
619dispi_get_x_offset:
620 push dx
621 mov dx, # VBE_DISPI_IOPORT_INDEX
622 mov ax, # VBE_DISPI_INDEX_X_OFFSET
623#ifdef VBE_BYTEWISE_IO
624 call out_dx_ax
625#else
626 out dx, ax
627#endif
628 mov dx, # VBE_DISPI_IOPORT_DATA
629#ifdef VBE_BYTEWISE_IO
630 call in_ax_dx
631#else
632 in ax, dx
633#endif
634 pop dx
635 ret
636
637dispi_set_y_offset:
638 push dx
639 push ax
640 mov dx, # VBE_DISPI_IOPORT_INDEX
641 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
642#ifdef VBE_BYTEWISE_IO
643 call out_dx_ax
644#else
645 out dx, ax
646#endif
647 pop ax
648 mov dx, # VBE_DISPI_IOPORT_DATA
649#ifdef VBE_BYTEWISE_IO
650 call out_dx_ax
651#else
652 out dx, ax
653#endif
654 pop dx
655 ret
656
657dispi_get_y_offset:
658 push dx
659 mov dx, # VBE_DISPI_IOPORT_INDEX
660 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
661#ifdef VBE_BYTEWISE_IO
662 call out_dx_ax
663#else
664 out dx, ax
665#endif
666 mov dx, # VBE_DISPI_IOPORT_DATA
667#ifdef VBE_BYTEWISE_IO
668 call in_ax_dx
669#else
670 in ax, dx
671#endif
672 pop dx
673 ret
674
675vga_set_virt_width:
676 push ax
677 push bx
678 push dx
679 mov bx, ax
680 call dispi_get_bpp
681 cmp al, #0x04
682 ja set_width_svga
683 shr bx, #1
684set_width_svga:
685 shr bx, #3
686 mov dx, # VGAREG_VGA_CRTC_ADDRESS
687 mov ah, bl
688 mov al, #0x13
689#ifdef VBE_BYTEWISE_IO
690 call out_dx_ax
691#else
692 out dx, ax
693#endif
694 pop dx
695 pop bx
696 pop ax
697 ret
698
699dispi_set_virt_width:
700 call vga_set_virt_width
701 push dx
702 push ax
703 mov dx, # VBE_DISPI_IOPORT_INDEX
704 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
705#ifdef VBE_BYTEWISE_IO
706 call out_dx_ax
707#else
708 out dx, ax
709#endif
710 pop ax
711 mov dx, # VBE_DISPI_IOPORT_DATA
712#ifdef VBE_BYTEWISE_IO
713 call out_dx_ax
714#else
715 out dx, ax
716#endif
717 pop dx
718 ret
719
720dispi_get_virt_width:
721 push dx
722 mov dx, # VBE_DISPI_IOPORT_INDEX
723 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
724#ifdef VBE_BYTEWISE_IO
725 call out_dx_ax
726#else
727 out dx, ax
728#endif
729 mov dx, # VBE_DISPI_IOPORT_DATA
730#ifdef VBE_BYTEWISE_IO
731 call in_ax_dx
732#else
733 in ax, dx
734#endif
735 pop dx
736 ret
737
738dispi_get_virt_height:
739 push dx
740 mov dx, # VBE_DISPI_IOPORT_INDEX
741 mov ax, # VBE_DISPI_INDEX_VIRT_HEIGHT
742#ifdef VBE_BYTEWISE_IO
743 call out_dx_ax
744#else
745 out dx, ax
746#endif
747 mov dx, # VBE_DISPI_IOPORT_DATA
748#ifdef VBE_BYTEWISE_IO
749 call in_ax_dx
750#else
751 in ax, dx
752#endif
753 pop dx
754 ret
755
756_vga_compat_setup:
757 push ax
758 push dx
759
760 ; set CRT X resolution
761 mov dx, # VBE_DISPI_IOPORT_INDEX
762 mov ax, # VBE_DISPI_INDEX_XRES
763#ifdef VBE_BYTEWISE_IO
764 call out_dx_ax
765#else
766 out dx, ax
767#endif
768 mov dx, # VBE_DISPI_IOPORT_DATA
769#ifdef VBE_BYTEWISE_IO
770 call in_ax_dx
771#else
772 in ax, dx
773#endif
774 push ax
775 mov dx, # VGAREG_VGA_CRTC_ADDRESS
776 mov ax, #0x0011
777#ifdef VBE_BYTEWISE_IO
778 call out_dx_ax
779#else
780 out dx, ax
781#endif
782 pop ax
783 push ax
784 shr ax, #3
785 dec ax
786 mov ah, al
787 mov al, #0x01
788#ifdef VBE_BYTEWISE_IO
789 call out_dx_ax
790#else
791 out dx, ax
792#endif
793 pop ax
794 call vga_set_virt_width
795
796 ; set CRT Y resolution
797 mov dx, # VBE_DISPI_IOPORT_INDEX
798 mov ax, # VBE_DISPI_INDEX_YRES
799#ifdef VBE_BYTEWISE_IO
800 call out_dx_ax
801#else
802 out dx, ax
803#endif
804 mov dx, # VBE_DISPI_IOPORT_DATA
805#ifdef VBE_BYTEWISE_IO
806 call in_ax_dx
807#else
808 in ax, dx
809#endif
810 dec ax
811 push ax
812 mov dx, # VGAREG_VGA_CRTC_ADDRESS
813 mov ah, al
814 mov al, #0x12
815#ifdef VBE_BYTEWISE_IO
816 call out_dx_ax
817#else
818 out dx, ax
819#endif
820 pop ax
821 mov al, #0x07
822 out dx, al
823 inc dx
824 in al, dx
825 and al, #0xbd
826 test ah, #0x01
827 jz bit8_clear
828 or al, #0x02
829bit8_clear:
830 test ah, #0x02
831 jz bit9_clear
832 or al, #0x40
833bit9_clear:
834 out dx, al
835
836 ; other settings
837 mov dx, # VGAREG_VGA_CRTC_ADDRESS
838 mov ax, #0x0009
839#ifdef VBE_BYTEWISE_IO
840 call out_dx_ax
841#else
842 out dx, ax
843#endif
844 mov al, #0x17
845 out dx, al
846 mov dx, # VGAREG_VGA_CRTC_DATA
847 in al, dx
848 or al, #0x03
849 out dx, al
850 mov dx, # VGAREG_ACTL_RESET
851 in al, dx
852 mov dx, # VGAREG_ACTL_ADDRESS
853 mov al, #0x10
854 out dx, al
855 mov dx, # VGAREG_ACTL_READ_DATA
856 in al, dx
857 or al, #0x01
858 mov dx, # VGAREG_ACTL_ADDRESS
859 out dx, al
860 mov al, #0x20
861 out dx, al
862 mov dx, # VGAREG_GRDC_ADDRESS
863 mov ax, #0x0506
864#ifdef VBE_BYTEWISE_IO
865 call out_dx_ax
866#else
867 out dx, ax
868#endif
869 mov dx, # VGAREG_SEQU_ADDRESS
870 mov ax, #0x0f02
871#ifdef VBE_BYTEWISE_IO
872 call out_dx_ax
873#else
874 out dx, ax
875#endif
876
877 ; settings for >= 8bpp
878 mov dx, # VBE_DISPI_IOPORT_INDEX
879 mov ax, # VBE_DISPI_INDEX_BPP
880#ifdef VBE_BYTEWISE_IO
881 call out_dx_ax
882#else
883 out dx, ax
884#endif
885 mov dx, # VBE_DISPI_IOPORT_DATA
886#ifdef VBE_BYTEWISE_IO
887 call in_ax_dx
888#else
889 in ax, dx
890#endif
891 cmp al, #0x08
892 jb vga_compat_end
893 mov dx, # VGAREG_VGA_CRTC_ADDRESS
894 mov al, #0x14
895 out dx, al
896 mov dx, # VGAREG_VGA_CRTC_DATA
897 in al, dx
898 or al, #0x40
899 out dx, al
900 mov dx, # VGAREG_ACTL_RESET
901 in al, dx
902 mov dx, # VGAREG_ACTL_ADDRESS
903 mov al, #0x10
904 out dx, al
905 mov dx, # VGAREG_ACTL_READ_DATA
906 in al, dx
907 or al, #0x40
908 mov dx, # VGAREG_ACTL_ADDRESS
909 out dx, al
910 mov al, #0x20
911 out dx, al
912 mov dx, # VGAREG_SEQU_ADDRESS
913 mov al, #0x04
914 out dx, al
915 mov dx, # VGAREG_SEQU_DATA
916 in al, dx
917 or al, #0x08
918 out dx, al
919 mov dx, # VGAREG_GRDC_ADDRESS
920 mov al, #0x05
921 out dx, al
922 mov dx, # VGAREG_GRDC_DATA
923 in al, dx
924 and al, #0x9f
925 or al, #0x40
926 out dx, al
927
928vga_compat_end:
929 pop dx
930 pop ax
931ASM_END
932
933
934#ifdef VBE_NEW_DYN_LIST
935Bit16u in_word(port, addr)
936 Bit16u port; Bit16u addr;
937{
938 outw(port, addr);
939 return inw(port);
940}
941
942Bit8u in_byte(port, addr)
943 Bit16u port; Bit16u addr;
944{
945 outw(port, addr);
946 return inb(port);
947}
948#endif
949
950
951// ModeInfo helper function
952static ModeInfoListItem* mode_info_find_mode(mode, using_lfb)
953 Bit16u mode; Boolean using_lfb;
954{
955#ifdef VBE_NEW_DYN_LIST
956 Bit16u sig, vmode, attrs;
957 ModeInfoListItem *cur_info; /* used to get the mode list offset. */
958
959 /* Read VBE Extra Data signature */
960 sig = in_word(VBE_EXTRA_PORT, 0);
961 if (sig != VBEHEADER_MAGIC)
962 {
963 printf("Signature NOT found! %x\n", sig);
964 return 0;
965 }
966
967 cur_info = sizeof(VBEHeader);
968
969 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
970 while (vmode != VBE_VESA_MODE_END_OF_LIST)
971 {
972 attrs = in_word(VBE_EXTRA_PORT, &cur_info->info.ModeAttributes);
973
974 if (vmode == mode)
975 {
976 if (!using_lfb)
977 {
978 return cur_info;
979 }
980 else if (attrs & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
981 {
982 return cur_info;
983 }
984 else
985 {
986 cur_info++;
987 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
988 }
989 }
990 else
991 {
992 cur_info++;
993 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
994 }
995 }
996#else
997 ModeInfoListItem *cur_info=&mode_info_list;
998
999 while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
1000 {
1001 if (cur_info->mode == mode)
1002 {
1003 if (!using_lfb)
1004 {
1005 return cur_info;
1006 }
1007 else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
1008 {
1009 return cur_info;
1010 }
1011 else
1012 {
1013 cur_info++;
1014 }
1015 }
1016 else
1017 {
1018 cur_info++;
1019 }
1020 }
1021#endif
1022 return 0;
1023}
1024
1025ASM_START
1026
1027; Has VBE display - Returns true if VBE display detected
1028
1029_vbe_has_vbe_display:
1030 push ds
1031 push bx
1032 mov ax, # BIOSMEM_SEG
1033 mov ds, ax
1034 mov bx, # BIOSMEM_VBE_FLAG
1035 mov al, [bx]
1036 and al, #0x01
1037 xor ah, ah
1038 pop bx
1039 pop ds
1040 ret
1041
1042; VBE Init - Initialise the Vesa Bios Extension Code
1043; This function does a sanity check on the host side display code interface.
1044
1045vbe_init:
1046 mov ax, # VBE_DISPI_ID0
1047 call dispi_set_id
1048 call dispi_get_id
1049 cmp ax, # VBE_DISPI_ID0
1050 jne no_vbe_interface
1051 push ds
1052 push bx
1053 mov ax, # BIOSMEM_SEG
1054 mov ds, ax
1055 mov bx, # BIOSMEM_VBE_FLAG
1056 mov al, #0x01
1057 mov [bx], al
1058 pop bx
1059 pop ds
1060; mov ax, # VBE_DISPI_ID3
1061 mov ax, # VBE_DISPI_ID4
1062 call dispi_set_id
1063no_vbe_interface:
1064#if defined(DEBUG)
1065 mov bx, #msg_vbe_init
1066 push bx
1067 call _printf
1068 inc sp
1069 inc sp
1070#endif
1071 ret
1072
1073#ifndef VBOX
1074; VBE Display Info - Display information on screen about the VBE
1075
1076vbe_display_info:
1077 call _vbe_has_vbe_display
1078 test ax, ax
1079 jz no_vbe_flag
1080 mov ax, #0xc000
1081 mov ds, ax
1082 mov si, #_vbebios_info_string
1083 jmp _display_string
1084no_vbe_flag:
1085 mov ax, #0xc000
1086 mov ds, ax
1087 mov si, #_no_vbebios_info_string
1088 jmp _display_string
1089#endif
1090
1091ASM_END
1092
1093/** Function 00h - Return VBE Controller Information
1094 *
1095 * Input:
1096 * AX = 4F00h
1097 * ES:DI = Pointer to buffer in which to place VbeInfoBlock structure
1098 * (VbeSignature should be VBE2 when VBE 2.0 information is desired and
1099 * the info block is 512 bytes in size)
1100 * Output:
1101 * AX = VBE Return Status
1102 *
1103 */
1104void vbe_biosfn_return_controller_information(AX, ES, DI)
1105Bit16u *AX;Bit16u ES;Bit16u DI;
1106{
1107 Bit16u ss=get_SS();
1108 VbeInfoBlock vbe_info_block;
1109 Bit16u status;
1110 Bit16u result;
1111 Bit16u vbe2_info;
1112 Bit16u cur_mode=0;
1113 Bit16u cur_ptr=34;
1114#ifdef VBE_NEW_DYN_LIST
1115 ModeInfoListItem *cur_info; /* used to get the mode list offset. */
1116 Bit16u sig, vmode;
1117 Bit16u max_bpp=dispi_get_max_bpp();
1118#else
1119 ModeInfoListItem *cur_info=&mode_info_list;
1120#endif
1121
1122#ifdef VBE_NEW_DYN_LIST
1123 /* Read VBE Extra Data signature */
1124 sig = in_word(VBE_EXTRA_PORT, 0);
1125 if (sig != VBEHEADER_MAGIC)
1126 {
1127 result = 0x100;
1128
1129 write_word(ss, AX, result);
1130
1131 printf("Signature NOT found\n");
1132 return;
1133 }
1134 cur_info = sizeof(VBEHeader);
1135#endif
1136 status = read_word(ss, AX);
1137
1138#ifdef DEBUG
1139 printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
1140#endif
1141
1142 vbe2_info = 0;
1143#ifdef VBE2_NO_VESA_CHECK
1144#else
1145 // get vbe_info_block into local variable
1146 memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
1147
1148 // check for VBE2 signature
1149 if (((vbe_info_block.VbeSignature[0] == 'V') &&
1150 (vbe_info_block.VbeSignature[1] == 'B') &&
1151 (vbe_info_block.VbeSignature[2] == 'E') &&
1152 (vbe_info_block.VbeSignature[3] == '2')) ||
1153
1154 ((vbe_info_block.VbeSignature[0] == 'V') &&
1155 (vbe_info_block.VbeSignature[1] == 'E') &&
1156 (vbe_info_block.VbeSignature[2] == 'S') &&
1157 (vbe_info_block.VbeSignature[3] == 'A')) )
1158 {
1159 vbe2_info = 1;
1160#ifdef DEBUG
1161 printf("VBE correct VESA/VBE2 signature found\n");
1162#endif
1163 }
1164#endif
1165
1166 // VBE Signature
1167 vbe_info_block.VbeSignature[0] = 'V';
1168 vbe_info_block.VbeSignature[1] = 'E';
1169 vbe_info_block.VbeSignature[2] = 'S';
1170 vbe_info_block.VbeSignature[3] = 'A';
1171
1172 // VBE Version supported
1173 vbe_info_block.VbeVersion = 0x0200;
1174
1175 // OEM String
1176 vbe_info_block.OemStringPtr_Seg = 0xc000;
1177 vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
1178
1179 // Capabilities
1180 vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
1181 vbe_info_block.Capabilities[1] = 0;
1182 vbe_info_block.Capabilities[2] = 0;
1183 vbe_info_block.Capabilities[3] = 0;
1184
1185 // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
1186 vbe_info_block.VideoModePtr_Seg= ES ;
1187 vbe_info_block.VideoModePtr_Off= DI + 34;
1188
1189 // VBE Total Memory (in 64b blocks)
1190 vbe_info_block.TotalMemory = in_word(VBE_EXTRA_PORT, 0xffff);
1191
1192 if (vbe2_info)
1193 {
1194 // OEM Stuff
1195 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
1196 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
1197 vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
1198 vbe_info_block.OemProductNamePtr_Seg = 0xc000;
1199 vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
1200 vbe_info_block.OemProductRevPtr_Seg = 0xc000;
1201 vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
1202
1203 // copy updates in vbe_info_block back
1204 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
1205 }
1206 else
1207 {
1208 // copy updates in vbe_info_block back (VBE 1.x compatibility)
1209 memcpyb(ES, DI, ss, &vbe_info_block, 256);
1210 }
1211
1212#ifdef VBE_NEW_DYN_LIST
1213 do
1214 {
1215 Bit16u data;
1216 Bit8u data_b;
1217
1218 data_b = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1219 if (data_b <= max_bpp)
1220 {
1221 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
1222#ifdef DEBUG
1223 printf("VBE found mode %x => %x\n", vmode, cur_mode);
1224#endif
1225 write_word(ES, DI + cur_ptr, vmode);
1226 cur_mode++;
1227 cur_ptr+=2;
1228 }
1229 cur_info++;
1230 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
1231 } while (vmode != VBE_VESA_MODE_END_OF_LIST);
1232
1233 // Add vesa mode list terminator
1234 write_word(ES, DI + cur_ptr, vmode);
1235#else
1236 do
1237 {
1238 if (cur_info->info.BitsPerPixel <= max_bpp) {
1239#ifdef DEBUG
1240 printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
1241#endif
1242 write_word(ES, DI + cur_ptr, cur_info->mode);
1243 cur_mode++;
1244 cur_ptr+=2;
1245 }
1246 cur_info++;
1247 } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
1248
1249 // Add vesa mode list terminator
1250 write_word(ES, DI + cur_ptr, cur_info->mode);
1251#endif // VBE_NEW_DYN_LIST
1252
1253 result = 0x4f;
1254
1255 write_word(ss, AX, result);
1256}
1257
1258
1259/** Function 01h - Return VBE Mode Information
1260 *
1261 * Input:
1262 * AX = 4F01h
1263 * CX = Mode Number
1264 * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure
1265 * Output:
1266 * AX = VBE Return Status
1267 *
1268 */
1269void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
1270Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
1271{
1272 Bit16u result=0x0100;
1273 Bit16u ss=get_SS();
1274 ModeInfoBlock info;
1275 ModeInfoListItem *cur_info;
1276 Boolean using_lfb;
1277
1278#ifdef DEBUG
1279 printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
1280#endif
1281
1282 using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
1283
1284 CX = (CX & 0x1ff);
1285
1286 cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
1287
1288 if (cur_info != 0)
1289 {
1290#ifdef VBE_NEW_DYN_LIST
1291 Bit16u i;
1292#endif
1293#ifdef DEBUG
1294 printf("VBE found mode %x\n",CX);
1295#endif
1296 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
1297#ifdef VBE_NEW_DYN_LIST
1298 for (i = 0; i < sizeof(ModeInfoBlockCompact); i++)
1299 {
1300 Bit8u b;
1301
1302 b = in_byte(VBE_EXTRA_PORT, (char *)(&(cur_info->info)) + i);
1303 write_byte(ss, (char *)(&info) + i, b);
1304 }
1305#else
1306 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
1307#endif
1308 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
1309 info.WinFuncPtr = 0xC0000000UL;
1310 *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
1311 }
1312
1313 result = 0x4f;
1314 }
1315 else
1316 {
1317#ifdef DEBUG
1318 printf("VBE *NOT* found mode %x\n",CX);
1319#endif
1320 result = 0x100;
1321 }
1322
1323 if (result == 0x4f)
1324 {
1325 // copy updates in mode_info_block back
1326 memcpyb(ES, DI, ss, &info, sizeof(info));
1327 }
1328
1329 write_word(ss, AX, result);
1330}
1331
1332/** Function 02h - Set VBE Mode
1333 *
1334 * Input:
1335 * AX = 4F02h
1336 * BX = Desired Mode to set
1337 * ES:DI = Pointer to CRTCInfoBlock structure
1338 * Output:
1339 * AX = VBE Return Status
1340 *
1341 */
1342void vbe_biosfn_set_mode(AX, BX, ES, DI)
1343Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
1344{
1345 Bit16u ss = get_SS();
1346 Bit16u result;
1347 ModeInfoListItem *cur_info;
1348 Boolean using_lfb;
1349 Bit8u no_clear;
1350 Bit8u lfb_flag;
1351
1352 using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
1353 lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
1354 no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
1355
1356 BX = (BX & 0x1ff);
1357
1358 //result=read_word(ss,AX);
1359
1360 // check for non vesa mode
1361 if (BX<VBE_MODE_VESA_DEFINED)
1362 {
1363 Bit8u mode;
1364
1365 dispi_set_enable(VBE_DISPI_DISABLED);
1366 // call the vgabios in order to set the video mode
1367 // this allows for going back to textmode with a VBE call (some applications expect that to work)
1368
1369 mode=(BX & 0xff);
1370 biosfn_set_video_mode(mode);
1371 result = 0x4f;
1372 goto leave;
1373 }
1374
1375 cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
1376
1377 if (cur_info != 0)
1378 {
1379#ifdef VBE_NEW_DYN_LIST
1380 Bit16u data;
1381 Bit8u data_b;
1382 Bit16u x, y;
1383 Bit8u bpp;
1384
1385 x = in_word(VBE_EXTRA_PORT, &cur_info->info.XResolution); /* cur_info is really an offset here */
1386 y = in_word(VBE_EXTRA_PORT, &cur_info->info.YResolution);
1387 bpp = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1388
1389#ifdef DEBUG
1390 printf("VBE found mode %x, setting:\n", BX);
1391 printf("\txres%x yres%x bpp%x\n", x, y, bpp);
1392#endif
1393#else
1394#ifdef DEBUG
1395 printf("VBE found mode %x, setting:\n", BX);
1396 printf("\txres%x yres%x bpp%x\n",
1397 cur_info->info.XResolution,
1398 cur_info->info.YResolution,
1399 cur_info->info.BitsPerPixel);
1400#endif
1401#endif // VBE_NEW_DYN_LIST
1402
1403 // first disable current mode (when switching between vesa modi)
1404 dispi_set_enable(VBE_DISPI_DISABLED);
1405
1406#ifdef VBE_NEW_DYN_LIST
1407 data = in_word(VBE_EXTRA_PORT, &cur_info->mode);
1408 if (data == VBE_VESA_MODE_800X600X4)
1409#else
1410 if (cur_info->mode == VBE_VESA_MODE_800X600X4)
1411#endif
1412 {
1413 biosfn_set_video_mode(0x6a);
1414 }
1415
1416#ifdef VBE_NEW_DYN_LIST
1417 data_b = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1418 dispi_set_bpp(data_b);
1419 data = in_word(VBE_EXTRA_PORT, &cur_info->info.XResolution);
1420 dispi_set_xres(data);
1421 data = in_word(VBE_EXTRA_PORT, &cur_info->info.YResolution);
1422 dispi_set_yres(data);
1423#else
1424 dispi_set_bpp(cur_info->info.BitsPerPixel);
1425 dispi_set_xres(cur_info->info.XResolution);
1426 dispi_set_yres(cur_info->info.YResolution);
1427#endif
1428 dispi_set_bank(0);
1429 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
1430 vga_compat_setup();
1431
1432 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
1433 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
1434
1435 result = 0x4f;
1436 }
1437 else
1438 {
1439#ifdef DEBUG
1440 printf("VBE *NOT* found mode %x\n" , BX);
1441#endif
1442 result = 0x100;
1443 }
1444
1445leave:
1446 write_word(ss, AX, result);
1447}
1448
1449/** Function 03h - Return Current VBE Mode
1450 *
1451 * Input:
1452 * AX = 4F03h
1453 * Output:
1454 * AX = VBE Return Status
1455 * BX = Current VBE Mode
1456 *
1457 */
1458ASM_START
1459vbe_biosfn_return_current_mode:
1460 push ds
1461 mov ax, # BIOSMEM_SEG
1462 mov ds, ax
1463 call dispi_get_enable
1464 and ax, # VBE_DISPI_ENABLED
1465 jz no_vbe_mode
1466 mov bx, # BIOSMEM_VBE_MODE
1467 mov ax, [bx]
1468 mov bx, ax
1469 jnz vbe_03_ok
1470no_vbe_mode:
1471 mov bx, # BIOSMEM_CURRENT_MODE
1472 mov al, [bx]
1473 mov bl, al
1474 xor bh, bh
1475vbe_03_ok:
1476 mov ax, #0x004f
1477 pop ds
1478 ret
1479ASM_END
1480
1481Bit16u vbe_biosfn_read_video_state_size()
1482{
1483 return 9 * 2;
1484}
1485
1486void vbe_biosfn_save_video_state(ES, BX)
1487 Bit16u ES; Bit16u BX;
1488{
1489 Bit16u enable, i;
1490
1491 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1492 enable = inw(VBE_DISPI_IOPORT_DATA);
1493 write_word(ES, BX, enable);
1494 BX += 2;
1495 if (!(enable & VBE_DISPI_ENABLED))
1496 return;
1497 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
1498 if (i != VBE_DISPI_INDEX_ENABLE) {
1499 outw(VBE_DISPI_IOPORT_INDEX, i);
1500 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
1501 BX += 2;
1502 }
1503 }
1504}
1505
1506
1507void vbe_biosfn_restore_video_state(ES, BX)
1508 Bit16u ES; Bit16u BX;
1509{
1510 Bit16u enable, i;
1511
1512 enable = read_word(ES, BX);
1513 BX += 2;
1514
1515 if (!(enable & VBE_DISPI_ENABLED)) {
1516 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1517 outw(VBE_DISPI_IOPORT_DATA, enable);
1518 } else {
1519 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
1520 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1521 BX += 2;
1522 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
1523 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1524 BX += 2;
1525 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
1526 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1527 BX += 2;
1528 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1529 outw(VBE_DISPI_IOPORT_DATA, enable);
1530
1531 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
1532 outw(VBE_DISPI_IOPORT_INDEX, i);
1533 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1534 BX += 2;
1535 }
1536 }
1537}
1538
1539/** Function 04h - Save/Restore State
1540 *
1541 * Input:
1542 * AX = 4F04h
1543 * DL = 00h Return Save/Restore State buffer size
1544 * 01h Save State
1545 * 02h Restore State
1546 * CX = Requested states
1547 * ES:BX = Pointer to buffer (if DL <> 00h)
1548 * Output:
1549 * AX = VBE Return Status
1550 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
1551 *
1552 */
1553void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
1554Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
1555{
1556 Bit16u ss=get_SS();
1557 Bit16u result, val;
1558
1559 result = 0x4f;
1560 switch(GET_DL()) {
1561 case 0x00:
1562 val = biosfn_read_video_state_size2(CX);
1563#ifdef DEBUG
1564 printf("VGA state size=%x\n", val);
1565#endif
1566 if (CX & 8)
1567 val += vbe_biosfn_read_video_state_size();
1568 write_word(ss, BX, val);
1569 break;
1570 case 0x01:
1571 val = read_word(ss, BX);
1572 val = biosfn_save_video_state(CX, ES, val);
1573#ifdef DEBUG
1574 printf("VGA save_state offset=%x\n", val);
1575#endif
1576 if (CX & 8)
1577 vbe_biosfn_save_video_state(ES, val);
1578 break;
1579 case 0x02:
1580 val = read_word(ss, BX);
1581 val = biosfn_restore_video_state(CX, ES, val);
1582#ifdef DEBUG
1583 printf("VGA restore_state offset=%x\n", val);
1584#endif
1585 if (CX & 8)
1586 vbe_biosfn_restore_video_state(ES, val);
1587 break;
1588 default:
1589 // function failed
1590 result = 0x100;
1591 break;
1592 }
1593 write_word(ss, AX, result);
1594}
1595
1596
1597/** Function 05h - Display Window Control
1598 *
1599 * Input:
1600 * AX = 4F05h
1601 * (16-bit) BH = 00h Set memory window
1602 * = 01h Get memory window
1603 * BL = Window number
1604 * = 00h Window A
1605 * = 01h Window B
1606 * DX = Window number in video memory in window
1607 * granularity units (Set Memory Window only)
1608 * Note:
1609 * If this function is called while in a linear frame buffer mode,
1610 * this function must fail with completion code AH=03h
1611 *
1612 * Output:
1613 * AX = VBE Return Status
1614 * DX = Window number in window granularity units
1615 * (Get Memory Window only)
1616 */
1617ASM_START
1618vbe_biosfn_display_window_control:
1619 cmp bl, #0x00
1620 jne vbe_05_failed
1621 cmp bh, #0x01
1622 je get_display_window
1623 jb set_display_window
1624 mov ax, #0x0100
1625 ret
1626set_display_window:
1627 mov ax, dx
1628 call _dispi_set_bank
1629 call dispi_get_bank
1630 cmp ax, dx
1631 jne vbe_05_failed
1632 mov ax, #0x004f
1633 ret
1634get_display_window:
1635 call dispi_get_bank
1636 mov dx, ax
1637 mov ax, #0x004f
1638 ret
1639vbe_05_failed:
1640 mov ax, #0x014f
1641 ret
1642ASM_END
1643
1644
1645/** Function 06h - Set/Get Logical Scan Line Length
1646 *
1647 * Input:
1648 * AX = 4F06h
1649 * BL = 00h Set Scan Line Length in Pixels
1650 * = 01h Get Scan Line Length
1651 * = 02h Set Scan Line Length in Bytes
1652 * = 03h Get Maximum Scan Line Length
1653 * CX = If BL=00h Desired Width in Pixels
1654 * If BL=02h Desired Width in Bytes
1655 * (Ignored for Get Functions)
1656 *
1657 * Output:
1658 * AX = VBE Return Status
1659 * BX = Bytes Per Scan Line
1660 * CX = Actual Pixels Per Scan Line
1661 * (truncated to nearest complete pixel)
1662 * DX = Maximum Number of Scan Lines
1663 */
1664ASM_START
1665vbe_biosfn_set_get_logical_scan_line_length:
1666 mov ax, cx
1667 cmp bl, #0x01
1668 je get_logical_scan_line_length
1669 cmp bl, #0x02
1670 je set_logical_scan_line_bytes
1671 jb set_logical_scan_line_pixels
1672 mov ax, #0x0100
1673 ret
1674set_logical_scan_line_bytes:
1675 push ax
1676 call dispi_get_bpp
1677 xor bh, bh
1678 mov bl, ah
1679 or bl, bl
1680 jnz no_4bpp_1
1681 shl ax, #3
1682 mov bl, #1
1683no_4bpp_1:
1684 xor dx, dx
1685 pop ax
1686 div bx
1687set_logical_scan_line_pixels:
1688 call dispi_set_virt_width
1689get_logical_scan_line_length:
1690 call dispi_get_bpp
1691 xor bh, bh
1692 mov bl, ah
1693 call dispi_get_virt_width
1694 mov cx, ax
1695 or bl, bl
1696 jnz no_4bpp_2
1697 shr ax, #3
1698 mov bl, #1
1699no_4bpp_2:
1700 mul bx
1701 mov bx, ax
1702 call dispi_get_virt_height
1703 mov dx, ax
1704 mov ax, #0x004f
1705 ret
1706ASM_END
1707
1708
1709/** Function 07h - Set/Get Display Start
1710 *
1711 * Input(16-bit):
1712 * AX = 4F07h
1713 * BH = 00h Reserved and must be 00h
1714 * BL = 00h Set Display Start
1715 * = 01h Get Display Start
1716 * = 02h Schedule Display Start (Alternate)
1717 * = 03h Schedule Stereoscopic Display Start
1718 * = 04h Get Scheduled Display Start Status
1719 * = 05h Enable Stereoscopic Mode
1720 * = 06h Disable Stereoscopic Mode
1721 * = 80h Set Display Start during Vertical Retrace
1722 * = 82h Set Display Start during Vertical Retrace (Alternate)
1723 * = 83h Set Stereoscopic Display Start during Vertical Retrace
1724 * ECX = If BL=02h/82h Display Start Address in bytes
1725 * If BL=03h/83h Left Image Start Address in bytes
1726 * EDX = If BL=03h/83h Right Image Start Address in bytes
1727 * CX = If BL=00h/80h First Displayed Pixel In Scan Line
1728 * DX = If BL=00h/80h First Displayed Scan Line
1729 *
1730 * Output:
1731 * AX = VBE Return Status
1732 * BH = If BL=01h Reserved and will be 0
1733 * CX = If BL=01h First Displayed Pixel In Scan Line
1734 * If BL=04h 0 if flip has not occurred, not 0 if it has
1735 * DX = If BL=01h First Displayed Scan Line
1736 *
1737 * Input(32-bit):
1738 * BH = 00h Reserved and must be 00h
1739 * BL = 00h Set Display Start
1740 * = 80h Set Display Start during Vertical Retrace
1741 * CX = Bits 0-15 of display start address
1742 * DX = Bits 16-31 of display start address
1743 * ES = Selector for memory mapped registers
1744 */
1745ASM_START
1746vbe_biosfn_set_get_display_start:
1747 cmp bl, #0x80
1748 je set_display_start
1749 cmp bl, #0x01
1750 je get_display_start
1751 jb set_display_start
1752 mov ax, #0x0100
1753 ret
1754set_display_start:
1755 mov ax, cx
1756 call dispi_set_x_offset
1757 mov ax, dx
1758 call dispi_set_y_offset
1759 mov ax, #0x004f
1760 ret
1761get_display_start:
1762 call dispi_get_x_offset
1763 mov cx, ax
1764 call dispi_get_y_offset
1765 mov dx, ax
1766 xor bh, bh
1767 mov ax, #0x004f
1768 ret
1769ASM_END
1770
1771
1772/** Function 08h - Set/Get Dac Palette Format
1773 *
1774 * Input:
1775 * AX = 4F08h
1776 * BL = 00h set DAC palette width
1777 * = 01h get DAC palette width
1778 * BH = If BL=00h: desired number of bits per primary color
1779 * Output:
1780 * AX = VBE Return Status
1781 * BH = current number of bits per primary color (06h = standard VGA)
1782 */
1783ASM_START
1784vbe_biosfn_set_get_dac_palette_format:
1785 cmp bl, #0x01
1786 je get_dac_palette_format
1787 jb set_dac_palette_format
1788 mov ax, #0x0100
1789 ret
1790set_dac_palette_format:
1791 call dispi_get_enable
1792 cmp bh, #0x06
1793 je set_normal_dac
1794 cmp bh, #0x08
1795 jne vbe_08_unsupported
1796 or ax, # VBE_DISPI_8BIT_DAC
1797 jnz set_dac_mode
1798set_normal_dac:
1799 and ax, #~ VBE_DISPI_8BIT_DAC
1800set_dac_mode:
1801 call _dispi_set_enable
1802get_dac_palette_format:
1803 mov bh, #0x06
1804 call dispi_get_enable
1805 and ax, # VBE_DISPI_8BIT_DAC
1806 jz vbe_08_ok
1807 mov bh, #0x08
1808vbe_08_ok:
1809 mov ax, #0x004f
1810 ret
1811vbe_08_unsupported:
1812 mov ax, #0x014f
1813 ret
1814ASM_END
1815
1816
1817/** Function 09h - Set/Get Palette Data
1818 *
1819 * Input:
1820 * AX = 4F09h
1821 * (16-bit) BL = 00h Set palette data
1822 * = 01h Get palette data
1823 * = 02h Set secondary palette data
1824 * = 03h Get secondary palette data
1825 * = 80h Set palette data during VRetrace
1826 * CX = Number of entries to update (<= 256)
1827 * DX = First entry to update
1828 * ES:DI = Table of palette values
1829 * Output:
1830 * AX = VBE Return Status
1831 *
1832 * Notes:
1833 * Secondary palette support is a "future extension".
1834 * Attempts to set/get it should return status 02h.
1835 *
1836 * In VBE 3.0, reading palette data is optional and
1837 * subfunctions 01h and 03h may return failure.
1838 *
1839 * The format of palette entries is as follows:
1840 *
1841 * PaletteEntry struc
1842 * Blue db ? ; Blue channel value (6 or 8 bits)
1843 * Green db ? ; Green channel value (6 or 8 bits)
1844 * Red db ? ; Red channel value (6 or 8 bits)
1845 * Padding db ? ; DWORD alignment byte (unused)
1846 * PaletteEntry ends
1847 *
1848 * Most applications use VGA DAC registers directly to
1849 * set/get palette in VBE modes. However, subfn 4F09h is
1850 * required for NonVGA controllers (eg. XGA).
1851 */
1852ASM_START
1853vbe_biosfn_set_get_palette_data:
1854 test bl, bl
1855 jz set_palette_data
1856 cmp bl, #0x01
1857 je get_palette_data
1858 cmp bl, #0x03
1859 jbe vbe_09_nohw
1860 cmp bl, #0x80
1861 jne vbe_09_unsupported
1862#if 0
1863 /* this is where we could wait for vertical retrace */
1864#endif
1865set_palette_data:
1866 pushad
1867 push ds
1868 push es
1869 pop ds
1870 mov al, dl
1871 mov dx, # VGAREG_DAC_WRITE_ADDRESS
1872 out dx, al
1873 inc dx
1874 mov si, di
1875set_pal_loop:
1876 lodsd
1877 ror eax, #16
1878 out dx, al
1879 rol eax, #8
1880 out dx, al
1881 rol eax, #8
1882 out dx, al
1883 loop set_pal_loop
1884 pop ds
1885 popad
1886vbe_09_ok:
1887 mov ax, #0x004f
1888 ret
1889
1890get_palette_data:
1891 pushad
1892 mov al, dl
1893 mov dx, # VGAREG_DAC_READ_ADDRESS
1894 out dx, al
1895 add dl, #2
1896get_pal_loop:
1897 xor eax, eax
1898 in al, dx
1899 shl eax, #8
1900 in al, dx
1901 shl eax, #8
1902 in al, dx
1903 stosd
1904 loop get_pal_loop
1905 popad
1906 jmp vbe_09_ok
1907
1908vbe_09_unsupported:
1909 mov ax, #0x014f
1910 ret
1911vbe_09_nohw:
1912 mov ax, #0x024f
1913 ret
1914ASM_END
1915
1916
1917/** Function 0Ah - Return VBE Protected Mode Interface
1918 *
1919 * Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface
1920 * BL = 00h Return protected mode table
1921 * Output: AX = Status
1922 * ES = Real Mode Segment of Table
1923 * DI = Offset of Table
1924 * CX = Length of Table including protected mode code
1925 * (for copying purposes)
1926 */
1927ASM_START
1928vbe_biosfn_return_protected_mode_interface:
1929 test bl, bl
1930 jnz _fail
1931 mov di, #0xc000
1932 mov es, di
1933 mov di, # vesa_pm_start
1934 mov cx, # vesa_pm_end
1935 sub cx, di
1936 mov ax, #0x004f
1937 ret
1938_fail:
1939 mov ax, #0x014f
1940 ret
1941ASM_END
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette