mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
As recommended in http://www.gnu.org/licenses/gpl-howto.en.html. This is the result of: $ git grep -El Mass\|Temple\|Franklin | xargs ./fsf.pl Where fsf.pl is: #!/usr/bin/perl -w -pi.bak -0777 my $repl = 'If not, see <http://www.gnu.org/licenses/>.'; my $br = qr/(?:\s*\n\s*(?:[\*\#]|\/\/|\.\\" )?\s*|\s+)/; my $inwt = qr/[Ii]f${br}not,${br}write${br}(?:to${br})?the${br}Free${br}Software${br}Foundation,(?:${br}Inc\.,)?/; my $mass = qr/675${br}Mass${br}Ave,?${br}Cambridge,?${br}MA${br}02139,?${br}USA,?\.?/; my $franklin = qr/51${br}Franklin${br}St(?:reet)?(?:,${br}| - )Fifth${br}Floor,?${br}Boston,?${br}MA,?${br}02110-1301,?${br}USA,?\.?/; my $temple = qr/59${br}Temple${br}Place(?:,${br}| - )Suite${br}330,?${br}Boston,?${br}MA,?${br}021110?-1307,?${br}USA,?\.?/; s|$inwt$br$mass|$repl|m; s|$inwt$br$franklin|$repl|m; s|$inwt$br$temple|$repl|m; The only remaining mentions of these addresses are in COPYING files which I haven't touched. Some of the changed files are imports from elsewhere, however filtering them out is tricky, I think it is tolerable to have these files be modified here and then perhaps reverted on the next sync, since it's only 1-2 lines and obvious what is going on. Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
1717 lines
32 KiB
C
1717 lines
32 KiB
C
//
|
|
// 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, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
//#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
|
|
#define PM_BIOSMEM_VBE_POWER 0x4BC
|
|
|
|
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, #0x103 ;; 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
|
|
call cirrus_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: ;; Power management functions
|
|
;; Set up DS to read stored power info from RAM
|
|
push ds
|
|
#ifdef CIRRUS_VESA3_PMINFO
|
|
db 0x2e ;; cs:
|
|
mov ax, [cirrus_vesa_sel0000_data]
|
|
#else
|
|
xor ax, ax
|
|
#endif
|
|
mov ds, ax
|
|
;; Now choose the right function
|
|
cmp bl, #0x00
|
|
ja cirrus_vesa_10h_01
|
|
;;
|
|
;; Function 00h: Get capabilities
|
|
;;
|
|
mov bx, #0x0720 ;; 07: standby/suspend/off, 20: VBE/PM 2.0
|
|
mov ax, #0x004f
|
|
jmp cirrus_vesa_10h_done
|
|
cirrus_vesa_10h_01:
|
|
cmp bl, #0x01
|
|
ja cirrus_vesa_10h_02
|
|
;;
|
|
;; Function 01h: Set power state
|
|
;;
|
|
mov ax, bx
|
|
mov bx, # PM_BIOSMEM_VBE_POWER
|
|
mov [bx], ah
|
|
mov ax, #0x004f
|
|
jmp cirrus_vesa_10h_done
|
|
cirrus_vesa_10h_02:
|
|
cmp bl, #0x02
|
|
ja cirrus_vesa_10h_unimplemented
|
|
;;
|
|
;; Function 02h: Get power state
|
|
;;
|
|
mov bx, # PM_BIOSMEM_VBE_POWER
|
|
mov bh, [bx]
|
|
mov ax, #0x004f
|
|
jmp cirrus_vesa_10h_done
|
|
cirrus_vesa_10h_unimplemented:
|
|
mov ax, #0x014F ;; not implemented
|
|
cirrus_vesa_10h_done:
|
|
pop ds
|
|
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
|
|
|
|
; get LFB address
|
|
; out - ax:LFB address (high 16 bit)
|
|
;; NOTE - may be called in protected mode
|
|
cirrus_get_lfb_addr:
|
|
push cx
|
|
push dx
|
|
push eax
|
|
xor cx, cx
|
|
mov dl, #0x00
|
|
call cirrus_pci_read
|
|
cmp ax, #0xffff
|
|
jz cirrus_get_lfb_addr_5
|
|
cirrus_get_lfb_addr_3:
|
|
mov dl, #0x00
|
|
call cirrus_pci_read
|
|
cmp ax, #0x1013 ;; cirrus
|
|
jz cirrus_get_lfb_addr_4
|
|
add cx, #0x8
|
|
cmp cx, #0x200 ;; search bus #0 and #1
|
|
jb cirrus_get_lfb_addr_3
|
|
cirrus_get_lfb_addr_5:
|
|
xor dx, dx ;; no LFB
|
|
jmp cirrus_get_lfb_addr_6
|
|
cirrus_get_lfb_addr_4:
|
|
mov dl, #0x10 ;; I/O space #0
|
|
call cirrus_pci_read
|
|
test ax, #0xfff1
|
|
jnz cirrus_get_lfb_addr_5
|
|
shr eax, #16
|
|
mov dx, ax ;; LFB address
|
|
cirrus_get_lfb_addr_6:
|
|
pop eax
|
|
mov ax, dx
|
|
pop dx
|
|
pop cx
|
|
ret
|
|
|
|
cirrus_pci_read:
|
|
mov eax, #0x00800000
|
|
mov ax, cx
|
|
shl eax, #8
|
|
mov al, dl
|
|
mov dx, #0xcf8
|
|
out dx, eax
|
|
add dl, #4
|
|
in eax, dx
|
|
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
|
|
|
|
;; Windows Vista appears to be emulating this sequence as part of changing
|
|
;; screen resolution, but it generates 4096 writes per iteration.
|
|
;; Instead, use a magic register sequence to write the whole bank.
|
|
;;mov cx, #0xa000
|
|
;;mov es, cx
|
|
;;xor di, di
|
|
;;mov ax, si
|
|
;;mov cx, #8192
|
|
;;cld
|
|
;;rep
|
|
;; stosw
|
|
mov ax, si
|
|
shl ax, #8
|
|
mov al, #0xfe
|
|
out dx, ax ;; Low byte of value to be written to the bank
|
|
mov ax, si
|
|
mov al, #0xff
|
|
out dx, ax ;; High byte and trigger the write
|
|
|
|
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
|