VirtualBox

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

Last change on this file since 42852 was 40433, checked in by vboxsync, 13 years ago

VGA: Do not hardcode LFB base in BIOS.

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