VirtualBox

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

最後變更 在這個檔案從33360是 33173,由 vboxsync 提交於 14 年 前

VBE: Do not allocate big buffers on stack (get mode info fn).

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette