ref: 0dbbe79116b4ced3ee0e777a3c31bc87edb81b5e
parent: 98640950d7ff742aeafd4910d67a0ed5a9871b86
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Jun 11 12:04:24 EDT 2015
zynq: add support for hardware cursor to enable hardware cursor, write "addr va" to /dev/mousectl where va is the virtual address of the cursor position register.
--- a/sys/src/9/zynq/screen.c
+++ b/sys/src/9/zynq/screen.c
@@ -23,9 +23,19 @@
uintptr addr;
} fbscreen;
+static struct {
+ Rendez;
+
+ Cursor;
+
+ Proc *proc;
+ uintptr addr;
+} hwcursor;
+
void
cursoron(void)
{
+ wakeup(&hwcursor);
}
void
@@ -34,8 +44,9 @@
}
void
-setcursor(Cursor*)
+setcursor(Cursor *curs)
{
+ hwcursor.Cursor = *curs;
}
void
@@ -88,9 +99,80 @@
{
}
+
+static void
+cursorproc(void *arg)
+{
+ uchar *set, *clr;
+ u32int *reg;
+ Point xy;
+ int i;
+
+ for(i = 0; i < NSEG; i++)
+ if(up->seg[i] == nil && i != ESEG)
+ break;
+ if(i == NSEG)
+ panic(up->text);
+
+ up->seg[i] = arg;
+
+ cclose(up->dot);
+ up->dot = up->slash;
+ incref(up->dot);
+
+ hwcursor.proc = up;
+ if(waserror()){
+ hwcursor.addr = 0;
+ hwcursor.proc = nil;
+ return;
+ }
+
+ reg = (u32int*)hwcursor.addr;
+ for(;;){
+ eqlock(&drawlock);
+ xy = addpt(mousexy(), hwcursor.offset);
+ qunlock(&drawlock);
+
+ set = hwcursor.set;
+ clr = hwcursor.clr;
+ for(i=0; i<8; i++){
+ reg[0x70/4 + i] = clr[i*4]<<24 | clr[i*4+1]<<16 | clr[i*4+2]<<8 | clr[i*4+3];
+ reg[0x90/4 + i] = set[i*4]<<24 | set[i*4+1]<<16 | set[i*4+2]<<8 | set[i*4+3];
+ }
+ reg[0] = (xy.x<<16) | (xy.y&0xFFFF);
+
+ sleep(&hwcursor, return0, nil);
+ }
+}
+
void
-mousectl(Cmdbuf *)
+mousectl(Cmdbuf *cb)
{
+ Segment *s;
+ uintptr addr;
+
+ if(strcmp(cb->f[0], "addr") == 0 && cb->nf == 2){
+ s = nil;
+ addr = strtoul(cb->f[1], 0, 0);
+ if(addr != 0){
+ if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0
+ || (addr&3) != 0 || addr+0xB0 > s->top)
+ error(Ebadarg);
+ incref(s);
+ }
+ if(hwcursor.proc != nil){
+ postnote(hwcursor.proc, 0, "die", NUser);
+ while(hwcursor.proc != nil)
+ sched();
+ }
+ if(addr != 0){
+ hwcursor.addr = addr;
+ kproc("cursor", cursorproc, s);
+ }
+ return;
+ }
+
+ error("unknown control message");
}
static int
@@ -100,7 +182,7 @@
}
static void
-flushproc(void *arg)
+screenproc(void *arg)
{
int sno, n, w;
uchar *sp, *dp, *top;
@@ -110,7 +192,7 @@
if(up->seg[sno] == nil && sno != ESEG)
break;
if(sno == NSEG)
- panic("flushproc");
+ panic(up->text);
up->seg[sno] = arg;
@@ -183,23 +265,22 @@
ct = lookupcmd(cb, fbctlmsg, nelem(fbctlmsg));
switch(ct->index){
case CMaddr:
+ s = nil;
addr = strtoul(cb->f[1], 0, 0);
-
- eqlock(&up->seglock);
- if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0){
- qunlock(&up->seglock);
- error(Ebadarg);
+ if(addr != 0){
+ if((s = seg(up, addr, 0)) == nil || (s->type&SG_RONLY) != 0)
+ error(Ebadarg);
+ incref(s);
}
- incref(s);
- qunlock(&up->seglock);
-
if(fbscreen.proc != nil){
postnote(fbscreen.proc, 0, "die", NUser);
while(fbscreen.proc != nil)
sched();
}
- fbscreen.addr = addr;
- kproc("fbflush", flushproc, s);
+ if(addr != 0){
+ fbscreen.addr = addr;
+ kproc("screen", screenproc, s);
+ }
break;
case CMsize:
@@ -220,7 +301,6 @@
if(chantodepth(chan) != z)
error("depth, channel do not match");
- cursoroff();
deletescreenimage();
eqlock(&drawlock);
if(memimageinit() < 0){
@@ -239,7 +319,6 @@
if(gscreen == nil)
error("no framebuffer");
resetscreenimage();
- cursoron();
break;
}
free(cb);
@@ -264,4 +343,3 @@
seprint(p, e, "addr %#p\n", fbscreen.addr);
return readstr(offset, a, n, buf);
}
-