VirtualBox

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

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

more branding

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