jehanne/sys/src/cmd/hmi/vga/t2r4.c

330 lines
8.6 KiB
C

/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include <u.h>
#include <lib9.h>
#include <bio.h>
#include "pci.h"
#include "vga.h"
/*
* #9 Ticket to Ride IV.
*/
typedef struct {
Pcidev* pci;
uint32_t io;
uint8_t* mmio;
uint32_t ioreg[13];
uint32_t g[25];
uint32_t w[25];
} T2r4;
enum { /* memory mapped global registers */
IntVcnt = 0x20/4, /* vertical interrupt counter */
IntHcnt = 0x24/4, /* horizontal interrupt counter */
DbAdr = 0x28/4, /* display start address */
DbPtch = 0x2C/4, /* display pitch */
CrtHac = 0x30/4, /* horizontal active line width */
CrtHbl = 0x34/4, /* horizontal blank width */
CrtHfp = 0x38/4, /* horizontal front porch */
CrtHs = 0x3C/4, /* horizontal sync width */
CrtVac = 0x40/4, /* vertical active field width */
CrtVbl = 0x44/4, /* vertical blank width */
CrtVfp = 0x48/4, /* vertical front porch */
CrtVs = 0x4C/4, /* vertical sync width */
CrtLcnt = 0x50/4, /* CRT line counter */
CrtZoom = 0x54/4, /* display zoom factor */
Crt1con = 0x58/4, /* CRT configuration register 1 */
Crt2con = 0x5C/4, /* CRT configuration register 2 */
DbAdr2 = 0x60/4, /* CRT display start address 2 */
};
enum { /* memory windows registers */
Mw0Ctrl = 0x00/4, /* memory window 0 control */
Mw0Ad = 0x04/4, /* memory window 0 address */
Mw0Sz = 0x08/4, /* memory window 0 size */
Mw0Org = 0x10/4, /* memory window 0 origin */
Mw0Mask = 0x24/4, /* Memory window 0 plane mask */
Mw1Ctlr = 0x28/4, /* memory window 1 control */
Mw1Ad = 0x2C/4, /* memory window 1 address */
Mw1Sz = 0x30/4, /* memory window 1 size */
Mw1Org = 0x38/4, /* memory window 1 origin */
Mw1Mask = 0x4C/4, /* Memory window 1 plane mask */
MwcFcnt = 0x50/4, /* memory window cache flush counter */
MwcFlsh = 0x54/4, /* manual cache flush */
YuvLi = 0x58/4, /* YUV LUT index */
YuvLa = 0x5C/4, /* YUV LUT address */
MwCtrl = 0x60/4, /* memory window 0 and 1 control */
};
enum {
IndexLo = 4,
IndexHi = 5,
Data = 6,
IndexCtl = 7,
};
static uint8_t
_rgb524xi(Vga* vga, int index)
{
uint32_t *mmio;
mmio = (uint32_t*)((T2r4*)vga->private)->mmio;
mmio[IndexLo] = index & 0xFF;
mmio[IndexHi] = (index>>8) & 0xFF;
return mmio[Data];
}
static void
_rgb524xo(Vga* vga, int index, uint8_t data)
{
uint32_t *mmio;
mmio = (uint32_t*)((T2r4*)vga->private)->mmio;
mmio[IndexLo] = index & 0xFF;
mmio[IndexHi] = (index>>8) & 0xFF;
mmio[Data] = data;
}
static void
snarf(Vga* vga, Ctlr* ctlr)
{
uint32_t *mmio;
int f, i, x;
Pcidev *p;
T2r4 *t2r4;
uint32_t *rp;
if(vga->private == nil){
vga->private = alloc(sizeof(T2r4));
if((p = pcimatch(0, 0x105D, 0)) == nil)
error("%s: not found\n", ctlr->name);
switch(p->did){
case 0x5348: /* */
break;
default:
error("%s: not found\n", ctlr->name);
}
if((f = sys_open("#v/vgactl", OWRITE)) < 0)
error("%s: can't open vgactl\n", ctlr->name);
if(jehanne_write(f, "type t2r4", 9) != 9)
error("%s: can't set type\n", ctlr->name);
sys_close(f);
mmio = segattach(0, "t2r4mmio", 0, p->mem[4].size);
if(mmio == (void*)-1)
error("%s: can't attach mmio segment\n", ctlr->name);
t2r4 = vga->private;
t2r4->pci = p;
t2r4->io = p->mem[5].bar & ~0x0F;
t2r4->mmio = (uint8_t*)mmio;
}
t2r4 = vga->private;
for(i = 0; i < nelem(t2r4->ioreg); i++)
t2r4->ioreg[i] = inportl(t2r4->io+(i*4));
x = t2r4->ioreg[7] & 0xFF00001F; /* config1 */
outportl(t2r4->io+0x1C, x|0x00331F10);
x = t2r4->ioreg[8] & 0xFF0FFFFF; /* config2 */
outportl(t2r4->io+0x20, x|0x00100000);
x = inportl(t2r4->io+0x30) & 0xFF; /* vgactl */
outportl(t2r4->io+0x30, x|0x82);
rp = (uint32_t*)t2r4->mmio;
for(i = 0; i < nelem(t2r4->g); i++)
t2r4->g[i] = *rp++;
rp = (uint32_t*)(t2r4->mmio+8192);
for(i = 0; i < nelem(t2r4->w); i++)
t2r4->w[i] = *rp++;
vga->vma = vga->vmz = t2r4->pci->mem[0].size;
ctlr->flag |= Hlinear;
/*
* Currently, the RGB524 has no need of a snarf
* routine so this will be called before any RGB524 code.
*/
if(vga->ramdac && strncmp(vga->ramdac->name, "rgb524mn", 8) == 0){
rgb524mnxi = _rgb524xi;
rgb524mnxo = _rgb524xo;
}
ctlr->flag |= Fsnarf;
}
static void
options(Vga* vga, Ctlr* ctlr)
{
USED(vga);
ctlr->flag |= Foptions;
}
static void
init(Vga* vga, Ctlr* ctlr)
{
char *val;
T2r4 *t2r4;
int crtclocks, zoom;
t2r4 = vga->private;
crtclocks = 64/vga->mode->z;
zoom = 1;
if((val = dbattr(vga->mode->attr, "zoom")) && strtol(val, 0, 0))
zoom = 2;
t2r4->g[DbAdr] = 0;
switch(vga->mode->z){
case 8:
t2r4->g[DbPtch] = vga->mode->x*1;
break;
case 16:
t2r4->g[DbPtch] = vga->mode->x*2;
break;
case 32:
t2r4->g[DbPtch] = vga->mode->x*4;
break;
}
t2r4->g[CrtHac] = vga->mode->x/crtclocks;
t2r4->g[CrtHbl] = (vga->mode->ht-vga->mode->x)/crtclocks;
if(vga->mode->shs == 0)
vga->mode->shs = vga->mode->shb;
t2r4->g[CrtHfp] = (vga->mode->shs-vga->mode->x)/crtclocks;
if(vga->mode->ehs == 0)
vga->mode->ehs = vga->mode->ehb;
t2r4->g[CrtHs] = (vga->mode->ehs-vga->mode->shs)/crtclocks;
t2r4->g[CrtVac] = vga->mode->y * zoom;
t2r4->g[CrtVbl] = (vga->mode->vt-vga->mode->y) * zoom;
t2r4->g[CrtVfp] = (vga->mode->vrs-vga->mode->y) * zoom;
t2r4->g[CrtVs] = (vga->mode->vre-vga->mode->vrs) * zoom;
t2r4->g[CrtZoom] = 0;
/*
* Turn on the syncs and video.
* Bts (bit 0x100) is digital RGB output enable. If there's
* a flat-panel then this is hopefully already set by the BIOS,
* so don't touch it. (It's possible that bit 0 of SoftSw
* indicates flat-panel or CRT).
*/
t2r4->g[Crt1con] &= 0x00000100;
t2r4->g[Crt1con] |= 0x70;
t2r4->g[Crt2con] = 0x20000100;
if(zoom == 2)
t2r4->g[CrtZoom] = 1;
t2r4->w[Mw0Ctrl] = 0;
t2r4->w[Mw0Sz] = 0x0D; /* 32MB */
t2r4->w[Mw0Org] = 0;
t2r4->w[Mw0Mask] = 0xFFFFFFFF;
if(vga->linear && (ctlr->flag & Hlinear))
ctlr->flag |= Ulinear;
ctlr->flag |= Finit;
}
static void
load(Vga* vga, Ctlr* ctlr)
{
T2r4 *t2r4;
uint32_t *g, *w;
t2r4 = vga->private;
g = (uint32_t*)t2r4->mmio;
g[DbAdr] = t2r4->g[DbAdr];
g[DbPtch] = t2r4->g[DbPtch];
g[CrtHac] = t2r4->g[CrtHac];
g[CrtHbl] = t2r4->g[CrtHbl];
g[CrtHfp] = t2r4->g[CrtHfp];
g[CrtHs] = t2r4->g[CrtHs];
g[CrtVac] = t2r4->g[CrtVac];
g[CrtVbl] = t2r4->g[CrtVbl];
g[CrtVfp] = t2r4->g[CrtVfp];
g[CrtVs] = t2r4->g[CrtVs];
g[Crt1con] = t2r4->g[Crt1con];
g[Crt2con] = t2r4->g[Crt2con];
g[CrtZoom] = t2r4->g[CrtZoom];
w = (uint32_t*)(t2r4->mmio+8192);
w[Mw0Ctrl] = t2r4->w[Mw0Ctrl];
w[Mw0Sz] = t2r4->w[Mw0Sz];
w[Mw0Org] = t2r4->w[Mw0Org];
w[Mw0Mask] = t2r4->w[Mw0Mask];
if(t2r4->g[CrtZoom])
outportl(t2r4->io+0x30, 0xA2); /* vgactl */
else
outportl(t2r4->io+0x30, 0x82); /* vgactl */
outportl(t2r4->io+0x24, 0x211BF030); /* sgram */
sleep(500);
outportl(t2r4->io+0x24, 0xA11BF030); /* sgram */
ctlr->flag |= Fload;
}
static void
dump(Vga* vga, Ctlr* ctlr)
{
int i;
T2r4 *t2r4;
t2r4 = vga->private;
Bprint(&stdout, "\n");
Bprint(&stdout, "%s ioreg\t\t%8.8luX\n", ctlr->name, t2r4->io);
Bprint(&stdout, "%s rbase_g\t%8.8luX\n", ctlr->name, t2r4->ioreg[0]);
Bprint(&stdout, "%s rbase_w\t%8.8luX\n", ctlr->name, t2r4->ioreg[1]);
Bprint(&stdout, "%s rbase_d\t%8.8luX\n", ctlr->name, t2r4->ioreg[2]);
Bprint(&stdout, "%s rbase_i\t%8.8luX\n", ctlr->name, t2r4->ioreg[4]);
Bprint(&stdout, "%s rbase_e\t%8.8luX\n", ctlr->name, t2r4->ioreg[5]);
Bprint(&stdout, "%s id\t\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[6]);
Bprint(&stdout, "%s config1\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[7]);
Bprint(&stdout, "%s config2\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[8]);
Bprint(&stdout, "%s sgram\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[9]);
Bprint(&stdout, "%s softsw\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[10]);
Bprint(&stdout, "%s ddc\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[11]);
Bprint(&stdout, "%s vgactl\t\t%8.8luX\n", ctlr->name, t2r4->ioreg[12]);
Bprint(&stdout, "\n");
for(i = 0; i < nelem(t2r4->g); i++)
Bprint(&stdout, "%s g reg0x%2.2uX\t\t%8.8luX\n",
ctlr->name, i*4, t2r4->g[i]);
Bprint(&stdout, "\n");
for(i = 0; i < nelem(t2r4->w); i++)
Bprint(&stdout, "%s w reg0x%2.2uX\t\t%8.8luX\n",
ctlr->name, i*4, t2r4->w[i]);
}
Ctlr t2r4 = {
"t2r4", /* name */
snarf, /* snarf */
options, /* options */
init, /* init */
load, /* load */
dump, /* dump */
};
Ctlr t2r4hwgc = {
"t2r4hwgc", /* name */
0, /* snarf */
0, /* options */
0, /* init */
0, /* load */
0, /* dump */
};