M gnot/dev.c => gnot/dev.c +2 -0
@@ 67,6 67,8 @@ devattach(int tc, char *spec)
Chan *
devclone(Chan *c, Chan *nc)
{
+ if(c->flag & COPEN)
+ panic("clone of open file type %c\n", devchar[c->type]);
if(nc == 0)
nc = newchan();
nc->type = c->type;
M gnot/errno.h => gnot/errno.h +1 -0
@@ 49,5 49,6 @@ enum{
Ebadblt, /* bad bitblt or bitmap request */
Enobitmap, /* out of bitmap descriptors */
Enobitstore, /* out of bitmap storage */
+ Ebadbitmap, /* unallocated bitmap */
Egreg, /* it's all greg's fault */
};
M gnot/fns.h => gnot/fns.h +1 -0
@@ 69,6 69,7 @@ void machinit(void);
void mapstack(Proc*);
void mmuinit(void);
int mount(Chan*, Chan*, int);
+void mousebuttons(int);
Chan *namec(char*, int, int, ulong);
void nexterror(void);
Alarm *newalarm(void);
M gnot/screen.c => gnot/screen.c +75 -7
@@ 16,6 16,8 @@ struct{
int bwid;
}out;
+void duartinit(void);
+
Bitmap screen =
{
(ulong*)((4*1024*1024-256*1024)|KZERO), /* BUG */
@@ 29,7 31,8 @@ Bitmap screen =
void
screeninit(void)
{
- bitblt(&screen, Pt(0, 0), &screen, screen.rect, 0);
+ duartinit();
+ bitblt(&screen, Pt(0, 0), &screen, screen.r, 0);
out.pos.x = MINX;
out.pos.y = 0;
out.bwid = defont0.info[' '].width;
@@ 44,14 47,14 @@ screenputc(int c)
if(c == '\n'){
out.pos.x = MINX;
out.pos.y += defont0.height;
- if(out.pos.y > screen.rect.max.y-defont0.height)
- out.pos.y = screen.rect.min.y;
+ if(out.pos.y > screen.r.max.y-defont0.height)
+ out.pos.y = screen.r.min.y;
bitblt(&screen, Pt(0, out.pos.y), &screen,
- Rect(0, out.pos.y, screen.rect.max.x, out.pos.y+2*defont0.height), 0);
+ Rect(0, out.pos.y, screen.r.max.x, out.pos.y+2*defont0.height), 0);
}else if(c == '\t'){
nx = out.pos.x + (8-(out.pos.x/out.bwid&7))*out.bwid;
out.pos.x = nx;
- if(out.pos.x >= screen.rect.max.x)
+ if(out.pos.x >= screen.r.max.x)
screenputc('\n');
}else if(c == '\b'){
if(out.pos.x >= out.bwid+MINX){
@@ 60,7 63,7 @@ screenputc(int c)
out.pos.x -= out.bwid;
}
}else{
- if(out.pos.x >= screen.rect.max.x-out.bwid)
+ if(out.pos.x >= screen.r.max.x-out.bwid)
screenputc('\n');
buf[0] = c&0x7F;
buf[1] = 0;
@@ 77,13 80,18 @@ struct Duart{
uchar cmnd; /* Command Register */
uchar data; /* RX Holding / TX Holding Register */
uchar ipc_acr; /* Input Port Change/Aux. Control Register */
+#define ivr ivr /* Interrupt Vector Register */
uchar is_imr; /* Interrupt Status/Interrupt Mask Register */
+#define ip_opcr is_imr /* Input Port/Output Port Configuration Register */
uchar ctur; /* Counter/Timer Upper Register */
+#define scc_sopbc ctur /* Start Counter Command/Set Output Port Bits Command */
uchar ctlr; /* Counter/Timer Lower Register */
+#define scc_ropbc ctlr /* Stop Counter Command/Reset Output Port Bits Command */
};
enum{
CHAR_ERR =0x00, /* MR1x - Mode Register 1 */
+ PAR_ENB =0x00,
EVEN_PAR =0x00,
ODD_PAR =0x04,
NO_PAR =0x10,
@@ 113,6 121,9 @@ enum{
PAR_ERR =0x20,
FRM_ERR =0x40,
RCVD_BRK =0x80,
+ BD9600 =0xBB,
+ BD4800 =0x99,
+ BD2400 =0x88,
IM_IPC =0x80, /* IMRx/ISRx - Interrupt Mask/Interrupt Status */
IM_DBB =0x40,
IM_RRDYB =0x20,
@@ 143,6 154,54 @@ uchar keymap[]={
};
void
+duartinit(void)
+{
+ Duart *duart;
+
+ duart = DUARTREG;
+
+ /*
+ * Keyboard
+ */
+ duart[0].cmnd = RESET_RCV|DIS_TX|DIS_RX;
+ duart[0].cmnd = RESET_TRANS;
+ duart[0].cmnd = RESET_ERR;
+ duart[0].cmnd = RESET_MR;
+ duart[0].mr1_2 = CHAR_ERR|PAR_ENB|EVEN_PAR|CBITS8;
+ duart[0].mr1_2 = NORM_OP|ONESTOPB;
+ duart[0].sr_csr = BD4800;
+
+ /*
+ * Pen
+ */
+ duart[1].cmnd = RESET_RCV|DIS_TX|DIS_RX;
+ duart[1].cmnd = RESET_TRANS;
+ duart[1].cmnd = RESET_ERR;
+ duart[1].cmnd = RESET_MR;
+ duart[1].mr1_2 = CHAR_ERR|NO_PAR|CBITS8;
+ duart[1].mr1_2 = NORM_OP|ONESTOPB;
+ duart[1].sr_csr = BD2400;
+
+ /*
+ * Output port
+ */
+ duart[0].ipc_acr = 0xBF; /* allow change of state interrupt */
+ duart[1].ip_opcr = 0x00;
+ duart[1].scc_ropbc = 0xFF; /* make sure the port is reset first */
+ duart[1].scc_sopbc = 0x04; /* dtr = 1, pp = 01 */
+ duart[0].is_imr = IM_IPC|IM_RRDYB|IM_XRDYB|IM_RRDYA;
+ duart[0].cmnd = ENB_TX|ENB_RX; /* enable TX and RX last */
+ duart[1].cmnd = ENB_TX|ENB_RX;
+
+ /*
+ * Initialize keyboard
+ */
+ while (!(duart[0].sr_csr & (XMT_EMT|XMT_RDY)))
+ ;
+ duart[0].data = 0x02;
+}
+
+void
duartintr(void)
{
int cause, status, c;
@@ 176,5 235,14 @@ duartintr(void)
*/
if(cause & IM_RRDYB) /* pen input */
c = duart[1].data;
+ /*
+ * Is it 4?
+ */
+ if(cause & IM_XRDYB)
+ duart[1].cmnd = DIS_TX;
+ /*
+ * Is it 3?
+ */
+ if(cause & IM_IPC)
+ mousebuttons((~duart[0].ipc_acr) & 7);
}
-
M port/dev.c => port/dev.c +2 -0
@@ 67,6 67,8 @@ devattach(int tc, char *spec)
Chan *
devclone(Chan *c, Chan *nc)
{
+ if(c->flag & COPEN)
+ panic("clone of open file type %c\n", devchar[c->type]);
if(nc == 0)
nc = newchan();
nc->type = c->type;
M port/devbit.c => port/devbit.c +176 -25
@@ 9,6 9,13 @@
#include "gnot.h"
+extern Font defont0; /* BUG */
+
+/*
+ * Device (#b/bitblt) is exclusive use on open, so no locks are necessary
+ * for i/o
+ */
+
/*
* Some fields in Bitmaps are overloaded:
* ldepth = -1 means free.
@@ 20,27 27,30 @@
struct{
Ref;
int bltuse;
- QLock blt; /* a group of bitblts in a single write is atomic */
Bitmap *map; /* arena */
Bitmap *free; /* free list */
ulong *words; /* storage */
ulong nwords; /* total in arena */
ulong *wfree; /* pointer to next free word */
int lastid; /* last allocated bitmap id */
+ int init; /* freshly opened; init message pending */
}bit;
#define FREE 0x80000000
void bitcompact(void);
void bitfree(Bitmap*);
extern Bitmap screen;
+Mouse mouse;
enum{
Qdir,
Qbitblt,
+ Qmouse,
};
Dirtab bitdir[]={
"bitblt", Qbitblt, 0, 0600,
+ "mouse", Qmouse, 0, 0600,
};
#define NBIT (sizeof bitdir/sizeof(Dirtab))
@@ 113,6 123,7 @@ bitopen(Chan *c, int omode)
error(0, Einuse);
}
bit.lastid = -1;
+ bit.init = 1;
unlock(&bit);
incref(&bit);
}
@@ 147,7 158,7 @@ bitclose(Chan *c)
Bitmap *bp;
if(c->qid != CHDIR){
- lock(&bit); /* FREE ALL THE BITMAPS: BUG */
+ lock(&bit);
if(--bit.ref == 0){
for(i=1,bp=&bit.map[1]; i<conf.nbitmap; i++,bp++)
if(bp->ldepth >= 0)
@@ 160,6 171,15 @@ bitclose(Chan *c)
#define GSHORT(p) (((p)[0]<<0) | ((p)[1]<<8))
#define GLONG(p) ((GSHORT(p)<<0) | (GSHORT(p+2)<<16))
+#define PSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
+#define PLONG(p, v) (PSHORT(p, (v)), PSHORT(p+2, (v)>>16))
+
+/*
+ * These macros turn user-level (high bit at left) into internal (whatever)
+ * bit order. On the gnot they're trivial.
+ */
+#define U2K(x) (x)
+#define K2U(x) (x)
long
bitread(Chan *c, void *va, long n)
@@ 172,20 192,37 @@ bitread(Chan *c, void *va, long n)
if(c->qid != Qbitblt)
error(0, Egreg);
p = va;
- qlock(&bit.blt);
- if(waserror()){
- qunlock(&bit.blt);
- nexterror();
- }
/*
* Fuss about and figure out what to say.
*/
+ if(bit.init){
+ /*
+ * init:
+ * 'I' 1
+ * ldepth 2
+ * rectangle 16
+ */
+ if(n < 19)
+ error(0, Ebadblt);
+ p[0] = 'I';
+ PSHORT(p+1, screen.ldepth);
+ PLONG(p+3, screen.r.min.x);
+ PLONG(p+7, screen.r.min.y);
+ PLONG(p+11, screen.r.max.x);
+ PLONG(p+15, screen.r.max.y);
+ bit.init = 0;
+ goto done;
+ }
if(bit.lastid > 0){
+ /*
+ * allocate:
+ * 'A' 1
+ * bitmap id 2
+ */
if(n < 3)
error(0, Ebadblt);
p[0] = 'A';
- p[1] = bit.lastid;
- p[2] = bit.lastid>>8;
+ PSHORT(p+1, bit.lastid);
bit.lastid = -1;
n = 3;
goto done;
@@ 193,7 230,6 @@ bitread(Chan *c, void *va, long n)
error(0, Ebadblt);
done:
- qunlock(&bit.blt);
return n;
}
@@ 201,9 237,8 @@ bitread(Chan *c, void *va, long n)
long
bitwrite(Chan *c, void *va, long n)
{
- uchar *p;
- long m;
- long v;
+ uchar *p, *q;
+ long m, v, miny, maxy, t, x, y;
ulong l, nw, ws;
Point pt;
Rectangle rect;
@@ 217,13 252,12 @@ bitwrite(Chan *c, void *va, long n)
p = va;
m = n;
- qlock(&bit.blt);
- if(waserror()){
- qunlock(&bit.blt);
- nexterror();
- }
while(m > 0)
switch(*p){
+ default:
+ pprint("bitblt request 0x%x\n", *p);
+ error(0, Ebadblt);
+
case 'a':
/*
* allocate:
@@ 247,7 281,6 @@ bitwrite(Chan *c, void *va, long n)
if(rect.min.x >= 0)
l = (rect.max.x+ws-1)/ws - rect.min.x/ws;
else{ /* make positive before divide */
- long t;
t = (-rect.min.x)+ws-1;
t = (t/ws)*ws;
l = (t+rect.max.x+ws-1)/ws;
@@ 273,7 306,7 @@ bitwrite(Chan *c, void *va, long n)
bp->zero = -bp->zero;
bp->width = l;
bp->ldepth = v;
- bp->rect = rect;
+ bp->r = rect;
bp->cache = 0;
bit.lastid = bp-bit.map;
m -= 18;
@@ 295,13 328,13 @@ bitwrite(Chan *c, void *va, long n)
v = GSHORT(p+1);
dst = &bit.map[v];
if(v<0 || v>=conf.nbitmap || dst->ldepth < 0)
- error(0, Ebadblt);
+ error(0, Ebadbitmap);
pt.x = GLONG(p+3);
pt.y = GLONG(p+7);
v = GSHORT(p+11);
src = &bit.map[v];
if(v<0 || v>=conf.nbitmap || src->ldepth < 0)
- error(0, Ebadblt);
+ error(0, Ebadbitmap);
rect.min.x = GLONG(p+13);
rect.min.y = GLONG(p+17);
rect.max.x = GLONG(p+21);
@@ 322,15 355,124 @@ bitwrite(Chan *c, void *va, long n)
error(0, Ebadblt);
v = GSHORT(p+1);
dst = &bit.map[v];
- if(v >= conf.nbitmap || dst->ldepth<0)
- error(0, Ebadblt);
+ if(v>=conf.nbitmap || dst->ldepth<0)
+ error(0, Ebadbitmap);
bitfree(dst);
m -= 3;
p += 3;
break;
+
+ case 's':
+ /*
+ * string
+ * 's' 1
+ * id 2
+ * pt 8
+ * font id 2
+ * fcode 2
+ * string n (null terminated)
+ */
+ if(m < 16)
+ error(0, Ebadblt);
+ v = GSHORT(p+1);
+ dst = &bit.map[v];
+ if(v>=conf.nbitmap || dst->ldepth<0)
+ error(0, Ebadbitmap);
+ pt.x = GLONG(p+3);
+ pt.y = GLONG(p+7);
+ v = GSHORT(p+11);
+ if(v != 0) /* BUG */
+ error(0, Ebadblt);
+ v = GSHORT(p+13);
+ p += 15;
+ m -= 15;
+ q = memchr(p, 0, m);
+ if(q == 0)
+ error(0, Ebadblt);
+ string(dst, pt, &defont0/*BUG*/, (char*)p, v);
+ q++;
+ m -= q-p;
+ p = q;
+ break;
+
+ case 't':
+ /*
+ * texture
+ * 't' 1
+ * dst id 2
+ * Rectangle 16
+ * src id 2
+ * fcode 2
+ */
+ if(m < 23)
+ error(0, Ebadblt);
+ v = GSHORT(p+1);
+ dst = &bit.map[v];
+ if(v>=conf.nbitmap || dst->ldepth<0)
+ error(0, Ebadbitmap);
+ rect.min.x = GLONG(p+3);
+ rect.min.y = GLONG(p+7);
+ rect.max.x = GLONG(p+11);
+ rect.max.y = GLONG(p+15);
+ v = GSHORT(p+19);
+ src = &bit.map[v];
+ if(v>=conf.nbitmap || src->ldepth<0)
+ error(0, Ebadbitmap);
+ if(src->r.min.x!=0 || src->r.min.y!=0 || src->r.max.x!=16 || src->r.max.y!=16)
+ error(0, Ebadblt);
+ v = GSHORT(p+21);
+ {
+ int i;
+ Texture t;
+
+ for(i=0; i<16; i++)
+ t.bits[i] = src->base[i]>>16;
+ texture(dst, rect, &t, v);
+ }
+ m -= 23;
+ p += 23;
+ break;
+
+ case 'w':
+ /*
+ * write
+ * 'w' 1
+ * dst id 2
+ * miny 4
+ * maxy 4
+ * data bytewidth*(maxy-miny)
+ */
+ if(m < 11)
+ error(0, Ebadblt);
+ v = GSHORT(p+1);
+ dst = &bit.map[v];
+ if(v>=conf.nbitmap || dst->ldepth<0)
+ error(0, Ebadbitmap);
+ miny = GLONG(p+3);
+ maxy = GLONG(p+7);
+ ws = 1<<(3-dst->ldepth); /* pixels per byte */
+ /* set l to number of bytes of incoming data per scan line */
+ if(dst->r.min.x >= 0)
+ l = (dst->r.max.x+ws-1)/ws - dst->r.min.x/ws;
+ else{ /* make positive before divide */
+ t = (-dst->r.min.x)+ws-1;
+ t = (t/ws)*ws;
+ l = (t+dst->r.max.x+ws-1)/ws;
+ }
+ p += 11;
+ m -= 11;
+ if(m < l*(maxy-miny))
+ error(0, Ebadblt);
+ for(y=miny; y<maxy; y++){
+ q = (uchar*)addr(dst, Pt(dst->r.min.x, y));
+ q += (dst->r.min.x&((sizeof(ulong))*ws-1))/8;
+ for(x=0; x<l; x++)
+ *q++ = U2K(*p++);
+ m -= l;
+ }
+ break;
}
- qunlock(&bit.blt);
return n;
}
@@ 377,3 519,12 @@ print("bitcompact\n");
bit.wfree = p1;
print("bitcompact done\n");
}
+
+void
+mousebuttons(int b)
+{
+ if(mouse.buttons != b){
+ print("buttons %x\n", b);
+ mouse.buttons = b;
+ }
+}