ref: a3dadbb7da20c3d408bc4df8f4a4e330c31ce28b
parent: 4f5158212c2a448575966da9116715a95cfc7056
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Tue Aug 23 01:33:51 EDT 2011
implement vesa screenblanking (issue #36)
--- a/sys/src/9/pc/devvga.c
+++ b/sys/src/9/pc/devvga.c
@@ -277,8 +277,13 @@
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 @@
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);
--- 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 @@
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);
+ qunlock(&callq);
nexterror();
}
- creg = namec("/dev/realmode", Aopen, ORDWR, 0);- if(waserror()){- cclose(creg);
- nexterror();
- }
+
pa = PADDR(RMBUF);
if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), pa) != sizeof(modebuf))
error("write modebuf");@@ -77,9 +78,7 @@
error("read modebuf");poperror();
- cclose(creg);
- poperror();
- cclose(cmem);
+ qunlock(&callq);
}
static void
@@ -216,13 +215,88 @@
}
}
+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",
+ vesaenable,
+ vesadisable,
0,
- 0,
- 0,
vesalinear,
- 0,
+ vesadrawinit,
0,
0,
0,
--
⑨