- VBE set bank functions failure handling added
[vgabios.git] / vbe.c
blob7bf7aeed75cc331569c07fbd96dd532777303b11
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 in ax, dx
117 pop dx
118 cmp dx, ax
119 jne illegal_window
120 mov ax, #0x004f
122 illegal_window:
123 mov ax, #0x014f
126 vesa_pm_set_display_start:
127 cmp bl, #0x80
128 je vesa_pm_set_display_start1
129 cmp bl, #0x00
130 je vesa_pm_set_display_start1
131 mov ax, #0x0100
133 vesa_pm_set_display_start1:
134 ; convert offset to (X, Y) coordinate
135 ; (would be simpler to change Bochs VBE API...)
136 push eax
137 push ecx
138 push edx
139 push esi
140 push edi
141 shl edx, #16
142 and ecx, #0xffff
143 or ecx, edx
144 shl ecx, #2
145 mov eax, ecx
147 push eax
148 mov dx, # VBE_DISPI_IOPORT_INDEX
149 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
150 out dx, ax
151 mov dx, # VBE_DISPI_IOPORT_DATA
152 in ax, dx
153 movzx ecx, ax
155 mov dx, # VBE_DISPI_IOPORT_INDEX
156 mov ax, # VBE_DISPI_INDEX_BPP
157 out dx, ax
158 mov dx, # VBE_DISPI_IOPORT_DATA
159 in ax, dx
160 movzx esi, ax
161 pop eax
163 cmp esi, #4
164 jz bpp4_mode
165 add esi, #7
166 shr esi, #3
167 imul ecx, esi
168 xor edx, edx
169 div ecx
170 mov edi, eax
171 mov eax, edx
172 xor edx, edx
173 div esi
174 jmp set_xy_regs
176 bpp4_mode:
177 shr ecx, #1
178 xor edx, edx
179 div ecx
180 mov edi, eax
181 mov eax, edx
182 shl eax, #1
184 set_xy_regs:
185 push dx
186 push ax
187 mov dx, # VBE_DISPI_IOPORT_INDEX
188 mov ax, # VBE_DISPI_INDEX_X_OFFSET
189 out dx, ax
190 pop ax
191 mov dx, # VBE_DISPI_IOPORT_DATA
192 out dx, ax
193 pop dx
195 mov ax, di
196 push dx
197 push ax
198 mov dx, # VBE_DISPI_IOPORT_INDEX
199 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
200 out dx, ax
201 pop ax
202 mov dx, # VBE_DISPI_IOPORT_DATA
203 out dx, ax
204 pop dx
206 pop edi
207 pop esi
208 pop edx
209 pop ecx
210 pop eax
211 mov ax, #0x004f
214 vesa_pm_unimplemented:
215 mov ax, #0x014f
217 USE16
218 vesa_pm_end:
220 ; DISPI ioport functions
222 dispi_get_id:
223 push dx
224 mov dx, # VBE_DISPI_IOPORT_INDEX
225 mov ax, # VBE_DISPI_INDEX_ID
226 out dx, ax
227 mov dx, # VBE_DISPI_IOPORT_DATA
228 in ax, dx
229 pop dx
232 dispi_set_id:
233 push dx
234 push ax
235 mov dx, # VBE_DISPI_IOPORT_INDEX
236 mov ax, # VBE_DISPI_INDEX_ID
237 out dx, ax
238 pop ax
239 mov dx, # VBE_DISPI_IOPORT_DATA
240 out dx, ax
241 pop dx
243 ASM_END
245 static void dispi_set_xres(xres)
246 Bit16u xres;
248 ASM_START
249 push bp
250 mov bp, sp
251 push ax
252 push dx
254 mov dx, # VBE_DISPI_IOPORT_INDEX
255 mov ax, # VBE_DISPI_INDEX_XRES
256 out dx, ax
257 mov dx, # VBE_DISPI_IOPORT_DATA
258 mov ax, 4[bp] ; xres
259 out dx, ax
260 push ax
261 mov dx, #0x03d4
262 mov ax, #0x0011
263 out dx, ax
264 mov dx, #0x03d4
265 pop ax
266 push ax
267 shr ax, #3
268 dec ax
269 mov ah, al
270 mov al, #0x01
271 out dx, ax
272 pop ax
273 call vga_set_virt_width
275 pop dx
276 pop ax
277 pop bp
278 ASM_END
281 static void dispi_set_yres(yres)
282 Bit16u yres;
284 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_YRES);
285 outw(VBE_DISPI_IOPORT_DATA,yres);
288 static void dispi_set_bpp(bpp)
289 Bit16u bpp;
291 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_BPP);
292 outw(VBE_DISPI_IOPORT_DATA,bpp);
295 ASM_START
296 ; AL = bits per pixel / AH = bytes per pixel
297 dispi_get_bpp:
298 push dx
299 mov dx, # VBE_DISPI_IOPORT_INDEX
300 mov ax, # VBE_DISPI_INDEX_BPP
301 out dx, ax
302 mov dx, # VBE_DISPI_IOPORT_DATA
303 in ax, dx
304 mov ah, al
305 shr ah, 3
306 test al, #0x07
307 jz get_bpp_noinc
308 inc ah
309 get_bpp_noinc:
310 pop dx
313 ; get display capabilities
315 _dispi_get_max_xres:
316 push dx
317 push bx
318 call dispi_get_enable
319 mov bx, ax
320 or ax, # VBE_DISPI_GETCAPS
321 call _dispi_set_enable
322 mov dx, # VBE_DISPI_IOPORT_INDEX
323 mov ax, # VBE_DISPI_INDEX_XRES
324 out dx, ax
325 mov dx, # VBE_DISPI_IOPORT_DATA
326 in ax, dx
327 push ax
328 mov ax, bx
329 call _dispi_set_enable
330 pop ax
331 pop bx
332 pop dx
335 _dispi_get_max_bpp:
336 push dx
337 push bx
338 call dispi_get_enable
339 mov bx, ax
340 or ax, # VBE_DISPI_GETCAPS
341 call _dispi_set_enable
342 mov dx, # VBE_DISPI_IOPORT_INDEX
343 mov ax, # VBE_DISPI_INDEX_BPP
344 out dx, ax
345 mov dx, # VBE_DISPI_IOPORT_DATA
346 in ax, dx
347 push ax
348 mov ax, bx
349 call _dispi_set_enable
350 pop ax
351 pop bx
352 pop dx
355 _dispi_set_enable:
356 push dx
357 push ax
358 mov dx, # VBE_DISPI_IOPORT_INDEX
359 mov ax, # VBE_DISPI_INDEX_ENABLE
360 out dx, ax
361 pop ax
362 mov dx, # VBE_DISPI_IOPORT_DATA
363 out dx, ax
364 pop dx
367 dispi_get_enable:
368 push dx
369 mov dx, # VBE_DISPI_IOPORT_INDEX
370 mov ax, # VBE_DISPI_INDEX_ENABLE
371 out dx, ax
372 mov dx, # VBE_DISPI_IOPORT_DATA
373 in ax, dx
374 pop dx
377 _dispi_set_bank:
378 push dx
379 push ax
380 mov dx, # VBE_DISPI_IOPORT_INDEX
381 mov ax, # VBE_DISPI_INDEX_BANK
382 out dx, ax
383 pop ax
384 mov dx, # VBE_DISPI_IOPORT_DATA
385 out dx, ax
386 pop dx
389 dispi_get_bank:
390 push dx
391 mov dx, # VBE_DISPI_IOPORT_INDEX
392 mov ax, # VBE_DISPI_INDEX_BANK
393 out dx, ax
394 mov dx, # VBE_DISPI_IOPORT_DATA
395 in ax, dx
396 pop dx
398 ASM_END
400 static void dispi_set_bank_farcall()
402 ASM_START
403 cmp bx,#0x0100
404 je dispi_set_bank_farcall_get
405 or bx,bx
406 jnz dispi_set_bank_farcall_error
407 mov ax,dx
408 push dx
409 push ax
410 mov ax,# VBE_DISPI_INDEX_BANK
411 mov dx,# VBE_DISPI_IOPORT_INDEX
412 out dx,ax
413 pop ax
414 mov dx,# VBE_DISPI_IOPORT_DATA
415 out dx,ax
416 in ax,dx
417 pop dx
418 cmp dx,ax
419 jne dispi_set_bank_farcall_error
420 mov ax, #0x004f
421 retf
422 dispi_set_bank_farcall_get:
423 mov ax,# VBE_DISPI_INDEX_BANK
424 mov dx,# VBE_DISPI_IOPORT_INDEX
425 out dx,ax
426 mov dx,# VBE_DISPI_IOPORT_DATA
427 in ax,dx
428 mov dx,ax
429 retf
430 dispi_set_bank_farcall_error:
431 mov ax,#0x014F
432 retf
433 ASM_END
436 ASM_START
437 dispi_set_x_offset:
438 push dx
439 push ax
440 mov dx, # VBE_DISPI_IOPORT_INDEX
441 mov ax, # VBE_DISPI_INDEX_X_OFFSET
442 out dx, ax
443 pop ax
444 mov dx, # VBE_DISPI_IOPORT_DATA
445 out dx, ax
446 pop dx
449 dispi_get_x_offset:
450 push dx
451 mov dx, # VBE_DISPI_IOPORT_INDEX
452 mov ax, # VBE_DISPI_INDEX_X_OFFSET
453 out dx, ax
454 mov dx, # VBE_DISPI_IOPORT_DATA
455 in ax, dx
456 pop dx
459 dispi_set_y_offset:
460 push dx
461 push ax
462 mov dx, # VBE_DISPI_IOPORT_INDEX
463 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
464 out dx, ax
465 pop ax
466 mov dx, # VBE_DISPI_IOPORT_DATA
467 out dx, ax
468 pop dx
471 dispi_get_y_offset:
472 push dx
473 mov dx, # VBE_DISPI_IOPORT_INDEX
474 mov ax, # VBE_DISPI_INDEX_Y_OFFSET
475 out dx, ax
476 mov dx, # VBE_DISPI_IOPORT_DATA
477 in ax, dx
478 pop dx
481 vga_set_virt_width:
482 push ax
483 push bx
484 push dx
485 mov bx, ax
486 call dispi_get_bpp
487 cmp al, #0x04
488 ja set_width_svga
489 shr bx, #2
490 set_width_svga:
491 shr bx, #2
492 mov dx, #0x03d4
493 mov ah, bl
494 mov al, #0x13
495 out dx, ax
496 pop dx
497 pop bx
498 pop ax
501 dispi_set_virt_width:
502 call vga_set_virt_width
503 push dx
504 push ax
505 mov dx, # VBE_DISPI_IOPORT_INDEX
506 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
507 out dx, ax
508 pop ax
509 mov dx, # VBE_DISPI_IOPORT_DATA
510 out dx, ax
511 pop dx
514 dispi_get_virt_width:
515 push dx
516 mov dx, # VBE_DISPI_IOPORT_INDEX
517 mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
518 out dx, ax
519 mov dx, # VBE_DISPI_IOPORT_DATA
520 in ax, dx
521 pop dx
524 dispi_get_virt_height:
525 push dx
526 mov dx, # VBE_DISPI_IOPORT_INDEX
527 mov ax, # VBE_DISPI_INDEX_VIRT_HEIGHT
528 out dx, ax
529 mov dx, # VBE_DISPI_IOPORT_DATA
530 in ax, dx
531 pop dx
533 ASM_END
536 // ModeInfo helper function
537 static ModeInfoListItem* mode_info_find_mode(mode, using_lfb)
538 Bit16u mode; Boolean using_lfb;
540 ModeInfoListItem *cur_info=&mode_info_list;
542 while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
544 if (cur_info->mode == mode)
546 if (!using_lfb)
548 return cur_info;
550 else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
552 return cur_info;
554 else
556 cur_info++;
559 else
561 cur_info++;
565 return 0;
568 ASM_START
570 ; Has VBE display - Returns true if VBE display detected
572 _vbe_has_vbe_display:
573 push ds
574 push bx
575 mov ax, # BIOSMEM_SEG
576 mov ds, ax
577 mov bx, # BIOSMEM_VBE_FLAG
578 mov al, [bx]
579 and al, #0x01
580 xor ah, ah
581 pop bx
582 pop ds
585 ; VBE Init - Initialise the Vesa Bios Extension Code
586 ; This function does a sanity check on the host side display code interface.
588 vbe_init:
589 mov ax, # VBE_DISPI_ID0
590 call dispi_set_id
591 call dispi_get_id
592 cmp ax, # VBE_DISPI_ID0
593 jne no_vbe_interface
594 push ds
595 push bx
596 mov ax, # BIOSMEM_SEG
597 mov ds, ax
598 mov bx, # BIOSMEM_VBE_FLAG
599 mov al, #0x01
600 mov [bx], al
601 pop bx
602 pop ds
603 mov ax, # VBE_DISPI_ID3
604 call dispi_set_id
605 no_vbe_interface:
606 #if defined(USE_BX_INFO) || defined(DEBUG)
607 mov bx, #msg_vbe_init
608 push bx
609 call _printf
610 inc sp
611 inc sp
612 #endif
615 ; VBE Display Info - Display information on screen about the VBE
617 vbe_display_info:
618 call _vbe_has_vbe_display
619 test ax, ax
620 jz no_vbe_flag
621 mov ax, #0xc000
622 mov ds, ax
623 mov si, #_vbebios_info_string
624 jmp _display_string
625 no_vbe_flag:
626 mov ax, #0xc000
627 mov ds, ax
628 mov si, #_no_vbebios_info_string
629 jmp _display_string
630 ASM_END
632 /** Function 00h - Return VBE Controller Information
634 * Input:
635 * AX = 4F00h
636 * ES:DI = Pointer to buffer in which to place VbeInfoBlock structure
637 * (VbeSignature should be VBE2 when VBE 2.0 information is desired and
638 * the info block is 512 bytes in size)
639 * Output:
640 * AX = VBE Return Status
643 void vbe_biosfn_return_controller_information(AX, ES, DI)
644 Bit16u *AX;Bit16u ES;Bit16u DI;
646 Bit16u ss=get_SS();
647 VbeInfoBlock vbe_info_block;
648 Bit16u status;
649 Bit16u result;
650 Bit16u vbe2_info;
651 Bit16u cur_mode=0;
652 Bit16u cur_ptr=34;
653 ModeInfoListItem *cur_info=&mode_info_list;
655 status = read_word(ss, AX);
657 #ifdef DEBUG
658 printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
659 #endif
661 vbe2_info = 0;
662 #ifdef VBE2_NO_VESA_CHECK
663 #else
664 // get vbe_info_block into local variable
665 memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
667 // check for VBE2 signature
668 if (((vbe_info_block.VbeSignature[0] == 'V') &&
669 (vbe_info_block.VbeSignature[1] == 'B') &&
670 (vbe_info_block.VbeSignature[2] == 'E') &&
671 (vbe_info_block.VbeSignature[3] == '2')) ||
673 ((vbe_info_block.VbeSignature[0] == 'V') &&
674 (vbe_info_block.VbeSignature[1] == 'E') &&
675 (vbe_info_block.VbeSignature[2] == 'S') &&
676 (vbe_info_block.VbeSignature[3] == 'A')) )
678 vbe2_info = 1;
679 #ifdef DEBUG
680 printf("VBE correct VESA/VBE2 signature found\n");
681 #endif
683 #endif
685 // VBE Signature
686 vbe_info_block.VbeSignature[0] = 'V';
687 vbe_info_block.VbeSignature[1] = 'E';
688 vbe_info_block.VbeSignature[2] = 'S';
689 vbe_info_block.VbeSignature[3] = 'A';
691 // VBE Version supported
692 vbe_info_block.VbeVersion = 0x0200;
694 // OEM String
695 vbe_info_block.OemStringPtr_Seg = 0xc000;
696 vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
698 // Capabilities
699 vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
700 vbe_info_block.Capabilities[1] = 0;
701 vbe_info_block.Capabilities[2] = 0;
702 vbe_info_block.Capabilities[3] = 0;
704 // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
705 vbe_info_block.VideoModePtr_Seg= ES ;
706 vbe_info_block.VideoModePtr_Off= DI + 34;
708 // VBE Total Memory (in 64b blocks)
709 vbe_info_block.TotalMemory = VBE_TOTAL_VIDEO_MEMORY_DIV_64K;
711 if (vbe2_info)
713 // OEM Stuff
714 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
715 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
716 vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
717 vbe_info_block.OemProductNamePtr_Seg = 0xc000;
718 vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
719 vbe_info_block.OemProductRevPtr_Seg = 0xc000;
720 vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
722 // copy updates in vbe_info_block back
723 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
725 else
727 // copy updates in vbe_info_block back (VBE 1.x compatibility)
728 memcpyb(ES, DI, ss, &vbe_info_block, 256);
733 if ((cur_info->info.XResolution <= dispi_get_max_xres()) &&
734 (cur_info->info.BitsPerPixel <= dispi_get_max_bpp())) {
735 #ifdef DEBUG
736 printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
737 #endif
738 write_word(ES, DI + cur_ptr, cur_info->mode);
739 cur_mode++;
740 cur_ptr+=2;
742 cur_info++;
743 } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
745 // Add vesa mode list terminator
746 write_word(ES, DI + cur_ptr, cur_info->mode);
748 result = 0x4f;
750 write_word(ss, AX, result);
754 /** Function 01h - Return VBE Mode Information
756 * Input:
757 * AX = 4F01h
758 * CX = Mode Number
759 * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure
760 * Output:
761 * AX = VBE Return Status
764 void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
765 Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
767 Bit16u result=0x0100;
768 Bit16u ss=get_SS();
769 ModeInfoBlock info;
770 ModeInfoListItem *cur_info;
771 Boolean using_lfb;
773 #ifdef DEBUG
774 printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
775 #endif
777 using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
779 CX = (CX & 0x1ff);
781 cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
783 if (cur_info != 0)
785 #ifdef DEBUG
786 printf("VBE found mode %x\n",CX);
787 #endif
788 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
789 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
790 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
791 info.WinFuncPtr = 0xC0000000UL;
792 *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
795 result = 0x4f;
797 else
799 #ifdef DEBUG
800 printf("VBE *NOT* found mode %x\n",CX);
801 #endif
802 result = 0x100;
805 if (result == 0x4f)
807 // copy updates in mode_info_block back
808 memcpyb(ES, DI, ss, &info, sizeof(info));
811 write_word(ss, AX, result);
814 /** Function 02h - Set VBE Mode
816 * Input:
817 * AX = 4F02h
818 * BX = Desired Mode to set
819 * ES:DI = Pointer to CRTCInfoBlock structure
820 * Output:
821 * AX = VBE Return Status
824 void vbe_biosfn_set_mode(AX, BX, ES, DI)
825 Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
827 Bit16u ss = get_SS();
828 Bit16u result;
829 ModeInfoListItem *cur_info;
830 Boolean using_lfb;
831 Bit8u no_clear;
832 Bit8u lfb_flag;
834 using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
835 lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
836 no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
838 BX = (BX & 0x1ff);
840 //result=read_word(ss,AX);
842 // check for non vesa mode
843 if (BX<VBE_MODE_VESA_DEFINED)
845 Bit8u mode;
847 dispi_set_enable(VBE_DISPI_DISABLED);
848 // call the vgabios in order to set the video mode
849 // this allows for going back to textmode with a VBE call (some applications expect that to work)
851 mode=(BX & 0xff);
852 biosfn_set_video_mode(mode);
853 result = 0x4f;
856 cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
858 if (cur_info != 0)
860 #ifdef DEBUG
861 printf("VBE found mode %x, setting:\n", BX);
862 printf("\txres%x yres%x bpp%x\n",
863 cur_info->info.XResolution,
864 cur_info->info.YResolution,
865 cur_info->info.BitsPerPixel);
866 #endif
868 // first disable current mode (when switching between vesa modi)
869 dispi_set_enable(VBE_DISPI_DISABLED);
871 if (cur_info->mode == VBE_VESA_MODE_800X600X4)
873 biosfn_set_video_mode(0x6a);
876 dispi_set_bpp(cur_info->info.BitsPerPixel);
877 dispi_set_xres(cur_info->info.XResolution);
878 dispi_set_yres(cur_info->info.YResolution);
879 dispi_set_bank(0);
880 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
882 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
883 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
885 result = 0x4f;
887 else
889 #ifdef DEBUG
890 printf("VBE *NOT* found mode %x\n" , BX);
891 #endif
892 result = 0x100;
894 // FIXME: redirect non VBE modi to normal VGA bios operation
895 // (switch back to VGA mode
896 if (BX == 3)
897 result = 0x4f;
900 write_word(ss, AX, result);
903 /** Function 03h - Return Current VBE Mode
905 * Input:
906 * AX = 4F03h
907 * Output:
908 * AX = VBE Return Status
909 * BX = Current VBE Mode
912 ASM_START
913 vbe_biosfn_return_current_mode:
914 push ds
915 mov ax, # BIOSMEM_SEG
916 mov ds, ax
917 call dispi_get_enable
918 and ax, # VBE_DISPI_ENABLED
919 jz no_vbe_mode
920 mov bx, # BIOSMEM_VBE_MODE
921 mov ax, [bx]
922 mov bx, ax
923 jnz vbe_03_ok
924 no_vbe_mode:
925 mov bx, # BIOSMEM_CURRENT_MODE
926 mov al, [bx]
927 mov bl, al
928 xor bh, bh
929 vbe_03_ok:
930 mov ax, #0x004f
931 pop ds
933 ASM_END
936 Bit16u vbe_biosfn_read_video_state_size()
938 return 9 * 2;
941 void vbe_biosfn_save_video_state(ES, BX)
942 Bit16u ES; Bit16u BX;
944 Bit16u enable, i;
946 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
947 enable = inw(VBE_DISPI_IOPORT_DATA);
948 write_word(ES, BX, enable);
949 BX += 2;
950 if (!(enable & VBE_DISPI_ENABLED))
951 return;
952 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
953 if (i != VBE_DISPI_INDEX_ENABLE) {
954 outw(VBE_DISPI_IOPORT_INDEX, i);
955 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
956 BX += 2;
962 void vbe_biosfn_restore_video_state(ES, BX)
963 Bit16u ES; Bit16u BX;
965 Bit16u enable, i;
967 enable = read_word(ES, BX);
968 BX += 2;
970 if (!(enable & VBE_DISPI_ENABLED)) {
971 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
972 outw(VBE_DISPI_IOPORT_DATA, enable);
973 } else {
974 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
975 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
976 BX += 2;
977 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
978 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
979 BX += 2;
980 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
981 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
982 BX += 2;
983 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
984 outw(VBE_DISPI_IOPORT_DATA, enable);
986 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
987 outw(VBE_DISPI_IOPORT_INDEX, i);
988 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
989 BX += 2;
994 /** Function 04h - Save/Restore State
996 * Input:
997 * AX = 4F04h
998 * DL = 00h Return Save/Restore State buffer size
999 * 01h Save State
1000 * 02h Restore State
1001 * CX = Requested states
1002 * ES:BX = Pointer to buffer (if DL <> 00h)
1003 * Output:
1004 * AX = VBE Return Status
1005 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
1008 void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
1009 Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
1011 Bit16u ss=get_SS();
1012 Bit16u result, val;
1014 result = 0x4f;
1015 switch(GET_DL()) {
1016 case 0x00:
1017 val = biosfn_read_video_state_size2(CX);
1018 #ifdef DEBUG
1019 printf("VGA state size=%x\n", val);
1020 #endif
1021 if (CX & 8)
1022 val += vbe_biosfn_read_video_state_size();
1023 write_word(ss, BX, val);
1024 break;
1025 case 0x01:
1026 val = read_word(ss, BX);
1027 val = biosfn_save_video_state(CX, ES, val);
1028 #ifdef DEBUG
1029 printf("VGA save_state offset=%x\n", val);
1030 #endif
1031 if (CX & 8)
1032 vbe_biosfn_save_video_state(ES, val);
1033 break;
1034 case 0x02:
1035 val = read_word(ss, BX);
1036 val = biosfn_restore_video_state(CX, ES, val);
1037 #ifdef DEBUG
1038 printf("VGA restore_state offset=%x\n", val);
1039 #endif
1040 if (CX & 8)
1041 vbe_biosfn_restore_video_state(ES, val);
1042 break;
1043 default:
1044 // function failed
1045 result = 0x100;
1046 break;
1048 write_word(ss, AX, result);
1051 /** Function 05h - Display Window Control
1053 * Input:
1054 * AX = 4F05h
1055 * (16-bit) BH = 00h Set memory window
1056 * = 01h Get memory window
1057 * BL = Window number
1058 * = 00h Window A
1059 * = 01h Window B
1060 * DX = Window number in video memory in window
1061 * granularity units (Set Memory Window only)
1062 * Note:
1063 * If this function is called while in a linear frame buffer mode,
1064 * this function must fail with completion code AH=03h
1066 * Output:
1067 * AX = VBE Return Status
1068 * DX = Window number in window granularity units
1069 * (Get Memory Window only)
1071 ASM_START
1072 vbe_biosfn_display_window_control:
1073 cmp bl, #0x00
1074 jne vbe_05_failed
1075 cmp bh, #0x01
1076 je get_display_window
1077 jb set_display_window
1078 mov ax, #0x0100
1080 set_display_window:
1081 mov ax, dx
1082 call _dispi_set_bank
1083 call dispi_get_bank
1084 cmp ax, dx
1085 jne vbe_05_failed
1086 mov ax, #0x004f
1088 get_display_window:
1089 call dispi_get_bank
1090 mov dx, ax
1091 mov ax, #0x004f
1093 vbe_05_failed:
1094 mov ax, #0x014f
1096 ASM_END
1099 /** Function 06h - Set/Get Logical Scan Line Length
1101 * Input:
1102 * AX = 4F06h
1103 * BL = 00h Set Scan Line Length in Pixels
1104 * = 01h Get Scan Line Length
1105 * = 02h Set Scan Line Length in Bytes
1106 * = 03h Get Maximum Scan Line Length
1107 * CX = If BL=00h Desired Width in Pixels
1108 * If BL=02h Desired Width in Bytes
1109 * (Ignored for Get Functions)
1111 * Output:
1112 * AX = VBE Return Status
1113 * BX = Bytes Per Scan Line
1114 * CX = Actual Pixels Per Scan Line
1115 * (truncated to nearest complete pixel)
1116 * DX = Maximum Number of Scan Lines
1118 ASM_START
1119 vbe_biosfn_set_get_logical_scan_line_length:
1120 mov ax, cx
1121 cmp bl, #0x01
1122 je get_logical_scan_line_length
1123 cmp bl, #0x02
1124 je set_logical_scan_line_bytes
1125 jb set_logical_scan_line_pixels
1126 mov ax, #0x0100
1128 set_logical_scan_line_bytes:
1129 push ax
1130 call dispi_get_bpp
1131 xor bh, bh
1132 mov bl, ah
1133 or bl, bl
1134 jnz no_4bpp_1
1135 shl ax, #3
1136 mov bl, #1
1137 no_4bpp_1:
1138 xor dx, dx
1139 pop ax
1140 div bx
1141 set_logical_scan_line_pixels:
1142 call dispi_set_virt_width
1143 get_logical_scan_line_length:
1144 call dispi_get_bpp
1145 xor bh, bh
1146 mov bl, ah
1147 call dispi_get_virt_width
1148 mov cx, ax
1149 or bl, bl
1150 jnz no_4bpp_2
1151 shr ax, #3
1152 mov bl, #1
1153 no_4bpp_2:
1154 mul bx
1155 mov bx, ax
1156 call dispi_get_virt_height
1157 mov dx, ax
1158 mov ax, #0x004f
1160 ASM_END
1163 /** Function 07h - Set/Get Display Start
1165 * Input(16-bit):
1166 * AX = 4F07h
1167 * BH = 00h Reserved and must be 00h
1168 * BL = 00h Set Display Start
1169 * = 01h Get Display Start
1170 * = 02h Schedule Display Start (Alternate)
1171 * = 03h Schedule Stereoscopic Display Start
1172 * = 04h Get Scheduled Display Start Status
1173 * = 05h Enable Stereoscopic Mode
1174 * = 06h Disable Stereoscopic Mode
1175 * = 80h Set Display Start during Vertical Retrace
1176 * = 82h Set Display Start during Vertical Retrace (Alternate)
1177 * = 83h Set Stereoscopic Display Start during Vertical Retrace
1178 * ECX = If BL=02h/82h Display Start Address in bytes
1179 * If BL=03h/83h Left Image Start Address in bytes
1180 * EDX = If BL=03h/83h Right Image Start Address in bytes
1181 * CX = If BL=00h/80h First Displayed Pixel In Scan Line
1182 * DX = If BL=00h/80h First Displayed Scan Line
1184 * Output:
1185 * AX = VBE Return Status
1186 * BH = If BL=01h Reserved and will be 0
1187 * CX = If BL=01h First Displayed Pixel In Scan Line
1188 * If BL=04h 0 if flip has not occurred, not 0 if it has
1189 * DX = If BL=01h First Displayed Scan Line
1191 * Input(32-bit):
1192 * BH = 00h Reserved and must be 00h
1193 * BL = 00h Set Display Start
1194 * = 80h Set Display Start during Vertical Retrace
1195 * CX = Bits 0-15 of display start address
1196 * DX = Bits 16-31 of display start address
1197 * ES = Selector for memory mapped registers
1199 ASM_START
1200 vbe_biosfn_set_get_display_start:
1201 cmp bl, #0x80
1202 je set_display_start
1203 cmp bl, #0x01
1204 je get_display_start
1205 jb set_display_start
1206 mov ax, #0x0100
1208 set_display_start:
1209 mov ax, cx
1210 call dispi_set_x_offset
1211 mov ax, dx
1212 call dispi_set_y_offset
1213 mov ax, #0x004f
1215 get_display_start:
1216 call dispi_get_x_offset
1217 mov cx, ax
1218 call dispi_get_y_offset
1219 mov dx, ax
1220 xor bh, bh
1221 mov ax, #0x004f
1223 ASM_END
1226 /** Function 08h - Set/Get Dac Palette Format
1228 * Input:
1229 * AX = 4F08h
1230 * BL = 00h set DAC palette width
1231 * = 01h get DAC palette width
1232 * BH = If BL=00h: desired number of bits per primary color
1233 * Output:
1234 * AX = VBE Return Status
1235 * BH = current number of bits per primary color (06h = standard VGA)
1237 ASM_START
1238 vbe_biosfn_set_get_dac_palette_format:
1239 cmp bl, #0x01
1240 je get_dac_palette_format
1241 jb set_dac_palette_format
1242 mov ax, #0x0100
1244 set_dac_palette_format:
1245 call dispi_get_enable
1246 cmp bh, #0x06
1247 je set_normal_dac
1248 cmp bh, #0x08
1249 jne vbe_08_unsupported
1250 or ax, # VBE_DISPI_8BIT_DAC
1251 jnz set_dac_mode
1252 set_normal_dac:
1253 and ax, #~ VBE_DISPI_8BIT_DAC
1254 set_dac_mode:
1255 call _dispi_set_enable
1256 get_dac_palette_format:
1257 mov bh, #0x06
1258 call dispi_get_enable
1259 and ax, # VBE_DISPI_8BIT_DAC
1260 jz vbe_08_ok
1261 mov bh, #0x08
1262 vbe_08_ok:
1263 mov ax, #0x004f
1265 vbe_08_unsupported:
1266 mov ax, #0x014f
1268 ASM_END
1271 /** Function 09h - Set/Get Palette Data
1273 * Input:
1274 * AX = 4F09h
1275 * Output:
1276 * AX = VBE Return Status
1278 * FIXME: incomplete API description, Input & Output
1280 void vbe_biosfn_set_get_palette_data(AX)
1284 /** Function 0Ah - Return VBE Protected Mode Interface
1285 * Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface
1286 * BL = 00h Return protected mode table
1289 * Output: AX = Status
1290 * ES = Real Mode Segment of Table
1291 * DI = Offset of Table
1292 * CX = Length of Table including protected mode code
1293 * (for copying purposes)
1295 ASM_START
1296 vbe_biosfn_return_protected_mode_interface:
1297 test bl, bl
1298 jnz _fail
1299 mov di, #0xc000
1300 mov es, di
1301 mov di, # vesa_pm_start
1302 mov cx, # vesa_pm_end
1303 sub cx, di
1304 mov ax, #0x004f
1306 _fail:
1307 mov ax, #0x014f
1309 ASM_END