VirtualBox

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

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

VGA: Documented VBE_BYTEWISE_IO purpose.

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