Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"

#define Image   IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"

static int
clgd542xpageset(VGAscr*, int page)
{
        uchar gr09;
        int opage;
        
        if(vgaxi(Seqx, 0x07) & 0xF0)
                page = 0;
        gr09 = vgaxi(Grx, 0x09);
        if(vgaxi(Grx, 0x0B) & 0x20){
                vgaxo(Grx, 0x09, page<<2);
                opage = gr09>>2;
        }
        else{
                vgaxo(Grx, 0x09, page<<4);
                opage = gr09>>4;
        }

        return opage;
}

static void
clgd542xpage(VGAscr* scr, int page)
{
        lock(&scr->devlock);
        clgd542xpageset(scr, page);
        unlock(&scr->devlock);
}

static void
clgd542xlinear(VGAscr* scr, int, int)
{
        vgalinearpciid(scr, 0x1013, 0);
}

static void
clgd542xdisable(VGAscr*)
{
        uchar sr12;

        sr12 = vgaxi(Seqx, 0x12);
        vgaxo(Seqx, 0x12, sr12 & ~0x01);
}

static void
clgd542xenable(VGAscr* scr)
{
        uchar sr12;
        int mem, x;
 
        /*
         * Disable the cursor.
         */
        sr12 = vgaxi(Seqx, 0x12);
        vgaxo(Seqx, 0x12, sr12 & ~0x01);

        /*
         * Cursor colours.
         * Can't call setcolor here as cursor is already locked.
         */
        vgaxo(Seqx, 0x12, sr12|0x02);
        vgao(PaddrW, 0x00);
        vgao(Pdata, Pwhite);
        vgao(Pdata, Pwhite);
        vgao(Pdata, Pwhite);
        vgao(PaddrW, 0x0F);
        vgao(Pdata, Pblack);
        vgao(Pdata, Pblack);
        vgao(Pdata, Pblack);
        vgaxo(Seqx, 0x12, sr12);

        mem = 0;
        switch(vgaxi(Crtx, 0x27) & ~0x03){

        case 0x88:                              /* CL-GD5420 */
        case 0x8C:                              /* CL-GD5422 */
        case 0x94:                              /* CL-GD5424 */
        case 0x80:                              /* CL-GD5425 */
        case 0x90:                              /* CL-GD5426 */
        case 0x98:                              /* CL-GD5427 */
        case 0x9C:                              /* CL-GD5429 */
                /*
                 * The BIOS leaves the memory size in Seq0A, bits 4 and 3.
                 * See Technical Reference Manual Appendix E1, Section 1.3.2.
                 *
                 * The storage area for the 64x64 cursors is the last 16Kb of
                 * display memory.
                 */
                mem = (vgaxi(Seqx, 0x0A)>>3) & 0x03;
                break;

        case 0xA0:                              /* CL-GD5430 */
        case 0xA8:                              /* CL-GD5434 */
        case 0xAC:                              /* CL-GD5436 */
        case 0xB8:                              /* CL-GD5446 */
        case 0x30:                              /* CL-GD7543 */
                /*
                 * Attempt to intuit the memory size from the DRAM control
                 * register. Minimum is 512KB.
                 * If DRAM bank switching is on then there's double.
                 */
                x = vgaxi(Seqx, 0x0F);
                mem = (x>>3) & 0x03;
                if(x & 0x80)
                        mem++;
                break;

        case 0xBC:                              /* CL-GD5480 */
                mem = 2;                        /* 1024 = 256<<2 */
                x = vgaxi(Seqx, 0x0F);
                if((x & 0x18) == 0x18){
                        mem <<= 1;              /* 2048 = 256<<3 */
                        if(x & 0x80)
                                mem <<= 2;      /* 2048 = 256<<4 */
                }
                if(vgaxi(Seqx, 0x17) & 0x80)
                        mem <<= 1;
                break;

        default:                                /* uh, ah dunno */
                break;
        }
        scr->storage = ((256<<mem)-16)*1024;

        /*
         * Set the current cursor to index 0
         * and turn the 64x64 cursor on.
         */
        vgaxo(Seqx, 0x13, 0);
        vgaxo(Seqx, 0x12, sr12|0x05);
}

static void
clgd542xinitcursor(VGAscr* scr, int xo, int yo, int index)
{
        uchar *p, seq07;
        uint p0, p1;
        int opage, x, y;

        /*
         * Is linear addressing turned on? This will determine
         * how we access the cursor storage.
         */
        seq07 = vgaxi(Seqx, 0x07);
        opage = 0;
        p = scr->vaddr;
        if(!(seq07 & 0xF0)){
                lock(&scr->devlock);
                opage = clgd542xpageset(scr, scr->storage>>16);
                p += (scr->storage & 0xFFFF);
        }
        else
                p += scr->storage;
        p += index*1024;

        for(y = yo; y < 16; y++){
                p0 = scr->set[2*y];
                p1 = scr->set[2*y+1];
                if(xo){
                        p0 = (p0<<xo)|(p1>>(8-xo));
                        p1 <<= xo;
                }
                *p++ = p0;
                *p++ = p1;

                for(x = 16; x < 64; x += 8)
                        *p++ = 0x00;

                p0 = scr->clr[2*y]|scr->set[2*y];
                p1 = scr->clr[2*y+1]|scr->set[2*y+1];
                if(xo){
                        p0 = (p0<<xo)|(p1>>(8-xo));
                        p1 <<= xo;
                }
                *p++ = p0;
                *p++ = p1;

                for(x = 16; x < 64; x += 8)
                        *p++ = 0x00;
        }
        while(y < 64+yo){
                for(x = 0; x < 64; x += 8){
                        *p++ = 0x00;
                        *p++ = 0x00;
                }
                y++;
        }

        if(!(seq07 & 0xF0)){
                clgd542xpageset(scr, opage);
                unlock(&scr->devlock);
        }
}

static void
clgd542xload(VGAscr* scr, Cursor* curs)
{
        uchar sr12;

        /*
         * Disable the cursor.
         */
        sr12 = vgaxi(Seqx, 0x12);
        vgaxo(Seqx, 0x12, sr12 & ~0x01);

        memmove(&scr->Cursor, curs, sizeof(Cursor));
        clgd542xinitcursor(scr, 0, 0, 0);

        /*
         * Enable the cursor.
         */
        vgaxo(Seqx, 0x13, 0);
        vgaxo(Seqx, 0x12, sr12|0x05);
}

static int
clgd542xmove(VGAscr* scr, Point p)
{
        int index, x, xo, y, yo;

        index = 0;
        if((x = p.x+scr->offset.x) < 0){
                xo = -x;
                x = 0;
        }
        else
                xo = 0;
        if((y = p.y+scr->offset.y) < 0){
                yo = -y;
                y = 0;
        }
        else
                yo = 0;

        if(xo || yo){
                clgd542xinitcursor(scr, xo, yo, 1);
                index = 1;
        }
        vgaxo(Seqx, 0x13, index<<2);
        
        vgaxo(Seqx, 0x10|((x & 0x07)<<5), (x>>3) & 0xFF);
        vgaxo(Seqx, 0x11|((y & 0x07)<<5), (y>>3) & 0xFF);

        return 0;
}

VGAdev vgaclgd542xdev = {
        "clgd542x",

        0,
        0,
        clgd542xpage,
        clgd542xlinear,
};

VGAcur vgaclgd542xcur = {
        "clgd542xhwgc",

        clgd542xenable,
        clgd542xdisable,
        clgd542xload,
        clgd542xmove,
};