VirtualBox

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

Last change on this file since 37636 was 35026, checked in by vboxsync, 14 years ago

VBE: As the comment says, returned size is in 64-byte blocks (avoids uvesafb error/warning).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.8 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 result = 0x4f;
1225 }
1226 else
1227 {
1228#ifdef DEBUG
1229 printf("VBE *NOT* found mode %x\n",CX);
1230#endif
1231 result = 0x100;
1232 }
1233
1234 write_word(ss, AX, result);
1235}
1236
1237/** Function 02h - Set VBE Mode
1238 *
1239 * Input:
1240 * AX = 4F02h
1241 * BX = Desired Mode to set
1242 * ES:DI = Pointer to CRTCInfoBlock structure
1243 * Output:
1244 * AX = VBE Return Status
1245 *
1246 */
1247void vbe_biosfn_set_mode(AX, BX, ES, DI)
1248Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
1249{
1250 Bit16u ss = get_SS();
1251 Bit16u result;
1252 ModeInfoListItem *cur_info;
1253 Boolean using_lfb;
1254 Bit8u no_clear;
1255 Bit8u lfb_flag;
1256
1257 using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
1258 lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
1259 no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
1260
1261 BX = (BX & 0x1ff);
1262
1263 //result=read_word(ss,AX);
1264
1265 // check for non vesa mode
1266 if (BX<VBE_MODE_VESA_DEFINED)
1267 {
1268 Bit8u mode;
1269
1270 dispi_set_enable(VBE_DISPI_DISABLED);
1271 // call the vgabios in order to set the video mode
1272 // this allows for going back to textmode with a VBE call (some applications expect that to work)
1273
1274 mode=(BX & 0xff);
1275 biosfn_set_video_mode(mode);
1276 result = 0x4f;
1277 goto leave;
1278 }
1279
1280 cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
1281
1282 if (cur_info != 0)
1283 {
1284#ifdef VBE_NEW_DYN_LIST
1285 Bit16u data;
1286 Bit8u data_b;
1287 Bit16u x, y;
1288 Bit8u bpp;
1289
1290 x = in_word(VBE_EXTRA_PORT, &cur_info->info.XResolution); /* cur_info is really an offset here */
1291 y = in_word(VBE_EXTRA_PORT, &cur_info->info.YResolution);
1292 bpp = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1293
1294#ifdef DEBUG
1295 printf("VBE found mode %x, setting:\n", BX);
1296 printf("\txres%x yres%x bpp%x\n", x, y, bpp);
1297#endif
1298#else
1299#ifdef DEBUG
1300 printf("VBE found mode %x, setting:\n", BX);
1301 printf("\txres%x yres%x bpp%x\n",
1302 cur_info->info.XResolution,
1303 cur_info->info.YResolution,
1304 cur_info->info.BitsPerPixel);
1305#endif
1306#endif // VBE_NEW_DYN_LIST
1307
1308 // first disable current mode (when switching between vesa modi)
1309 dispi_set_enable(VBE_DISPI_DISABLED);
1310
1311#ifdef VBE_NEW_DYN_LIST
1312 if (bpp == 4)
1313#else
1314 if (cur_info->info.BitsPerPixel == 4)
1315#endif
1316 {
1317 biosfn_set_video_mode(0x6a);
1318 }
1319
1320#ifdef VBE_NEW_DYN_LIST
1321 data_b = in_byte(VBE_EXTRA_PORT, &cur_info->info.BitsPerPixel);
1322 dispi_set_bpp(data_b);
1323 data = in_word(VBE_EXTRA_PORT, &cur_info->info.XResolution);
1324 dispi_set_xres(data);
1325 data = in_word(VBE_EXTRA_PORT, &cur_info->info.YResolution);
1326 dispi_set_yres(data);
1327#else
1328 dispi_set_bpp(cur_info->info.BitsPerPixel);
1329 dispi_set_xres(cur_info->info.XResolution);
1330 dispi_set_yres(cur_info->info.YResolution);
1331#endif
1332 dispi_set_bank(0);
1333 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
1334 vga_compat_setup();
1335
1336 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
1337 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
1338
1339 result = 0x4f;
1340 }
1341 else
1342 {
1343#ifdef DEBUG
1344 printf("VBE *NOT* found mode %x\n" , BX);
1345#endif
1346 result = 0x100;
1347 }
1348
1349leave:
1350 write_word(ss, AX, result);
1351}
1352
1353/** Function 03h - Return Current VBE Mode
1354 *
1355 * Input:
1356 * AX = 4F03h
1357 * Output:
1358 * AX = VBE Return Status
1359 * BX = Current VBE Mode
1360 *
1361 */
1362ASM_START
1363vbe_biosfn_return_current_mode:
1364 push ds
1365 mov ax, # BIOSMEM_SEG
1366 mov ds, ax
1367 call dispi_get_enable
1368 and ax, # VBE_DISPI_ENABLED
1369 jz no_vbe_mode
1370 mov bx, # BIOSMEM_VBE_MODE
1371 mov ax, [bx]
1372 mov bx, ax
1373 jnz vbe_03_ok
1374no_vbe_mode:
1375 mov bx, # BIOSMEM_CURRENT_MODE
1376 mov al, [bx]
1377 mov bl, al
1378 xor bh, bh
1379vbe_03_ok:
1380 mov ax, #0x004f
1381 pop ds
1382 ret
1383ASM_END
1384
1385Bit16u vbe_biosfn_read_video_state_size()
1386{
1387 return 9 * 2;
1388}
1389
1390void vbe_biosfn_save_video_state(ES, BX)
1391 Bit16u ES; Bit16u BX;
1392{
1393 Bit16u enable, i;
1394
1395 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1396 enable = inw(VBE_DISPI_IOPORT_DATA);
1397 write_word(ES, BX, enable);
1398 BX += 2;
1399 if (!(enable & VBE_DISPI_ENABLED))
1400 return;
1401 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
1402 if (i != VBE_DISPI_INDEX_ENABLE) {
1403 outw(VBE_DISPI_IOPORT_INDEX, i);
1404 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
1405 BX += 2;
1406 }
1407 }
1408}
1409
1410
1411void vbe_biosfn_restore_video_state(ES, BX)
1412 Bit16u ES; Bit16u BX;
1413{
1414 Bit16u enable, i;
1415
1416 enable = read_word(ES, BX);
1417 BX += 2;
1418
1419 if (!(enable & VBE_DISPI_ENABLED)) {
1420 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1421 outw(VBE_DISPI_IOPORT_DATA, enable);
1422 } else {
1423 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
1424 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1425 BX += 2;
1426 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
1427 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1428 BX += 2;
1429 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
1430 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1431 BX += 2;
1432 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
1433 outw(VBE_DISPI_IOPORT_DATA, enable);
1434
1435 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
1436 outw(VBE_DISPI_IOPORT_INDEX, i);
1437 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
1438 BX += 2;
1439 }
1440 }
1441}
1442
1443/** Function 04h - Save/Restore State
1444 *
1445 * Input:
1446 * AX = 4F04h
1447 * DL = 00h Return Save/Restore State buffer size
1448 * 01h Save State
1449 * 02h Restore State
1450 * CX = Requested states
1451 * ES:BX = Pointer to buffer (if DL <> 00h)
1452 * Output:
1453 * AX = VBE Return Status
1454 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
1455 *
1456 */
1457void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
1458Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
1459{
1460 Bit16u ss=get_SS();
1461 Bit16u result, val;
1462
1463 result = 0x4f;
1464 switch(GET_DL()) {
1465 case 0x00:
1466 val = biosfn_read_video_state_size2(CX);
1467#ifdef DEBUG
1468 printf("VGA state size=%x\n", val);
1469#endif
1470 if (CX & 8)
1471 val += vbe_biosfn_read_video_state_size();
1472 write_word(ss, BX, (val + 63) / 64);
1473 break;
1474 case 0x01:
1475 val = read_word(ss, BX);
1476 val = biosfn_save_video_state(CX, ES, val);
1477#ifdef DEBUG
1478 printf("VGA save_state offset=%x\n", val);
1479#endif
1480 if (CX & 8)
1481 vbe_biosfn_save_video_state(ES, val);
1482 break;
1483 case 0x02:
1484 val = read_word(ss, BX);
1485 val = biosfn_restore_video_state(CX, ES, val);
1486#ifdef DEBUG
1487 printf("VGA restore_state offset=%x\n", val);
1488#endif
1489 if (CX & 8)
1490 vbe_biosfn_restore_video_state(ES, val);
1491 break;
1492 default:
1493 // function failed
1494 result = 0x100;
1495 break;
1496 }
1497 write_word(ss, AX, result);
1498}
1499
1500
1501/** Function 05h - Display Window Control
1502 *
1503 * Input:
1504 * AX = 4F05h
1505 * (16-bit) BH = 00h Set memory window
1506 * = 01h Get memory window
1507 * BL = Window number
1508 * = 00h Window A
1509 * = 01h Window B
1510 * DX = Window number in video memory in window
1511 * granularity units (Set Memory Window only)
1512 * Note:
1513 * If this function is called while in a linear frame buffer mode,
1514 * this function must fail with completion code AH=03h
1515 *
1516 * Output:
1517 * AX = VBE Return Status
1518 * DX = Window number in window granularity units
1519 * (Get Memory Window only)
1520 */
1521ASM_START
1522vbe_biosfn_display_window_control:
1523 cmp bl, #0x00
1524 jne vbe_05_failed
1525 cmp bh, #0x01
1526 je get_display_window
1527 jb set_display_window
1528 mov ax, #0x0100
1529 ret
1530set_display_window:
1531 mov ax, dx
1532 call _dispi_set_bank
1533 call dispi_get_bank
1534 cmp ax, dx
1535 jne vbe_05_failed
1536 mov ax, #0x004f
1537 ret
1538get_display_window:
1539 call dispi_get_bank
1540 mov dx, ax
1541 mov ax, #0x004f
1542 ret
1543vbe_05_failed:
1544 mov ax, #0x014f
1545 ret
1546ASM_END
1547
1548
1549/** Function 06h - Set/Get Logical Scan Line Length
1550 *
1551 * Input:
1552 * AX = 4F06h
1553 * BL = 00h Set Scan Line Length in Pixels
1554 * = 01h Get Scan Line Length
1555 * = 02h Set Scan Line Length in Bytes
1556 * = 03h Get Maximum Scan Line Length
1557 * CX = If BL=00h Desired Width in Pixels
1558 * If BL=02h Desired Width in Bytes
1559 * (Ignored for Get Functions)
1560 *
1561 * Output:
1562 * AX = VBE Return Status
1563 * BX = Bytes Per Scan Line
1564 * CX = Actual Pixels Per Scan Line
1565 * (truncated to nearest complete pixel)
1566 * DX = Maximum Number of Scan Lines
1567 */
1568ASM_START
1569vbe_biosfn_set_get_logical_scan_line_length:
1570 mov ax, cx
1571 cmp bl, #0x01
1572 je get_logical_scan_line_length
1573 cmp bl, #0x02
1574 je set_logical_scan_line_bytes
1575 jb set_logical_scan_line_pixels
1576 mov ax, #0x0100
1577 ret
1578set_logical_scan_line_bytes:
1579 push ax
1580 call dispi_get_bpp
1581 xor bh, bh
1582 mov bl, ah
1583 or bl, bl
1584 jnz no_4bpp_1
1585 shl ax, #3
1586 mov bl, #1
1587no_4bpp_1:
1588 xor dx, dx
1589 pop ax
1590 div bx
1591set_logical_scan_line_pixels:
1592 call dispi_set_virt_width
1593get_logical_scan_line_length:
1594 call dispi_get_bpp
1595 xor bh, bh
1596 mov bl, ah
1597 call dispi_get_virt_width
1598 mov cx, ax
1599 or bl, bl
1600 jnz no_4bpp_2
1601 shr ax, #3
1602 mov bl, #1
1603no_4bpp_2:
1604 mul bx
1605 mov bx, ax
1606 call dispi_get_virt_height
1607 mov dx, ax
1608 mov ax, #0x004f
1609 ret
1610ASM_END
1611
1612
1613/** Function 07h - Set/Get Display Start
1614 *
1615 * Input(16-bit):
1616 * AX = 4F07h
1617 * BH = 00h Reserved and must be 00h
1618 * BL = 00h Set Display Start
1619 * = 01h Get Display Start
1620 * = 02h Schedule Display Start (Alternate)
1621 * = 03h Schedule Stereoscopic Display Start
1622 * = 04h Get Scheduled Display Start Status
1623 * = 05h Enable Stereoscopic Mode
1624 * = 06h Disable Stereoscopic Mode
1625 * = 80h Set Display Start during Vertical Retrace
1626 * = 82h Set Display Start during Vertical Retrace (Alternate)
1627 * = 83h Set Stereoscopic Display Start during Vertical Retrace
1628 * ECX = If BL=02h/82h Display Start Address in bytes
1629 * If BL=03h/83h Left Image Start Address in bytes
1630 * EDX = If BL=03h/83h Right Image Start Address in bytes
1631 * CX = If BL=00h/80h First Displayed Pixel In Scan Line
1632 * DX = If BL=00h/80h First Displayed Scan Line
1633 *
1634 * Output:
1635 * AX = VBE Return Status
1636 * BH = If BL=01h Reserved and will be 0
1637 * CX = If BL=01h First Displayed Pixel In Scan Line
1638 * If BL=04h 0 if flip has not occurred, not 0 if it has
1639 * DX = If BL=01h First Displayed Scan Line
1640 *
1641 * Input(32-bit):
1642 * BH = 00h Reserved and must be 00h
1643 * BL = 00h Set Display Start
1644 * = 80h Set Display Start during Vertical Retrace
1645 * CX = Bits 0-15 of display start address
1646 * DX = Bits 16-31 of display start address
1647 * ES = Selector for memory mapped registers
1648 */
1649ASM_START
1650vbe_biosfn_set_get_display_start:
1651 cmp bl, #0x80
1652 je set_display_start_wait
1653 cmp bl, #0x01
1654 je get_display_start
1655 jb set_display_start
1656 mov ax, #0x0100
1657 ret
1658set_display_start_wait:
1659 call wait_not_vsync
1660 call wait_vsync
1661set_display_start:
1662 mov ax, cx
1663 call dispi_set_x_offset
1664 mov ax, dx
1665 call dispi_set_y_offset
1666 mov ax, #0x004f
1667 ret
1668get_display_start:
1669 call dispi_get_x_offset
1670 mov cx, ax
1671 call dispi_get_y_offset
1672 mov dx, ax
1673 xor bh, bh
1674 mov ax, #0x004f
1675 ret
1676ASM_END
1677
1678
1679/** Function 08h - Set/Get Dac Palette Format
1680 *
1681 * Input:
1682 * AX = 4F08h
1683 * BL = 00h set DAC palette width
1684 * = 01h get DAC palette width
1685 * BH = If BL=00h: desired number of bits per primary color
1686 * Output:
1687 * AX = VBE Return Status
1688 * BH = current number of bits per primary color (06h = standard VGA)
1689 */
1690ASM_START
1691vbe_biosfn_set_get_dac_palette_format:
1692 cmp bl, #0x01
1693 je get_dac_palette_format
1694 jb set_dac_palette_format
1695 mov ax, #0x0100
1696 ret
1697set_dac_palette_format:
1698 call dispi_get_enable
1699 cmp bh, #0x06
1700 je set_normal_dac
1701 cmp bh, #0x08
1702 jne vbe_08_unsupported
1703 or ax, # VBE_DISPI_8BIT_DAC
1704 jnz set_dac_mode
1705set_normal_dac:
1706 and ax, #~ VBE_DISPI_8BIT_DAC
1707set_dac_mode:
1708 call _dispi_set_enable
1709get_dac_palette_format:
1710 mov bh, #0x06
1711 call dispi_get_enable
1712 and ax, # VBE_DISPI_8BIT_DAC
1713 jz vbe_08_ok
1714 mov bh, #0x08
1715vbe_08_ok:
1716 mov ax, #0x004f
1717 ret
1718vbe_08_unsupported:
1719 mov ax, #0x014f
1720 ret
1721ASM_END
1722
1723
1724/** Function 09h - Set/Get Palette Data
1725 *
1726 * Input:
1727 * AX = 4F09h
1728 * (16-bit) BL = 00h Set palette data
1729 * = 01h Get palette data
1730 * = 02h Set secondary palette data
1731 * = 03h Get secondary palette data
1732 * = 80h Set palette data during VRetrace
1733 * CX = Number of entries to update (<= 256)
1734 * DX = First entry to update
1735 * ES:DI = Table of palette values
1736 * Output:
1737 * AX = VBE Return Status
1738 *
1739 * Notes:
1740 * Secondary palette support is a "future extension".
1741 * Attempts to set/get it should return status 02h.
1742 *
1743 * In VBE 3.0, reading palette data is optional and
1744 * subfunctions 01h and 03h may return failure.
1745 *
1746 * The format of palette entries is as follows:
1747 *
1748 * PaletteEntry struc
1749 * Blue db ? ; Blue channel value (6 or 8 bits)
1750 * Green db ? ; Green channel value (6 or 8 bits)
1751 * Red db ? ; Red channel value (6 or 8 bits)
1752 * Padding db ? ; DWORD alignment byte (unused)
1753 * PaletteEntry ends
1754 *
1755 * Most applications use VGA DAC registers directly to
1756 * set/get palette in VBE modes. However, subfn 4F09h is
1757 * required for NonVGA controllers (eg. XGA).
1758 */
1759ASM_START
1760vbe_biosfn_set_get_palette_data:
1761 test bl, bl
1762 jz set_palette_data
1763 cmp bl, #0x01
1764 je get_palette_data
1765 cmp bl, #0x03
1766 jbe vbe_09_nohw
1767 cmp bl, #0x80
1768 jne vbe_09_unsupported
1769#if 0
1770 /* this is where we could wait for vertical retrace */
1771#endif
1772set_palette_data:
1773 pushad
1774 push ds
1775 push es
1776 pop ds
1777 mov al, dl
1778 mov dx, # VGAREG_DAC_WRITE_ADDRESS
1779 out dx, al
1780 inc dx
1781 mov si, di
1782set_pal_loop:
1783 lodsd
1784 ror eax, #16
1785 out dx, al
1786 rol eax, #8
1787 out dx, al
1788 rol eax, #8
1789 out dx, al
1790 loop set_pal_loop
1791 pop ds
1792 popad
1793vbe_09_ok:
1794 mov ax, #0x004f
1795 ret
1796
1797get_palette_data:
1798 pushad
1799 mov al, dl
1800 mov dx, # VGAREG_DAC_READ_ADDRESS
1801 out dx, al
1802 add dl, #2
1803get_pal_loop:
1804 xor eax, eax
1805 in al, dx
1806 shl eax, #8
1807 in al, dx
1808 shl eax, #8
1809 in al, dx
1810 stosd
1811 loop get_pal_loop
1812 popad
1813 jmp vbe_09_ok
1814
1815vbe_09_unsupported:
1816 mov ax, #0x014f
1817 ret
1818vbe_09_nohw:
1819 mov ax, #0x024f
1820 ret
1821ASM_END
1822
1823
1824/** Function 0Ah - Return VBE Protected Mode Interface
1825 *
1826 * Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface
1827 * BL = 00h Return protected mode table
1828 * Output: AX = Status
1829 * ES = Real Mode Segment of Table
1830 * DI = Offset of Table
1831 * CX = Length of Table including protected mode code
1832 * (for copying purposes)
1833 */
1834ASM_START
1835vbe_biosfn_return_protected_mode_interface:
1836 test bl, bl
1837 jnz _fail
1838 mov di, #0xc000
1839 mov es, di
1840 mov di, # vesa_pm_start
1841 mov cx, # vesa_pm_end
1842 sub cx, di
1843 mov ax, #0x004f
1844 ret
1845_fail:
1846 mov ax, #0x014f
1847 ret
1848ASM_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