- improved VBE display capabilities check (X resulution checked now)
[vgabios.git] / vbe.c
blob78bfd8f49374e80d2a5582fb1a629d48a1b364ba
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.
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.
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
29 // ============================================================================================
32 // defines available
34 // disable VESA/VBE2 check in vbe info
35 //#define VBE2_NO_VESA_CHECK
38 #include "vbe.h"
39 #include "vbetables.h"
42 // The current OEM Software Revision of this VBE Bios
43 #define VBE_OEM_SOFTWARE_REV 0x0002;
45 extern char vbebios_copyright;
46 extern char vbebios_vendor_name;
47 extern char vbebios_product_name;
48 extern char vbebios_product_revision;
50 ASM_START
51 // FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
52 _vbebios_copyright:
53 .ascii "Bochs/Plex86 VBE(C) 2003 http://savannah.nongnu.org/projects/vgabios/"
54 .byte 0x00
56 _vbebios_vendor_name:
57 .ascii "Bochs/Plex86 Developers"
58 .byte 0x00
60 _vbebios_product_name:
61 .ascii "Bochs/Plex86 VBE Adapter"
62 .byte 0x00
64 _vbebios_product_revision:
65 .ascii "$Id$"
66 .byte 0x00
68 _vbebios_info_string:
69 .ascii "Bochs VBE Display Adapter enabled"
70 .byte 0x0a,0x0d
71 .byte 0x0a,0x0d
72 .byte 0x00
74 _no_vbebios_info_string:
75 .ascii "NO Bochs VBE Support available!"
76 .byte 0x0a,0x0d
77 .byte 0x0a,0x0d
78 .byte 0x00
80 #if defined(USE_BX_INFO) || defined(DEBUG)
81 msg_vbe_init:
82 .ascii "VBE Bios $Id$"
83 .byte 0x0a,0x0d, 0x00
84 #endif
86 .align 2
87 vesa_pm_start:
88 dw vesa_pm_set_window - vesa_pm_start
89 dw vesa_pm_set_display_start - vesa_pm_start
90 dw vesa_pm_unimplemented - vesa_pm_start
91 dw vesa_pm_io_ports_table - vesa_pm_start
92 vesa_pm_io_ports_table:
93 dw VBE_DISPI_IOPORT_INDEX
94 dw VBE_DISPI_IOPORT_INDEX + 1
95 dw VBE_DISPI_IOPORT_DATA
96 dw VBE_DISPI_IOPORT_DATA + 1
97 dw 0xffff
98 dw 0xffff
100 USE32
101 vesa_pm_set_window:
102 cmp bx, #0x00
103 je vesa_pm_set_display_window1
104 mov ax, #0x0100
106 vesa_pm_set_display_window1:
107 mov ax, dx
108 push dx
109 push ax
110 mov dx, # VBE_DISPI_IOPORT_INDEX
111 mov ax, # VBE_DISPI_INDEX_BANK
112 out dx, ax
113 pop ax
114 mov dx, # VBE_DISPI_IOPORT_DATA
115 out dx, ax
116 pop dx
117 mov ax, #0x004f
120 vesa_pm_set_display_start:
121 cmp bl, #0x80
122 je vesa_pm_set_display_start1
123 cmp bl, #0x00
124 je vesa_pm_set_display_start1
125 mov ax, #0x0100
127 vesa_pm_set_display_start1:
128 ; convert offset to (X, Y) coordinate
129 ; (would be simpler to change Bochs VBE API...)
130 push eax
131 push ecx
132 push edx
133 push esi
134 push edi
135 shl edx, #16
136 and ecx, #0xffff
137 or ecx, edx
138 shl ecx, #2
139 mov eax, ecx
141 push eax
142 mov dx, # VBE_DISPI_IOPORT_INDEX
143 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
144 out dx, ax
145 mov dx, # VBE_DISPI_IOPORT_DATA
146 in ax, dx
147 movzx ecx, ax
149 mov dx, # VBE_DISPI_IOPORT_INDEX
150 mov ax, # VBE_DISPI_INDEX_BPP
151 out dx, ax
152 mov dx, # VBE_DISPI_IOPORT_DATA
153 in ax, dx
154 movzx esi, ax
155 pop eax
157 add esi, #7
158 shr esi, #3
159 imul ecx, esi
160 xor edx, edx
161 div ecx
162 mov edi, eax
163 mov eax, edx
164 xor edx, edx
165 div esi
167 push dx
168 push ax
169 mov dx, # VBE_DISPI_IOPORT_INDEX
170 mov ax, # VBE_DISPI_INDEX_X_OFFSET
171 out dx, ax
172 pop ax
173 mov dx, # VBE_DISPI_IOPORT_DATA
174 out dx, ax
175 pop dx
177 mov ax, di
178 push dx
179 push ax
180 mov dx, # VBE_DISPI_IOPORT_INDEX
181 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
182 out dx, ax
183 pop ax
184 mov dx, # VBE_DISPI_IOPORT_DATA
185 out dx, ax
186 pop dx
188 pop edi
189 pop esi
190 pop edx
191 pop ecx
192 pop eax
193 mov ax, #0x004f
196 vesa_pm_unimplemented:
197 mov ax, #0x014f
199 USE16
200 vesa_pm_end:
202 ; DISPI ioport functions
204 dispi_get_id:
205 push dx
206 mov dx, # VBE_DISPI_IOPORT_INDEX
207 mov ax, # VBE_DISPI_INDEX_ID
208 out dx, ax
209 mov dx, # VBE_DISPI_IOPORT_DATA
210 in ax, dx
211 pop dx
214 dispi_set_id:
215 push dx
216 push ax
217 mov dx, # VBE_DISPI_IOPORT_INDEX
218 mov ax, # VBE_DISPI_INDEX_ID
219 out dx, ax
220 pop ax
221 mov dx, # VBE_DISPI_IOPORT_DATA
222 out dx, ax
223 pop dx
225 ASM_END
227 static void dispi_set_xres(xres)
228 Bit16u xres;
230 ASM_START
231 push bp
232 mov bp, sp
233 push ax
234 push dx
236 mov dx, # VBE_DISPI_IOPORT_INDEX
237 mov ax, # VBE_DISPI_INDEX_XRES
238 out dx, ax
239 mov dx, # VBE_DISPI_IOPORT_DATA
240 mov ax, 4[bp] ; xres
241 out dx, ax
242 push ax
243 mov dx, #0x03d4
244 mov ax, #0x0011
245 out dx, ax
246 mov dx, #0x03d4
247 pop ax
248 push ax
249 shr ax, #3
250 dec ax
251 mov ah, al
252 mov al, #0x01
253 out dx, ax
254 pop ax
255 call vga_set_virt_width
257 pop dx
258 pop ax
259 pop bp
260 ASM_END
263 static void dispi_set_yres(yres)
264 Bit16u yres;
266 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_YRES);
267 outw(VBE_DISPI_IOPORT_DATA,yres);
270 static void dispi_set_bpp(bpp)
271 Bit16u bpp;
273 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_BPP);
274 outw(VBE_DISPI_IOPORT_DATA,bpp);
277 ASM_START
278 ; AL = bits per pixel / AH = bytes per pixel
279 dispi_get_bpp:
280 push dx
281 mov dx, # VBE_DISPI_IOPORT_INDEX
282 mov ax, # VBE_DISPI_INDEX_BPP
283 out dx, ax
284 mov dx, # VBE_DISPI_IOPORT_DATA
285 in ax, dx
286 mov ah, al
287 shr ah, 3
288 test al, #0x07
289 jz get_bpp_noinc
290 inc ah
291 get_bpp_noinc:
292 pop dx
295 ; get display capabilities
297 _dispi_get_max_xres:
298 push dx
299 push bx
300 call dispi_get_enable
301 mov bx, ax
302 or ax, # VBE_DISPI_GETCAPS
303 call _dispi_set_enable
304 mov dx, # VBE_DISPI_IOPORT_INDEX
305 mov ax, # VBE_DISPI_INDEX_XRES
306 out dx, ax
307 mov dx, # VBE_DISPI_IOPORT_DATA
308 in ax, dx
309 push ax
310 mov ax, bx
311 call _dispi_set_enable
312 pop ax
313 pop bx
314 pop dx
317 _dispi_get_max_bpp:
318 push dx
319 push bx
320 call dispi_get_enable
321 mov bx, ax
322 or ax, # VBE_DISPI_GETCAPS
323 call _dispi_set_enable
324 mov dx, # VBE_DISPI_IOPORT_INDEX
325 mov ax, # VBE_DISPI_INDEX_BPP
326 out dx, ax
327 mov dx, # VBE_DISPI_IOPORT_DATA
328 in ax, dx
329 push ax
330 mov ax, bx
331 call _dispi_set_enable
332 pop ax
333 pop bx
334 pop dx
337 _dispi_set_enable:
338 push dx
339 push ax
340 mov dx, # VBE_DISPI_IOPORT_INDEX
341 mov ax, # VBE_DISPI_INDEX_ENABLE
342 out dx, ax
343 pop ax
344 mov dx, # VBE_DISPI_IOPORT_DATA
345 out dx, ax
346 pop dx
349 dispi_get_enable:
350 push dx
351 mov dx, # VBE_DISPI_IOPORT_INDEX
352 mov ax, # VBE_DISPI_INDEX_ENABLE
353 out dx, ax
354 mov dx, # VBE_DISPI_IOPORT_DATA
355 in ax, dx
356 pop dx
359 _dispi_set_bank:
360 push dx
361 push ax
362 mov dx, # VBE_DISPI_IOPORT_INDEX
363 mov ax, # VBE_DISPI_INDEX_BANK
364 out dx, ax
365 pop ax
366 mov dx, # VBE_DISPI_IOPORT_DATA
367 out dx, ax
368 pop dx
371 dispi_get_bank:
372 push dx
373 mov dx, # VBE_DISPI_IOPORT_INDEX
374 mov ax, # VBE_DISPI_INDEX_BANK
375 out dx, ax
376 mov dx, # VBE_DISPI_IOPORT_DATA
377 in ax, dx
378 pop dx
380 ASM_END
382 static void dispi_set_bank_farcall()
384 ASM_START
385 cmp bx,#0x0100
386 je dispi_set_bank_farcall_get
387 or bx,bx
388 jnz dispi_set_bank_farcall_error
389 push dx
390 mov ax,# VBE_DISPI_INDEX_BANK
391 mov dx,# VBE_DISPI_IOPORT_INDEX
392 out dx,ax
393 pop ax
394 mov dx,# VBE_DISPI_IOPORT_DATA
395 out dx,ax
396 retf
397 dispi_set_bank_farcall_get:
398 mov ax,# VBE_DISPI_INDEX_BANK
399 mov dx,# VBE_DISPI_IOPORT_INDEX
400 out dx,ax
401 mov dx,# VBE_DISPI_IOPORT_DATA
402 in ax,dx
403 mov dx,ax
404 retf
405 dispi_set_bank_farcall_error:
406 mov ax,#0x014F
407 retf
408 ASM_END
411 ASM_START
412 dispi_set_x_offset:
413 push dx
414 push ax
415 mov dx, # VBE_DISPI_IOPORT_INDEX
416 mov ax, # VBE_DISPI_INDEX_X_OFFSET
417 out dx, ax
418 pop ax
419 mov dx, # VBE_DISPI_IOPORT_DATA
420 out dx, ax
421 pop dx
424 dispi_get_x_offset:
425 push dx
426 mov dx, # VBE_DISPI_IOPORT_INDEX
427 mov ax, # VBE_DISPI_INDEX_X_OFFSET
428 out dx, ax
429 mov dx, # VBE_DISPI_IOPORT_DATA
430 in ax, dx
431 pop dx
434 dispi_set_y_offset:
435 push dx
436 push ax
437 mov dx, # VBE_DISPI_IOPORT_INDEX
438 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
439 out dx, ax
440 pop ax
441 mov dx, # VBE_DISPI_IOPORT_DATA
442 out dx, ax
443 pop dx
446 dispi_get_y_offset:
447 push dx
448 mov dx, # VBE_DISPI_IOPORT_INDEX
449 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
450 out dx, ax
451 mov dx, # VBE_DISPI_IOPORT_DATA
452 in ax, dx
453 pop dx
456 vga_set_virt_width:
457 push ax
458 push bx
459 push dx
460 mov bx, ax
461 call dispi_get_bpp
462 cmp al, #0x04
463 ja set_width_svga
464 shr bx, #2
465 set_width_svga:
466 shr bx, #2
467 mov dx, #0x03d4
468 mov ah, bl
469 mov al, #0x13
470 out dx, ax
471 pop dx
472 pop bx
473 pop ax
476 dispi_set_virt_width:
477 call vga_set_virt_width
478 push dx
479 push ax
480 mov dx, # VBE_DISPI_IOPORT_INDEX
481 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
482 out dx, ax
483 pop ax
484 mov dx, # VBE_DISPI_IOPORT_DATA
485 out dx, ax
486 pop dx
489 dispi_get_virt_width:
490 push dx
491 mov dx, # VBE_DISPI_IOPORT_INDEX
492 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
493 out dx, ax
494 mov dx, # VBE_DISPI_IOPORT_DATA
495 in ax, dx
496 pop dx
499 dispi_get_virt_height:
500 push dx
501 mov dx, # VBE_DISPI_IOPORT_INDEX
502 mov ax, # VBE_DISPI_INDEX_VIRT_HEIGHT
503 out dx, ax
504 mov dx, # VBE_DISPI_IOPORT_DATA
505 in ax, dx
506 pop dx
508 ASM_END
511 // ModeInfo helper function
512 static ModeInfoListItem* mode_info_find_mode(mode, using_lfb)
513 Bit16u mode; Boolean using_lfb;
515 ModeInfoListItem *cur_info=&mode_info_list;
517 while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
519 if (cur_info->mode == mode)
521 if (!using_lfb)
523 return cur_info;
525 else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
527 return cur_info;
529 else
531 cur_info++;
534 else
536 cur_info++;
540 return 0;
543 ASM_START
545 ; Has VBE display - Returns true if VBE display detected
547 _vbe_has_vbe_display:
548 push ds
549 push bx
550 mov ax, # BIOSMEM_SEG
551 mov ds, ax
552 mov bx, # BIOSMEM_VBE_FLAG
553 mov al, [bx]
554 and al, #0x01
555 xor ah, ah
556 pop bx
557 pop ds
560 ; VBE Init - Initialise the Vesa Bios Extension Code
561 ; This function does a sanity check on the host side display code interface.
563 vbe_init:
564 mov ax, # VBE_DISPI_ID0
565 call dispi_set_id
566 call dispi_get_id
567 cmp ax, # VBE_DISPI_ID0
568 jne no_vbe_interface
569 push ds
570 push bx
571 mov ax, # BIOSMEM_SEG
572 mov ds, ax
573 mov bx, # BIOSMEM_VBE_FLAG
574 mov al, #0x01
575 mov [bx], al
576 pop bx
577 pop ds
578 mov ax, # VBE_DISPI_ID3
579 call dispi_set_id
580 no_vbe_interface:
581 #if defined(USE_BX_INFO) || defined(DEBUG)
582 mov bx, #msg_vbe_init
583 push bx
584 call _printf
585 inc sp
586 inc sp
587 #endif
590 ; VBE Display Info - Display information on screen about the VBE
592 vbe_display_info:
593 call _vbe_has_vbe_display
594 test ax, ax
595 jz no_vbe_flag
596 mov ax, #0xc000
597 mov ds, ax
598 mov si, #_vbebios_info_string
599 jmp _display_string
600 no_vbe_flag:
601 mov ax, #0xc000
602 mov ds, ax
603 mov si, #_no_vbebios_info_string
604 jmp _display_string
605 ASM_END
607 /** Function 00h - Return VBE Controller Information
609 * Input:
610 * AX = 4F00h
611 * ES:DI = Pointer to buffer in which to place VbeInfoBlock structure
612 * (VbeSignature should be VBE2 when VBE 2.0 information is desired and
613 * the info block is 512 bytes in size)
614 * Output:
615 * AX = VBE Return Status
618 void vbe_biosfn_return_controller_information(AX, ES, DI)
619 Bit16u *AX;Bit16u ES;Bit16u DI;
621 Bit16u ss=get_SS();
622 VbeInfoBlock vbe_info_block;
623 Bit16u status;
624 Bit16u result;
625 Bit16u vbe2_info;
626 Bit16u cur_mode=0;
627 Bit16u cur_ptr=34;
628 ModeInfoListItem *cur_info=&mode_info_list;
630 status = read_word(ss, AX);
632 #ifdef DEBUG
633 printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
634 #endif
636 vbe2_info = 0;
637 #ifdef VBE2_NO_VESA_CHECK
638 #else
639 // get vbe_info_block into local variable
640 memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
642 // check for VBE2 signature
643 if (((vbe_info_block.VbeSignature[0] == 'V') &&
644 (vbe_info_block.VbeSignature[1] == 'B') &&
645 (vbe_info_block.VbeSignature[2] == 'E') &&
646 (vbe_info_block.VbeSignature[3] == '2')) ||
648 ((vbe_info_block.VbeSignature[0] == 'V') &&
649 (vbe_info_block.VbeSignature[1] == 'E') &&
650 (vbe_info_block.VbeSignature[2] == 'S') &&
651 (vbe_info_block.VbeSignature[3] == 'A')) )
653 vbe2_info = 1;
654 #ifdef DEBUG
655 printf("VBE correct VESA/VBE2 signature found\n");
656 #endif
658 #endif
660 // VBE Signature
661 vbe_info_block.VbeSignature[0] = 'V';
662 vbe_info_block.VbeSignature[1] = 'E';
663 vbe_info_block.VbeSignature[2] = 'S';
664 vbe_info_block.VbeSignature[3] = 'A';
666 // VBE Version supported
667 vbe_info_block.VbeVersion = 0x0200;
669 // OEM String
670 vbe_info_block.OemStringPtr_Seg = 0xc000;
671 vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
673 // Capabilities
674 vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
675 vbe_info_block.Capabilities[1] = 0;
676 vbe_info_block.Capabilities[2] = 0;
677 vbe_info_block.Capabilities[3] = 0;
679 // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
680 vbe_info_block.VideoModePtr_Seg= ES ;
681 vbe_info_block.VideoModePtr_Off= DI + 34;
683 // VBE Total Memory (in 64b blocks)
684 vbe_info_block.TotalMemory = VBE_TOTAL_VIDEO_MEMORY_DIV_64K;
686 if (vbe2_info)
688 // OEM Stuff
689 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
690 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
691 vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
692 vbe_info_block.OemProductNamePtr_Seg = 0xc000;
693 vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
694 vbe_info_block.OemProductRevPtr_Seg = 0xc000;
695 vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
697 // copy updates in vbe_info_block back
698 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
700 else
702 // copy updates in vbe_info_block back (VBE 1.x compatibility)
703 memcpyb(ES, DI, ss, &vbe_info_block, 256);
708 if ((cur_info->info.XResolution <= dispi_get_max_xres()) &&
709 (cur_info->info.BitsPerPixel <= dispi_get_max_bpp())) {
710 #ifdef DEBUG
711 printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
712 #endif
713 write_word(ES, DI + cur_ptr, cur_info->mode);
714 cur_mode++;
715 cur_ptr+=2;
717 cur_info++;
718 } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
720 // Add vesa mode list terminator
721 write_word(ES, DI + cur_ptr, cur_info->mode);
723 result = 0x4f;
725 write_word(ss, AX, result);
729 /** Function 01h - Return VBE Mode Information
731 * Input:
732 * AX = 4F01h
733 * CX = Mode Number
734 * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure
735 * Output:
736 * AX = VBE Return Status
739 void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
740 Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
742 Bit16u result=0x0100;
743 Bit16u ss=get_SS();
744 ModeInfoBlock info;
745 ModeInfoListItem *cur_info;
746 Boolean using_lfb;
748 #ifdef DEBUG
749 printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
750 #endif
752 using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
754 CX = (CX & 0x1ff);
756 cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
758 if (cur_info != 0)
760 #ifdef DEBUG
761 printf("VBE found mode %x\n",CX);
762 #endif
763 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
764 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
765 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
766 info.WinFuncPtr = 0xC0000000UL;
767 *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
770 result = 0x4f;
772 else
774 #ifdef DEBUG
775 printf("VBE *NOT* found mode %x\n",CX);
776 #endif
777 result = 0x100;
780 if (result == 0x4f)
782 // copy updates in mode_info_block back
783 memcpyb(ES, DI, ss, &info, sizeof(info));
786 write_word(ss, AX, result);
789 /** Function 02h - Set VBE Mode
791 * Input:
792 * AX = 4F02h
793 * BX = Desired Mode to set
794 * ES:DI = Pointer to CRTCInfoBlock structure
795 * Output:
796 * AX = VBE Return Status
799 void vbe_biosfn_set_mode(AX, BX, ES, DI)
800 Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
802 Bit16u ss = get_SS();
803 Bit16u result;
804 ModeInfoListItem *cur_info;
805 Boolean using_lfb;
806 Bit8u no_clear;
807 Bit8u lfb_flag;
809 using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
810 lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
811 no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
813 BX = (BX & 0x1ff);
815 //result=read_word(ss,AX);
817 // check for non vesa mode
818 if (BX<VBE_MODE_VESA_DEFINED)
820 Bit8u mode;
822 dispi_set_enable(VBE_DISPI_DISABLED);
823 // call the vgabios in order to set the video mode
824 // this allows for going back to textmode with a VBE call (some applications expect that to work)
826 mode=(BX & 0xff);
827 biosfn_set_video_mode(mode);
828 result = 0x4f;
831 cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
833 if (cur_info != 0)
835 #ifdef DEBUG
836 printf("VBE found mode %x, setting:\n", BX);
837 printf("\txres%x yres%x bpp%x\n",
838 cur_info->info.XResolution,
839 cur_info->info.YResolution,
840 cur_info->info.BitsPerPixel);
841 #endif
843 // first disable current mode (when switching between vesa modi)
844 dispi_set_enable(VBE_DISPI_DISABLED);
846 if (cur_info->mode == VBE_VESA_MODE_800X600X4)
848 biosfn_set_video_mode(0x6a);
851 dispi_set_bpp(cur_info->info.BitsPerPixel);
852 dispi_set_xres(cur_info->info.XResolution);
853 dispi_set_yres(cur_info->info.YResolution);
854 dispi_set_bank(0);
855 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
857 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
858 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
860 result = 0x4f;
862 else
864 #ifdef DEBUG
865 printf("VBE *NOT* found mode %x\n" , BX);
866 #endif
867 result = 0x100;
869 // FIXME: redirect non VBE modi to normal VGA bios operation
870 // (switch back to VGA mode
871 if (BX == 3)
872 result = 0x4f;
875 write_word(ss, AX, result);
878 /** Function 03h - Return Current VBE Mode
880 * Input:
881 * AX = 4F03h
882 * Output:
883 * AX = VBE Return Status
884 * BX = Current VBE Mode
887 ASM_START
888 vbe_biosfn_return_current_mode:
889 push ds
890 mov ax, # BIOSMEM_SEG
891 mov ds, ax
892 call dispi_get_enable
893 and ax, # VBE_DISPI_ENABLED
894 jz no_vbe_mode
895 mov bx, # BIOSMEM_VBE_MODE
896 mov ax, [bx]
897 mov bx, ax
898 jnz vbe_03_ok
899 no_vbe_mode:
900 mov bx, # BIOSMEM_CURRENT_MODE
901 mov al, [bx]
902 mov bl, al
903 xor bh, bh
904 vbe_03_ok:
905 mov ax, #0x004f
906 pop ds
908 ASM_END
911 Bit16u vbe_biosfn_read_video_state_size()
913 return 9 * 2;
916 void vbe_biosfn_save_video_state(ES, BX)
917 Bit16u ES; Bit16u BX;
919 Bit16u enable, i;
921 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
922 enable = inw(VBE_DISPI_IOPORT_DATA);
923 write_word(ES, BX, enable);
924 BX += 2;
925 if (!(enable & VBE_DISPI_ENABLED))
926 return;
927 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
928 if (i != VBE_DISPI_INDEX_ENABLE) {
929 outw(VBE_DISPI_IOPORT_INDEX, i);
930 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
931 BX += 2;
937 void vbe_biosfn_restore_video_state(ES, BX)
938 Bit16u ES; Bit16u BX;
940 Bit16u enable, i;
942 enable = read_word(ES, BX);
943 BX += 2;
945 if (!(enable & VBE_DISPI_ENABLED)) {
946 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
947 outw(VBE_DISPI_IOPORT_DATA, enable);
948 } else {
949 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
950 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
951 BX += 2;
952 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
953 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
954 BX += 2;
955 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
956 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
957 BX += 2;
958 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
959 outw(VBE_DISPI_IOPORT_DATA, enable);
961 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
962 outw(VBE_DISPI_IOPORT_INDEX, i);
963 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
964 BX += 2;
969 /** Function 04h - Save/Restore State
971 * Input:
972 * AX = 4F04h
973 * DL = 00h Return Save/Restore State buffer size
974 * 01h Save State
975 * 02h Restore State
976 * CX = Requested states
977 * ES:BX = Pointer to buffer (if DL <> 00h)
978 * Output:
979 * AX = VBE Return Status
980 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
983 void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
984 Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
986 Bit16u ss=get_SS();
987 Bit16u result, val;
989 result = 0x4f;
990 switch(GET_DL()) {
991 case 0x00:
992 val = biosfn_read_video_state_size2(CX);
993 #ifdef DEBUG
994 printf("VGA state size=%x\n", val);
995 #endif
996 if (CX & 8)
997 val += vbe_biosfn_read_video_state_size();
998 write_word(ss, BX, val);
999 break;
1000 case 0x01:
1001 val = read_word(ss, BX);
1002 val = biosfn_save_video_state(CX, ES, val);
1003 #ifdef DEBUG
1004 printf("VGA save_state offset=%x\n", val);
1005 #endif
1006 if (CX & 8)
1007 vbe_biosfn_save_video_state(ES, val);
1008 break;
1009 case 0x02:
1010 val = read_word(ss, BX);
1011 val = biosfn_restore_video_state(CX, ES, val);
1012 #ifdef DEBUG
1013 printf("VGA restore_state offset=%x\n", val);
1014 #endif
1015 if (CX & 8)
1016 vbe_biosfn_restore_video_state(ES, val);
1017 break;
1018 default:
1019 // function failed
1020 result = 0x100;
1021 break;
1023 write_word(ss, AX, result);
1026 /** Function 05h - Display Window Control
1028 * Input:
1029 * AX = 4F05h
1030 * (16-bit) BH = 00h Set memory window
1031 * = 01h Get memory window
1032 * BL = Window number
1033 * = 00h Window A
1034 * = 01h Window B
1035 * DX = Window number in video memory in window
1036 * granularity units (Set Memory Window only)
1037 * Note:
1038 * If this function is called while in a linear frame buffer mode,
1039 * this function must fail with completion code AH=03h
1041 * Output:
1042 * AX = VBE Return Status
1043 * DX = Window number in window granularity units
1044 * (Get Memory Window only)
1046 ASM_START
1047 vbe_biosfn_display_window_control:
1048 cmp bl, #0x00
1049 jne vbe_05_failed
1050 cmp bh, #0x01
1051 je get_display_window
1052 jb set_display_window
1053 mov ax, #0x0100
1055 set_display_window:
1056 mov ax, dx
1057 call _dispi_set_bank
1058 call dispi_get_bank
1059 cmp ax, dx
1060 jne vbe_05_failed
1061 mov ax, #0x004f
1063 get_display_window:
1064 call dispi_get_bank
1065 mov dx, ax
1066 mov ax, #0x004f
1068 vbe_05_failed:
1069 mov ax, #0x014f
1071 ASM_END
1074 /** Function 06h - Set/Get Logical Scan Line Length
1076 * Input:
1077 * AX = 4F06h
1078 * BL = 00h Set Scan Line Length in Pixels
1079 * = 01h Get Scan Line Length
1080 * = 02h Set Scan Line Length in Bytes
1081 * = 03h Get Maximum Scan Line Length
1082 * CX = If BL=00h Desired Width in Pixels
1083 * If BL=02h Desired Width in Bytes
1084 * (Ignored for Get Functions)
1086 * Output:
1087 * AX = VBE Return Status
1088 * BX = Bytes Per Scan Line
1089 * CX = Actual Pixels Per Scan Line
1090 * (truncated to nearest complete pixel)
1091 * DX = Maximum Number of Scan Lines
1093 ASM_START
1094 vbe_biosfn_set_get_logical_scan_line_length:
1095 mov ax, cx
1096 cmp bl, #0x01
1097 je get_logical_scan_line_length
1098 cmp bl, #0x02
1099 je set_logical_scan_line_bytes
1100 jb set_logical_scan_line_pixels
1101 mov ax, #0x0100
1103 set_logical_scan_line_bytes:
1104 push ax
1105 call dispi_get_bpp
1106 xor bh, bh
1107 mov bl, ah
1108 xor dx, dx
1109 pop ax
1110 div bx
1111 set_logical_scan_line_pixels:
1112 call dispi_set_virt_width
1113 get_logical_scan_line_length:
1114 call dispi_get_bpp
1115 xor bh, bh
1116 mov bl, ah
1117 call dispi_get_virt_width
1118 mov cx, ax
1119 mul bx
1120 mov bx, ax
1121 call dispi_get_virt_height
1122 mov dx, ax
1123 mov ax, #0x004f
1125 ASM_END
1128 /** Function 07h - Set/Get Display Start
1130 * Input(16-bit):
1131 * AX = 4F07h
1132 * BH = 00h Reserved and must be 00h
1133 * BL = 00h Set Display Start
1134 * = 01h Get Display Start
1135 * = 02h Schedule Display Start (Alternate)
1136 * = 03h Schedule Stereoscopic Display Start
1137 * = 04h Get Scheduled Display Start Status
1138 * = 05h Enable Stereoscopic Mode
1139 * = 06h Disable Stereoscopic Mode
1140 * = 80h Set Display Start during Vertical Retrace
1141 * = 82h Set Display Start during Vertical Retrace (Alternate)
1142 * = 83h Set Stereoscopic Display Start during Vertical Retrace
1143 * ECX = If BL=02h/82h Display Start Address in bytes
1144 * If BL=03h/83h Left Image Start Address in bytes
1145 * EDX = If BL=03h/83h Right Image Start Address in bytes
1146 * CX = If BL=00h/80h First Displayed Pixel In Scan Line
1147 * DX = If BL=00h/80h First Displayed Scan Line
1149 * Output:
1150 * AX = VBE Return Status
1151 * BH = If BL=01h Reserved and will be 0
1152 * CX = If BL=01h First Displayed Pixel In Scan Line
1153 * If BL=04h 0 if flip has not occurred, not 0 if it has
1154 * DX = If BL=01h First Displayed Scan Line
1156 * Input(32-bit):
1157 * BH = 00h Reserved and must be 00h
1158 * BL = 00h Set Display Start
1159 * = 80h Set Display Start during Vertical Retrace
1160 * CX = Bits 0-15 of display start address
1161 * DX = Bits 16-31 of display start address
1162 * ES = Selector for memory mapped registers
1164 ASM_START
1165 vbe_biosfn_set_get_display_start:
1166 cmp bl, #0x80
1167 je set_display_start
1168 cmp bl, #0x01
1169 je get_display_start
1170 jb set_display_start
1171 mov ax, #0x0100
1173 set_display_start:
1174 mov ax, cx
1175 call dispi_set_x_offset
1176 mov ax, dx
1177 call dispi_set_y_offset
1178 mov ax, #0x004f
1180 get_display_start:
1181 call dispi_get_x_offset
1182 mov cx, ax
1183 call dispi_get_y_offset
1184 mov dx, ax
1185 xor bh, bh
1186 mov ax, #0x004f
1188 ASM_END
1191 /** Function 08h - Set/Get Dac Palette Format
1193 * Input:
1194 * AX = 4F08h
1195 * BL = 00h set DAC palette width
1196 * = 01h get DAC palette width
1197 * BH = If BL=00h: desired number of bits per primary color
1198 * Output:
1199 * AX = VBE Return Status
1200 * BH = current number of bits per primary color (06h = standard VGA)
1202 ASM_START
1203 vbe_biosfn_set_get_dac_palette_format:
1204 cmp bl, #0x01
1205 je get_dac_palette_format
1206 jb set_dac_palette_format
1207 mov ax, #0x0100
1209 set_dac_palette_format:
1210 call dispi_get_enable
1211 cmp bh, #0x06
1212 je set_normal_dac
1213 cmp bh, #0x08
1214 jne vbe_08_unsupported
1215 or ax, # VBE_DISPI_8BIT_DAC
1216 jnz set_dac_mode
1217 set_normal_dac:
1218 and ax, #~ VBE_DISPI_8BIT_DAC
1219 set_dac_mode:
1220 call _dispi_set_enable
1221 get_dac_palette_format:
1222 mov bh, #0x06
1223 call dispi_get_enable
1224 and ax, # VBE_DISPI_8BIT_DAC
1225 jz vbe_08_ok
1226 mov bh, #0x08
1227 vbe_08_ok:
1228 mov ax, #0x004f
1230 vbe_08_unsupported:
1231 mov ax, #0x014f
1233 ASM_END
1236 /** Function 09h - Set/Get Palette Data
1238 * Input:
1239 * AX = 4F09h
1240 * Output:
1241 * AX = VBE Return Status
1243 * FIXME: incomplete API description, Input & Output
1245 void vbe_biosfn_set_get_palette_data(AX)
1249 /** Function 0Ah - Return VBE Protected Mode Interface
1250 * Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface
1251 * BL = 00h Return protected mode table
1254 * Output: AX = Status
1255 * ES = Real Mode Segment of Table
1256 * DI = Offset of Table
1257 * CX = Length of Table including protected mode code
1258 * (for copying purposes)
1260 ASM_START
1261 vbe_biosfn_return_protected_mode_interface:
1262 test bl, bl
1263 jnz _fail
1264 mov di, #0xc000
1265 mov es, di
1266 mov di, # vesa_pm_start
1267 mov cx, # vesa_pm_end
1268 sub cx, di
1269 mov ax, #0x004f
1271 _fail:
1272 mov ax, #0x014f
1274 ASM_END