/**
 ** VESAINFO.H ---- routines to retrieve info from the VESA BIOS
 **
 ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
 ** Copyright (C) 1992 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
 ** Copyright (C) 1993 Grzegorz Mazur, gbm@ii.pw.edu.pl
 ** Modified by Jih-Shin Ho to support VESA 2.0
 **
 ** This file is distributed under the terms listed in the document
 ** "copying.dj", available from DJ Delorie at the address above.
 ** A copy of "copying.dj" should accompany this file; if not, a copy
 ** should be available from where this file was obtained.  This file
 ** may not be distributed without a verbatim copy of "copying.dj".
 **
 ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
 ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 **/

/*
 * VESA BIOS extended function number and return code
 */
#define VESA_FUNC	0x4f00
#define VESA_SUCCESS	0x004f

#define VESA_VERSION(major,minor)	((((major) & 0xff) << 8) | ((minor) & 0xff))
#define VESA_VERSION_MAJOR(vers)	(((vers) >> 8) & 0xff)
#define VESA_VERSION_MINOR(vers)	((vers) & 0xff)

/*
 * VESA BIOS sub-function numbers
 */
#define VESA_VGA_INFO	0		/* get VGA adapter info */
#define VESA_MODE_INFO  1		/* get SVGA mode info */
#define VESA_SET_MODE	2		/* set video mode */
#define VESA_GET_MODE	3		/* get current video mode */
#define VESA_VGA_STATE  4		/* save/restore VGA state */
#define VESA_PAGE_CTL	5		/* memory control */
/* VESA 1.1 +++ */
#define VESA_SCAN_LNLEN 6		/* set/get scan line length */
#define VESA_DISP_START 7		/* set/get display start address */
/* VESA 1.2 +++ */
#define VESA_PAL_CNTRL  8		/* DAC palette control */

/*
 * The VGA info structure (without padding)
 */
typedef struct {
    char	    VESASignature[4];	/* should be "VESA" */
    short	    VESAVersion;	/* VESA version number */
    char  far	   *OEMStringPtr;	/* Pointer to OEM string */
    long	    Capabilities;	/* capabilities of the video env */
    short far	   *VideoModePtr;	/* ptr to supported Super VGA modes */
    /*
     * memory size in 64K blocks in VESA 1.2 and later
     */
    short	    MemorySize;		/* # of 64K pages */
} VgaInfoBlock;

/*
 * The mode information structure (without padding)
 */
typedef struct {
    short	    ModeAttributes;	/* mode attributes */
    char	    WinAAttributes;	/* Window A attributes */
    char	    WinBAttributes;	/* Window B attributes */
    short	    WinGranularity;	/* window granularity */
    short	    WinSize;		/* window size */
    unsigned short  WinASegment;	/* Window A start segment */
    unsigned short  WinBSegment;	/* Window B start segment */
    void     far   (*WinFuncPtr)();	/* pointer to window function */
    short	    BytesPerScanLine;	/* bytes per scan line */
    /*
     * extended information
     * optional information
     */
    short	    XResolution;	/* horizontal resolution */
    short	    YResolution;	/* vertical resolution */
    char	    XCharSize;		/* character cell width */
    char	    YCharSize;		/* character cell height */
    char	    NumberOfPlanes;	/* number of memory planes */
    char	    BitsPerPixel;	/* bits per pixel */
    char	    NumberOfBanks;	/* number of banks */
    char	    MemoryModel;	/* memory model type */
    char	    BankSize;		/* bank size in K */
    char	    NumImagePages;	/* number of image pages */
    char	    reserved[1];
    /*
     * VESA 1.2 and later
     */
    char	    RedMaskSize;	/* number of bits in red mask */
    char	    RedMaskPos;		/* starting bit for red mask */
    char	    GreenMaskSize;
    char	    GreenMaskPos;
    char	    BlueMaskSize;
    char	    BlueMaskPos;
    char	    ReservedMaskSize;	/* reserved bits in pixel */
    char	    ReservedMaskPos;
    char	    DirectScreenMode;
    /*
     * VESA 2.0 and later
     */
    unsigned long   PhysBasePtr;
    unsigned long   OffScreenMemOffset;
    unsigned short  OffScreenMemSize;
} ModeInfoBlock;

/*
 * MODE attribute bits
 */
#define MODE_SUPPORTED  1		/* Mode supported in hardware */
#define MODE_EXTINFO	2		/* Extended information available */
#define MODE_SUPBIOS	4		/* Text output supported by BIOS */
#define MODE_ISCOLOR	8		/* Monochrome/color mode */
#define MODE_ISGRAPHICS 16		/* Mode type (0: text, 1:graphics) */
#define MODE_NO_WINDOW  0x40            /* No windowed memory mode */
#define MODE_LINEAR_FRAME 0x80         /* Support Linear frame buffer */

/*
 * Window attribute bits
 */
#define WIN_SUPPORTED	1		/* Window supported */
#define WIN_READABLE	2		/* Window readable */
#define WIN_WRITABLE	4		/* Window writable */

/*
 * MemoryModel values
 */
#define MODEL_TEXT	0		/* 00h = Text mode */
#define MODEL_CGA	1		/* 01h = CGA graphics */
#define MODEL_HERC	2		/* 02h = Hercules graphics */
#define MODEL_4PLANE	3		/* 03h = 4-plane planar */
#define MODEL_PACKED	4		/* 04h = Packed pixel */
#define MODEL_256_NC	5		/* 05h = Non-chain 4, 256 color */
#define MODEL_DIRECT	6		/* 06h = direct color mode */
/* 07h-0Fh = Reserved, to be defined by VESA */
/* 10h-FFh = To be defined by OEM	     */

union {
    VgaInfoBlock  _vgainfo;
    ModeInfoBlock _modeinfo;
    char	  _safety_buffer[256];
} VESAinfoBlock;
int VESAversion = 0;

VgaInfoBlock *VESAgetInfo(void)
{
	_ES = FP_SEG(&VESAinfoBlock._vgainfo);
	_DI = FP_OFF(&VESAinfoBlock._vgainfo);
	_AX = VESA_FUNC + VESA_VGA_INFO;
	geninterrupt(0x10);
	if((_AX == VESA_SUCCESS) &&
	   (VESAinfoBlock._vgainfo.VESASignature[0] == 'V') &&
	   (VESAinfoBlock._vgainfo.VESASignature[1] == 'E') &&
	   (VESAinfoBlock._vgainfo.VESASignature[2] == 'S') &&
	   (VESAinfoBlock._vgainfo.VESASignature[3] == 'A')) {
	    VESAversion = VESAinfoBlock._vgainfo.VESAVersion;
	    return(&VESAinfoBlock._vgainfo);
	}
	return(0);
}

ModeInfoBlock *VESAgetModeInfo(int mode)
{
	_ES = FP_SEG(&VESAinfoBlock._modeinfo);
	_DI = FP_OFF(&VESAinfoBlock._modeinfo);
	_CX = mode;
	_AX = VESA_FUNC + VESA_MODE_INFO;
	geninterrupt(0x10);
	if(_AX != VESA_SUCCESS) return(0);
	if((VESAinfoBlock._modeinfo.ModeAttributes & MODE_SUPPORTED) == 0) return(0);
	return(&VESAinfoBlock._modeinfo);
}

