159cc4ca5SDavid du Colombier #include "u.h"
259cc4ca5SDavid du Colombier #include "../port/lib.h"
359cc4ca5SDavid du Colombier #include "mem.h"
459cc4ca5SDavid du Colombier #include "dat.h"
559cc4ca5SDavid du Colombier #include "fns.h"
659cc4ca5SDavid du Colombier #include "io.h"
759cc4ca5SDavid du Colombier #include "../port/error.h"
859cc4ca5SDavid du Colombier
959cc4ca5SDavid du Colombier #define Image IMAGE
1059cc4ca5SDavid du Colombier #include <draw.h>
1159cc4ca5SDavid du Colombier #include <memdraw.h>
1259cc4ca5SDavid du Colombier #include <cursor.h>
1359cc4ca5SDavid du Colombier #include "screen.h"
1459cc4ca5SDavid du Colombier
1559c21d95SDavid du Colombier typedef struct Cursor3dfx Cursor3dfx;
1659c21d95SDavid du Colombier struct Cursor3dfx {
1759cc4ca5SDavid du Colombier int vidProcCfg;
1859cc4ca5SDavid du Colombier int hwCurPatAddr;
1959cc4ca5SDavid du Colombier int hwCurLoc;
2059cc4ca5SDavid du Colombier int hwCurC0;
2159cc4ca5SDavid du Colombier int hwCurC1;
2259c21d95SDavid du Colombier };
2359cc4ca5SDavid du Colombier
2459cc4ca5SDavid du Colombier enum {
2559cc4ca5SDavid du Colombier dramInit0 = 0x18,
2659cc4ca5SDavid du Colombier dramInit1 = 0x1C,
2759cc4ca5SDavid du Colombier
2859cc4ca5SDavid du Colombier hwCur = 0x5C,
2959cc4ca5SDavid du Colombier };
3059cc4ca5SDavid du Colombier
3159cc4ca5SDavid du Colombier static void
tdfxenable(VGAscr * scr)3259cc4ca5SDavid du Colombier tdfxenable(VGAscr* scr)
3359cc4ca5SDavid du Colombier {
3459cc4ca5SDavid du Colombier Pcidev *p;
35*4de34a7eSDavid du Colombier int i, *mmio;
3659cc4ca5SDavid du Colombier
37*4de34a7eSDavid du Colombier if(scr->mmio)
3859cc4ca5SDavid du Colombier return;
3959cc4ca5SDavid du Colombier if(p = pcimatch(nil, 0x121A, 0)){
4059cc4ca5SDavid du Colombier switch(p->did){
4180ee5cbfSDavid du Colombier case 0x0003: /* Banshee */
4259cc4ca5SDavid du Colombier case 0x0005: /* Avenger (a.k.a. Voodoo3) */
4359cc4ca5SDavid du Colombier break;
4459cc4ca5SDavid du Colombier default:
4559cc4ca5SDavid du Colombier return;
4659cc4ca5SDavid du Colombier }
4759cc4ca5SDavid du Colombier }
4859cc4ca5SDavid du Colombier else
4959cc4ca5SDavid du Colombier return;
50*4de34a7eSDavid du Colombier
51*4de34a7eSDavid du Colombier scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
52*4de34a7eSDavid du Colombier if(scr->mmio == nil)
5359cc4ca5SDavid du Colombier return;
54*4de34a7eSDavid du Colombier scr->pci = p;
5559cc4ca5SDavid du Colombier
56*4de34a7eSDavid du Colombier addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
57*4de34a7eSDavid du Colombier vgalinearpci(scr);
58*4de34a7eSDavid du Colombier if(scr->apsize)
59*4de34a7eSDavid du Colombier addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
6059cc4ca5SDavid du Colombier
6159cc4ca5SDavid du Colombier /*
6259cc4ca5SDavid du Colombier * Find a place for the cursor data in display memory.
6359cc4ca5SDavid du Colombier * If SDRAM then there's 16MB memory else it's SGRAM
6459cc4ca5SDavid du Colombier * and can count it based on the power-on straps -
6559cc4ca5SDavid du Colombier * chip size can be 8Mb or 16Mb, and there can be 4 or
6659cc4ca5SDavid du Colombier * 8 of them.
6759cc4ca5SDavid du Colombier * Use the last 1KB of the framebuffer.
6859cc4ca5SDavid du Colombier */
69*4de34a7eSDavid du Colombier mmio = (void*)((uchar*)scr->mmio+dramInit0);
7059cc4ca5SDavid du Colombier if(*(mmio+1) & 0x40000000)
7159cc4ca5SDavid du Colombier i = 16*1024*1024;
7259cc4ca5SDavid du Colombier else{
7359cc4ca5SDavid du Colombier if(*mmio & 0x08000000)
7459cc4ca5SDavid du Colombier i = 16*1024*1024/8;
7559cc4ca5SDavid du Colombier else
7659cc4ca5SDavid du Colombier i = 8*1024*1024/8;
7759cc4ca5SDavid du Colombier if(*mmio & 0x04000000)
7859cc4ca5SDavid du Colombier i *= 8;
7959cc4ca5SDavid du Colombier else
8059cc4ca5SDavid du Colombier i *= 4;
8159cc4ca5SDavid du Colombier }
8259cc4ca5SDavid du Colombier scr->storage = i - 1024;
8359cc4ca5SDavid du Colombier }
8459cc4ca5SDavid du Colombier
8559cc4ca5SDavid du Colombier static void
tdfxcurdisable(VGAscr * scr)8659cc4ca5SDavid du Colombier tdfxcurdisable(VGAscr* scr)
8759cc4ca5SDavid du Colombier {
8859cc4ca5SDavid du Colombier Cursor3dfx *cursor3dfx;
8959cc4ca5SDavid du Colombier
90*4de34a7eSDavid du Colombier if(scr->mmio == 0)
9159cc4ca5SDavid du Colombier return;
92*4de34a7eSDavid du Colombier cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
9359cc4ca5SDavid du Colombier cursor3dfx->vidProcCfg &= ~0x08000000;
9459cc4ca5SDavid du Colombier }
9559cc4ca5SDavid du Colombier
9659cc4ca5SDavid du Colombier static void
tdfxcurload(VGAscr * scr,Cursor * curs)9759cc4ca5SDavid du Colombier tdfxcurload(VGAscr* scr, Cursor* curs)
9859cc4ca5SDavid du Colombier {
9959cc4ca5SDavid du Colombier int y;
10059cc4ca5SDavid du Colombier uchar *p;
10159cc4ca5SDavid du Colombier Cursor3dfx *cursor3dfx;
10259cc4ca5SDavid du Colombier
103*4de34a7eSDavid du Colombier if(scr->mmio == 0)
10459cc4ca5SDavid du Colombier return;
105*4de34a7eSDavid du Colombier cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
10659cc4ca5SDavid du Colombier
10759cc4ca5SDavid du Colombier /*
10859cc4ca5SDavid du Colombier * Disable the cursor then load the new image in
10959cc4ca5SDavid du Colombier * the top-left of the 64x64 array.
11059cc4ca5SDavid du Colombier * The cursor data is stored in memory as 128-bit
11159cc4ca5SDavid du Colombier * words consisting of plane 0 in the least significant 64-bits
11259cc4ca5SDavid du Colombier * and plane 1 in the most significant.
11359cc4ca5SDavid du Colombier * The X11 cursor truth table is:
11459cc4ca5SDavid du Colombier * p0 p1 colour
11559cc4ca5SDavid du Colombier * 0 0 transparent
11659cc4ca5SDavid du Colombier * 0 1 transparent
11759cc4ca5SDavid du Colombier * 1 0 hwCurC0
11859cc4ca5SDavid du Colombier * 1 1 hwCurC1
11959cc4ca5SDavid du Colombier * Unused portions of the image have been initialised to be
12059cc4ca5SDavid du Colombier * transparent.
12159cc4ca5SDavid du Colombier */
12259cc4ca5SDavid du Colombier cursor3dfx->vidProcCfg &= ~0x08000000;
123*4de34a7eSDavid du Colombier p = (uchar*)scr->vaddr + scr->storage;
12459cc4ca5SDavid du Colombier for(y = 0; y < 16; y++){
12559cc4ca5SDavid du Colombier *p++ = curs->clr[2*y]|curs->set[2*y];
12659cc4ca5SDavid du Colombier *p++ = curs->clr[2*y+1]|curs->set[2*y+1];
12759cc4ca5SDavid du Colombier p += 6;
12859cc4ca5SDavid du Colombier *p++ = curs->set[2*y];
12959cc4ca5SDavid du Colombier *p++ = curs->set[2*y+1];
13059cc4ca5SDavid du Colombier p += 6;
13159cc4ca5SDavid du Colombier }
13259cc4ca5SDavid du Colombier
13359cc4ca5SDavid du Colombier /*
13459cc4ca5SDavid du Colombier * Save the cursor hotpoint and enable the cursor.
13559cc4ca5SDavid du Colombier * The 0,0 cursor point is bottom-right.
13659cc4ca5SDavid du Colombier */
13759cc4ca5SDavid du Colombier scr->offset.x = 63+curs->offset.x;
13859cc4ca5SDavid du Colombier scr->offset.y = 63+curs->offset.y;
13959cc4ca5SDavid du Colombier cursor3dfx->vidProcCfg |= 0x08000000;
14059cc4ca5SDavid du Colombier }
14159cc4ca5SDavid du Colombier
14259cc4ca5SDavid du Colombier static int
tdfxcurmove(VGAscr * scr,Point p)14359cc4ca5SDavid du Colombier tdfxcurmove(VGAscr* scr, Point p)
14459cc4ca5SDavid du Colombier {
14559cc4ca5SDavid du Colombier Cursor3dfx *cursor3dfx;
14659cc4ca5SDavid du Colombier
147*4de34a7eSDavid du Colombier if(scr->mmio == 0)
14859cc4ca5SDavid du Colombier return 1;
149*4de34a7eSDavid du Colombier cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
15059cc4ca5SDavid du Colombier
15159cc4ca5SDavid du Colombier cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
15259cc4ca5SDavid du Colombier
15359cc4ca5SDavid du Colombier return 0;
15459cc4ca5SDavid du Colombier }
15559cc4ca5SDavid du Colombier
15659cc4ca5SDavid du Colombier static void
tdfxcurenable(VGAscr * scr)15759cc4ca5SDavid du Colombier tdfxcurenable(VGAscr* scr)
15859cc4ca5SDavid du Colombier {
15959cc4ca5SDavid du Colombier Cursor3dfx *cursor3dfx;
16059cc4ca5SDavid du Colombier
16159cc4ca5SDavid du Colombier tdfxenable(scr);
162*4de34a7eSDavid du Colombier if(scr->mmio == 0)
16359cc4ca5SDavid du Colombier return;
164*4de34a7eSDavid du Colombier cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
16559cc4ca5SDavid du Colombier
16659cc4ca5SDavid du Colombier /*
16759cc4ca5SDavid du Colombier * Cursor colours.
16859cc4ca5SDavid du Colombier */
16959cc4ca5SDavid du Colombier cursor3dfx->hwCurC0 = 0xFFFFFFFF;
17059cc4ca5SDavid du Colombier cursor3dfx->hwCurC1 = 0x00000000;
17159cc4ca5SDavid du Colombier
17259cc4ca5SDavid du Colombier /*
17359cc4ca5SDavid du Colombier * Initialise the 64x64 cursor to be transparent (X11 mode).
17459cc4ca5SDavid du Colombier */
17559cc4ca5SDavid du Colombier cursor3dfx->hwCurPatAddr = scr->storage;
176*4de34a7eSDavid du Colombier memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
17759cc4ca5SDavid du Colombier
17859cc4ca5SDavid du Colombier /*
17959cc4ca5SDavid du Colombier * Load, locate and enable the 64x64 cursor in X11 mode.
18059cc4ca5SDavid du Colombier */
18159cc4ca5SDavid du Colombier tdfxcurload(scr, &arrow);
18259cc4ca5SDavid du Colombier tdfxcurmove(scr, ZP);
18359cc4ca5SDavid du Colombier cursor3dfx->vidProcCfg |= 0x08000002;
18459cc4ca5SDavid du Colombier }
18559cc4ca5SDavid du Colombier
18659cc4ca5SDavid du Colombier VGAdev vga3dfxdev = {
18759cc4ca5SDavid du Colombier "3dfx",
18859cc4ca5SDavid du Colombier
18959cc4ca5SDavid du Colombier tdfxenable,
19059cc4ca5SDavid du Colombier nil,
19159cc4ca5SDavid du Colombier nil,
192*4de34a7eSDavid du Colombier nil,
19359cc4ca5SDavid du Colombier };
19459cc4ca5SDavid du Colombier
19559cc4ca5SDavid du Colombier VGAcur vga3dfxcur = {
19659cc4ca5SDavid du Colombier "3dfxhwgc",
19759cc4ca5SDavid du Colombier
19859cc4ca5SDavid du Colombier tdfxcurenable,
19959cc4ca5SDavid du Colombier tdfxcurdisable,
20059cc4ca5SDavid du Colombier tdfxcurload,
20159cc4ca5SDavid du Colombier tdfxcurmove,
20259cc4ca5SDavid du Colombier };
203