From e54222fb0df35c9738947a6757dde09bf361a576 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 23 Aug 2011 05:33:51 +0200 Subject: [PATCH] implement vesa screenblanking (issue #36) --- sys/src/9/pc/devvga.c | 11 ++++- sys/src/9/pc/vgavesa.c | 108 ++++++++++++++++++++++++++++++++++------- 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/sys/src/9/pc/devvga.c b/sys/src/9/pc/devvga.c index f1ecba8e9..10875f450 100644 --- a/sys/src/9/pc/devvga.c +++ b/sys/src/9/pc/devvga.c @@ -277,8 +277,13 @@ vgactl(Cmdbuf *cb) for(i = 0; vgadev[i]; i++){ if(strcmp(cb->f[1], vgadev[i]->name)) continue; - if(scr->dev && scr->dev->disable) - scr->dev->disable(scr); + if(scr->dev){ + if(scr->dev->disable) + scr->dev->disable(scr); + scr->fill = nil; + scr->scroll = nil; + scr->blank = nil; + } scr->dev = vgadev[i]; if(scr->dev->enable) scr->dev->enable(scr); @@ -352,6 +357,8 @@ vgactl(Cmdbuf *cb) error("drawinit: no gscreen"); if(scr->dev && scr->dev->drawinit) scr->dev->drawinit(scr); + hwblank = scr->blank != nil; + hwaccel = scr->scroll || scr->fill; vgascreenwin(scr); resetscreenimage(); cursoron(1); diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c index c2ea65138..d6e899890 100644 --- a/sys/src/9/pc/vgavesa.c +++ b/sys/src/9/pc/vgavesa.c @@ -1,8 +1,5 @@ /* * 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 "../port/lib.h" @@ -21,10 +18,18 @@ enum { Usesoftscreen = 1, + + Cdisable = 0, + Cenable, + Cblank, }; static void *hardscreen; 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 LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) @@ -48,19 +53,15 @@ vbesetup(Ureg *u, int ax) static void vbecall(Ureg *u) { - Chan *creg, *cmem; + static QLock callq; ulong pa; - cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0); + eqlock(&callq); if(waserror()){ - cclose(cmem); - nexterror(); - } - creg = namec("/dev/realmode", Aopen, ORDWR, 0); - if(waserror()){ - cclose(creg); + qunlock(&callq); nexterror(); } + pa = PADDR(RMBUF); if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), pa) != sizeof(modebuf)) error("write modebuf"); @@ -77,9 +78,7 @@ vbecall(Ureg *u) error("read modebuf"); poperror(); - cclose(creg); - poperror(); - cclose(cmem); + qunlock(&callq); } 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 = { "vesa", - 0, - 0, + vesaenable, + vesadisable, 0, vesalinear, - 0, + vesadrawinit, 0, 0, 0,