From dddced867518bc3d3ab9bbb0b9d728e35d495f12 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 29 Mar 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-03-29 --- gnot/dev.c | 2 + gnot/errno.h | 1 + gnot/fns.h | 1 + gnot/screen.c | 82 ++++++++++++++++++-- port/dev.c | 2 + port/devbit.c | 201 +++++++++++++++++++++++++++++++++++++++++++------- 6 files changed, 257 insertions(+), 32 deletions(-) diff --git a/gnot/dev.c b/gnot/dev.c index 03e8b481bdb54ac2dfc300eb20595dac6415e3d3..ee50ff468959d001ab32abc344e25bea4be5ee9e 100644 --- a/gnot/dev.c +++ b/gnot/dev.c @@ -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; diff --git a/gnot/errno.h b/gnot/errno.h index 98b6518f4e3ab0458ab091a95d7e66dba45a3ef4..d58c8573ed7c1edc1e8ea9cfb9a97c4ce39e7d84 100644 --- a/gnot/errno.h +++ b/gnot/errno.h @@ -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 */ }; diff --git a/gnot/fns.h b/gnot/fns.h index 62ab5f9dbf1aca37d1cd9a04ed536acfc9c503dc..7b93230314656049f5f5e0a07eb25dba6004ae97 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -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); diff --git a/gnot/screen.c b/gnot/screen.c index 8cff5d32f29febcb9a83a47bd567a552a706156c..f485dea75db5d382c8e8198c6c9922478d2c84dd 100644 --- a/gnot/screen.c +++ b/gnot/screen.c @@ -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, @@ -142,6 +153,54 @@ uchar keymap[]={ 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0xb2, }; +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) { @@ -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); } - diff --git a/port/dev.c b/port/dev.c index 03e8b481bdb54ac2dfc300eb20595dac6415e3d3..ee50ff468959d001ab32abc344e25bea4be5ee9e 100644 --- a/port/dev.c +++ b/port/dev.c @@ -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; diff --git a/port/devbit.c b/port/devbit.c index c842e548030f0bea074a25cfce93a4436c67f3e3..843e134a85353e2cf4bd0d5c095613bb1171fafb 100644 --- a/port/devbit.c +++ b/port/devbit.c @@ -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]; ildepth >= 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; yr.min.x, y)); + q += (dst->r.min.x&((sizeof(ulong))*ws-1))/8; + for(x=0; x