VirtualBox

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

Last change on this file since 11565 was 11565, checked in by vboxsync, 16 years ago

Workaround for bug(s) in the Ubuntu splash screen instruction emulator

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 46.2 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#ifndef VBOX
1109 VbeInfoBlock vbe_info_block;
1110#endif
1111 Bit16u status;
1112 Bit16u result;
1113 Bit16u vbe2_info;
1114 Bit16u cur_mode=0;
1115 Bit16u cur_ptr=34;
1116#ifdef VBE_NEW_DYN_LIST
1117 ModeInfoListItem *cur_info; /* used to get the mode list offset. */
1118 Bit16u sig, vmode;
1119 Bit16u max_bpp=dispi_get_max_bpp();
1120#else
1121 ModeInfoListItem *cur_info=&mode_info_list;
1122#endif
1123
1124#ifdef VBE_NEW_DYN_LIST
1125 /* Read VBE Extra Data signature */
1126 sig = in_word(VBE_EXTRA_PORT, 0);
1127 if (sig != VBEHEADER_MAGIC)
1128 {
1129 result = 0x100;
1130
1131 write_word(ss, AX, result);
1132
1133 printf("Signature NOT found\n");
1134 return;
1135 }
1136 cur_info = sizeof(VBEHeader);
1137#endif
1138 status = read_word(ss, AX);
1139
1140#ifdef DEBUG
1141 printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
1142#endif
1143
1144 vbe2_info = 0;
1145#ifdef VBOX
1146 #define RT_OFFSETOF(type, member) ( (int)(unsigned)&( ((type *)(void *)0)->member) )
1147
1148 /* Don't use a local copy of VbeInfoBlock on the stack; it's too big.
1149 * The Ubuntu 8.04 64 bits splash screen emulator can't handle this.
1150 */
1151#ifdef VBE2_NO_VESA_CHECK
1152#else
1153 // check for VBE2 signature
1154 if (((read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[0])) == 'V') &&
1155 (read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[1])) == 'B') &&
1156 (read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[2])) == 'E') &&
1157 (read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[3])) == '2')) ||
1158
1159 ((read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[0])) == 'V') &&
1160 (read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[1])) == 'E') &&
1161 (read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[2])) == 'S') &&
1162 (read_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[3])) == 'A')) )
1163 {
1164 vbe2_info = 1;
1165#ifdef DEBUG
1166 printf("VBE correct VESA/VBE2 signature found\n");
1167#endif
1168 }
1169#endif
1170
1171 // VBE Signature
1172 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[0]), 'V');
1173 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[1]), 'E');
1174 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[2]), 'S');
1175 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeSignature[3]), 'A');
1176
1177 // VBE Version supported
1178 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, VbeVersion), 0x0200);
1179
1180 // OEM String
1181 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemStringPtr_Seg), 0xc000);
1182 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemStringPtr_Off), &vbebios_copyright);
1183
1184 // Capabilities
1185 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, Capabilities[0]), VBE_CAPABILITY_8BIT_DAC);
1186 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, Capabilities[1]), 0);
1187 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, Capabilities[2]), 0);
1188 write_byte(ES, DI + RT_OFFSETOF(VbeInfoBlock, Capabilities[3]), 0);
1189
1190 // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
1191 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, VideoModePtr_Seg), ES);
1192 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, VideoModePtr_Off), DI + 34);
1193
1194 // VBE Total Memory (in 64b blocks)
1195 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, TotalMemory), in_word(VBE_EXTRA_PORT, 0xffff));
1196
1197 if (vbe2_info)
1198 {
1199 // OEM Stuff
1200 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemSoftwareRev), VBE_OEM_SOFTWARE_REV);
1201 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemVendorNamePtr_Seg), 0xc000);
1202 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemVendorNamePtr_Off), &vbebios_vendor_name);
1203 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemProductNamePtr_Seg), 0xc000);
1204 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemProductNamePtr_Off), &vbebios_product_name);
1205 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemProductRevPtr_Seg), 0xc000);
1206 write_word(ES, DI + RT_OFFSETOF(VbeInfoBlock, OemProductRevPtr_Off), &vbebios_product_revision);
1207 }
1208#else
1209 // get vbe_info_block into local variable
1210 memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
1211
1212#ifdef VBE2_NO_VESA_CHECK
1213#else
1214 // check for VBE2 signature
1215 if (((vbe_info_block.VbeSignature[0] == 'V') &&
1216 (vbe_info_block.VbeSignature[1] == 'B') &&
1217 (vbe_info_block.VbeSignature[2] == 'E') &&
1218 (vbe_info_block.VbeSignature[3] == '2')) ||
1219
1220 ((vbe_info_block.VbeSignature[0] == 'V') &&
1221 (vbe_info_block.VbeSignature[1] == 'E') &&
1222 (vbe_info_block.VbeSignature[2] == 'S') &&
1223 (vbe_info_block.VbeSignature[3] == 'A')) )
1224 {
1225 vbe2_info = 1;
1226#ifdef DEBUG
1227 printf("VBE correct VESA/VBE2 signature found\n");
1228#endif
1229 }
1230#endif
1231
1232 // VBE Signature
1233 vbe_info_block.VbeSignature[0] = 'V';
1234 vbe_info_block.VbeSignature[1] = 'E';
1235 vbe_info_block.VbeSignature[2] = 'S';
1236 vbe_info_block.VbeSignature[3] = 'A';
1237
1238 // VBE Version supported
1239 vbe_info_block.VbeVersion = 0x0200;
1240
1241 // OEM String
1242 vbe_info_block.OemStringPtr_Seg = 0xc000;
1243 vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
1244
1245 // Capabilities
1246 vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
1247 vbe_info_block.Capabilities[1] = 0;
1248 vbe_info_block.Capabilities[2] = 0;
1249 vbe_info_block.Capabilities[3] = 0;
1250
1251 // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
1252 vbe_info_block.VideoModePtr_Seg= ES ;
1253 vbe_info_block.VideoModePtr_Off= DI + 34;
1254
1255 // VBE Total Memory (in 64b blocks)
1256 vbe_info_block.TotalMemory = in_word(VBE_EXTRA_PORT, 0xffff);
1257
1258 if (vbe2_info)
1259 {
1260 // OEM Stuff
1261 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
1262 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
1263 vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
1264 vbe_info_block.OemProductNamePtr_Seg = 0xc000;
1265 vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
1266 vbe_info_block.OemProductRevPtr_Seg = 0xc000;
1267 vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
1268
1269 // copy updates in vbe_info_block back
1270 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
1271 }
1272 else
1273 {
1274 // copy updates in vbe_info_block back (VBE 1.x compatibility)
1275 memcpyb(ES, DI, ss, &vbe_info_block, 256);
1276 }
1277#endif /* VBOX */
1278
1279#ifdef VBE_NEW_DYN_LIST
1280 do
1281 {
1282 Bit16u data;
1283 Bit8u data_b;
1284
1285 data_b = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1286 if (data_b <= max_bpp)
1287 {
1288 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
1289#ifdef DEBUG
1290 printf("VBE found mode %x => %x\n", vmode, cur_mode);
1291#endif
1292 write_word(ES, DI + cur_ptr, vmode);
1293 cur_mode++;
1294 cur_ptr+=2;
1295 }
1296 cur_info++;
1297 vmode = in_word(VBE_EXTRA_PORT, &cur_info->mode);
1298 } while (vmode != VBE_VESA_MODE_END_OF_LIST);
1299
1300 // Add vesa mode list terminator
1301 write_word(ES, DI + cur_ptr, vmode);
1302#else
1303 do
1304 {
1305 if (cur_info->info.BitsPerPixel <= max_bpp) {
1306#ifdef DEBUG
1307 printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
1308#endif
1309 write_word(ES, DI + cur_ptr, cur_info->mode);
1310 cur_mode++;
1311 cur_ptr+=2;
1312 }
1313 cur_info++;
1314 } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
1315
1316 // Add vesa mode list terminator
1317 write_word(ES, DI + cur_ptr, cur_info->mode);
1318#endif // VBE_NEW_DYN_LIST
1319
1320 result = 0x4f;
1321
1322 write_word(ss, AX, result);
1323}
1324
1325
1326/** Function 01h - Return VBE Mode Information
1327 *
1328 * Input:
1329 * AX = 4F01h
1330 * CX = Mode Number
1331 * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure
1332 * Output:
1333 * AX = VBE Return Status
1334 *
1335 */
1336void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
1337Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
1338{
1339 Bit16u result=0x0100;
1340 Bit16u ss=get_SS();
1341 ModeInfoBlock info;
1342 ModeInfoListItem *cur_info;
1343 Boolean using_lfb;
1344
1345#ifdef DEBUG
1346 printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
1347#endif
1348
1349 using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
1350
1351 CX = (CX & 0x1ff);
1352
1353 cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
1354
1355 if (cur_info != 0)
1356 {
1357#ifdef VBE_NEW_DYN_LIST
1358 Bit16u i;
1359#endif
1360#ifdef DEBUG
1361 printf("VBE found mode %x\n",CX);
1362#endif
1363 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
1364#ifdef VBE_NEW_DYN_LIST
1365 for (i = 0; i < sizeof(ModeInfoBlockCompact); i++)
1366 {
1367 Bit8u b;
1368
1369 b = in_byte(VBE_EXTRA_PORT, (char *)(&(cur_info->info)) + i);
1370 write_byte(ss, (char *)(&info) + i, b);
1371 }
1372#else
1373 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
1374#endif
1375 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
1376 info.WinFuncPtr = 0xC0000000UL;
1377 *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
1378 }
1379
1380 result = 0x4f;
1381 }
1382 else
1383 {
1384#ifdef DEBUG
1385 printf("VBE *NOT* found mode %x\n",CX);
1386#endif
1387 result = 0x100;
1388 }
1389
1390 if (result == 0x4f)
1391 {
1392 // copy updates in mode_info_block back
1393 memcpyb(ES, DI, ss, &info, sizeof(info));
1394 }
1395
1396 write_word(ss, AX, result);
1397}
1398
1399/** Function 02h - Set VBE Mode
1400 *
1401 * Input:
1402 * AX = 4F02h
1403 * BX = Desired Mode to set
1404 * ES:DI = Pointer to CRTCInfoBlock structure
1405 * Output:
1406 * AX = VBE Return Status
1407 *
1408 */
1409void vbe_biosfn_set_mode(AX, BX, ES, DI)
1410Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
1411{
1412 Bit16u ss = get_SS();
1413 Bit16u result;
1414 ModeInfoListItem *cur_info;
1415 Boolean using_lfb;
1416 Bit8u no_clear;
1417 Bit8u lfb_flag;
1418
1419 using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
1420 lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
1421 no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
1422
1423 BX = (BX & 0x1ff);
1424
1425 //result=read_word(ss,AX);
1426
1427 // check for non vesa mode
1428 if (BX<VBE_MODE_VESA_DEFINED)
1429 {
1430 Bit8u mode;
1431
1432 dispi_set_enable(VBE_DISPI_DISABLED);
1433 // call the vgabios in order to set the video mode
1434 // this allows for going back to textmode with a VBE call (some applications expect that to work)
1435
1436 mode=(BX & 0xff);
1437 biosfn_set_video_mode(mode);
1438 result = 0x4f;
1439 goto leave;
1440 }
1441
1442 cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
1443
1444 if (cur_info != 0)
1445 {
1446#ifdef VBE_NEW_DYN_LIST
1447 Bit16u data;
1448 Bit8u data_b;
1449 Bit16u x, y;
1450 Bit8u bpp;
1451
1452 x = in_word(VBE_EXTRA_PORT, &cur_info->info.XResolution); /* cur_info is really an offset here */
1453 y = in_word(VBE_EXTRA_PORT, &cur_info->info.YResolution);
1454 bpp = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1455
1456#ifdef DEBUG
1457 printf("VBE found mode %x, setting:\n", BX);
1458 printf("\txres%x yres%x bpp%x\n", x, y, bpp);
1459#endif
1460#else
1461#ifdef DEBUG
1462 printf("VBE found mode %x, setting:\n", BX);
1463 printf("\txres%x yres%x bpp%x\n",
1464 cur_info->info.XResolution,
1465 cur_info->info.YResolution,
1466 cur_info->info.BitsPerPixel);
1467#endif
1468#endif // VBE_NEW_DYN_LIST
1469
1470 // first disable current mode (when switching between vesa modi)
1471 dispi_set_enable(VBE_DISPI_DISABLED);
1472
1473#ifdef VBE_NEW_DYN_LIST
1474 data = in_word(VBE_EXTRA_PORT, &cur_info->mode);
1475 if (data == VBE_VESA_MODE_800X600X4)
1476#else
1477 if (cur_info->mode == VBE_VESA_MODE_800X600X4)
1478#endif
1479 {
1480 biosfn_set_video_mode(0x6a);
1481 }
1482
1483#ifdef VBE_NEW_DYN_LIST
1484 data_b = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1485 dispi_set_bpp(data_b);
1486 data = in_word(VBE_EXTRA_PORT, &cur_info->info.XResolution);
1487 dispi_set_xres(data);
1488 data = in_word(VBE_EXTRA_PORT, &cur_info->info.YResolution);
1489 dispi_set_yres(data);
1490#else
1491 dispi_set_bpp(cur_info->info.BitsPerPixel);
1492 dispi_set_xres(cur_info->info.XResolution);
1493 dispi_set_yres(cur_info->info.YResolution);
1494#endif
1495 dispi_set_bank(0);
1496 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
1497 vga_compat_setup();
1498
1499 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
1500 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
1501
1502 result = 0x4f;
1503 }
1504 else
1505 {
1506#ifdef DEBUG
1507 printf("VBE *NOT* found mode %x\n" , BX);
1508#endif
1509 result = 0x100;
1510 }
1511
1512leave:
1513 write_word(ss, AX, result);
1514}
1515
1516/** Function 03h - Return Current VBE Mode
1517 *
1518 * Input:
1519 * AX = 4F03h
1520 * Output:
1521 * AX = VBE Return Status
1522 * BX = Current VBE Mode
1523 *
1524 */
1525ASM_START
1526vbe_biosfn_return_current_mode:
1527 push ds
1528 mov ax, # BIOSMEM_SEG
1529 mov ds, ax
1530 call dispi_get_enable
1531 and ax, # VBE_DISPI_ENABLED
1532 jz no_vbe_mode
1533 mov bx, # BIOSMEM_VBE_MODE
1534 mov ax, [bx]
1535 mov bx, ax
1536 jnz vbe_03_ok
1537no_vbe_mode:
1538 mov bx, # BIOSMEM_CURRENT_MODE
1539 mov al, [bx]
1540 mov bl, al
1541 xor bh, bh
1542vbe_03_ok:
1543 mov ax, #0x004f
1544 pop ds
1545 ret
1546ASM_END
1547
1548Bit16u vbe_biosfn_read_video_state_size()
1549{
1550 return 9 * 2;
1551}
1552
1553void vbe_biosfn_save_video_state(ES, BX)
1554 Bit16u ES; Bit16u BX;
1555{
1556 Bit16u enable, i;
1557
1558 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1559 enable = inw(VBE_DISPI_IOPORT_DATA);
1560 write_word(ES, BX, enable);
1561 BX += 2;
1562 if (!(enable & VBE_DISPI_ENABLED))
1563 return;
1564 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
1565 if (i != VBE_DISPI_INDEX_ENABLE) {
1566 outw(VBE_DISPI_IOPORT_INDEX, i);
1567 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
1568 BX += 2;
1569 }
1570 }
1571}
1572
1573
1574void vbe_biosfn_restore_video_state(ES, BX)
1575 Bit16u ES; Bit16u BX;
1576{
1577 Bit16u enable, i;
1578
1579 enable = read_word(ES, BX);
1580 BX += 2;
1581
1582 if (!(enable & VBE_DISPI_ENABLED)) {
1583 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1584 outw(VBE_DISPI_IOPORT_DATA, enable);
1585 } else {
1586 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
1587 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1588 BX += 2;
1589 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
1590 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1591 BX += 2;
1592 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
1593 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1594 BX += 2;
1595 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1596 outw(VBE_DISPI_IOPORT_DATA, enable);
1597
1598 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
1599 outw(VBE_DISPI_IOPORT_INDEX, i);
1600 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1601 BX += 2;
1602 }
1603 }
1604}
1605
1606/** Function 04h - Save/Restore State
1607 *
1608 * Input:
1609 * AX = 4F04h
1610 * DL = 00h Return Save/Restore State buffer size
1611 * 01h Save State
1612 * 02h Restore State
1613 * CX = Requested states
1614 * ES:BX = Pointer to buffer (if DL <> 00h)
1615 * Output:
1616 * AX = VBE Return Status
1617 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
1618 *
1619 */
1620void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
1621Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
1622{
1623 Bit16u ss=get_SS();
1624 Bit16u result, val;
1625
1626 result = 0x4f;
1627 switch(GET_DL()) {
1628 case 0x00:
1629 val = biosfn_read_video_state_size2(CX);
1630#ifdef DEBUG
1631 printf("VGA state size=%x\n", val);
1632#endif
1633 if (CX & 8)
1634 val += vbe_biosfn_read_video_state_size();
1635 write_word(ss, BX, val);
1636 break;
1637 case 0x01:
1638 val = read_word(ss, BX);
1639 val = biosfn_save_video_state(CX, ES, val);
1640#ifdef DEBUG
1641 printf("VGA save_state offset=%x\n", val);
1642#endif
1643 if (CX & 8)
1644 vbe_biosfn_save_video_state(ES, val);
1645 break;
1646 case 0x02:
1647 val = read_word(ss, BX);
1648 val = biosfn_restore_video_state(CX, ES, val);
1649#ifdef DEBUG
1650 printf("VGA restore_state offset=%x\n", val);
1651#endif
1652 if (CX & 8)
1653 vbe_biosfn_restore_video_state(ES, val);
1654 break;
1655 default:
1656 // function failed
1657 result = 0x100;
1658 break;
1659 }
1660 write_word(ss, AX, result);
1661}
1662
1663
1664/** Function 05h - Display Window Control
1665 *
1666 * Input:
1667 * AX = 4F05h
1668 * (16-bit) BH = 00h Set memory window
1669 * = 01h Get memory window
1670 * BL = Window number
1671 * = 00h Window A
1672 * = 01h Window B
1673 * DX = Window number in video memory in window
1674 * granularity units (Set Memory Window only)
1675 * Note:
1676 * If this function is called while in a linear frame buffer mode,
1677 * this function must fail with completion code AH=03h
1678 *
1679 * Output:
1680 * AX = VBE Return Status
1681 * DX = Window number in window granularity units
1682 * (Get Memory Window only)
1683 */
1684ASM_START
1685vbe_biosfn_display_window_control:
1686 cmp bl, #0x00
1687 jne vbe_05_failed
1688 cmp bh, #0x01
1689 je get_display_window
1690 jb set_display_window
1691 mov ax, #0x0100
1692 ret
1693set_display_window:
1694 mov ax, dx
1695 call _dispi_set_bank
1696 call dispi_get_bank
1697 cmp ax, dx
1698 jne vbe_05_failed
1699 mov ax, #0x004f
1700 ret
1701get_display_window:
1702 call dispi_get_bank
1703 mov dx, ax
1704 mov ax, #0x004f
1705 ret
1706vbe_05_failed:
1707 mov ax, #0x014f
1708 ret
1709ASM_END
1710
1711
1712/** Function 06h - Set/Get Logical Scan Line Length
1713 *
1714 * Input:
1715 * AX = 4F06h
1716 * BL = 00h Set Scan Line Length in Pixels
1717 * = 01h Get Scan Line Length
1718 * = 02h Set Scan Line Length in Bytes
1719 * = 03h Get Maximum Scan Line Length
1720 * CX = If BL=00h Desired Width in Pixels
1721 * If BL=02h Desired Width in Bytes
1722 * (Ignored for Get Functions)
1723 *
1724 * Output:
1725 * AX = VBE Return Status
1726 * BX = Bytes Per Scan Line
1727 * CX = Actual Pixels Per Scan Line
1728 * (truncated to nearest complete pixel)
1729 * DX = Maximum Number of Scan Lines
1730 */
1731ASM_START
1732vbe_biosfn_set_get_logical_scan_line_length:
1733 mov ax, cx
1734 cmp bl, #0x01
1735 je get_logical_scan_line_length
1736 cmp bl, #0x02
1737 je set_logical_scan_line_bytes
1738 jb set_logical_scan_line_pixels
1739 mov ax, #0x0100
1740 ret
1741set_logical_scan_line_bytes:
1742 push ax
1743 call dispi_get_bpp
1744 xor bh, bh
1745 mov bl, ah
1746 or bl, bl
1747 jnz no_4bpp_1
1748 shl ax, #3
1749 mov bl, #1
1750no_4bpp_1:
1751 xor dx, dx
1752 pop ax
1753 div bx
1754set_logical_scan_line_pixels:
1755 call dispi_set_virt_width
1756get_logical_scan_line_length:
1757 call dispi_get_bpp
1758 xor bh, bh
1759 mov bl, ah
1760 call dispi_get_virt_width
1761 mov cx, ax
1762 or bl, bl
1763 jnz no_4bpp_2
1764 shr ax, #3
1765 mov bl, #1
1766no_4bpp_2:
1767 mul bx
1768 mov bx, ax
1769 call dispi_get_virt_height
1770 mov dx, ax
1771 mov ax, #0x004f
1772 ret
1773ASM_END
1774
1775
1776/** Function 07h - Set/Get Display Start
1777 *
1778 * Input(16-bit):
1779 * AX = 4F07h
1780 * BH = 00h Reserved and must be 00h
1781 * BL = 00h Set Display Start
1782 * = 01h Get Display Start
1783 * = 02h Schedule Display Start (Alternate)
1784 * = 03h Schedule Stereoscopic Display Start
1785 * = 04h Get Scheduled Display Start Status
1786 * = 05h Enable Stereoscopic Mode
1787 * = 06h Disable Stereoscopic Mode
1788 * = 80h Set Display Start during Vertical Retrace
1789 * = 82h Set Display Start during Vertical Retrace (Alternate)
1790 * = 83h Set Stereoscopic Display Start during Vertical Retrace
1791 * ECX = If BL=02h/82h Display Start Address in bytes
1792 * If BL=03h/83h Left Image Start Address in bytes
1793 * EDX = If BL=03h/83h Right Image Start Address in bytes
1794 * CX = If BL=00h/80h First Displayed Pixel In Scan Line
1795 * DX = If BL=00h/80h First Displayed Scan Line
1796 *
1797 * Output:
1798 * AX = VBE Return Status
1799 * BH = If BL=01h Reserved and will be 0
1800 * CX = If BL=01h First Displayed Pixel In Scan Line
1801 * If BL=04h 0 if flip has not occurred, not 0 if it has
1802 * DX = If BL=01h First Displayed Scan Line
1803 *
1804 * Input(32-bit):
1805 * BH = 00h Reserved and must be 00h
1806 * BL = 00h Set Display Start
1807 * = 80h Set Display Start during Vertical Retrace
1808 * CX = Bits 0-15 of display start address
1809 * DX = Bits 16-31 of display start address
1810 * ES = Selector for memory mapped registers
1811 */
1812ASM_START
1813vbe_biosfn_set_get_display_start:
1814 cmp bl, #0x80
1815 je set_display_start
1816 cmp bl, #0x01
1817 je get_display_start
1818 jb set_display_start
1819 mov ax, #0x0100
1820 ret
1821set_display_start:
1822 mov ax, cx
1823 call dispi_set_x_offset
1824 mov ax, dx
1825 call dispi_set_y_offset
1826 mov ax, #0x004f
1827 ret
1828get_display_start:
1829 call dispi_get_x_offset
1830 mov cx, ax
1831 call dispi_get_y_offset
1832 mov dx, ax
1833 xor bh, bh
1834 mov ax, #0x004f
1835 ret
1836ASM_END
1837
1838
1839/** Function 08h - Set/Get Dac Palette Format
1840 *
1841 * Input:
1842 * AX = 4F08h
1843 * BL = 00h set DAC palette width
1844 * = 01h get DAC palette width
1845 * BH = If BL=00h: desired number of bits per primary color
1846 * Output:
1847 * AX = VBE Return Status
1848 * BH = current number of bits per primary color (06h = standard VGA)
1849 */
1850ASM_START
1851vbe_biosfn_set_get_dac_palette_format:
1852 cmp bl, #0x01
1853 je get_dac_palette_format
1854 jb set_dac_palette_format
1855 mov ax, #0x0100
1856 ret
1857set_dac_palette_format:
1858 call dispi_get_enable
1859 cmp bh, #0x06
1860 je set_normal_dac
1861 cmp bh, #0x08
1862 jne vbe_08_unsupported
1863 or ax, # VBE_DISPI_8BIT_DAC
1864 jnz set_dac_mode
1865set_normal_dac:
1866 and ax, #~ VBE_DISPI_8BIT_DAC
1867set_dac_mode:
1868 call _dispi_set_enable
1869get_dac_palette_format:
1870 mov bh, #0x06
1871 call dispi_get_enable
1872 and ax, # VBE_DISPI_8BIT_DAC
1873 jz vbe_08_ok
1874 mov bh, #0x08
1875vbe_08_ok:
1876 mov ax, #0x004f
1877 ret
1878vbe_08_unsupported:
1879 mov ax, #0x014f
1880 ret
1881ASM_END
1882
1883
1884/** Function 09h - Set/Get Palette Data
1885 *
1886 * Input:
1887 * AX = 4F09h
1888 * (16-bit) BL = 00h Set palette data
1889 * = 01h Get palette data
1890 * = 02h Set secondary palette data
1891 * = 03h Get secondary palette data
1892 * = 80h Set palette data during VRetrace
1893 * CX = Number of entries to update (<= 256)
1894 * DX = First entry to update
1895 * ES:DI = Table of palette values
1896 * Output:
1897 * AX = VBE Return Status
1898 *
1899 * Notes:
1900 * Secondary palette support is a "future extension".
1901 * Attempts to set/get it should return status 02h.
1902 *
1903 * In VBE 3.0, reading palette data is optional and
1904 * subfunctions 01h and 03h may return failure.
1905 *
1906 * The format of palette entries is as follows:
1907 *
1908 * PaletteEntry struc
1909 * Blue db ? ; Blue channel value (6 or 8 bits)
1910 * Green db ? ; Green channel value (6 or 8 bits)
1911 * Red db ? ; Red channel value (6 or 8 bits)
1912 * Padding db ? ; DWORD alignment byte (unused)
1913 * PaletteEntry ends
1914 *
1915 * Most applications use VGA DAC registers directly to
1916 * set/get palette in VBE modes. However, subfn 4F09h is
1917 * required for NonVGA controllers (eg. XGA).
1918 */
1919ASM_START
1920vbe_biosfn_set_get_palette_data:
1921 test bl, bl
1922 jz set_palette_data
1923 cmp bl, #0x01
1924 je get_palette_data
1925 cmp bl, #0x03
1926 jbe vbe_09_nohw
1927 cmp bl, #0x80
1928 jne vbe_09_unsupported
1929#if 0
1930 /* this is where we could wait for vertical retrace */
1931#endif
1932set_palette_data:
1933 pushad
1934 push ds
1935 push es
1936 pop ds
1937 mov al, dl
1938 mov dx, # VGAREG_DAC_WRITE_ADDRESS
1939 out dx, al
1940 inc dx
1941 mov si, di
1942set_pal_loop:
1943 lodsd
1944 ror eax, #16
1945 out dx, al
1946 rol eax, #8
1947 out dx, al
1948 rol eax, #8
1949 out dx, al
1950 loop set_pal_loop
1951 pop ds
1952 popad
1953vbe_09_ok:
1954 mov ax, #0x004f
1955 ret
1956
1957get_palette_data:
1958 pushad
1959 mov al, dl
1960 mov dx, # VGAREG_DAC_READ_ADDRESS
1961 out dx, al
1962 add dl, #2
1963get_pal_loop:
1964 xor eax, eax
1965 in al, dx
1966 shl eax, #8
1967 in al, dx
1968 shl eax, #8
1969 in al, dx
1970 stosd
1971 loop get_pal_loop
1972 popad
1973 jmp vbe_09_ok
1974
1975vbe_09_unsupported:
1976 mov ax, #0x014f
1977 ret
1978vbe_09_nohw:
1979 mov ax, #0x024f
1980 ret
1981ASM_END
1982
1983
1984/** Function 0Ah - Return VBE Protected Mode Interface
1985 *
1986 * Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface
1987 * BL = 00h Return protected mode table
1988 * Output: AX = Status
1989 * ES = Real Mode Segment of Table
1990 * DI = Offset of Table
1991 * CX = Length of Table including protected mode code
1992 * (for copying purposes)
1993 */
1994ASM_START
1995vbe_biosfn_return_protected_mode_interface:
1996 test bl, bl
1997 jnz _fail
1998 mov di, #0xc000
1999 mov es, di
2000 mov di, # vesa_pm_start
2001 mov cx, # vesa_pm_end
2002 sub cx, di
2003 mov ax, #0x004f
2004 ret
2005_fail:
2006 mov ax, #0x014f
2007 ret
2008ASM_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