Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / vgabios / clext.c
diff --git a/qemu/roms/vgabios/clext.c b/qemu/roms/vgabios/clext.c
new file mode 100644 (file)
index 0000000..b0b6834
--- /dev/null
@@ -0,0 +1,1641 @@
+//
+//  QEMU Cirrus CLGD 54xx VGABIOS Extension.
+//
+//  Copyright (c) 2004 Makoto Suzuki (suzu)
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+// 
+
+//#define CIRRUS_VESA3_PMINFO
+#ifdef VBE
+#undef CIRRUS_VESA3_PMINFO
+#endif
+
+#define PM_BIOSMEM_CURRENT_MODE 0x449
+#define PM_BIOSMEM_CRTC_ADDRESS 0x463
+#define PM_BIOSMEM_VBE_MODE 0x4BA
+
+typedef struct
+{
+  /* + 0 */
+  unsigned short mode;
+  unsigned short width;
+  unsigned short height;
+  unsigned short depth;
+  /* + 8 */
+  unsigned short hidden_dac; /* 0x3c6 */
+  unsigned short *seq; /* 0x3c4 */
+  unsigned short *graph; /* 0x3ce */
+  unsigned short *crtc; /* 0x3d4 */
+  /* +16 */
+  unsigned char bitsperpixel;
+  unsigned char vesacolortype;
+  unsigned char vesaredmask;
+  unsigned char vesaredpos;
+  unsigned char vesagreenmask;
+  unsigned char vesagreenpos;
+  unsigned char vesabluemask;
+  unsigned char vesabluepos;
+  /* +24 */
+  unsigned char vesareservedmask;
+  unsigned char vesareservedpos;
+} cirrus_mode_t;
+#define CIRRUS_MODE_SIZE 26
+
+
+/* For VESA BIOS 3.0 */
+#define CIRRUS_PM16INFO_SIZE 20
+
+/* VGA */
+unsigned short cseq_vga[] = {0x0007,0xffff};
+unsigned short cgraph_vga[] = {0x0009,0x000a,0x000b,0xffff};
+unsigned short ccrtc_vga[] = {0x001a,0x001b,0x001d,0xffff};
+
+/* extensions */
+unsigned short cgraph_svgacolor[] = {
+0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08,
+0x0009,0x000a,0x000b,
+0xffff
+};
+/* 640x480x8 */
+unsigned short cseq_640x480x8[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
+0x580b,0x580c,0x580d,0x580e,
+0x0412,0x0013,0x2017,
+0x331b,0x331c,0x331d,0x331e,
+0xffff
+};
+unsigned short ccrtc_640x480x8[] = {
+0x2c11,
+0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
+0x4009,0x000c,0x000d,
+0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+/* 640x480x16 */
+unsigned short cseq_640x480x16[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
+0x580b,0x580c,0x580d,0x580e,
+0x0412,0x0013,0x2017,
+0x331b,0x331c,0x331d,0x331e,
+0xffff
+};
+unsigned short ccrtc_640x480x16[] = {
+0x2c11,
+0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
+0x4009,0x000c,0x000d,
+0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+/* 640x480x24 */
+unsigned short cseq_640x480x24[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
+0x580b,0x580c,0x580d,0x580e,
+0x0412,0x0013,0x2017,
+0x331b,0x331c,0x331d,0x331e,
+0xffff
+};
+unsigned short ccrtc_640x480x24[] = {
+0x2c11,
+0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
+0x4009,0x000c,0x000d,
+0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
+0x001a,0x321b,0x001d,
+0xffff
+};
+/* 800x600x8 */
+unsigned short cseq_800x600x8[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
+0x230b,0x230c,0x230d,0x230e,
+0x0412,0x0013,0x2017,
+0x141b,0x141c,0x141d,0x141e,
+0xffff
+};
+unsigned short ccrtc_800x600x8[] = {
+0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
+0x6009,0x000c,0x000d,
+0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+/* 800x600x16 */
+unsigned short cseq_800x600x16[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
+0x230b,0x230c,0x230d,0x230e,
+0x0412,0x0013,0x2017,
+0x141b,0x141c,0x141d,0x141e,
+0xffff
+};
+unsigned short ccrtc_800x600x16[] = {
+0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
+0x6009,0x000c,0x000d,
+0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+/* 800x600x24 */
+unsigned short cseq_800x600x24[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
+0x230b,0x230c,0x230d,0x230e,
+0x0412,0x0013,0x2017,
+0x141b,0x141c,0x141d,0x141e,
+0xffff
+};
+unsigned short ccrtc_800x600x24[] = {
+0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
+0x6009,0x000c,0x000d,
+0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18,
+0x001a,0x321b,0x001d,
+0xffff
+};
+/* 1024x768x8 */
+unsigned short cseq_1024x768x8[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
+0x760b,0x760c,0x760d,0x760e,
+0x0412,0x0013,0x2017,
+0x341b,0x341c,0x341d,0x341e,
+0xffff
+};
+unsigned short ccrtc_1024x768x8[] = {
+0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
+0x6009,0x000c,0x000d,
+0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+/* 1024x768x16 */
+unsigned short cseq_1024x768x16[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
+0x760b,0x760c,0x760d,0x760e,
+0x0412,0x0013,0x2017,
+0x341b,0x341c,0x341d,0x341e,
+0xffff
+};
+unsigned short ccrtc_1024x768x16[] = {
+0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
+0x6009,0x000c,0x000d,
+0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18,
+0x001a,0x321b,0x001d,
+0xffff
+};
+/* 1024x768x24 */
+unsigned short cseq_1024x768x24[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
+0x760b,0x760c,0x760d,0x760e,
+0x0412,0x0013,0x2017,
+0x341b,0x341c,0x341d,0x341e,
+0xffff
+};
+unsigned short ccrtc_1024x768x24[] = {
+0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
+0x6009,0x000c,0x000d,
+0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
+0x001a,0x321b,0x001d,
+0xffff
+};
+/* 1280x1024x8 */
+unsigned short cseq_1280x1024x8[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
+0x760b,0x760c,0x760d,0x760e,
+0x0412,0x0013,0x2017,
+0x341b,0x341c,0x341d,0x341e,
+0xffff
+};
+unsigned short ccrtc_1280x1024x8[] = {
+0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
+0x6009,0x000c,0x000d,
+0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+/* 1280x1024x16 */
+unsigned short cseq_1280x1024x16[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
+0x760b,0x760c,0x760d,0x760e,
+0x0412,0x0013,0x2017,
+0x341b,0x341c,0x341d,0x341e,
+0xffff
+};
+unsigned short ccrtc_1280x1024x16[] = {
+0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
+0x6009,0x000c,0x000d,
+0x0310,0xff12,0x4013,0x4014,0xff15,0x2416,0xc317,0xff18,
+0x001a,0x321b,0x001d,
+0xffff
+};
+
+/* 1600x1200x8 */
+unsigned short cseq_1600x1200x8[] = {
+0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
+0x760b,0x760c,0x760d,0x760e,
+0x0412,0x0013,0x2017,
+0x341b,0x341c,0x341d,0x341e,
+0xffff
+};
+unsigned short ccrtc_1600x1200x8[] = {
+0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
+0x6009,0x000c,0x000d,
+0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
+0x001a,0x221b,0x001d,
+0xffff
+};
+
+cirrus_mode_t cirrus_modes[] =
+{
+ {0x5f,640,480,8,0x00,
+   cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8,
+   4,0,0,0,0,0,0,0,0},
+ {0x64,640,480,16,0xe1,
+   cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
+   6,5,11,6,5,5,0,0,0},
+ {0x66,640,480,15,0xf0,
+   cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
+   6,5,10,5,5,5,0,1,15},
+ {0x71,640,480,24,0xe5,
+   cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24,
+   6,8,16,8,8,8,0,0,0},
+
+ {0x5c,800,600,8,0x00,
+   cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8,
+   4,0,0,0,0,0,0,0,0},
+ {0x65,800,600,16,0xe1,
+   cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
+   6,5,11,6,5,5,0,0,0},
+ {0x67,800,600,15,0xf0,
+   cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
+   6,5,10,5,5,5,0,1,15},
+
+ {0x60,1024,768,8,0x00,
+   cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8,
+   4,0,0,0,0,0,0,0,0},
+ {0x74,1024,768,16,0xe1,
+   cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
+   6,5,11,6,5,5,0,0,0},
+ {0x68,1024,768,15,0xf0,
+   cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
+   6,5,10,5,5,5,0,1,15},
+
+ {0x78,800,600,24,0xe5,
+   cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24,
+   6,8,16,8,8,8,0,0,0},
+ {0x79,1024,768,24,0xe5,
+   cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24,
+   6,8,16,8,8,8,0,0,0},
+
+ {0x6d,1280,1024,8,0x00,
+   cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8,
+   4,0,0,0,0,0,0,0,0},
+ {0x69,1280,1024,15,0xf0,
+   cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16,
+   6,5,10,5,5,5,0,1,15},
+ {0x75,1280,1024,16,0xe1,
+   cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16,
+   6,5,11,6,5,5,0,0,0},
+
+ {0x7b,1600,1200,8,0x00,
+   cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8,8,
+   4,0,0,0,0,0,0,0,0},
+
+ {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0,
+   0xff,0,0,0,0,0,0,0,0},
+ {0xff,0,0,0,0,0,0,0,0,
+   0xff,0,0,0,0,0,0,0,0},
+};
+
+unsigned char cirrus_id_table[] = {
+  // 5430
+  0xA0, 0x32,
+  // 5446
+  0xB8, 0x39,
+
+  0xff, 0xff
+};
+
+
+unsigned short cirrus_vesa_modelist[] = {
+// 640x480x8
+  0x101, 0x5f,
+// 640x480x15
+  0x110, 0x66,
+// 640x480x16
+  0x111, 0x64,
+// 640x480x24
+  0x112, 0x71,
+// 800x600x8
+  0x103, 0x5c,
+// 800x600x15
+  0x113, 0x67,
+// 800x600x16
+  0x114, 0x65,
+// 800x600x24
+  0x115, 0x78,
+// 1024x768x8
+  0x105, 0x60,
+// 1024x768x15
+  0x116, 0x68,
+// 1024x768x16
+  0x117, 0x74,
+// 1024x768x24
+  0x118, 0x79,
+// 1280x1024x8
+  0x107, 0x6d,
+// 1280x1024x15
+  0x119, 0x69,
+// 1280x1024x16
+  0x11a, 0x75,
+// invalid
+  0xffff,0xffff
+};
+
+
+ASM_START
+
+cirrus_installed:
+.ascii "cirrus-compatible VGA is detected"
+.byte 0x0d,0x0a
+.byte 0x0d,0x0a,0x00
+
+cirrus_not_installed:
+.ascii "cirrus-compatible VGA is not detected"
+.byte 0x0d,0x0a
+.byte 0x0d,0x0a,0x00
+
+cirrus_vesa_vendorname:
+cirrus_vesa_productname:
+cirrus_vesa_oemname:
+.ascii "VGABIOS Cirrus extension"
+.byte 0
+cirrus_vesa_productrevision:
+.ascii "1.0"
+.byte 0
+
+cirrus_init:
+  call cirrus_check
+  jnz no_cirrus
+  SET_INT_VECTOR(0x10, #0xC000, #cirrus_int10_handler)
+  mov al, #0x0f ; memory setup
+  mov dx, #0x3C4
+  out dx, al
+  inc dx
+  in  al, dx
+  and al, #0x18
+  mov ah, al
+  mov al, #0x0a
+  dec dx
+  out dx, ax
+  mov ax, #0x0007 ; set vga mode
+  out dx, ax
+  mov ax, #0x0431 ; reset bitblt
+  mov dx, #0x3CE
+  out dx, ax
+  mov ax, #0x0031
+  out dx, ax
+no_cirrus:
+  ret
+
+cirrus_display_info:
+  push ds
+  push si
+  push cs
+  pop ds
+  call cirrus_check
+  mov si, #cirrus_not_installed
+  jnz cirrus_msgnotinstalled
+  mov si, #cirrus_installed
+
+cirrus_msgnotinstalled:
+  call _display_string
+  pop si
+  pop ds
+  ret
+
+cirrus_check:
+  push ax
+  push dx
+  mov ax, #0x9206
+  mov dx, #0x3C4
+  out dx, ax
+  inc dx
+  in al, dx
+  cmp al, #0x12
+  pop dx
+  pop ax
+  ret
+
+
+cirrus_int10_handler:
+  pushf
+  push bp
+  cmp ah, #0x00  ;; set video mode
+  jz cirrus_set_video_mode
+  cmp ah, #0x12  ;; cirrus extension
+  jz cirrus_extbios
+  cmp ah, #0x4F  ;; VESA extension
+  jz cirrus_vesa
+
+cirrus_unhandled:
+  pop bp
+  popf
+  jmp vgabios_int10_handler
+
+cirrus_return:
+#ifdef CIRRUS_DEBUG
+  call cirrus_debug_dump
+#endif
+  pop bp
+  popf
+  iret
+
+cirrus_set_video_mode:
+#ifdef CIRRUS_DEBUG
+  call cirrus_debug_dump
+#endif
+  push si
+  push ax
+  push bx
+  push ds
+#ifdef CIRRUS_VESA3_PMINFO
+ db 0x2e ;; cs:
+  mov si, [cirrus_vesa_sel0000_data]
+#else
+  xor si, si
+#endif
+  mov ds, si
+  xor bx, bx
+  mov [PM_BIOSMEM_VBE_MODE], bx
+  pop ds
+  pop bx
+  call cirrus_get_modeentry
+  jnc cirrus_set_video_mode_extended
+  mov al, #0xfe
+  call cirrus_get_modeentry_nomask
+  call cirrus_switch_mode
+  pop ax
+  pop si
+  jmp cirrus_unhandled
+
+cirrus_extbios:
+#ifdef CIRRUS_DEBUG
+  call cirrus_debug_dump
+#endif
+  cmp bl, #0x80
+  jb cirrus_unhandled
+  cmp bl, #0xAF
+  ja cirrus_unhandled
+  push bx
+  and bx, #0x7F
+  shl bx, 1
+ db 0x2e ;; cs:
+  mov bp, cirrus_extbios_handlers[bx]
+  pop bx
+  push #cirrus_return
+  push bp
+  ret
+
+cirrus_vesa:
+#ifdef CIRRUS_DEBUG
+  call cirrus_debug_dump
+#endif
+  cmp al, #0x10
+  ja cirrus_vesa_not_handled
+  push bx
+  xor bx, bx
+  mov bl, al
+  shl bx, 1
+ db 0x2e ;; cs:
+  mov bp, cirrus_vesa_handlers[bx]
+  pop bx
+  push #cirrus_return
+  push bp
+  ret
+
+cirrus_vesa_not_handled:
+  mov ax, #0x014F ;; not implemented
+  jmp cirrus_return
+
+#ifdef CIRRUS_DEBUG
+cirrus_debug_dump:
+  push es
+  push ds
+  pusha
+  push cs
+  pop ds
+  call _cirrus_debugmsg
+  popa
+  pop ds
+  pop es
+  ret
+#endif
+
+cirrus_set_video_mode_extended:
+  call cirrus_switch_mode
+  pop ax ;; mode
+  test al, #0x80
+  jnz cirrus_set_video_mode_extended_1
+  push ax
+  mov ax, #0xffff ; set to 0xff to keep win 2K happy
+  call cirrus_clear_vram
+  pop ax
+cirrus_set_video_mode_extended_1:
+  and al, #0x7f
+
+  push ds
+#ifdef CIRRUS_VESA3_PMINFO
+ db 0x2e ;; cs:
+  mov si, [cirrus_vesa_sel0000_data]
+#else
+  xor si, si
+#endif
+  mov ds, si
+  mov [PM_BIOSMEM_CURRENT_MODE], al
+  pop ds
+
+  mov al, #0x20
+
+  pop si
+  jmp cirrus_return
+
+cirrus_vesa_pmbios_init:
+  retf
+cirrus_vesa_pmbios_entry:
+  pushf
+  push bp
+  cmp ah, #0x4F
+  jnz cirrus_vesa_pmbios_unimplemented
+  cmp al, #0x0F
+  ja cirrus_vesa_pmbios_unimplemented
+  push bx
+  xor bx, bx
+  mov bl, al
+  shl bx, 1
+ db 0x2e ;; cs:
+  mov bp, cirrus_vesa_handlers[bx]
+  pop bx
+  push #cirrus_vesa_pmbios_return
+  push bp
+  ret
+cirrus_vesa_pmbios_unimplemented:
+  mov ax, #0x014F
+cirrus_vesa_pmbios_return:
+  pop bp
+  popf
+  retf
+
+; in si:mode table
+cirrus_switch_mode:
+  push ds
+  push bx
+  push dx
+  push cs
+  pop ds
+
+  mov bx, [si+10] ;; seq
+  mov dx, #0x3c4
+  mov ax, #0x1206
+  out dx, ax ;; Unlock cirrus special
+  call cirrus_switch_mode_setregs
+
+  mov bx, [si+12] ;; graph
+  mov dx, #0x3ce
+  call cirrus_switch_mode_setregs
+
+  mov bx, [si+14] ;; crtc
+  call cirrus_get_crtc
+  call cirrus_switch_mode_setregs
+
+  mov dx, #0x3c6
+  mov al, #0x00
+  out dx, al
+  in al, dx
+  in al, dx
+  in al, dx
+  in al, dx
+  mov al, [si+8]  ;; hidden dac
+  out dx, al
+  mov al, #0xff
+  out dx, al
+
+  mov al, #0x00
+  mov bl, [si+17]  ;; memory model
+  or  bl, bl
+  jz is_text_mode
+  mov al, #0x01
+  cmp bl, #0x03
+  jnz is_text_mode
+  or al, #0x40
+is_text_mode:
+  mov bl, #0x10
+  call biosfn_get_single_palette_reg
+  and bh, #0xfe
+  or bh, al
+  call biosfn_set_single_palette_reg
+
+  pop dx
+  pop bx
+  pop ds
+  ret
+
+cirrus_enable_16k_granularity:
+  push ax
+  push dx
+  mov dx, #0x3ce
+  mov al, #0x0b
+  out dx, al
+  inc dx
+  in al, dx
+  or al, #0x20 ;; enable 16k
+  out dx, al
+  pop dx
+  pop ax
+  ret
+
+cirrus_switch_mode_setregs:
+csms_1:
+  mov ax, [bx]
+  cmp ax, #0xffff
+  jz csms_2
+  out dx, ax
+  add bx, #0x2
+  jmp csms_1
+csms_2:
+  ret
+
+cirrus_extbios_80h:
+  push dx
+  call cirrus_get_crtc
+  mov al, #0x27
+  out dx, al
+  inc dx
+  in al, dx
+  mov bx, #_cirrus_id_table
+c80h_1:
+ db 0x2e ;; cs:
+  mov ah, [bx]
+  cmp ah, al
+  jz c80h_2
+  cmp ah, #0xff
+  jz c80h_2
+  inc bx
+  inc bx
+  jmp c80h_1
+c80h_2:
+ db 0x2e ;; cs:
+  mov al, 0x1[bx]
+  pop dx
+  mov ah, #0x00
+  xor bx, bx
+  ret
+
+cirrus_extbios_81h:
+  mov ax, #0x100 ;; XXX
+  ret
+cirrus_extbios_82h:
+  push dx
+  call cirrus_get_crtc
+  xor ax, ax
+  mov al, #0x27
+  out dx, al
+  inc dx
+  in al, dx
+  and al, #0x03
+  mov ah, #0xAF
+  pop dx
+  ret
+
+cirrus_extbios_85h:
+  push cx
+  push dx
+  mov dx, #0x3C4
+  mov al, #0x0f ;; get DRAM band width
+  out dx, al
+  inc dx
+  in al, dx
+  ;; al = 4 << bandwidth
+  mov cl, al
+  shr cl, #0x03
+  and cl, #0x03
+  cmp cl, #0x03
+  je c85h2
+  mov al, #0x04
+  shl al, cl
+  jmp c85h3
+c85h2:
+;; 4MB or 2MB
+  and al, #0x80
+  mov al, #0x20 ;; 2 MB
+  je c85h3
+  mov al, #0x40 ;; 4 MB
+c85h3:
+  pop dx
+  pop cx
+  ret
+
+cirrus_extbios_9Ah:
+  mov ax, #0x4060
+  mov cx, #0x1132
+  ret
+
+cirrus_extbios_A0h:
+  call cirrus_get_modeentry
+  mov ah, #0x01
+  sbb ah, #0x00
+  mov bx, cirrus_extbios_A0h_callback
+  mov si, #0xffff
+  mov di, bx
+  mov ds, bx
+  mov es, bx
+  ret
+
+cirrus_extbios_A0h_callback:
+  ;; fatal: not implemented yet
+  cli
+  hlt
+  retf
+
+cirrus_extbios_A1h:
+  mov bx, #0x0E00 ;; IBM 8512/8513, color
+  ret
+
+cirrus_extbios_A2h:
+  mov al, #0x07   ;; HSync 31.5 - 64.0 kHz
+  ret
+
+cirrus_extbios_AEh:
+  mov al, #0x01   ;; High Refresh 75Hz
+  ret
+
+cirrus_extbios_unimplemented:
+  ret
+
+cirrus_vesa_00h:
+  push ds
+  push si
+  mov bp, di
+  push es
+  pop ds
+  cld
+  mov ax, [di]
+  cmp ax, #0x4256 ;; VB
+  jnz cv00_1
+  mov ax, [di+2]
+  cmp ax, #0x3245 ;; E2
+  jnz cv00_1
+  ;; VBE2
+  lea di, 0x14[bp]
+  mov ax, #0x0100 ;; soft ver.
+  stosw
+  mov ax, # cirrus_vesa_vendorname
+  stosw
+  mov ax, cs
+  stosw
+  mov ax, # cirrus_vesa_productname
+  stosw
+  mov ax, cs
+  stosw
+  mov ax, # cirrus_vesa_productrevision
+  stosw
+  mov ax, cs
+  stosw
+cv00_1:
+  mov di, bp
+  mov ax, #0x4556 ;; VE
+  stosw
+  mov ax, #0x4153 ;; SA
+  stosw
+  mov ax, #0x0200 ;; v2.00
+  stosw
+  mov ax, # cirrus_vesa_oemname
+  stosw
+  mov ax, cs
+  stosw
+  xor ax, ax ;; caps
+  stosw
+  stosw
+  lea ax, 0x40[bp]
+  stosw
+  mov ax, es
+  stosw
+  call cirrus_extbios_85h ;; vram in 64k
+  mov ah, #0x00
+  stosw
+
+  push cs
+  pop ds
+  lea di, 0x40[bp]
+  mov si, #_cirrus_vesa_modelist
+cv00_2:
+  lodsw
+  stosw
+  add si, #2
+  cmp ax, #0xffff
+  jnz cv00_2
+
+  mov ax, #0x004F
+  mov di, bp
+  pop si
+  pop ds
+  ret
+
+cirrus_vesa_01h:
+  mov ax, cx
+  and ax, #0x3fff
+  call cirrus_vesamode_to_mode
+  cmp ax, #0xffff
+  jnz cirrus_vesa_01h_1
+  jmp cirrus_vesa_unimplemented
+cirrus_vesa_01h_1:
+  push ds
+  push si
+  push cx
+  push dx
+  push bx
+  mov bp, di
+  cld
+  push cs
+  pop ds
+  call cirrus_get_modeentry_nomask
+
+  push di
+  xor ax, ax
+  mov cx, #0x80
+  rep
+    stosw ;; clear buffer
+  pop di
+
+  mov ax, #0x003b ;; mode
+  stosw
+  mov ax, #0x0007 ;; attr
+  stosw
+  mov ax, #0x0010 ;; granularity =16K
+  stosw
+  mov ax, #0x0040 ;; size =64K
+  stosw
+  mov ax, #0xA000 ;; segment A
+  stosw
+  xor ax, ax ;; no segment B
+  stosw
+  mov ax, #cirrus_vesa_05h_farentry
+  stosw
+  mov ax, cs
+  stosw
+  call cirrus_get_line_offset_entry
+  stosw ;; bytes per scan line
+  mov ax, [si+2] ;; width
+  stosw
+  mov ax, [si+4] ;; height
+  stosw
+  mov ax, #0x08
+  stosb
+  mov ax, #0x10
+  stosb
+  mov al, #1 ;; count of planes
+  stosb
+  mov al, [si+6] ;; bpp
+  stosb
+  mov al, #0x1 ;; XXX number of banks
+  stosb
+  mov al, [si+17]
+  stosb ;; memory model
+  mov al, #0x0   ;; XXX size of bank in K
+  stosb
+  call cirrus_get_line_offset_entry
+  mov bx, [si+4]
+  mul bx ;; dx:ax=vramdisp
+  or ax, ax
+  jz cirrus_vesa_01h_3
+  inc dx
+cirrus_vesa_01h_3:
+  call cirrus_extbios_85h ;; al=vram in 64k
+  mov ah, #0x00
+  mov cx, dx
+  xor dx, dx
+  div cx
+  dec ax
+  stosb  ;; number of image pages = vramtotal/vramdisp-1
+  mov al, #0x00
+  stosb
+
+  ;; v1.2+ stuffs
+  push si
+  add si, #18
+  movsw
+  movsw
+  movsw
+  movsw
+  pop si
+
+  mov ah, [si+16]
+  mov al, #0x0
+  sub ah, #9
+  rcl al, #1 ; bit 0=palette flag
+  stosb ;; direct screen mode info
+
+  ;; v2.0+ stuffs
+  ;; 32-bit LFB address
+  xor ax, ax
+  stosw
+  mov ax, #0x1013 ;; vendor Cirrus
+  call _pci_get_lfb_addr
+  stosw
+  or ax, ax
+  jz cirrus_vesa_01h_4
+  push di
+  mov di, bp
+ db 0x26 ;; es:
+  mov ax, [di]
+  or ax, #0x0080 ;; mode bit 7:LFB
+  stosw
+  pop di
+cirrus_vesa_01h_4:
+
+  xor ax, ax
+  stosw ; reserved
+  stosw ; reserved
+  stosw ; reserved
+
+  mov ax, #0x004F
+  mov di, bp
+  pop bx
+  pop dx
+  pop cx
+  pop si
+  pop ds
+
+  test cx, #0x4000 ;; LFB flag
+  jz cirrus_vesa_01h_5
+  push cx
+ db 0x26 ;; es:
+  mov cx, [di]
+  cmp cx, #0x0080 ;; is LFB supported?
+  jnz cirrus_vesa_01h_6
+  mov ax, #0x014F ;; error - no LFB
+cirrus_vesa_01h_6:
+  pop cx
+cirrus_vesa_01h_5:
+  ret
+
+cirrus_vesa_02h:
+  ;; XXX support CRTC registers
+  test bx, #0x3e00
+  jnz cirrus_vesa_02h_2 ;; unknown flags
+  mov ax, bx
+  and ax, #0x1ff ;; bit 8-0 mode
+  cmp ax, #0x100 ;; legacy VGA mode
+  jb cirrus_vesa_02h_legacy
+  call cirrus_vesamode_to_mode
+  cmp ax, #0xffff
+  jnz cirrus_vesa_02h_1
+cirrus_vesa_02h_2:
+  jmp cirrus_vesa_unimplemented
+cirrus_vesa_02h_legacy:
+#ifdef CIRRUS_VESA3_PMINFO
+ db 0x2e ;; cs:
+  cmp byte ptr [cirrus_vesa_is_protected_mode], #0
+  jnz cirrus_vesa_02h_2
+#endif // CIRRUS_VESA3_PMINFO
+  int #0x10
+  mov ax, #0x004F
+  ret
+cirrus_vesa_02h_1:
+  push si
+  push ax
+  call cirrus_get_modeentry_nomask
+  call cirrus_switch_mode
+  test bx, #0x4000 ;; LFB
+  jnz cirrus_vesa_02h_3
+  call cirrus_enable_16k_granularity
+cirrus_vesa_02h_3:
+  test bx, #0x8000 ;; no clear
+  jnz cirrus_vesa_02h_4
+  push ax
+  xor ax,ax
+  call cirrus_clear_vram
+  pop ax
+cirrus_vesa_02h_4:
+  pop ax
+  push ds
+#ifdef CIRRUS_VESA3_PMINFO
+ db 0x2e ;; cs:
+  mov si, [cirrus_vesa_sel0000_data]
+#else
+  xor si, si
+#endif
+  mov ds, si
+  mov [PM_BIOSMEM_CURRENT_MODE], al
+  mov [PM_BIOSMEM_VBE_MODE], bx
+  pop ds
+  pop si
+  mov ax, #0x004F
+  ret
+
+cirrus_vesa_03h:
+  push ds
+#ifdef CIRRUS_VESA3_PMINFO
+ db 0x2e ;; cs:
+  mov ax, [cirrus_vesa_sel0000_data]
+#else
+  xor ax, ax
+#endif
+  mov  ds, ax
+  mov  bx, # PM_BIOSMEM_VBE_MODE
+  mov  ax, [bx]
+  mov  bx, ax
+  test bx, bx
+  jnz   cirrus_vesa_03h_1
+  mov  bx, # PM_BIOSMEM_CURRENT_MODE
+  mov  al, [bx]
+  mov  bl, al
+  xor  bh, bh
+cirrus_vesa_03h_1:
+  mov  ax, #0x004f
+  pop  ds
+  ret
+
+cirrus_vesa_05h_farentry:
+  call cirrus_vesa_05h
+  retf
+
+cirrus_vesa_05h:
+  cmp bl, #0x01
+  ja cirrus_vesa_05h_1
+  cmp bh, #0x00
+  jz cirrus_vesa_05h_setmempage
+  cmp bh, #0x01
+  jz cirrus_vesa_05h_getmempage
+cirrus_vesa_05h_1:
+  jmp cirrus_vesa_unimplemented
+cirrus_vesa_05h_setmempage:
+  or dh, dh ; address must be < 0x100
+  jnz cirrus_vesa_05h_1
+  push dx
+  mov al, bl ;; bl=bank number
+  add al, #0x09
+  mov ah, dl ;; dx=window address in granularity
+  mov dx, #0x3ce
+  out dx, ax
+  pop dx
+  mov ax, #0x004F
+  ret
+cirrus_vesa_05h_getmempage:
+  mov al, bl ;; bl=bank number
+  add al, #0x09
+  mov dx, #0x3ce
+  out dx, al
+  inc dx
+  in al, dx
+  xor dx, dx
+  mov dl, al ;; dx=window address in granularity
+  mov ax, #0x004F
+  ret
+
+cirrus_vesa_06h:
+  mov  ax, cx
+  cmp  bl, #0x01
+  je   cirrus_vesa_06h_3
+  cmp  bl, #0x02
+  je   cirrus_vesa_06h_2
+  jb   cirrus_vesa_06h_1
+  mov  ax, #0x0100
+  ret
+cirrus_vesa_06h_1:
+  call cirrus_get_bpp_bytes
+  mov  bl, al
+  xor  bh, bh
+  mov  ax, cx
+  mul  bx
+cirrus_vesa_06h_2:
+  call cirrus_set_line_offset
+cirrus_vesa_06h_3:
+  call cirrus_get_bpp_bytes
+  mov  bl, al
+  xor  bh, bh
+  xor  dx, dx
+  call cirrus_get_line_offset
+  push ax
+  div  bx
+  mov  cx, ax
+  pop  bx
+  call cirrus_extbios_85h ;; al=vram in 64k
+  xor  dx, dx
+  mov  dl, al
+  xor  ax, ax
+  div  bx
+  mov  dx, ax
+  mov  ax, #0x004f
+  ret
+
+cirrus_vesa_07h:
+  cmp  bl, #0x80
+  je   cirrus_vesa_07h_1
+  cmp  bl, #0x01
+  je   cirrus_vesa_07h_2
+  jb   cirrus_vesa_07h_1
+  mov  ax, #0x0100
+  ret
+cirrus_vesa_07h_1:
+  push dx
+  call cirrus_get_bpp_bytes
+  mov  bl, al
+  xor  bh, bh
+  mov  ax, cx
+  mul  bx
+  pop  bx
+  push ax
+  call cirrus_get_line_offset
+  mul  bx
+  pop  bx
+  add  ax, bx
+  jnc  cirrus_vesa_07h_3
+  inc  dx
+cirrus_vesa_07h_3:
+  push dx
+  and  dx, #0x0003
+  mov  bx, #0x04
+  div  bx
+  pop  dx
+  shr  dx, #2
+  call cirrus_set_start_addr
+  mov  ax, #0x004f
+  ret
+cirrus_vesa_07h_2:
+  call cirrus_get_start_addr
+  shl  dx, #2
+  push dx
+  mov  bx, #0x04
+  mul  bx
+  pop  bx
+  or   dx, bx
+  push ax
+  call cirrus_get_line_offset
+  mov  bx, ax
+  pop  ax
+  div  bx
+  push ax
+  push dx
+  call cirrus_get_bpp_bytes
+  mov  bl, al
+  xor  bh, bh
+  pop  ax
+  xor  dx, dx
+  div  bx
+  mov  cx, ax
+  pop  dx
+  mov  ax, #0x004f
+  ret
+
+cirrus_vesa_10h:
+  cmp bl, #0x00
+  jne cirrus_vesa_10h_01
+  mov bx, #0x0f30
+  mov ax, #0x004f
+  ret
+cirrus_vesa_10h_01:
+  cmp bl, #0x01
+  jne cirrus_vesa_10h_02
+  push dx
+  push ds
+  mov dx, #0x40
+  mov ds, dx
+  mov [0xb9], bh
+  pop ds
+  pop dx
+  mov ax, #0x004f
+  ret
+cirrus_vesa_10h_02:
+  cmp bl, #0x02
+  jne cirrus_vesa_unimplemented
+  push dx
+  push ds
+  mov dx, #0x40
+  mov ds, dx
+  mov bh, [0xb9]
+  pop ds
+  pop dx
+  mov ax, #0x004f
+  ret
+
+cirrus_vesa_unimplemented:
+  mov ax, #0x014F ;; not implemented
+  ret
+
+
+;; in ax:vesamode, out ax:cirrusmode
+cirrus_vesamode_to_mode:
+  push ds
+  push cx
+  push si
+  push cs
+  pop ds
+  mov cx, #0xffff
+  mov si, #_cirrus_vesa_modelist
+cvtm_1:
+  cmp [si],ax
+  jz cvtm_2
+  cmp [si],cx
+  jz cvtm_2
+  add si, #4
+  jmp cvtm_1
+cvtm_2:
+  mov ax,[si+2]
+  pop si
+  pop cx
+  pop ds
+  ret
+
+  ; cirrus_get_crtc
+  ;; NOTE - may be called in protected mode
+cirrus_get_crtc:
+  push ds
+  push ax
+  mov  dx, #0x3cc
+  in   al, dx
+  and  al, #0x01
+  shl  al, #5
+  mov  dx, #0x3b4
+  add  dl, al
+  pop  ax
+  pop  ds
+  ret
+
+;; in - al:mode, out - cflag:result, si:table, ax:destroyed
+cirrus_get_modeentry:
+  and al, #0x7f
+cirrus_get_modeentry_nomask:
+  mov si, #_cirrus_modes
+cgm_1:
+ db 0x2e ;; cs:
+  mov ah, [si]
+  cmp al, ah
+  jz cgm_2
+  cmp ah, #0xff
+  jz cgm_4
+  add si, # CIRRUS_MODE_SIZE
+  jmp cgm_1
+cgm_4:
+  xor si, si
+  stc ;; video mode is not supported
+  jmp cgm_3
+cgm_2:
+  clc ;; video mode is supported
+cgm_3:
+  ret
+
+;; out - al:bytes per pixel
+cirrus_get_bpp_bytes:
+  push dx
+  mov  dx, #0x03c4
+  mov  al, #0x07
+  out  dx, al
+  inc  dx
+  in   al, dx
+  and  al, #0x0e
+  cmp  al, #0x06
+  jne  cirrus_get_bpp_bytes_1
+  and  al, #0x02
+cirrus_get_bpp_bytes_1:
+  shr  al, #1
+  cmp  al, #0x04
+  je  cirrus_get_bpp_bytes_2
+  inc  al
+cirrus_get_bpp_bytes_2:
+  pop  dx
+  ret
+
+;; in - ax: new line offset
+cirrus_set_line_offset:
+  shr  ax, #3
+  push ax
+  call cirrus_get_crtc
+  mov  al, #0x13
+  out  dx, al
+  inc  dx
+  pop  ax
+  out  dx, al
+  dec  dx
+  mov  al, #0x1b
+  out  dx, al
+  inc  dx
+  shl  ah, #4
+  in   al, dx
+  and  al, #ef
+  or   al, ah
+  out  dx, al
+  ret
+
+;; out - ax: active line offset
+cirrus_get_line_offset:
+  push dx
+  push bx
+  call cirrus_get_crtc
+  mov  al, #0x13
+  out  dx, al
+  inc  dx
+  in   al, dx
+  mov  bl, al
+  dec  dx
+  mov  al, #0x1b
+  out  dx, al
+  inc  dx
+  in   al, dx
+  mov  ah, al
+  shr  ah, #4
+  and  ah, #0x01
+  mov  al, bl
+  shl  ax, #3
+  pop  bx
+  pop  dx
+  ret
+
+;; in - si: table
+;; out - ax: line offset for mode
+cirrus_get_line_offset_entry:
+  push bx
+  mov  bx, [si+14] ;; crtc table
+  push bx
+offset_loop1:
+  mov  ax, [bx]
+  cmp  al, #0x13
+  je   offset_found1
+  inc  bx
+  inc  bx
+  jnz  offset_loop1
+offset_found1:
+  xor  al, al
+  shr  ax, #5
+  pop  bx
+  push ax
+offset_loop2:
+  mov  ax, [bx]
+  cmp  al, #0x1b
+  je offset_found2
+  inc  bx
+  inc  bx
+  jnz offset_loop2
+offset_found2:
+  pop  bx
+  and  ax, #0x1000
+  shr  ax, #1
+  or   ax, bx
+  pop  bx
+  ret
+
+;; in - new address in DX:AX
+cirrus_set_start_addr:
+  push bx
+  push dx
+  push ax
+  call cirrus_get_crtc
+  mov  al, #0x0d
+  out  dx, al
+  inc  dx
+  pop  ax
+  out  dx, al
+  dec  dx
+  mov  al, #0x0c
+  out  dx, al
+  inc  dx
+  mov  al, ah
+  out  dx, al
+  dec  dx
+  mov  al, #0x1d
+  out  dx, al
+  inc  dx
+  in   al, dx
+  and  al, #0x7f
+  pop  bx
+  mov  ah, bl
+  shl  bl, #4
+  and  bl, #0x80
+  or   al, bl
+  out  dx, al
+  dec  dx
+  mov  bl, ah
+  and  ah, #0x01
+  shl  bl, #1
+  and  bl, #0x0c
+  or   ah, bl
+  mov  al, #0x1b
+  out  dx, al
+  inc  dx
+  in   al, dx
+  and  al, #0xf2
+  or   al, ah
+  out  dx, al
+  pop  bx
+  ret
+
+;; out - current address in DX:AX
+cirrus_get_start_addr:
+  push bx
+  call cirrus_get_crtc
+  mov  al, #0x0c
+  out  dx, al
+  inc  dx
+  in   al, dx
+  mov  ah, al
+  dec  dx
+  mov  al, #0x0d
+  out  dx, al
+  inc  dx
+  in   al, dx
+  push ax
+  dec  dx
+  mov  al, #0x1b
+  out  dx, al
+  inc  dx
+  in   al, dx
+  dec  dx
+  mov  bl, al
+  and  al, #0x01
+  and  bl, #0x0c
+  shr  bl, #1
+  or   bl, al
+  mov  al, #0x1d
+  out  dx, al
+  inc  dx
+  in   al, dx
+  and  al, #0x80
+  shr  al, #4
+  or   bl, al
+  mov  dl, bl
+  xor  dh, dh
+  pop  ax
+  pop  bx
+  ret
+
+cirrus_clear_vram:
+  pusha
+  push es
+  mov si, ax
+
+  call cirrus_enable_16k_granularity
+  call cirrus_extbios_85h
+  shl al, #2
+  mov bl, al
+  xor ah,ah
+cirrus_clear_vram_1:
+  mov al, #0x09
+  mov dx, #0x3ce
+  out dx, ax
+  push ax
+  mov cx, #0xa000
+  mov es, cx
+  xor di, di
+  mov ax, si
+  mov cx, #8192
+  cld
+  rep 
+      stosw
+  pop ax
+  inc ah
+  cmp ah, bl
+  jne cirrus_clear_vram_1
+
+  xor ah,ah
+  mov dx, #0x3ce
+  out dx, ax
+
+  pop es
+  popa
+  ret
+
+cirrus_extbios_handlers:
+  ;; 80h
+  dw cirrus_extbios_80h
+  dw cirrus_extbios_81h
+  dw cirrus_extbios_82h
+  dw cirrus_extbios_unimplemented
+  ;; 84h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_85h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; 88h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; 8Ch
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; 90h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; 94h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; 98h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_9Ah
+  dw cirrus_extbios_unimplemented
+  ;; 9Ch
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; A0h
+  dw cirrus_extbios_A0h
+  dw cirrus_extbios_A1h
+  dw cirrus_extbios_A2h
+  dw cirrus_extbios_unimplemented
+  ;; A4h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; A8h
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  ;; ACh
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_unimplemented
+  dw cirrus_extbios_AEh
+  dw cirrus_extbios_unimplemented
+
+cirrus_vesa_handlers:
+  ;; 00h
+  dw cirrus_vesa_00h
+  dw cirrus_vesa_01h
+  dw cirrus_vesa_02h
+  dw cirrus_vesa_03h
+  ;; 04h
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_05h
+  dw cirrus_vesa_06h
+  dw cirrus_vesa_07h
+  ;; 08h
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_unimplemented
+  ;; 0Ch
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_unimplemented
+  dw cirrus_vesa_unimplemented
+  ;; 10h
+  dw cirrus_vesa_10h
+
+
+ASM_END
+
+#ifdef CIRRUS_VESA3_PMINFO
+ASM_START
+cirrus_vesa_pminfo:
+  /* + 0 */
+  .byte 0x50,0x4d,0x49,0x44 ;; signature[4]
+  /* + 4 */
+  dw cirrus_vesa_pmbios_entry ;; entry_bios
+  dw cirrus_vesa_pmbios_init  ;; entry_init
+  /* + 8 */
+cirrus_vesa_sel0000_data:
+  dw 0x0000 ;; sel_00000
+cirrus_vesa_selA000_data:
+  dw 0xA000 ;; sel_A0000
+  /* +12 */
+cirrus_vesa_selB000_data:
+  dw 0xB000 ;; sel_B0000
+cirrus_vesa_selB800_data:
+  dw 0xB800 ;; sel_B8000
+  /* +16 */
+cirrus_vesa_selC000_data:
+  dw 0xC000 ;; sel_C0000
+cirrus_vesa_is_protected_mode:
+  ;; protected mode flag and checksum
+  dw (~((0xf2 + (cirrus_vesa_pmbios_entry >> 8) + (cirrus_vesa_pmbios_entry) \
+     + (cirrus_vesa_pmbios_init >> 8) + (cirrus_vesa_pmbios_init)) & 0xff) << 8) + 0x01
+ASM_END
+#endif // CIRRUS_VESA3_PMINFO
+
+
+#ifdef CIRRUS_DEBUG
+static void cirrus_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
+  Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
+{
+ if((GET_AH()!=0x0E)&&(GET_AH()!=0x02)&&(GET_AH()!=0x09)&&(AX!=0x4F05))
+  printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
+}
+#endif