Subversion Repositories planix.SVN

Rev

Go to most recent revision | 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"

enum {
        Xrx             = 0x3D6,        /* Configuration Extensions Index */
};

static uchar
hiqvideoxi(long port, uchar index)
{
        uchar data;

        outb(port, index);
        data = inb(port+1);

        return data;
}

static void
hiqvideoxo(long port, uchar index, uchar data)
{
        outb(port, index);
        outb(port+1, data);
}

static void
hiqvideolinear(VGAscr*, int, int)
{
}

static void
hiqvideoenable(VGAscr* scr)
{
        Pcidev *p;
        int vmsize;

        /*
         * Only once, can't be disabled for now.
         */
        if(scr->mmio)
                return;
        if(p = pcimatch(nil, 0x102C, 0)){
                switch(p->did){
                case 0x00C0:            /* 69000 HiQVideo */
                        vmsize = 2*1024*1024;
                        break;
                case 0x00E0:            /* 65550 HiQV32 */
                case 0x00E4:            /* 65554 HiQV32 */
                case 0x00E5:            /* 65555 HiQV32 */
                        switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
                        default:
                        case 0:
                                vmsize = 1*1024*1024;
                                break;
                        case 1:
                                vmsize = 2*1024*1024;
                                break;
                        }
                        break;
                default:
                        return;
                }
        }
        else
                return;

        scr->pci = p;
        vgalinearpci(scr);
        
        if(scr->paddr) {
                addvgaseg("hiqvideoscreen", scr->paddr, scr->apsize);
        }

        /*
         * Find a place for the cursor data in display memory.
         * Must be on a 4096-byte boundary.
         * scr->mmio holds the virtual address of the cursor
         * storage area in the framebuffer region.
         */
        scr->storage = vmsize-4096;
        scr->mmio = (ulong*)((uchar*)scr->vaddr+scr->storage);
}

static void
hiqvideocurdisable(VGAscr*)
{
        hiqvideoxo(Xrx, 0xA0, 0x10);
}

static void
hiqvideocurload(VGAscr* scr, Cursor* curs)
{
        uchar *p;
        int x, y;

        /*
         * Disable the cursor.
         */
        hiqvideocurdisable(scr);

        if(scr->mmio == 0)
                return;
        p = (uchar*)scr->mmio;

        for(y = 0; y < 16; y += 2){
                *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
                *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
                *p++ = 0xFF;
                *p++ = 0xFF;
                *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
                *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
                *p++ = 0xFF;
                *p++ = 0xFF;
                *p++ = curs->set[2*y];
                *p++ = curs->set[2*y+1];
                *p++ = 0x00;
                *p++ = 0x00;
                *p++ = curs->set[2*y+2];
                *p++ = curs->set[2*y+3];
                *p++ = 0x00;
                *p++ = 0x00;
        }
        while(y < 32){
                for(x = 0; x < 64; x += 8)
                        *p++ = 0xFF;
                for(x = 0; x < 64; x += 8)
                        *p++ = 0x00;
                y += 2;
        }

        /*
         * Save the cursor hotpoint and enable the cursor.
         */
        scr->offset = curs->offset;
        hiqvideoxo(Xrx, 0xA0, 0x11);
}

static int
hiqvideocurmove(VGAscr* scr, Point p)
{
        int x, y;

        if(scr->mmio == 0)
                return 1;

        if((x = p.x+scr->offset.x) < 0)
                x = 0x8000|(-x & 0x07FF);
        if((y = p.y+scr->offset.y) < 0)
                y = 0x8000|(-y & 0x07FF);

        hiqvideoxo(Xrx, 0xA4, x & 0xFF);
        hiqvideoxo(Xrx, 0xA5, (x>>8) & 0xFF);
        hiqvideoxo(Xrx, 0xA6, y & 0xFF);
        hiqvideoxo(Xrx, 0xA7, (y>>8) & 0xFF);

        return 0;
}

static void
hiqvideocurenable(VGAscr* scr)
{
        uchar xr80;

        hiqvideoenable(scr);
        if(scr->mmio == 0)
                return;

        /*
         * Disable the cursor.
         */
        hiqvideocurdisable(scr);

        /*
         * Cursor colours.
         * Can't call setcolor here as cursor is already locked.
         * When done make sure the cursor enable in Xr80 is set.
         */
        xr80 = hiqvideoxi(Xrx, 0x80);
        hiqvideoxo(Xrx, 0x80, xr80|0x01);
        vgao(PaddrW, 0x04);
        vgao(Pdata, Pwhite);
        vgao(Pdata, Pwhite);
        vgao(Pdata, Pwhite);
        vgao(Pdata, Pblack);
        vgao(Pdata, Pblack);
        vgao(Pdata, Pblack);
        hiqvideoxo(Xrx, 0x80, xr80|0x10);

        hiqvideoxo(Xrx, 0xA2, (scr->storage>>12)<<4);
        hiqvideoxo(Xrx, 0xA3, (scr->storage>>16) & 0x3F);

        /*
         * Load, locate and enable the 32x32 cursor.
         * Cursor enable in Xr80 better be set already.
         */
        hiqvideocurload(scr, &arrow);
        hiqvideocurmove(scr, ZP);
        hiqvideoxo(Xrx, 0xA0, 0x11);
}

VGAdev vgahiqvideodev = {
        "hiqvideo",

        hiqvideoenable,                 /* enable */
        nil,                            /* disable */
        nil,                            /* page */
        hiqvideolinear,                 /* linear */
};

VGAcur vgahiqvideocur = {
        "hiqvideohwgc",

        hiqvideocurenable,              /* enable */
        hiqvideocurdisable,             /* disable */
        hiqvideocurload,                /* load */
        hiqvideocurmove,                /* move */
};