implement vesa screenblanking (issue #36)

This commit is contained in:
cinap_lenrek 2011-08-23 05:33:51 +02:00
parent 1af6c6df32
commit e54222fb0d
2 changed files with 100 additions and 19 deletions

View file

@ -277,8 +277,13 @@ vgactl(Cmdbuf *cb)
for(i = 0; vgadev[i]; i++){ for(i = 0; vgadev[i]; i++){
if(strcmp(cb->f[1], vgadev[i]->name)) if(strcmp(cb->f[1], vgadev[i]->name))
continue; continue;
if(scr->dev && scr->dev->disable) if(scr->dev){
scr->dev->disable(scr); if(scr->dev->disable)
scr->dev->disable(scr);
scr->fill = nil;
scr->scroll = nil;
scr->blank = nil;
}
scr->dev = vgadev[i]; scr->dev = vgadev[i];
if(scr->dev->enable) if(scr->dev->enable)
scr->dev->enable(scr); scr->dev->enable(scr);
@ -352,6 +357,8 @@ vgactl(Cmdbuf *cb)
error("drawinit: no gscreen"); error("drawinit: no gscreen");
if(scr->dev && scr->dev->drawinit) if(scr->dev && scr->dev->drawinit)
scr->dev->drawinit(scr); scr->dev->drawinit(scr);
hwblank = scr->blank != nil;
hwaccel = scr->scroll || scr->fill;
vgascreenwin(scr); vgascreenwin(scr);
resetscreenimage(); resetscreenimage();
cursoron(1); cursoron(1);

View file

@ -1,8 +1,5 @@
/* /*
* vga driver using just vesa bios to set up. * vga driver using just vesa bios to set up.
*
* note that setting hwaccel to zero will cause cursor ghosts to be
* left behind. hwaccel set non-zero repairs this.
*/ */
#include "u.h" #include "u.h"
#include "../port/lib.h" #include "../port/lib.h"
@ -21,10 +18,18 @@
enum { enum {
Usesoftscreen = 1, Usesoftscreen = 1,
Cdisable = 0,
Cenable,
Cblank,
}; };
static void *hardscreen; static void *hardscreen;
static uchar modebuf[0x1000]; static uchar modebuf[0x1000];
static Chan *creg, *cmem;
static QLock vesaq;
static Rendez vesar;
static int vesactl;
#define WORD(p) ((p)[0] | ((p)[1]<<8)) #define WORD(p) ((p)[0] | ((p)[1]<<8))
#define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
@ -48,19 +53,15 @@ vbesetup(Ureg *u, int ax)
static void static void
vbecall(Ureg *u) vbecall(Ureg *u)
{ {
Chan *creg, *cmem; static QLock callq;
ulong pa; ulong pa;
cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0); eqlock(&callq);
if(waserror()){ if(waserror()){
cclose(cmem); qunlock(&callq);
nexterror();
}
creg = namec("/dev/realmode", Aopen, ORDWR, 0);
if(waserror()){
cclose(creg);
nexterror(); nexterror();
} }
pa = PADDR(RMBUF); pa = PADDR(RMBUF);
if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), pa) != sizeof(modebuf)) if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), pa) != sizeof(modebuf))
error("write modebuf"); error("write modebuf");
@ -77,9 +78,7 @@ vbecall(Ureg *u)
error("read modebuf"); error("read modebuf");
poperror(); poperror();
cclose(creg); qunlock(&callq);
poperror();
cclose(cmem);
} }
static void static void
@ -216,13 +215,88 @@ vesaflush(VGAscr *scr, Rectangle r)
} }
} }
static int
vesadisabled(void *)
{
return vesactl == Cdisable;
}
static void
vesaproc(void*)
{
Ureg u;
while(vesactl != Cdisable){
if(!waserror()){
sleep(&vesar, vesadisabled, nil);
vbesetup(&u, 0x4f10);
if(vesactl == Cblank)
u.bx = 0x0101;
else
u.bx = 0x0001;
vbecall(&u);
poperror();
}
}
cclose(cmem);
cclose(creg);
cmem = creg = nil;
qunlock(&vesaq);
pexit("", 1);
}
static void
vesaenable(VGAscr *)
{
eqlock(&vesaq);
if(waserror()){
qunlock(&vesaq);
nexterror();
}
cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0);
if(waserror()){
cclose(cmem);
cmem = nil;
nexterror();
}
creg = namec("/dev/realmode", Aopen, ORDWR, 0);
poperror();
poperror();
vesactl = Cenable;
kproc("vesa", vesaproc, nil);
}
static void
vesadisable(VGAscr *)
{
vesactl = Cdisable;
wakeup(&vesar);
}
static void
vesablank(VGAscr *, int blank)
{
if(vesactl != Cdisable){
vesactl = blank ? Cblank : Cenable;
wakeup(&vesar);
}
}
static void
vesadrawinit(VGAscr *scr)
{
scr->blank = vesablank;
}
VGAdev vgavesadev = { VGAdev vgavesadev = {
"vesa", "vesa",
0, vesaenable,
0, vesadisable,
0, 0,
vesalinear, vesalinear,
0, vesadrawinit,
0, 0,
0, 0,
0, 0,