plan9fox/sys/src/9/pc/vgai81x.c
cinap_lenrek b5008f3b56 devvga: disable hardware blanking when switching drivers, check softscreen
we have to reset hwblank when switching drivers to
prevent the generic vgablank() to be called by
blankscreen().

remove code setting hwblank from vga drivers as
devvga will always force hwblank to be 1 or 0
depending on if the driver provides a native blanking
routine.

set hwaccel to 1 when the driver provides native fill
and scroll routines independent of softscreen being
disabled. this allows hw acceleration to be used when
softscreen gets switched off.
2015-01-03 18:33:35 +01:00

236 lines
4 KiB
C

#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"
typedef struct
{
ushort ctl;
ushort pad;
ulong base;
ulong pos;
} CursorI81x;
enum {
Fbsize = 8*MB,
hwCur = 0x70080,
SRX = 0x3c4,
DPMSsync = 0x5002,
};
static void
i81xblank(VGAscr *scr, int blank)
{
char *srx, *srxd, *dpms;
char sr01, mode;
srx = (char *)scr->mmio+SRX;
srxd = srx+1;
dpms = (char *)scr->mmio+DPMSsync;
*srx = 0x01;
sr01 = *srxd & ~0x20;
mode = *dpms & 0xf0;
if(blank) {
sr01 |= 0x20;
mode |= 0x0a;
}
*srxd = sr01;
*dpms = mode;
}
static void
i81xenable(VGAscr* scr)
{
Pcidev *p;
int size;
Mach *mach0;
ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
if(scr->mmio)
return;
p = scr->pci;
if(p == nil)
return;
scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
if(scr->mmio == 0)
return;
addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
/* allocate page table */
pgtbl = xspanalloc(64*1024, BY2PG, 0);
scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
size = p->mem[0].size;
if(size > 0)
size = Fbsize;
vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
/*
* allocate backing store for frame buffer
* and populate device page tables.
*/
fbuf = PADDR(xspanalloc(size, BY2PG, 0));
fbend = PGROUND(fbuf+size);
rp = scr->mmio+0x10000/4;
while(fbuf < fbend) {
*rp++ = fbuf | 1;
fbuf += BY2PG;
}
/*
* allocate space for the cursor data in system memory.
* must be uncached.
*/
cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
mach0 = MACHP(0);
pte = mmuwalk(mach0->pdb, cursor, 2, 0);
if(pte == nil)
panic("i81x cursor mmuwalk");
*pte |= PTEUNCACHED;
scr->storage = cursor;
scr->blank = i81xblank;
}
static void
i81xcurdisable(VGAscr* scr)
{
CursorI81x *hwcurs;
if(scr->mmio == 0)
return;
hwcurs = (void*)((uchar*)scr->mmio+hwCur);
hwcurs->ctl = (1<<4);
}
static void
i81xcurload(VGAscr* scr, Cursor* curs)
{
int y;
uchar *p;
CursorI81x *hwcurs;
if(scr->mmio == 0)
return;
hwcurs = (void*)((uchar*)scr->mmio+hwCur);
/*
* Disable the cursor then load the new image in
* the top-left of the 32x32 array.
* Unused portions of the image have been initialised to be
* transparent.
*/
hwcurs->ctl = (1<<4);
p = (uchar*)scr->storage;
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 += 2;
*p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
*p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
p += 2;
*p++ = curs->set[2*y];
*p++ = curs->set[2*y+1];
p += 2;
*p++ = curs->set[2*y+2];
*p++ = curs->set[2*y+3];
p += 2;
}
/*
* Save the cursor hotpoint and enable the cursor.
* The 0,0 cursor point is top-left.
*/
scr->offset.x = curs->offset.x;
scr->offset.y = curs->offset.y;
hwcurs->ctl = (1<<4)|1;
}
static int
i81xcurmove(VGAscr* scr, Point p)
{
int x, y;
ulong pos;
CursorI81x *hwcurs;
if(scr->mmio == 0)
return 1;
hwcurs = (void*)((uchar*)scr->mmio+hwCur);
x = p.x+scr->offset.x;
y = p.y+scr->offset.y;
pos = 0;
if(x < 0) {
pos |= (1<<15);
x = -x;
}
if(y < 0) {
pos |= (1<<31);
y = -y;
}
pos |= ((y&0x7ff)<<16)|(x&0x7ff);
hwcurs->pos = pos;
return 0;
}
static void
i81xcurenable(VGAscr* scr)
{
int i;
uchar *p;
CursorI81x *hwcurs;
i81xenable(scr);
if(scr->mmio == 0)
return;
hwcurs = (void*)((uchar*)scr->mmio+hwCur);
/*
* Initialise the 32x32 cursor to be transparent in 2bpp mode.
*/
hwcurs->base = PADDR(scr->storage);
p = (uchar*)scr->storage;
for(i = 0; i < 32/2; i++) {
memset(p, 0xff, 8);
memset(p+8, 0, 8);
p += 16;
}
/*
* Load, locate and enable the 32x32 cursor in 2bpp mode.
*/
i81xcurload(scr, &arrow);
i81xcurmove(scr, ZP);
}
VGAdev vgai81xdev = {
"i81x",
i81xenable,
nil,
nil,
nil,
};
VGAcur vgai81xcur = {
"i81xhwgc",
i81xcurenable,
i81xcurdisable,
i81xcurload,
i81xcurmove,
};