Subversion Repositories shark

Rev

Rev 635 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed


/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#include <ll/i386/hw-data.h>
#include <ll/i386/mem.h>
#include <ll/i386/cons.h>
#include <ll/sys/ll/ll-func.h>

#include "drivers/gd.h"

#include "drivers/s3.h"
#include "drivers/trident.h"
#include "drivers/vesa.h"
#include "drivers/chips.h"

BYTE bus, dev;
ModeInfoBlock vbemi;
BYTE actbank;
BYTE type;

DWORD flb=0;
int linear;
BYTE trylinear;
/*BYTE gmode = FALSE;*/

#define NMODES 13
static struct gmode allmodes[NMODES] = {
        {640, 400, 640, 8, 0x100},
        {640, 480, 640, 8, 0x101},
        {800, 600, 800, 8, 0x103},
        {1024, 768, 1024, 8, 0x105},
        {640, 480, 1280, 15, 0x110},
        {800, 600, 1600, 15, 0x113},
        {1024, 768, 2048, 15, 0x116},
        {640, 480, 1280, 16, 0x111},
        {800, 600, 1600, 16, 0x114},
        {1024, 768, 2048, 16, 0x117},
        {640, 480, 1920, 24, 0x112},
        {800, 600, 2400, 24, 0x115},
        {1024, 768, 3072, 24, 0x118}
};
static struct gmode actualmode;


static int myceil(float f)
{
                int i = (int) f;
                float f1 = f - i;

                if (f1 != 0) {
                                return i + 1;
                } else {
                                return i;
                }
}

/************************************************************************/
/*          GD Common Interface             */
/************************************************************************/
int gd_init(WORD flags)
{
        memset(&actualmode, 0, sizeof(struct gmode));
        type = UNKNOWN;

        /* VESA driver needs the V86 Mode... */
        vm86_init();

        /* First, check VESA... */
        if (vbe_getinfo() == 1) {
                type = VESA;
                if (flags & NOLINEAR) {
                        trylinear = 0;
                } else {
                        trylinear = 1;
                }
                return 1;
        }

        /* Then, the other graph cards... Override VESA!!! */
        if (trident_test() == 1) {
                type = TRIDENT;
                trylinear = 0;
        }
       
        if (s3_test() == 1) {
                type = S3;
                if (flags & NOLINEAR) {
                        trylinear = 0;
                } else {
                        trylinear = 1;
                }
                return 1;
        }

        if (type == UNKNOWN) {
                return -1;
        }

        return -2;
}

void gd_showmodeinfo(void)
{
        cprintf("Mode number %x\n", actualmode.modenum);
        cprintf("MaxX: %u\n", actualmode.xdim);
        cprintf("MaxY: %u\n", actualmode.ydim);
        cprintf("BPR:  %u\n", actualmode.bpr);
}

void gd_showinfo(void)
{
        DWORD addr;

        addr = gd_getflb();

        if (addr != 0) {
                cprintf ("\t gd: Frame Linear Buffer @ %lx (%luM)\n",
                        addr, (addr / 0x1000000));
        }
       
        if (type == VESA) {
                cprintf("Vesa SVGA card\n");
                vbe_showinfo();
        }
        if (type == TRIDENT) {
                cprintf("Trident graphic card\n");
                trident_showinfo();
        }

        if (type == S3) {
                cprintf("S3 graphic card\n");
                s3_showinfo();
        }
}

