Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added movsx/movzx decoding to internal decoder
[palacios.git] / bios / vgabios / vbe.c
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 // defines available
33 // enable LFB support
34 #define VBE_HAVE_LFB
35
36 // disable VESA/VBE2 check in vbe info
37 //#define VBE2_NO_VESA_CHECK
38
39 // dynamicly generate a mode_info list
40 #define DYN_LIST
41
42
43 #include "vbe.h"
44 #include "vbetables.h"
45
46
47 // The current OEM Software Revision of this VBE Bios
48 #define VBE_OEM_SOFTWARE_REV 0x0002;
49
50 extern char vbebios_copyright;
51 extern char vbebios_vendor_name;
52 extern char vbebios_product_name;
53 extern char vbebios_product_revision;
54
55 #ifndef DYN_LIST
56 extern Bit16u vbebios_mode_list;
57 #endif
58
59 ASM_START
60 // FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
61 _vbebios_copyright:
62 .ascii       "Bochs/Plex86 VBE(C) 2003 http://savannah.nongnu.org/projects/vgabios/"
63 .byte        0x00
64
65 _vbebios_vendor_name:
66 .ascii       "Bochs/Plex86 Developers"
67 .byte        0x00
68
69 _vbebios_product_name:
70 .ascii       "Bochs/Plex86 VBE Adapter"
71 .byte        0x00
72
73 _vbebios_product_revision:
74 .ascii       "$Id: vbe.c,v 1.1 2007/11/29 20:26:38 pdinda Exp $"
75 .byte        0x00
76
77 _vbebios_info_string:
78 .ascii      "Bochs VBE Display Adapter enabled"
79 .byte   0x0a,0x0d
80 .byte   0x0a,0x0d
81 .byte   0x00
82
83 _no_vbebios_info_string:
84 .ascii      "NO Bochs VBE Support available!"
85 .byte   0x0a,0x0d
86 .byte   0x0a,0x0d
87 .byte 0x00
88
89 #if defined(USE_BX_INFO) || defined(DEBUG)
90 msg_vbe_init:
91 .ascii      "VBE Bios $Id: vbe.c,v 1.1 2007/11/29 20:26:38 pdinda Exp $"
92 .byte   0x0a,0x0d, 0x00
93 #endif
94
95 #ifndef DYN_LIST
96 // FIXME: for each new mode add a statement here
97 //        at least until dynamic list creation is working
98 _vbebios_mode_list:
99
100 .word VBE_VESA_MODE_640X400X8
101 .word VBE_VESA_MODE_640X480X8
102 .word VBE_VESA_MODE_800X600X4
103 .word VBE_VESA_MODE_800X600X8
104 .word VBE_VESA_MODE_1024X768X8
105 .word VBE_VESA_MODE_640X480X1555
106 .word VBE_VESA_MODE_640X480X565
107 .word VBE_VESA_MODE_640X480X888
108 .word VBE_VESA_MODE_800X600X1555
109 .word VBE_VESA_MODE_800X600X565
110 .word VBE_VESA_MODE_800X600X888
111 .word VBE_VESA_MODE_1024X768X1555
112 .word VBE_VESA_MODE_1024X768X565
113 .word VBE_VESA_MODE_1024X768X888
114 .word VBE_OWN_MODE_640X480X8888
115 .word VBE_OWN_MODE_800X600X8888
116 .word VBE_OWN_MODE_1024X768X8888
117 .word VBE_OWN_MODE_320X200X8
118 .word VBE_VESA_MODE_END_OF_LIST
119 #endif
120
121 ; DISPI ioport functions
122
123 dispi_get_id:
124   push dx
125   mov  dx, # VBE_DISPI_IOPORT_INDEX
126   mov  ax, # VBE_DISPI_INDEX_ID
127   out  dx, ax
128   mov  dx, # VBE_DISPI_IOPORT_DATA
129   in   ax, dx
130   pop  dx
131   ret
132
133 dispi_set_id:
134   push dx
135   push ax
136   mov  dx, # VBE_DISPI_IOPORT_INDEX
137   mov  ax, # VBE_DISPI_INDEX_ID
138   out  dx, ax
139   pop  ax
140   mov  dx, # VBE_DISPI_IOPORT_DATA
141   out  dx, ax
142   pop  dx
143   ret
144 ASM_END
145
146 static void dispi_set_xres(xres)
147   Bit16u xres;
148 {
149 ASM_START
150   push bp
151   mov  bp, sp
152   push ax
153   push dx
154
155   mov  dx, # VBE_DISPI_IOPORT_INDEX
156   mov  ax, # VBE_DISPI_INDEX_XRES
157   out  dx, ax
158   mov  dx, # VBE_DISPI_IOPORT_DATA
159   mov  ax, 4[bp] ; xres
160   out  dx, ax
161   push ax
162   mov  dx, #0x03d4
163   mov  ax, #0x0011
164   out  dx, ax
165   mov  dx, #0x03d4
166   pop  ax
167   push ax
168   shr  ax, #3
169   dec  ax
170   mov  ah, al
171   mov  al, #0x01
172   out  dx, ax
173   pop  ax
174   call vga_set_virt_width
175
176   pop  dx
177   pop  ax
178   pop  bp
179 ASM_END
180 }
181
182 static void dispi_set_yres(yres)
183   Bit16u yres;
184 {
185   outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_YRES);
186   outw(VBE_DISPI_IOPORT_DATA,yres);
187 }
188
189 static void dispi_set_bpp(bpp)
190   Bit16u bpp;
191 {
192   outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_BPP);
193   outw(VBE_DISPI_IOPORT_DATA,bpp);
194 }
195
196 ASM_START
197 ; AL = bits per pixel / AH = bytes per pixel
198 dispi_get_bpp:
199   push dx
200   mov  dx, # VBE_DISPI_IOPORT_INDEX
201   mov  ax, # VBE_DISPI_INDEX_BPP
202   out  dx, ax
203   mov  dx, # VBE_DISPI_IOPORT_DATA
204   in   ax, dx
205   mov  ah, al
206   shr  ah, 3
207   test al, #0x07
208   jz   get_bpp_noinc
209   inc  ah
210 get_bpp_noinc:
211   pop  dx
212   ret
213
214 _dispi_get_max_bpp:
215   push dx
216   push bx
217   call dispi_get_enable
218   mov  bx, ax
219   or   ax, # VBE_DISPI_GETCAPS
220   call _dispi_set_enable
221   mov  dx, # VBE_DISPI_IOPORT_INDEX
222   mov  ax, # VBE_DISPI_INDEX_BPP
223   out  dx, ax
224   mov  dx, # VBE_DISPI_IOPORT_DATA
225   in   ax, dx
226   push ax
227   mov  ax, bx
228   call _dispi_set_enable
229   pop  ax
230   pop  bx
231   pop  dx
232   ret
233
234 _dispi_set_enable:
235   push dx
236   push ax
237   mov  dx, # VBE_DISPI_IOPORT_INDEX
238   mov  ax, # VBE_DISPI_INDEX_ENABLE
239   out  dx, ax
240   pop  ax
241   mov  dx, # VBE_DISPI_IOPORT_DATA
242   out  dx, ax
243   pop  dx
244   ret
245
246 dispi_get_enable:
247   push dx
248   mov  dx, # VBE_DISPI_IOPORT_INDEX
249   mov  ax, # VBE_DISPI_INDEX_ENABLE
250   out  dx, ax
251   mov  dx, # VBE_DISPI_IOPORT_DATA
252   in   ax, dx
253   pop  dx
254   ret
255
256 _dispi_set_bank:
257   push dx
258   push ax
259   mov  dx, # VBE_DISPI_IOPORT_INDEX
260   mov  ax, # VBE_DISPI_INDEX_BANK
261   out  dx, ax
262   pop  ax
263   mov  dx, # VBE_DISPI_IOPORT_DATA
264   out  dx, ax
265   pop  dx
266   ret
267
268 dispi_get_bank:
269   push dx
270   mov  dx, # VBE_DISPI_IOPORT_INDEX
271   mov  ax, # VBE_DISPI_INDEX_BANK
272   out  dx, ax
273   mov  dx, # VBE_DISPI_IOPORT_DATA
274   in   ax, dx
275   pop  dx
276   ret
277 ASM_END
278
279 static void dispi_set_bank_farcall()
280 {
281 ASM_START
282   cmp bx,#0x0100
283   je dispi_set_bank_farcall_get
284   or bx,bx
285   jnz dispi_set_bank_farcall_error
286   push dx
287   mov ax,# VBE_DISPI_INDEX_BANK
288   mov dx,# VBE_DISPI_IOPORT_INDEX
289   out dx,ax
290   pop ax
291   mov dx,# VBE_DISPI_IOPORT_DATA
292   out dx,ax
293   retf
294 dispi_set_bank_farcall_get:
295   mov ax,# VBE_DISPI_INDEX_BANK
296   mov dx,# VBE_DISPI_IOPORT_INDEX
297   out dx,ax
298   mov dx,# VBE_DISPI_IOPORT_DATA
299   in ax,dx
300   mov dx,ax
301   retf
302 dispi_set_bank_farcall_error:
303   mov ax,#0x014F
304   retf
305 ASM_END
306 }
307
308 ASM_START
309 dispi_set_x_offset:
310   push dx
311   push ax
312   mov  dx, # VBE_DISPI_IOPORT_INDEX
313   mov  ax, # VBE_DISPI_INDEX_X_OFFSET
314   out  dx, ax
315   pop  ax
316   mov  dx, # VBE_DISPI_IOPORT_DATA
317   out  dx, ax
318   pop  dx
319   ret
320
321 dispi_get_x_offset:
322   push dx
323   mov  dx, # VBE_DISPI_IOPORT_INDEX
324   mov  ax, # VBE_DISPI_INDEX_X_OFFSET
325   out  dx, ax
326   mov  dx, # VBE_DISPI_IOPORT_DATA
327   in   ax, dx
328   pop  dx
329   ret
330
331 dispi_set_y_offset:
332   push dx
333   push ax
334   mov  dx, # VBE_DISPI_IOPORT_INDEX
335   mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
336   out  dx, ax
337   pop  ax
338   mov  dx, # VBE_DISPI_IOPORT_DATA
339   out  dx, ax
340   pop  dx
341   ret
342
343 dispi_get_y_offset:
344   push dx
345   mov  dx, # VBE_DISPI_IOPORT_INDEX
346   mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
347   out  dx, ax
348   mov  dx, # VBE_DISPI_IOPORT_DATA
349   in   ax, dx
350   pop  dx
351   ret
352
353 vga_set_virt_width:
354   push ax
355   push bx
356   push dx
357   mov  bx, ax
358   call dispi_get_bpp
359   cmp  al, #0x04
360   ja   set_width_svga
361   shr  bx, #2
362 set_width_svga:
363   shr  bx, #2
364   mov  dx, #0x03d4
365   mov  ah, bl
366   mov  al, #0x13
367   out  dx, ax
368   pop  dx
369   pop  bx
370   pop  ax
371   ret
372
373 dispi_set_virt_width:
374   call vga_set_virt_width
375   push dx
376   push ax
377   mov  dx, # VBE_DISPI_IOPORT_INDEX
378   mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
379   out  dx, ax
380   pop  ax
381   mov  dx, # VBE_DISPI_IOPORT_DATA
382   out  dx, ax
383   pop  dx
384   ret
385
386 dispi_get_virt_width:
387   push dx
388   mov  dx, # VBE_DISPI_IOPORT_INDEX
389   mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
390   out  dx, ax
391   mov  dx, # VBE_DISPI_IOPORT_DATA
392   in   ax, dx
393   pop  dx
394   ret
395
396 dispi_get_virt_height:
397   push dx
398   mov  dx, # VBE_DISPI_IOPORT_INDEX
399   mov  ax, # VBE_DISPI_INDEX_VIRT_HEIGHT
400   out  dx, ax
401   mov  dx, # VBE_DISPI_IOPORT_DATA
402   in   ax, dx
403   pop  dx
404   ret
405 ASM_END
406
407
408 // ModeInfo helper function
409 static ModeInfoListItem* mode_info_find_mode(mode, using_lfb)
410   Bit16u mode; Boolean using_lfb;
411 {
412   ModeInfoListItem  *cur_info=&mode_info_list;
413
414   while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
415   {
416     if (cur_info->mode == mode)
417     {
418       if (!using_lfb)
419       {
420         return cur_info;
421       }
422       else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
423       {
424         return cur_info;
425       }
426       else
427       {
428         cur_info++;
429       }
430     }
431     else
432     {
433       cur_info++;
434     }
435   }
436
437   return 0;
438 }
439
440 ASM_START
441
442 ; Has VBE display - Returns true if VBE display detected
443
444 _vbe_has_vbe_display:
445   push ds
446   push bx
447   mov  ax, # BIOSMEM_SEG
448   mov  ds, ax
449   mov  bx, # BIOSMEM_VBE_FLAG
450   mov  al, [bx]
451   and  al, #0x01
452   xor  ah, ah
453   pop  bx
454   pop  ds
455   ret
456
457 ; VBE Init - Initialise the Vesa Bios Extension Code
458 ; This function does a sanity check on the host side display code interface.
459
460 vbe_init:
461   mov  ax, # VBE_DISPI_ID0
462   call dispi_set_id
463   call dispi_get_id
464   cmp  ax, # VBE_DISPI_ID0
465   jne  no_vbe_interface
466   push ds
467   push bx
468   mov  ax, # BIOSMEM_SEG
469   mov  ds, ax
470   mov  bx, # BIOSMEM_VBE_FLAG
471   mov  al, #0x01
472   mov  [bx], al
473   pop  bx
474   pop  ds
475   mov  ax, # VBE_DISPI_ID3
476   call dispi_set_id
477 no_vbe_interface:
478 #if defined(USE_BX_INFO) || defined(DEBUG)
479   mov  bx, #msg_vbe_init
480   push bx
481   call _printf
482   inc  sp
483   inc  sp
484 #endif
485   ret
486
487 ; VBE Display Info - Display information on screen about the VBE
488
489 vbe_display_info:
490   call _vbe_has_vbe_display
491   test ax, ax
492   jz   no_vbe_flag
493   mov  ax, #0xc000
494   mov  ds, ax
495   mov  si, #_vbebios_info_string
496   jmp  _display_string
497 no_vbe_flag:
498   mov  ax, #0xc000
499   mov  ds, ax
500   mov  si, #_no_vbebios_info_string
501   jmp  _display_string
502 ASM_END  
503
504 /** Function 00h - Return VBE Controller Information
505  * 
506  * Input:
507  *              AX      = 4F00h
508  *              ES:DI   = Pointer to buffer in which to place VbeInfoBlock structure
509  *                        (VbeSignature should be VBE2 when VBE 2.0 information is desired and
510  *                        the info block is 512 bytes in size)
511  * Output:
512  *              AX      = VBE Return Status
513  * 
514  */
515 void vbe_biosfn_return_controller_information(AX, ES, DI)
516 Bit16u *AX;Bit16u ES;Bit16u DI;
517 {
518         Bit16u            ss=get_SS();
519         VbeInfoBlock      vbe_info_block;
520         Bit16u            status;
521         Bit16u            result;
522         Bit16u            vbe2_info;
523         Bit16u            cur_mode=0;
524         Bit16u            cur_ptr=34;
525         ModeInfoListItem  *cur_info=&mode_info_list;
526         
527         status = read_word(ss, AX);
528         
529 #ifdef DEBUG
530         printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
531 #endif
532
533         vbe2_info = 0;
534 #ifdef VBE2_NO_VESA_CHECK
535 #else
536         // get vbe_info_block into local variable
537         memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
538
539         // check for VBE2 signature
540         if (((vbe_info_block.VbeSignature[0] == 'V') &&
541              (vbe_info_block.VbeSignature[1] == 'B') &&
542              (vbe_info_block.VbeSignature[2] == 'E') &&
543              (vbe_info_block.VbeSignature[3] == '2')) ||
544              
545             ((vbe_info_block.VbeSignature[0] == 'V') &&
546              (vbe_info_block.VbeSignature[1] == 'E') &&
547              (vbe_info_block.VbeSignature[2] == 'S') &&
548              (vbe_info_block.VbeSignature[3] == 'A')) )
549         {
550                 vbe2_info = 1;
551 #ifdef DEBUG
552                 printf("VBE correct VESA/VBE2 signature found\n");
553 #endif
554         }
555 #endif
556                 
557         // VBE Signature
558         vbe_info_block.VbeSignature[0] = 'V';
559         vbe_info_block.VbeSignature[1] = 'E';
560         vbe_info_block.VbeSignature[2] = 'S';
561         vbe_info_block.VbeSignature[3] = 'A';
562         
563         // VBE Version supported
564         vbe_info_block.VbeVersion = 0x0200;
565         
566         // OEM String
567         vbe_info_block.OemStringPtr_Seg = 0xc000;
568         vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
569         
570         // Capabilities
571         vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
572         vbe_info_block.Capabilities[1] = 0;
573         vbe_info_block.Capabilities[2] = 0;
574         vbe_info_block.Capabilities[3] = 0;
575
576 #ifdef DYN_LIST
577         // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
578         vbe_info_block.VideoModePtr_Seg= ES ;
579         vbe_info_block.VideoModePtr_Off= DI + 34;
580 #else
581         // VBE Video Mode Pointer (staticly in rom)
582         vbe_info_block.VideoModePtr_Seg = 0xc000;
583         vbe_info_block.VideoModePtr_Off = &vbebios_mode_list;
584 #endif
585
586         // VBE Total Memory (in 64b blocks)
587         vbe_info_block.TotalMemory = VBE_TOTAL_VIDEO_MEMORY_DIV_64K;
588
589         if (vbe2_info)
590         {
591                 // OEM Stuff
592                 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
593                 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
594                 vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
595                 vbe_info_block.OemProductNamePtr_Seg = 0xc000;
596                 vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
597                 vbe_info_block.OemProductRevPtr_Seg = 0xc000;
598                 vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
599
600                 // copy updates in vbe_info_block back
601                 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
602         }
603         else
604         {
605                 // copy updates in vbe_info_block back (VBE 1.x compatibility)
606                 memcpyb(ES, DI, ss, &vbe_info_block, 256);
607         }
608                 
609 #ifdef DYN_LIST
610         do
611         {
612                 if (cur_info->info.BitsPerPixel <= dispi_get_max_bpp()) {
613 #ifdef DEBUG
614                   printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
615 #endif
616                   write_word(ES, DI + cur_ptr, cur_info->mode);
617                   cur_mode++;
618                   cur_ptr+=2;
619                 }
620                 cur_info++;
621         } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
622         
623         // Add vesa mode list terminator
624         write_word(ES, DI + cur_ptr, cur_info->mode);
625 #endif
626
627         result = 0x4f;
628
629         write_word(ss, AX, result);
630 }
631
632
633 /** Function 01h - Return VBE Mode Information
634  * 
635  * Input:
636  *              AX      = 4F01h
637  *              CX      = Mode Number
638  *              ES:DI   = Pointer to buffer in which to place ModeInfoBlock structure
639  * Output:
640  *              AX      = VBE Return Status
641  * 
642  */
643 void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
644 Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
645 {
646         Bit16u            result=0x0100;
647         Bit16u            ss=get_SS();
648         ModeInfoBlock     info;
649         ModeInfoListItem  *cur_info;
650         Boolean           using_lfb;
651
652 #ifdef DEBUG
653         printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
654 #endif
655
656         using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
657         
658         CX = (CX & 0x1ff);
659         
660         cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
661
662         if (cur_info != 0)
663         {
664 #ifdef DEBUG
665                 printf("VBE found mode %x\n",CX);
666 #endif        
667                 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
668                 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
669                 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
670                   info.WinFuncPtr = 0xC0000000UL;
671                   *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
672                 }
673                 
674                 result = 0x4f;
675         }
676         else
677         {
678 #ifdef DEBUG
679                 printf("VBE *NOT* found mode %x\n",CX);
680 #endif
681                 result = 0x100;
682         }
683         
684         if (result == 0x4f)
685         {
686                 // copy updates in mode_info_block back
687                 memcpyb(ES, DI, ss, &info, sizeof(info));
688         }
689
690         write_word(ss, AX, result);
691 }
692
693 /** Function 02h - Set VBE Mode
694  * 
695  * Input:
696  *              AX      = 4F02h
697  *              BX      = Desired Mode to set
698  *              ES:DI   = Pointer to CRTCInfoBlock structure
699  * Output:
700  *              AX      = VBE Return Status
701  * 
702  */
703 void vbe_biosfn_set_mode(AX, BX, ES, DI)
704 Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
705 {
706         Bit16u            ss = get_SS();
707         Bit16u            result;
708         ModeInfoListItem  *cur_info;
709         Boolean           using_lfb;
710         Bit8u             no_clear;
711         Bit8u             lfb_flag;
712
713         using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
714         lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
715         no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
716
717         BX = (BX & 0x1ff);
718
719         //result=read_word(ss,AX);
720         
721         // check for non vesa mode
722         if (BX<VBE_MODE_VESA_DEFINED)
723         {
724                 Bit8u   mode;
725                 
726                 dispi_set_enable(VBE_DISPI_DISABLED);
727                 // call the vgabios in order to set the video mode
728                 // this allows for going back to textmode with a VBE call (some applications expect that to work)
729                 
730                 mode=(BX & 0xff);
731                 biosfn_set_video_mode(mode);
732                 result = 0x4f;
733         }
734         
735         cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
736
737         if (cur_info != 0)
738         {
739 #ifdef DEBUG
740                 printf("VBE found mode %x, setting:\n", BX);
741                 printf("\txres%x yres%x bpp%x\n",
742                         cur_info->info.XResolution,
743                         cur_info->info.YResolution,
744                         cur_info->info.BitsPerPixel);
745 #endif
746                 
747                 // first disable current mode (when switching between vesa modi)
748                 dispi_set_enable(VBE_DISPI_DISABLED);
749
750                 if (cur_info->mode == VBE_VESA_MODE_800X600X4)
751                 {
752                   biosfn_set_video_mode(0x6a);
753                 }
754
755                 dispi_set_bpp(cur_info->info.BitsPerPixel);
756                 dispi_set_xres(cur_info->info.XResolution);
757                 dispi_set_yres(cur_info->info.YResolution);
758                 dispi_set_bank(0);
759                 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
760
761                 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
762                 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
763
764                 result = 0x4f;                  
765         }
766         else
767         {
768 #ifdef DEBUG
769                 printf("VBE *NOT* found mode %x\n" , BX);
770 #endif        
771                 result = 0x100;
772                 
773                 // FIXME: redirect non VBE modi to normal VGA bios operation
774                 //        (switch back to VGA mode
775                 if (BX == 3)
776                         result = 0x4f;
777         }
778
779         write_word(ss, AX, result);
780 }
781
782 /** Function 03h - Return Current VBE Mode
783  * 
784  * Input:
785  *              AX      = 4F03h
786  * Output:
787  *              AX      = VBE Return Status
788  *              BX      = Current VBE Mode
789  * 
790  */
791 ASM_START
792 vbe_biosfn_return_current_mode:
793   push ds
794   mov  ax, # BIOSMEM_SEG
795   mov  ds, ax
796   call dispi_get_enable
797   and  ax, # VBE_DISPI_ENABLED
798   jz   no_vbe_mode
799   mov  bx, # BIOSMEM_VBE_MODE
800   mov  ax, [bx]
801   mov  bx, ax
802   jnz  vbe_03_ok
803 no_vbe_mode:
804   mov  bx, # BIOSMEM_CURRENT_MODE
805   mov  al, [bx]
806   mov  bl, al
807   xor  bh, bh
808 vbe_03_ok:
809   mov  ax, #0x004f
810   pop  ds
811   ret
812 ASM_END
813
814
815 /** Function 04h - Save/Restore State
816  * 
817  * Input:
818  *              AX      = 4F04h
819  *              DL      = 00h Return Save/Restore State buffer size
820  *                        01h Save State
821  *                        02h Restore State
822  *              CX      = Requested states
823  *              ES:BX   = Pointer to buffer (if DL <> 00h)
824  * Output:
825  *              AX      = VBE Return Status
826  *              BX      = Number of 64-byte blocks to hold the state buffer (if DL=00h)
827  * 
828  */
829 void vbe_biosfn_save_restore_state(AX, DL, CX, ES, BX)
830 {
831 }
832
833
834 /** Function 05h - Display Window Control
835  * 
836  * Input:
837  *              AX      = 4F05h
838  *     (16-bit) BH      = 00h Set memory window
839  *                      = 01h Get memory window
840  *              BL      = Window number
841  *                      = 00h Window A
842  *                      = 01h Window B
843  *              DX      = Window number in video memory in window
844  *                        granularity units (Set Memory Window only)
845  * Note:
846  *              If this function is called while in a linear frame buffer mode,
847  *              this function must fail with completion code AH=03h
848  * 
849  * Output:
850  *              AX      = VBE Return Status
851  *              DX      = Window number in window granularity units
852  *                        (Get Memory Window only)
853  */
854 ASM_START
855 vbe_biosfn_display_window_control:
856   cmp  bl, #0x00
857   jne  vbe_05_failed
858   cmp  bh, #0x01
859   je   get_display_window
860   jb   set_display_window
861   mov  ax, #0x0100
862   ret
863 set_display_window:
864   mov  ax, dx
865   call _dispi_set_bank
866   call dispi_get_bank
867   cmp  ax, dx
868   jne  vbe_05_failed
869   mov  ax, #0x004f
870   ret
871 get_display_window:
872   call dispi_get_bank
873   mov  dx, ax
874   mov  ax, #0x004f
875   ret
876 vbe_05_failed:
877   mov  ax, #0x014f
878   ret
879 ASM_END
880
881
882 /** Function 06h - Set/Get Logical Scan Line Length
883  *
884  * Input:
885  *              AX      = 4F06h
886  *              BL      = 00h Set Scan Line Length in Pixels
887  *                      = 01h Get Scan Line Length
888  *                      = 02h Set Scan Line Length in Bytes
889  *                      = 03h Get Maximum Scan Line Length
890  *              CX      = If BL=00h Desired Width in Pixels
891  *                        If BL=02h Desired Width in Bytes
892  *                        (Ignored for Get Functions)
893  * 
894  * Output: 
895  *              AX      = VBE Return Status
896  *              BX      = Bytes Per Scan Line
897  *              CX      = Actual Pixels Per Scan Line
898  *                        (truncated to nearest complete pixel)
899  *              DX      = Maximum Number of Scan Lines 
900  */
901 ASM_START
902 vbe_biosfn_set_get_logical_scan_line_length:
903   mov  ax, cx
904   cmp  bl, #0x01
905   je   get_logical_scan_line_length
906   cmp  bl, #0x02
907   je   set_logical_scan_line_bytes
908   jb   set_logical_scan_line_pixels
909   mov  ax, #0x0100
910   ret
911 set_logical_scan_line_bytes:
912   push ax
913   call dispi_get_bpp
914   xor  bh, bh
915   mov  bl, ah
916   xor  dx, dx
917   pop  ax
918   div  bx
919 set_logical_scan_line_pixels:
920   call dispi_set_virt_width
921 get_logical_scan_line_length:
922   call dispi_get_bpp
923   xor  bh, bh
924   mov  bl, ah
925   call dispi_get_virt_width
926   mov  cx, ax
927   mul  bx
928   mov  bx, ax
929   call dispi_get_virt_height
930   mov  dx, ax
931   mov  ax, #0x004f
932   ret
933 ASM_END
934
935
936 /** Function 07h - Set/Get Display Start
937  * 
938  * Input(16-bit):
939  *              AX      = 4F07h
940  *              BH      = 00h Reserved and must be 00h
941  *              BL      = 00h Set Display Start
942  *                      = 01h Get Display Start
943  *                      = 02h Schedule Display Start (Alternate)
944  *                      = 03h Schedule Stereoscopic Display Start
945  *                      = 04h Get Scheduled Display Start Status
946  *                      = 05h Enable Stereoscopic Mode
947  *                      = 06h Disable Stereoscopic Mode
948  *                      = 80h Set Display Start during Vertical Retrace
949  *                      = 82h Set Display Start during Vertical Retrace (Alternate)
950  *                      = 83h Set Stereoscopic Display Start during Vertical Retrace
951  *              ECX     = If BL=02h/82h Display Start Address in bytes
952  *                        If BL=03h/83h Left Image Start Address in bytes
953  *              EDX     = If BL=03h/83h Right Image Start Address in bytes
954  *              CX      = If BL=00h/80h First Displayed Pixel In Scan Line
955  *              DX      = If BL=00h/80h First Displayed Scan Line
956  *
957  * Output:
958  *              AX      = VBE Return Status
959  *              BH      = If BL=01h Reserved and will be 0
960  *              CX      = If BL=01h First Displayed Pixel In Scan Line
961  *                        If BL=04h 0 if flip has not occurred, not 0 if it has
962  *              DX      = If BL=01h First Displayed Scan Line
963  *
964  * Input(32-bit): 
965  *              BH      = 00h Reserved and must be 00h
966  *              BL      = 00h Set Display Start
967  *                      = 80h Set Display Start during Vertical Retrace
968  *              CX      = Bits 0-15 of display start address
969  *              DX      = Bits 16-31 of display start address
970  *              ES      = Selector for memory mapped registers 
971  */
972 ASM_START
973 vbe_biosfn_set_get_display_start:
974   cmp  bl, #0x80
975   je   set_display_start
976   cmp  bl, #0x01
977   je   get_display_start
978   jb   set_display_start
979   mov  ax, #0x0100
980   ret
981 set_display_start:
982   mov  ax, cx
983   call dispi_set_x_offset
984   mov  ax, dx
985   call dispi_set_y_offset
986   mov  ax, #0x004f
987   ret
988 get_display_start:
989   call dispi_get_x_offset
990   mov  cx, ax
991   call dispi_get_y_offset
992   mov  dx, ax
993   xor  bh, bh
994   mov  ax, #0x004f
995   ret
996 ASM_END
997   
998
999 /** Function 08h - Set/Get Dac Palette Format
1000  * 
1001  * Input:
1002  *              AX      = 4F08h
1003  *              BL      = 00h set DAC palette width
1004  *                      = 01h get DAC palette width
1005  *              BH      = If BL=00h: desired number of bits per primary color
1006  * Output:
1007  *              AX      = VBE Return Status
1008  *              BH      = current number of bits per primary color (06h = standard VGA)
1009  */
1010 ASM_START
1011 vbe_biosfn_set_get_dac_palette_format:
1012   cmp  bl, #0x01
1013   je   get_dac_palette_format
1014   jb   set_dac_palette_format
1015   mov  ax, #0x0100
1016   ret
1017 set_dac_palette_format:
1018   call dispi_get_enable
1019   cmp  bh, #0x06
1020   je   set_normal_dac
1021   cmp  bh, #0x08
1022   jne  vbe_08_unsupported
1023   or   ax, # VBE_DISPI_8BIT_DAC
1024   jnz  set_dac_mode
1025 set_normal_dac:
1026   and  ax, #~ VBE_DISPI_8BIT_DAC
1027 set_dac_mode:
1028   call _dispi_set_enable
1029 get_dac_palette_format:
1030   mov  bh, #0x06
1031   call dispi_get_enable
1032   and  ax, # VBE_DISPI_8BIT_DAC
1033   jz   vbe_08_ok
1034   mov  bh, #0x08
1035 vbe_08_ok:
1036   mov  ax, #0x004f
1037   ret
1038 vbe_08_unsupported:
1039   mov  ax, #0x014f
1040   ret
1041 ASM_END
1042
1043
1044 /** Function 09h - Set/Get Palette Data
1045  * 
1046  * Input:
1047  *              AX      = 4F09h
1048  * Output:
1049  *              AX      = VBE Return Status
1050  *
1051  * FIXME: incomplete API description, Input & Output
1052  */
1053 void vbe_biosfn_set_get_palette_data(AX)
1054 {
1055 }
1056
1057 /** Function 0Ah - Return VBE Protected Mode Interface
1058  * 
1059  * Input:
1060  *              AX      = 4F0Ah
1061  * Output:
1062  *              AX      = VBE Return Status
1063  *
1064  * FIXME: incomplete API description, Input & Output
1065  */
1066 void vbe_biosfn_return_protected_mode_interface(AX)
1067 {
1068 }