VirtualBox

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

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

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

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