int gd_setmode(WORD mode)
{
        WORD app;
        int i;
#ifndef VM86
        BYTE p1, p2;
#endif

        if (mode == 0) {
                X_REGS16 inregs, outregs;
                X_SREGS16 sregs;

                if (actualmode.modenum != 0) {
                        inregs.x.ax = 0x03;
#ifndef VM86
                        p1 = inp(0x21);
                        p2 = inp(0xA1);
                        outp(0x21,0xFF);
                        outp(0xA1,0xFF);
                        X_callBIOS(0x10, &inregs, &outregs, &sregs);
                        outp(0x21,p1);
                        outp(0xA1,p2);
#else
                        vm86_callBIOS(0x10, &inregs, &outregs, &sregs);
#endif
                }
                return 1;
        }

        for (i = 0; i < NMODES; i++) {
                if ((mode == allmodes[i].modenum)) {
                        memcpy(&actualmode, &(allmodes[i]), sizeof(struct gmode));
                }
        }
         
        if (type == VESA) {

                if (vbe_getmodeinfo(&vbemi, mode) < 0) {
                        return -1;
                }

                app = mode;
                if (trylinear) {
                        /*  try linear...   */
                        mode = mode | 0x4000;
                        linear = TRUE;
                        if (vbe_setmode(mode) == 1) {
                                return linear;
                        }
                }
                actbank = 0;
                Load_Write_Bank_256(0);
                linear = FALSE;
                mode = app;
                if (vbe_setmode(mode) < 0) {
                        return -1;
                }
                return linear;
        }

        if (type == S3) {
/* Still use VESA to open graph... */
                if (vbe_getmodeinfo(&vbemi, mode) < 0) {
                        return -1;
                }
                if (vbe_setmode(mode) < 0) {
                        return -1;
                }
                if ((flb != 0) && trylinear) {
                        linear = TRUE;
                        s3_linear(flb);
                        return TRUE;
                }
                linear = FALSE;
                actbank = 0;
                Load_Write_Bank_256(0);
                return FALSE;
        }

        if (type == TRIDENT) {
/* Still use VESA to open graph... */
        if (vbe_getmodeinfo(&vbemi, mode) < 0) {
                return -1;
        }
        if (vbe_setmode(mode) < 0) {
                return -1;
        }

        actbank = 0;
        Load_Write_Bank_256(0);
        return FALSE;
        }

        return -2;
}

DWORD gd_getflb(void)
{
        if (type == VESA) {
        return vbe_getflb();
        }
        if (type == S3) {
        return flb;
        }
        return 0;
}

DWORD gd_getmem(void)
{
        if (type == VESA) {
        return vbe_getmem();
        }
        if (type == S3) {
        return s3_getmem();
        }
        if (type == TRIDENT) {
        return trident_getmem();
        }

        return 0;
}

WORD gd_getbpr(void)
{
        if (actualmode.bpr) return actualmode.bpr;
        return -2;
}

int gd_getmodeinfo(grx_vga_modeinfo *m)
{
        if (actualmode.modenum == 0) {
        return -1;
        }

        m->width = actualmode.xdim;
        m->height = actualmode.ydim;
        m->bytesperpixel = (myceil((float)actualmode.bpp / 8));
/*    m->colors = myexp(2, actualmode.bpp); */
        m->colors = 1 << actualmode.bpp;
        m->linewidth = gd_getbpr();
        m->maxlogicalwidth = gd_getbpr(); /* 4 the moment... */
        m->startaddressrange = 0;   /* don't know :( */
        m->maxpixels = gd_getmem() / m->bytesperpixel;
        m->haveblit = 0;
        m->flags = 0;

        /* Extended fields: */
        m->chiptype = type;     /* Chiptype detected */
        m->memory = gd_getmem();
        m->linewidth_unit = 0;  /* don't know :( */
        if (linear) {
        m->linear_aperture = (LIN_ADDR)gd_getflb();
        m->aperture_size = gd_getmem();
        } else {
        m->linear_aperture = 0;
        m->aperture_size = 0xFFFF;
        }
        m->set_aperture_page = NULL;
        m->extensions = NULL;
        return 1;
}
       
void Load_Write_Bank_256(BYTE bank)
{
        if (bank != actbank) {
        actbank = bank;
        if (type == VESA) {
                if (vbe_setbank(&vbemi, bank) < 0)
                        ll_abort(259);
        }
        if (type == S3) {
                s3_setpage(bank);
        }
        if (type == TRIDENT) {
                trident_setpage(bank);
        }
        }
}

/************************************************************************/
/*          BANK HANDLING FUNCS             */
/************************************************************************/

LIN_ADDR start_address(WORD bpr, WORD x, WORD y)
{
        LIN_ADDR a;

        a = (LIN_ADDR)(y * bpr +x);
        return a;
}

void Seg_Off_256(WORD x, WORD y, WORD pitch, WORD *offs, WORD *seg)
{
        DWORD a;

        a = y * pitch + x;
        *offs = a & 0x0000FFFF;
        *seg = a >> 16;
}

void Seg_Off_Hi(WORD x, WORD y, WORD pitch, WORD *offs, WORD *seg)
{
        DWORD a;

        a = y * pitch + x * 2;
        *offs = a & 0x0000FFFF;
        *seg = a >> 16;
}

int gd_modenum(WORD x, WORD y, BYTE depth)
{
        int  mode, i;

        mode = -1;

        for (i = 0; i < NMODES; i++) {
        if ((depth == allmodes[i].bpp) && (x == allmodes[i].xdim) && (y == allmodes[i].ydim)) {
                mode = allmodes[i].modenum;
        } else {
        }
        }

        if ((mode != -1) && (vbe_checkmode(mode) != -1))
                return mode;
        return -1;
}