VirtualBox

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

Last change on this file since 26003 was 26003, checked in by vboxsync, 15 years ago

VGA bios: fix the attribute during text scroll (fix from upstream)

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