Home | History | Annotate | Download | only in vgabios
      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 
     34 // disable VESA/VBE2 check in vbe info
     35 //#define VBE2_NO_VESA_CHECK
     36 
     37 
     38 #include "vbe.h"
     39 #include "vbetables.h"
     40 
     41 // The current OEM Software Revision of this VBE Bios
     42 #define VBE_OEM_SOFTWARE_REV 0x0002;
     43 
     44 extern char vbebios_copyright;
     45 extern char vbebios_vendor_name;
     46 extern char vbebios_product_name;
     47 extern char vbebios_product_revision;
     48 
     49 ASM_START
     50 // FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
     51 _vbebios_copyright:
     52 .ascii       "Bochs/Plex86 VBE(C) 2003 http://savannah.nongnu.org/projects/vgabios/"
     53 .byte        0x00
     54 
     55 _vbebios_vendor_name:
     56 .ascii       "Bochs/Plex86 Developers"
     57 .byte        0x00
     58 
     59 _vbebios_product_name:
     60 .ascii       "Bochs/Plex86 VBE Adapter"
     61 .byte        0x00
     62 
     63 _vbebios_product_revision:
     64 .ascii       "$Id$"
     65 .byte        0x00
     66 
     67 _vbebios_info_string:
     68 .ascii      "Bochs VBE Display Adapter enabled"
     69 .byte	0x0a,0x0d
     70 .byte	0x0a,0x0d
     71 .byte	0x00
     72 
     73 _no_vbebios_info_string:
     74 .ascii      "NO Bochs VBE Support available!"
     75 .byte	0x0a,0x0d
     76 .byte	0x0a,0x0d
     77 .byte 0x00
     78 
     79 #if defined(USE_BX_INFO) || defined(DEBUG)
     80 msg_vbe_init:
     81 .ascii      "VBE Bios $Id$"
     82 .byte	0x0a,0x0d, 0x00
     83 #endif
     84 
     85   .align 2
     86 vesa_pm_start:
     87   dw vesa_pm_set_window - vesa_pm_start
     88   dw vesa_pm_set_display_start - vesa_pm_start
     89   dw vesa_pm_unimplemented - vesa_pm_start
     90   dw vesa_pm_io_ports_table - vesa_pm_start
     91 vesa_pm_io_ports_table:
     92   dw VBE_DISPI_IOPORT_INDEX
     93   dw VBE_DISPI_IOPORT_INDEX + 1
     94   dw VBE_DISPI_IOPORT_DATA
     95   dw VBE_DISPI_IOPORT_DATA + 1
     96   dw 0xffff
     97   dw 0xffff
     98 
     99   USE32
    100 vesa_pm_set_window:
    101   cmp  bx, #0x00
    102   je  vesa_pm_set_display_window1
    103   mov  ax, #0x0100
    104   ret
    105 vesa_pm_set_display_window1:
    106   mov  ax, dx
    107   push dx
    108   push ax
    109   mov  dx, # VBE_DISPI_IOPORT_INDEX
    110   mov  ax, # VBE_DISPI_INDEX_BANK
    111   out  dx, ax
    112   pop  ax
    113   mov  dx, # VBE_DISPI_IOPORT_DATA
    114   out  dx, ax
    115   in   ax, dx
    116   pop  dx
    117   cmp  dx, ax
    118   jne  illegal_window
    119   mov  ax, #0x004f
    120   ret
    121 illegal_window:
    122   mov  ax, #0x014f
    123   ret
    124 
    125 vesa_pm_set_display_start:
    126   cmp  bl, #0x80
    127   je   vesa_pm_set_display_start1
    128   cmp  bl, #0x00
    129   je   vesa_pm_set_display_start1
    130   mov  ax, #0x0100
    131   ret
    132 vesa_pm_set_display_start1:
    133 ; convert offset to (X, Y) coordinate
    134 ; (would be simpler to change Bochs VBE API...)
    135   push eax
    136   push ecx
    137   push edx
    138   push esi
    139   push edi
    140   shl edx, #16
    141   and ecx, #0xffff
    142   or ecx, edx
    143   shl ecx, #2
    144   mov eax, ecx
    145 
    146   push eax
    147   mov  dx, # VBE_DISPI_IOPORT_INDEX
    148   mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
    149   out  dx, ax
    150   mov  dx, # VBE_DISPI_IOPORT_DATA
    151   in   ax, dx
    152   movzx ecx, ax
    153 
    154   mov  dx, # VBE_DISPI_IOPORT_INDEX
    155   mov  ax, # VBE_DISPI_INDEX_BPP
    156   out  dx, ax
    157   mov  dx, # VBE_DISPI_IOPORT_DATA
    158   in   ax, dx
    159   movzx esi, ax
    160   pop  eax
    161 
    162   cmp esi, #4
    163   jz bpp4_mode
    164   add esi, #7
    165   shr esi, #3
    166   imul ecx, esi
    167   xor edx, edx
    168   div ecx
    169   mov edi, eax
    170   mov eax, edx
    171   xor edx, edx
    172   div esi
    173   jmp set_xy_regs
    174 
    175 bpp4_mode:
    176   shr ecx, #1
    177   xor edx, edx
    178   div ecx
    179   mov edi, eax
    180   mov eax, edx
    181   shl eax, #1
    182 
    183 set_xy_regs:
    184   push dx
    185   push ax
    186   mov  dx, # VBE_DISPI_IOPORT_INDEX
    187   mov  ax, # VBE_DISPI_INDEX_X_OFFSET
    188   out  dx, ax
    189   pop  ax
    190   mov  dx, # VBE_DISPI_IOPORT_DATA
    191   out  dx, ax
    192   pop  dx
    193 
    194   mov  ax, di
    195   push dx
    196   push ax
    197   mov  dx, # VBE_DISPI_IOPORT_INDEX
    198   mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
    199   out  dx, ax
    200   pop  ax
    201   mov  dx, # VBE_DISPI_IOPORT_DATA
    202   out  dx, ax
    203   pop  dx
    204 
    205   pop edi
    206   pop esi
    207   pop edx
    208   pop ecx
    209   pop eax
    210   mov  ax, #0x004f
    211   ret
    212 
    213 vesa_pm_unimplemented:
    214   mov ax, #0x014f
    215   ret
    216   USE16
    217 vesa_pm_end:
    218 
    219 ; DISPI ioport functions
    220 
    221 dispi_get_id:
    222   push dx
    223   mov  dx, # VBE_DISPI_IOPORT_INDEX
    224   mov  ax, # VBE_DISPI_INDEX_ID
    225   out  dx, ax
    226   mov  dx, # VBE_DISPI_IOPORT_DATA
    227   in   ax, dx
    228   pop  dx
    229   ret
    230 
    231 dispi_set_id:
    232   push dx
    233   push ax
    234   mov  dx, # VBE_DISPI_IOPORT_INDEX
    235   mov  ax, # VBE_DISPI_INDEX_ID
    236   out  dx, ax
    237   pop  ax
    238   mov  dx, # VBE_DISPI_IOPORT_DATA
    239   out  dx, ax
    240   pop  dx
    241   ret
    242 ASM_END
    243 
    244 static void dispi_set_xres(xres)
    245   Bit16u xres;
    246 {
    247 ASM_START
    248   push bp
    249   mov  bp, sp
    250   push ax
    251   push dx
    252 
    253   mov  dx, # VBE_DISPI_IOPORT_INDEX
    254   mov  ax, # VBE_DISPI_INDEX_XRES
    255   out  dx, ax
    256   mov  dx, # VBE_DISPI_IOPORT_DATA
    257   mov  ax, 4[bp] ; xres
    258   out  dx, ax
    259 
    260   pop  dx
    261   pop  ax
    262   pop  bp
    263 ASM_END
    264 }
    265 
    266 static void dispi_set_yres(yres)
    267   Bit16u yres;
    268 {
    269   outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_YRES);
    270   outw(VBE_DISPI_IOPORT_DATA,yres);
    271 }
    272 
    273 static void dispi_set_bpp(bpp)
    274   Bit16u bpp;
    275 {
    276   outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_BPP);
    277   outw(VBE_DISPI_IOPORT_DATA,bpp);
    278 }
    279 
    280 ASM_START
    281 ; AL = bits per pixel / AH = bytes per pixel
    282 dispi_get_bpp:
    283   push dx
    284   mov  dx, # VBE_DISPI_IOPORT_INDEX
    285   mov  ax, # VBE_DISPI_INDEX_BPP
    286   out  dx, ax
    287   mov  dx, # VBE_DISPI_IOPORT_DATA
    288   in   ax, dx
    289   mov  ah, al
    290   shr  ah, 3
    291   test al, #0x07
    292   jz   get_bpp_noinc
    293   inc  ah
    294 get_bpp_noinc:
    295   pop  dx
    296   ret
    297 
    298 ; get display capabilities
    299 
    300 _dispi_get_max_xres:
    301   push dx
    302   push bx
    303   call dispi_get_enable
    304   mov  bx, ax
    305   or   ax, # VBE_DISPI_GETCAPS
    306   call _dispi_set_enable
    307   mov  dx, # VBE_DISPI_IOPORT_INDEX
    308   mov  ax, # VBE_DISPI_INDEX_XRES
    309   out  dx, ax
    310   mov  dx, # VBE_DISPI_IOPORT_DATA
    311   in   ax, dx
    312   push ax
    313   mov  ax, bx
    314   call _dispi_set_enable
    315   pop  ax
    316   pop  bx
    317   pop  dx
    318   ret
    319 
    320 _dispi_get_max_bpp:
    321   push dx
    322   push bx
    323   call dispi_get_enable
    324   mov  bx, ax
    325   or   ax, # VBE_DISPI_GETCAPS
    326   call _dispi_set_enable
    327   mov  dx, # VBE_DISPI_IOPORT_INDEX
    328   mov  ax, # VBE_DISPI_INDEX_BPP
    329   out  dx, ax
    330   mov  dx, # VBE_DISPI_IOPORT_DATA
    331   in   ax, dx
    332   push ax
    333   mov  ax, bx
    334   call _dispi_set_enable
    335   pop  ax
    336   pop  bx
    337   pop  dx
    338   ret
    339 
    340 _dispi_set_enable:
    341   push dx
    342   push ax
    343   mov  dx, # VBE_DISPI_IOPORT_INDEX
    344   mov  ax, # VBE_DISPI_INDEX_ENABLE
    345   out  dx, ax
    346   pop  ax
    347   mov  dx, # VBE_DISPI_IOPORT_DATA
    348   out  dx, ax
    349   pop  dx
    350   ret
    351 
    352 dispi_get_enable:
    353   push dx
    354   mov  dx, # VBE_DISPI_IOPORT_INDEX
    355   mov  ax, # VBE_DISPI_INDEX_ENABLE
    356   out  dx, ax
    357   mov  dx, # VBE_DISPI_IOPORT_DATA
    358   in   ax, dx
    359   pop  dx
    360   ret
    361 
    362 _dispi_set_bank:
    363   push dx
    364   push ax
    365   mov  dx, # VBE_DISPI_IOPORT_INDEX
    366   mov  ax, # VBE_DISPI_INDEX_BANK
    367   out  dx, ax
    368   pop  ax
    369   mov  dx, # VBE_DISPI_IOPORT_DATA
    370   out  dx, ax
    371   pop  dx
    372   ret
    373 
    374 dispi_get_bank:
    375   push dx
    376   mov  dx, # VBE_DISPI_IOPORT_INDEX
    377   mov  ax, # VBE_DISPI_INDEX_BANK
    378   out  dx, ax
    379   mov  dx, # VBE_DISPI_IOPORT_DATA
    380   in   ax, dx
    381   pop  dx
    382   ret
    383 ASM_END
    384 
    385 static void dispi_set_bank_farcall()
    386 {
    387 ASM_START
    388   cmp bx,#0x0100
    389   je dispi_set_bank_farcall_get
    390   or bx,bx
    391   jnz dispi_set_bank_farcall_error
    392   mov ax,dx
    393   push dx
    394   push ax
    395   mov ax,# VBE_DISPI_INDEX_BANK
    396   mov dx,# VBE_DISPI_IOPORT_INDEX
    397   out dx,ax
    398   pop ax
    399   mov dx,# VBE_DISPI_IOPORT_DATA
    400   out dx,ax
    401   in  ax,dx
    402   pop dx
    403   cmp dx,ax
    404   jne dispi_set_bank_farcall_error
    405   mov ax, #0x004f
    406   retf
    407 dispi_set_bank_farcall_get:
    408   mov ax,# VBE_DISPI_INDEX_BANK
    409   mov dx,# VBE_DISPI_IOPORT_INDEX
    410   out dx,ax
    411   mov dx,# VBE_DISPI_IOPORT_DATA
    412   in ax,dx
    413   mov dx,ax
    414   retf
    415 dispi_set_bank_farcall_error:
    416   mov ax,#0x014F
    417   retf
    418 ASM_END
    419 }
    420 
    421 ASM_START
    422 dispi_set_x_offset:
    423   push dx
    424   push ax
    425   mov  dx, # VBE_DISPI_IOPORT_INDEX
    426   mov  ax, # VBE_DISPI_INDEX_X_OFFSET
    427   out  dx, ax
    428   pop  ax
    429   mov  dx, # VBE_DISPI_IOPORT_DATA
    430   out  dx, ax
    431   pop  dx
    432   ret
    433 
    434 dispi_get_x_offset:
    435   push dx
    436   mov  dx, # VBE_DISPI_IOPORT_INDEX
    437   mov  ax, # VBE_DISPI_INDEX_X_OFFSET
    438   out  dx, ax
    439   mov  dx, # VBE_DISPI_IOPORT_DATA
    440   in   ax, dx
    441   pop  dx
    442   ret
    443 
    444 dispi_set_y_offset:
    445   push dx
    446   push ax
    447   mov  dx, # VBE_DISPI_IOPORT_INDEX
    448   mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
    449   out  dx, ax
    450   pop  ax
    451   mov  dx, # VBE_DISPI_IOPORT_DATA
    452   out  dx, ax
    453   pop  dx
    454   ret
    455 
    456 dispi_get_y_offset:
    457   push dx
    458   mov  dx, # VBE_DISPI_IOPORT_INDEX
    459   mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
    460   out  dx, ax
    461   mov  dx, # VBE_DISPI_IOPORT_DATA
    462   in   ax, dx
    463   pop  dx
    464   ret
    465 
    466 vga_set_virt_width:
    467   push ax
    468   push bx
    469   push dx
    470   mov  bx, ax
    471   call dispi_get_bpp
    472   cmp  al, #0x04
    473   ja   set_width_svga
    474   shr  bx, #1
    475 set_width_svga:
    476   shr  bx, #3
    477   mov  dx, # VGAREG_VGA_CRTC_ADDRESS
    478   mov  ah, bl
    479   mov  al, #0x13
    480   out  dx, ax
    481   pop  dx
    482   pop  bx
    483   pop  ax
    484   ret
    485 
    486 dispi_set_virt_width:
    487   call vga_set_virt_width
    488   push dx
    489   push ax
    490   mov  dx, # VBE_DISPI_IOPORT_INDEX
    491   mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
    492   out  dx, ax
    493   pop  ax
    494   mov  dx, # VBE_DISPI_IOPORT_DATA
    495   out  dx, ax
    496   pop  dx
    497   ret
    498 
    499 dispi_get_virt_width:
    500   push dx
    501   mov  dx, # VBE_DISPI_IOPORT_INDEX
    502   mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
    503   out  dx, ax
    504   mov  dx, # VBE_DISPI_IOPORT_DATA
    505   in   ax, dx
    506   pop  dx
    507   ret
    508 
    509 dispi_get_virt_height:
    510   push dx
    511   mov  dx, # VBE_DISPI_IOPORT_INDEX
    512   mov  ax, # VBE_DISPI_INDEX_VIRT_HEIGHT
    513   out  dx, ax
    514   mov  dx, # VBE_DISPI_IOPORT_DATA
    515   in   ax, dx
    516   pop  dx
    517   ret
    518 
    519 _vga_compat_setup:
    520   push ax
    521   push dx
    522 
    523   ; set CRT X resolution
    524   mov  dx, # VBE_DISPI_IOPORT_INDEX
    525   mov  ax, # VBE_DISPI_INDEX_XRES
    526   out  dx, ax
    527   mov  dx, # VBE_DISPI_IOPORT_DATA
    528   in   ax, dx
    529   push ax
    530   mov  dx, # VGAREG_VGA_CRTC_ADDRESS
    531   mov  ax, #0x0011
    532   out  dx, ax
    533   pop  ax
    534   push ax
    535   shr  ax, #3
    536   dec  ax
    537   mov  ah, al
    538   mov  al, #0x01
    539   out  dx, ax
    540   pop  ax
    541   call vga_set_virt_width
    542 
    543   ; set CRT Y resolution
    544   mov  dx, # VBE_DISPI_IOPORT_INDEX
    545   mov  ax, # VBE_DISPI_INDEX_YRES
    546   out  dx, ax
    547   mov  dx, # VBE_DISPI_IOPORT_DATA
    548   in   ax, dx
    549   dec  ax
    550   push ax
    551   mov  dx, # VGAREG_VGA_CRTC_ADDRESS
    552   mov  ah, al
    553   mov  al, #0x12
    554   out  dx, ax
    555   pop  ax
    556   mov  al, #0x07
    557   out  dx, al
    558   inc  dx
    559   in   al, dx
    560   and  al, #0xbd
    561   test ah, #0x01
    562   jz   bit8_clear
    563   or   al, #0x02
    564 bit8_clear:
    565   test ah, #0x02
    566   jz   bit9_clear
    567   or   al, #0x40
    568 bit9_clear:
    569   out  dx, al
    570 
    571   ; other settings
    572   mov  dx, # VGAREG_VGA_CRTC_ADDRESS
    573   mov  ax, #0x0009
    574   out  dx, ax
    575   mov  al, #0x17
    576   out  dx, al
    577   mov  dx, # VGAREG_VGA_CRTC_DATA
    578   in   al, dx
    579   or   al, #0x03
    580   out  dx, al
    581   mov  dx, # VGAREG_ACTL_RESET
    582   in   al, dx
    583   mov  dx, # VGAREG_ACTL_ADDRESS
    584   mov  al, #0x10
    585   out  dx, al
    586   mov  dx, # VGAREG_ACTL_READ_DATA
    587   in   al, dx
    588   or   al, #0x01
    589   mov  dx, # VGAREG_ACTL_ADDRESS
    590   out  dx, al
    591   mov  al, #0x20
    592   out  dx, al
    593   mov  dx, # VGAREG_GRDC_ADDRESS
    594   mov  ax, #0x0506
    595   out  dx, ax
    596   mov  dx, # VGAREG_SEQU_ADDRESS
    597   mov  ax, #0x0f02
    598   out  dx, ax
    599 
    600   ; settings for >= 8bpp
    601   mov  dx, # VBE_DISPI_IOPORT_INDEX
    602   mov  ax, # VBE_DISPI_INDEX_BPP
    603   out  dx, ax
    604   mov  dx, # VBE_DISPI_IOPORT_DATA
    605   in   ax, dx
    606   cmp  al, #0x08
    607   jb   vga_compat_end
    608   mov  dx, # VGAREG_VGA_CRTC_ADDRESS
    609   mov  al, #0x14
    610   out  dx, al
    611   mov  dx, # VGAREG_VGA_CRTC_DATA
    612   in   al, dx
    613   or   al, #0x40
    614   out  dx, al
    615   mov  dx, # VGAREG_ACTL_RESET
    616   in   al, dx
    617   mov  dx, # VGAREG_ACTL_ADDRESS
    618   mov  al, #0x10
    619   out  dx, al
    620   mov  dx, # VGAREG_ACTL_READ_DATA
    621   in   al, dx
    622   or   al, #0x40
    623   mov  dx, # VGAREG_ACTL_ADDRESS
    624   out  dx, al
    625   mov  al, #0x20
    626   out  dx, al
    627   mov  dx, # VGAREG_SEQU_ADDRESS
    628   mov  al, #0x04
    629   out  dx, al
    630   mov  dx, # VGAREG_SEQU_DATA
    631   in   al, dx
    632   or   al, #0x08
    633   out  dx, al
    634   mov  dx, # VGAREG_GRDC_ADDRESS
    635   mov  al, #0x05
    636   out  dx, al
    637   mov  dx, # VGAREG_GRDC_DATA
    638   in   al, dx
    639   and  al, #0x9f
    640   or   al, #0x40
    641   out  dx, al
    642 
    643 vga_compat_end:
    644   pop  dx
    645   pop  ax
    646 ASM_END
    647 
    648 
    649 // ModeInfo helper function
    650 static ModeInfoListItem* mode_info_find_mode(mode, using_lfb)
    651   Bit16u mode; Boolean using_lfb;
    652 {
    653   ModeInfoListItem  *cur_info=&mode_info_list;
    654 
    655   while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
    656   {
    657     if (cur_info->mode == mode)
    658     {
    659       if (!using_lfb)
    660       {
    661         return cur_info;
    662       }
    663       else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
    664       {
    665         return cur_info;
    666       }
    667       else
    668       {
    669         cur_info++;
    670       }
    671     }
    672     else
    673     {
    674       cur_info++;
    675     }
    676   }
    677 
    678   return 0;
    679 }
    680 
    681 ASM_START
    682 
    683 ; Has VBE display - Returns true if VBE display detected
    684 
    685 _vbe_has_vbe_display:
    686   push ds
    687   push bx
    688   mov  ax, # BIOSMEM_SEG
    689   mov  ds, ax
    690   mov  bx, # BIOSMEM_VBE_FLAG
    691   mov  al, [bx]
    692   and  al, #0x01
    693   xor  ah, ah
    694   pop  bx
    695   pop  ds
    696   ret
    697 
    698 ; VBE Init - Initialise the Vesa Bios Extension Code
    699 ; This function does a sanity check on the host side display code interface.
    700 
    701 vbe_init:
    702   mov  ax, # VBE_DISPI_ID0
    703   call dispi_set_id
    704   call dispi_get_id
    705   cmp  ax, # VBE_DISPI_ID0
    706   jne  no_vbe_interface
    707   push ds
    708   push bx
    709   mov  ax, # BIOSMEM_SEG
    710   mov  ds, ax
    711   mov  bx, # BIOSMEM_VBE_FLAG
    712   mov  al, #0x01
    713   mov  [bx], al
    714   pop  bx
    715   pop  ds
    716   mov  ax, # VBE_DISPI_ID5
    717   call dispi_set_id
    718 no_vbe_interface:
    719 #if defined(USE_BX_INFO) || defined(DEBUG)
    720   mov  bx, #msg_vbe_init
    721   push bx
    722   call _printf
    723   inc  sp
    724   inc  sp
    725 #endif
    726   ret
    727 
    728 ; VBE Display Info - Display information on screen about the VBE
    729 
    730 vbe_display_info:
    731   call _vbe_has_vbe_display
    732   test ax, ax
    733   jz   no_vbe_flag
    734   mov  ax, #0xc000
    735   mov  ds, ax
    736   mov  si, #_vbebios_info_string
    737   jmp  _display_string
    738 no_vbe_flag:
    739   mov  ax, #0xc000
    740   mov  ds, ax
    741   mov  si, #_no_vbebios_info_string
    742   jmp  _display_string
    743 
    744 ; helper function for memory size calculation
    745 
    746 lmulul:
    747   and eax, #0x0000FFFF
    748   shl ebx, #16
    749   or  eax, ebx
    750   SEG SS
    751   mul eax, dword ptr [di]
    752   mov ebx, eax
    753   shr ebx, #16
    754   ret
    755 ASM_END
    756 
    757 /** Function 00h - Return VBE Controller Information
    758  *
    759  * Input:
    760  *              AX      = 4F00h
    761  *              ES:DI   = Pointer to buffer in which to place VbeInfoBlock structure
    762  *                        (VbeSignature should be VBE2 when VBE 2.0 information is desired and
    763  *                        the info block is 512 bytes in size)
    764  * Output:
    765  *              AX      = VBE Return Status
    766  *
    767  */
    768 void vbe_biosfn_return_controller_information(AX, ES, DI)
    769 Bit16u *AX;Bit16u ES;Bit16u DI;
    770 {
    771         Bit16u            ss=get_SS();
    772         VbeInfoBlock      vbe_info_block;
    773         Bit16u            status;
    774         Bit16u            result;
    775         Bit16u            vbe2_info;
    776         Bit16u            cur_mode=0;
    777         Bit16u            cur_ptr=34;
    778         Bit16u            size_64k;
    779         ModeInfoListItem  *cur_info=&mode_info_list;
    780 
    781         status = read_word(ss, AX);
    782 
    783 #ifdef DEBUG
    784         printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
    785 #endif
    786 
    787         vbe2_info = 0;
    788 #ifdef VBE2_NO_VESA_CHECK
    789 #else
    790         // get vbe_info_block into local variable
    791         memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
    792 
    793         // check for VBE2 signature
    794         if (((vbe_info_block.VbeSignature[0] == 'V') &&
    795              (vbe_info_block.VbeSignature[1] == 'B') &&
    796              (vbe_info_block.VbeSignature[2] == 'E') &&
    797              (vbe_info_block.VbeSignature[3] == '2')) ||
    798 
    799             ((vbe_info_block.VbeSignature[0] == 'V') &&
    800              (vbe_info_block.VbeSignature[1] == 'E') &&
    801              (vbe_info_block.VbeSignature[2] == 'S') &&
    802              (vbe_info_block.VbeSignature[3] == 'A')) )
    803         {
    804                 vbe2_info = 1;
    805 #ifdef DEBUG
    806                 printf("VBE correct VESA/VBE2 signature found\n");
    807 #endif
    808         }
    809 #endif
    810 
    811         // VBE Signature
    812         vbe_info_block.VbeSignature[0] = 'V';
    813         vbe_info_block.VbeSignature[1] = 'E';
    814         vbe_info_block.VbeSignature[2] = 'S';
    815         vbe_info_block.VbeSignature[3] = 'A';
    816 
    817         // VBE Version supported
    818         vbe_info_block.VbeVersion = 0x0200;
    819 
    820         // OEM String
    821         vbe_info_block.OemStringPtr_Seg = 0xc000;
    822         vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
    823 
    824         // Capabilities
    825         vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
    826         vbe_info_block.Capabilities[1] = 0;
    827         vbe_info_block.Capabilities[2] = 0;
    828         vbe_info_block.Capabilities[3] = 0;
    829 
    830         // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
    831         vbe_info_block.VideoModePtr_Seg= ES ;
    832         vbe_info_block.VideoModePtr_Off= DI + 34;
    833 
    834         // VBE Total Memory (in 64k blocks)
    835         outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
    836         vbe_info_block.TotalMemory = inw(VBE_DISPI_IOPORT_DATA);
    837 
    838         if (vbe2_info)
    839         {
    840                 // OEM Stuff
    841                 vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
    842                 vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
    843                 vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
    844                 vbe_info_block.OemProductNamePtr_Seg = 0xc000;
    845                 vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
    846                 vbe_info_block.OemProductRevPtr_Seg = 0xc000;
    847                 vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
    848 
    849                 // copy updates in vbe_info_block back
    850                 memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
    851         }
    852         else
    853         {
    854                 // copy updates in vbe_info_block back (VBE 1.x compatibility)
    855                 memcpyb(ES, DI, ss, &vbe_info_block, 256);
    856         }
    857 
    858         do
    859         {
    860                 size_64k = (Bit16u)((Bit32u)cur_info->info.XResolution * cur_info->info.XResolution * cur_info->info.BitsPerPixel) >> 19;
    861 
    862                 if ((cur_info->info.XResolution <= dispi_get_max_xres()) &&
    863                     (cur_info->info.BitsPerPixel <= dispi_get_max_bpp()) &&
    864                     (size_64k <= vbe_info_block.TotalMemory)) {
    865 #ifdef DEBUG
    866                   printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
    867 #endif
    868                   write_word(ES, DI + cur_ptr, cur_info->mode);
    869                   cur_mode++;
    870                   cur_ptr+=2;
    871                 } else {
    872 #ifdef DEBUG
    873                   printf("VBE mode %x (xres=%x / bpp=%02x) not supported \n", cur_info->mode,cur_info->info.XResolution,cur_info->info.BitsPerPixel);
    874 #endif
    875                 }
    876                 cur_info++;
    877         } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
    878 
    879         // Add vesa mode list terminator
    880         write_word(ES, DI + cur_ptr, cur_info->mode);
    881 
    882         result = 0x4f;
    883 
    884         write_word(ss, AX, result);
    885 }
    886 
    887 
    888 /** Function 01h - Return VBE Mode Information
    889  *
    890  * Input:
    891  *              AX      = 4F01h
    892  *              CX      = Mode Number
    893  *              ES:DI   = Pointer to buffer in which to place ModeInfoBlock structure
    894  * Output:
    895  *              AX      = VBE Return Status
    896  *
    897  */
    898 void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
    899 Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
    900 {
    901         Bit16u            result=0x0100;
    902         Bit16u            ss=get_SS();
    903         ModeInfoBlock     info;
    904         ModeInfoListItem  *cur_info;
    905         Boolean           using_lfb;
    906         Bit16u            lfb_addr;
    907 
    908 #ifdef DEBUG
    909         printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
    910 #endif
    911 
    912         using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
    913 
    914         CX = (CX & 0x1ff);
    915 
    916         cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
    917 
    918         if (cur_info != 0)
    919         {
    920 #ifdef DEBUG
    921                 printf("VBE found mode %x\n",CX);
    922 #endif
    923                 memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
    924                 memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
    925                 if (using_lfb) {
    926                   info.NumberOfBanks = 1;
    927                 }
    928                 lfb_addr = pci_get_lfb_addr(0x1234); // experimental vendor
    929                 if (lfb_addr > 0) {
    930                   info.PhysBasePtr = ((Bit32u)lfb_addr << 16);
    931                 }
    932                 if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
    933                   info.WinFuncPtr = 0xC0000000UL;
    934                   *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
    935                 }
    936 
    937                 result = 0x4f;
    938         }
    939         else
    940         {
    941 #ifdef DEBUG
    942                 printf("VBE *NOT* found mode %x\n",CX);
    943 #endif
    944                 result = 0x100;
    945         }
    946 
    947         if (result == 0x4f)
    948         {
    949                 // copy updates in mode_info_block back
    950                 memcpyb(ES, DI, ss, &info, sizeof(info));
    951         }
    952 
    953         write_word(ss, AX, result);
    954 }
    955 
    956 /** Function 02h - Set VBE Mode
    957  *
    958  * Input:
    959  *              AX      = 4F02h
    960  *              BX      = Desired Mode to set
    961  *              ES:DI   = Pointer to CRTCInfoBlock structure
    962  * Output:
    963  *              AX      = VBE Return Status
    964  *
    965  */
    966 void vbe_biosfn_set_mode(AX, BX, ES, DI)
    967 Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
    968 {
    969         Bit16u            ss = get_SS();
    970         Bit16u            result;
    971         ModeInfoListItem  *cur_info;
    972         Boolean           using_lfb;
    973         Bit8u             no_clear;
    974         Bit8u             lfb_flag;
    975 
    976         using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
    977         lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
    978         no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
    979 
    980         BX = (BX & 0x1ff);
    981 
    982         //result=read_word(ss,AX);
    983 
    984         // check for non vesa mode
    985         if (BX<VBE_MODE_VESA_DEFINED)
    986         {
    987                 Bit8u   mode;
    988 
    989                 dispi_set_enable(VBE_DISPI_DISABLED);
    990                 // call the vgabios in order to set the video mode
    991                 // this allows for going back to textmode with a VBE call (some applications expect that to work)
    992 
    993                 mode=(BX & 0xff);
    994                 biosfn_set_video_mode(mode);
    995                 result = 0x4f;
    996         }
    997 
    998         cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
    999 
   1000         if (cur_info != 0)
   1001         {
   1002 #ifdef DEBUG
   1003                 printf("VBE found mode %x, setting:\n", BX);
   1004                 printf("\txres%x yres%x bpp%x\n",
   1005                         cur_info->info.XResolution,
   1006                         cur_info->info.YResolution,
   1007                         cur_info->info.BitsPerPixel);
   1008 #endif
   1009 
   1010                 // first disable current mode (when switching between vesa modi)
   1011                 dispi_set_enable(VBE_DISPI_DISABLED);
   1012 
   1013                 if (cur_info->info.BitsPerPixel == 4)
   1014                 {
   1015                   biosfn_set_video_mode(0x6a);
   1016                 }
   1017 
   1018                 dispi_set_bpp(cur_info->info.BitsPerPixel);
   1019                 dispi_set_xres(cur_info->info.XResolution);
   1020                 dispi_set_yres(cur_info->info.YResolution);
   1021                 dispi_set_bank(0);
   1022                 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
   1023                 vga_compat_setup();
   1024 
   1025                 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
   1026                 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
   1027 
   1028                 result = 0x4f;
   1029         }
   1030         else
   1031         {
   1032 #ifdef DEBUG
   1033                 printf("VBE *NOT* found mode %x\n" , BX);
   1034 #endif
   1035                 result = 0x100;
   1036 
   1037                 // FIXME: redirect non VBE modi to normal VGA bios operation
   1038                 //        (switch back to VGA mode
   1039                 if (BX == 3)
   1040                         result = 0x4f;
   1041         }
   1042 
   1043         write_word(ss, AX, result);
   1044 }
   1045 
   1046 /** Function 03h - Return Current VBE Mode
   1047  *
   1048  * Input:
   1049  *              AX      = 4F03h
   1050  * Output:
   1051  *              AX      = VBE Return Status
   1052  *              BX      = Current VBE Mode
   1053  *
   1054  */
   1055 ASM_START
   1056 vbe_biosfn_return_current_mode:
   1057   push ds
   1058   mov  ax, # BIOSMEM_SEG
   1059   mov  ds, ax
   1060   call dispi_get_enable
   1061   and  ax, # VBE_DISPI_ENABLED
   1062   jz   no_vbe_mode
   1063   mov  bx, # BIOSMEM_VBE_MODE
   1064   mov  ax, [bx]
   1065   mov  bx, ax
   1066   jnz  vbe_03_ok
   1067 no_vbe_mode:
   1068   mov  bx, # BIOSMEM_CURRENT_MODE
   1069   mov  al, [bx]
   1070   mov  bl, al
   1071   xor  bh, bh
   1072 vbe_03_ok:
   1073   mov  ax, #0x004f
   1074   pop  ds
   1075   ret
   1076 ASM_END
   1077 
   1078 
   1079 Bit16u vbe_biosfn_read_video_state_size()
   1080 {
   1081     return 9 * 2;
   1082 }
   1083 
   1084 void vbe_biosfn_save_video_state(ES, BX)
   1085      Bit16u ES; Bit16u BX;
   1086 {
   1087     Bit16u enable, i;
   1088 
   1089     outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
   1090     enable = inw(VBE_DISPI_IOPORT_DATA);
   1091     write_word(ES, BX, enable);
   1092     BX += 2;
   1093     if (!(enable & VBE_DISPI_ENABLED))
   1094         return;
   1095     for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
   1096         if (i != VBE_DISPI_INDEX_ENABLE) {
   1097             outw(VBE_DISPI_IOPORT_INDEX, i);
   1098             write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
   1099             BX += 2;
   1100         }
   1101     }
   1102 }
   1103 
   1104 
   1105 void vbe_biosfn_restore_video_state(ES, BX)
   1106      Bit16u ES; Bit16u BX;
   1107 {
   1108     Bit16u enable, i;
   1109 
   1110     enable = read_word(ES, BX);
   1111     BX += 2;
   1112 
   1113     if (!(enable & VBE_DISPI_ENABLED)) {
   1114         outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
   1115         outw(VBE_DISPI_IOPORT_DATA, enable);
   1116     } else {
   1117         outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
   1118         outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
   1119         BX += 2;
   1120         outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
   1121         outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
   1122         BX += 2;
   1123         outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
   1124         outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
   1125         BX += 2;
   1126         outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
   1127         outw(VBE_DISPI_IOPORT_DATA, enable);
   1128 
   1129         for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
   1130             outw(VBE_DISPI_IOPORT_INDEX, i);
   1131             outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
   1132             BX += 2;
   1133         }
   1134     }
   1135 }
   1136 
   1137 /** Function 04h - Save/Restore State
   1138  *
   1139  * Input:
   1140  *              AX      = 4F04h
   1141  *              DL      = 00h Return Save/Restore State buffer size
   1142  *                        01h Save State
   1143  *                        02h Restore State
   1144  *              CX      = Requested states
   1145  *              ES:BX   = Pointer to buffer (if DL <> 00h)
   1146  * Output:
   1147  *              AX      = VBE Return Status
   1148  *              BX      = Number of 64-byte blocks to hold the state buffer (if DL=00h)
   1149  *
   1150  */
   1151 void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
   1152 Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
   1153 {
   1154     Bit16u ss=get_SS();
   1155     Bit16u result, val;
   1156 
   1157     result = 0x4f;
   1158     switch(GET_DL()) {
   1159     case 0x00:
   1160         val = biosfn_read_video_state_size2(CX);
   1161 #ifdef DEBUG
   1162         printf("VGA state size=%x\n", val);
   1163 #endif
   1164         if (CX & 8)
   1165             val += vbe_biosfn_read_video_state_size();
   1166         write_word(ss, BX, val);
   1167         break;
   1168     case 0x01:
   1169         val = read_word(ss, BX);
   1170         val = biosfn_save_video_state(CX, ES, val);
   1171 #ifdef DEBUG
   1172         printf("VGA save_state offset=%x\n", val);
   1173 #endif
   1174         if (CX & 8)
   1175             vbe_biosfn_save_video_state(ES, val);
   1176         break;
   1177     case 0x02:
   1178         val = read_word(ss, BX);
   1179         val = biosfn_restore_video_state(CX, ES, val);
   1180 #ifdef DEBUG
   1181         printf("VGA restore_state offset=%x\n", val);
   1182 #endif
   1183         if (CX & 8)
   1184             vbe_biosfn_restore_video_state(ES, val);
   1185         break;
   1186     default:
   1187         // function failed
   1188         result = 0x100;
   1189         break;
   1190     }
   1191     write_word(ss, AX, result);
   1192 }
   1193 
   1194 /** Function 05h - Display Window Control
   1195  *
   1196  * Input:
   1197  *              AX      = 4F05h
   1198  *     (16-bit) BH      = 00h Set memory window
   1199  *                      = 01h Get memory window
   1200  *              BL      = Window number
   1201  *                      = 00h Window A
   1202  *                      = 01h Window B
   1203  *              DX      = Window number in video memory in window
   1204  *                        granularity units (Set Memory Window only)
   1205  * Note:
   1206  *              If this function is called while in a linear frame buffer mode,
   1207  *              this function must fail with completion code AH=03h
   1208  *
   1209  * Output:
   1210  *              AX      = VBE Return Status
   1211  *              DX      = Window number in window granularity units
   1212  *                        (Get Memory Window only)
   1213  */
   1214 ASM_START
   1215 vbe_biosfn_display_window_control:
   1216   cmp  bl, #0x00
   1217   jne  vbe_05_failed
   1218   cmp  bh, #0x01
   1219   je   get_display_window
   1220   jb   set_display_window
   1221   mov  ax, #0x0100
   1222   ret
   1223 set_display_window:
   1224   mov  ax, dx
   1225   call _dispi_set_bank
   1226   call dispi_get_bank
   1227   cmp  ax, dx
   1228   jne  vbe_05_failed
   1229   mov  ax, #0x004f
   1230   ret
   1231 get_display_window:
   1232   call dispi_get_bank
   1233   mov  dx, ax
   1234   mov  ax, #0x004f
   1235   ret
   1236 vbe_05_failed:
   1237   mov  ax, #0x014f
   1238   ret
   1239 ASM_END
   1240 
   1241 
   1242 /** Function 06h - Set/Get Logical Scan Line Length
   1243  *
   1244  * Input:
   1245  *              AX      = 4F06h
   1246  *              BL      = 00h Set Scan Line Length in Pixels
   1247  *                      = 01h Get Scan Line Length
   1248  *                      = 02h Set Scan Line Length in Bytes
   1249  *                      = 03h Get Maximum Scan Line Length
   1250  *              CX      = If BL=00h Desired Width in Pixels
   1251  *                        If BL=02h Desired Width in Bytes
   1252  *                        (Ignored for Get Functions)
   1253  *
   1254  * Output:
   1255  *              AX      = VBE Return Status
   1256  *              BX      = Bytes Per Scan Line
   1257  *              CX      = Actual Pixels Per Scan Line
   1258  *                        (truncated to nearest complete pixel)
   1259  *              DX      = Maximum Number of Scan Lines
   1260  */
   1261 ASM_START
   1262 vbe_biosfn_set_get_logical_scan_line_length:
   1263   mov  ax, cx
   1264   cmp  bl, #0x01
   1265   je   get_logical_scan_line_length
   1266   cmp  bl, #0x02
   1267   je   set_logical_scan_line_bytes
   1268   jb   set_logical_scan_line_pixels
   1269   mov  ax, #0x0100
   1270   ret
   1271 set_logical_scan_line_bytes:
   1272   push ax
   1273   call dispi_get_bpp
   1274   xor  bh, bh
   1275   mov  bl, ah
   1276   or   bl, bl
   1277   jnz  no_4bpp_1
   1278   shl  ax, #3
   1279   mov  bl, #1
   1280 no_4bpp_1:
   1281   xor  dx, dx
   1282   pop  ax
   1283   div  bx
   1284 set_logical_scan_line_pixels:
   1285   call dispi_set_virt_width
   1286 get_logical_scan_line_length:
   1287   call dispi_get_bpp
   1288   xor  bh, bh
   1289   mov  bl, ah
   1290   call dispi_get_virt_width
   1291   mov  cx, ax
   1292   or   bl, bl
   1293   jnz  no_4bpp_2
   1294   shr  ax, #3
   1295   mov  bl, #1
   1296 no_4bpp_2:
   1297   mul  bx
   1298   mov  bx, ax
   1299   call dispi_get_virt_height
   1300   mov  dx, ax
   1301   mov  ax, #0x004f
   1302   ret
   1303 ASM_END
   1304 
   1305 
   1306 /** Function 07h - Set/Get Display Start
   1307  *
   1308  * Input(16-bit):
   1309  *              AX      = 4F07h
   1310  *              BH      = 00h Reserved and must be 00h
   1311  *              BL      = 00h Set Display Start
   1312  *                      = 01h Get Display Start
   1313  *                      = 02h Schedule Display Start (Alternate)
   1314  *                      = 03h Schedule Stereoscopic Display Start
   1315  *                      = 04h Get Scheduled Display Start Status
   1316  *                      = 05h Enable Stereoscopic Mode
   1317  *                      = 06h Disable Stereoscopic Mode
   1318  *                      = 80h Set Display Start during Vertical Retrace
   1319  *                      = 82h Set Display Start during Vertical Retrace (Alternate)
   1320  *                      = 83h Set Stereoscopic Display Start during Vertical Retrace
   1321  *              ECX     = If BL=02h/82h Display Start Address in bytes
   1322  *                        If BL=03h/83h Left Image Start Address in bytes
   1323  *              EDX     = If BL=03h/83h Right Image Start Address in bytes
   1324  *              CX      = If BL=00h/80h First Displayed Pixel In Scan Line
   1325  *              DX      = If BL=00h/80h First Displayed Scan Line
   1326  *
   1327  * Output:
   1328  *              AX      = VBE Return Status
   1329  *              BH      = If BL=01h Reserved and will be 0
   1330  *              CX      = If BL=01h First Displayed Pixel In Scan Line
   1331  *                        If BL=04h 0 if flip has not occurred, not 0 if it has
   1332  *              DX      = If BL=01h First Displayed Scan Line
   1333  *
   1334  * Input(32-bit):
   1335  *              BH      = 00h Reserved and must be 00h
   1336  *              BL      = 00h Set Display Start
   1337  *                      = 80h Set Display Start during Vertical Retrace
   1338  *              CX      = Bits 0-15 of display start address
   1339  *              DX      = Bits 16-31 of display start address
   1340  *              ES      = Selector for memory mapped registers
   1341  */
   1342 ASM_START
   1343 vbe_biosfn_set_get_display_start:
   1344   cmp  bl, #0x80
   1345   je   set_display_start
   1346   cmp  bl, #0x01
   1347   je   get_display_start
   1348   jb   set_display_start
   1349   mov  ax, #0x0100
   1350   ret
   1351 set_display_start:
   1352   mov  ax, cx
   1353   call dispi_set_x_offset
   1354   mov  ax, dx
   1355   call dispi_set_y_offset
   1356   mov  ax, #0x004f
   1357   ret
   1358 get_display_start:
   1359   call dispi_get_x_offset
   1360   mov  cx, ax
   1361   call dispi_get_y_offset
   1362   mov  dx, ax
   1363   xor  bh, bh
   1364   mov  ax, #0x004f
   1365   ret
   1366 ASM_END
   1367 
   1368 
   1369 /** Function 08h - Set/Get Dac Palette Format
   1370  *
   1371  * Input:
   1372  *              AX      = 4F08h
   1373  *              BL      = 00h set DAC palette width
   1374  *                      = 01h get DAC palette width
   1375  *              BH      = If BL=00h: desired number of bits per primary color
   1376  * Output:
   1377  *              AX      = VBE Return Status
   1378  *              BH      = current number of bits per primary color (06h = standard VGA)
   1379  */
   1380 ASM_START
   1381 vbe_biosfn_set_get_dac_palette_format:
   1382   cmp  bl, #0x01
   1383   je   get_dac_palette_format
   1384   jb   set_dac_palette_format
   1385   mov  ax, #0x0100
   1386   ret
   1387 set_dac_palette_format:
   1388   call dispi_get_enable
   1389   cmp  bh, #0x06
   1390   je   set_normal_dac
   1391   cmp  bh, #0x08
   1392   jne  vbe_08_unsupported
   1393   or   ax, # VBE_DISPI_8BIT_DAC
   1394   jnz  set_dac_mode
   1395 set_normal_dac:
   1396   and  ax, #~ VBE_DISPI_8BIT_DAC
   1397 set_dac_mode:
   1398   call _dispi_set_enable
   1399 get_dac_palette_format:
   1400   mov  bh, #0x06
   1401   call dispi_get_enable
   1402   and  ax, # VBE_DISPI_8BIT_DAC
   1403   jz   vbe_08_ok
   1404   mov  bh, #0x08
   1405 vbe_08_ok:
   1406   mov  ax, #0x004f
   1407   ret
   1408 vbe_08_unsupported:
   1409   mov  ax, #0x014f
   1410   ret
   1411 ASM_END
   1412 
   1413 
   1414 /** Function 09h - Set/Get Palette Data
   1415  *
   1416  * Input:
   1417  *              AX      = 4F09h
   1418  * Output:
   1419  *              AX      = VBE Return Status
   1420  *
   1421  * FIXME: incomplete API description, Input & Output
   1422  */
   1423 void vbe_biosfn_set_get_palette_data(AX)
   1424 {
   1425 }
   1426 
   1427 /** Function 0Ah - Return VBE Protected Mode Interface
   1428  * Input:    AX   = 4F0Ah   VBE 2.0 Protected Mode Interface
   1429  *           BL   = 00h          Return protected mode table
   1430  *
   1431  *
   1432  * Output:   AX   =         Status
   1433  *           ES   =         Real Mode Segment of Table
   1434  *           DI   =         Offset of Table
   1435  *           CX   =         Length of Table including protected mode code
   1436  *                          (for copying purposes)
   1437  */
   1438 ASM_START
   1439 vbe_biosfn_return_protected_mode_interface:
   1440   test bl, bl
   1441   jnz _fail
   1442   mov di, #0xc000
   1443   mov es, di
   1444   mov di, # vesa_pm_start
   1445   mov cx, # vesa_pm_end
   1446   sub cx, di
   1447   mov ax, #0x004f
   1448   ret
   1449 _fail:
   1450   mov ax, #0x014f
   1451   ret
   1452 ASM_END
   1453