From 02f933bc0b55e1b9997e59f71ec80e8df3bb564a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 31 Aug 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-08-31 --- gnot/devcons.c | 316 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 240 insertions(+), 76 deletions(-) diff --git a/gnot/devcons.c b/gnot/devcons.c index a614996104e66986459e8a83659634ab0fe1d7b8..afc56d6a1b2ab666fb0797414f62fb44549b51e8 100644 --- a/gnot/devcons.c +++ b/gnot/devcons.c @@ -8,6 +8,8 @@ #include "devtab.h" +typedef struct IOQ IOQ; + static struct { Lock; @@ -15,8 +17,6 @@ static struct int c; }printq; -typedef struct IOQ IOQ; - #define NQ 2048 struct IOQ{ union{ @@ -31,8 +31,6 @@ struct IOQ{ }; IOQ lineq; -IOQ rs232iq; -IOQ rs232oq; struct{ IOQ; @@ -48,6 +46,44 @@ struct{ Ref raw; /* whether kbd i/o is raw (rcons is open) */ +/* + * rs232 stream module + */ +typedef struct Rs232 Rs232; +typedef struct IOBQ IOBQ; + +#define NBQ 4 +struct IOBQ{ + Block *bp[NBQ]; + int w; + int r; + int f; +}; +#define NEXT(x) ((x+1)%NBQ) + +struct Rs232{ + QLock; + QLock outlock; + IOQ in; + IOBQ out; + int kstarted; /* true if kproc started */ + Queue *wq; + Alarm *a; /* alarm for waking the rs232 kernel process */ + int txenabled; + Rendez r; +}; + +Rs232 rs232; + +static void rs232output(Rs232*); +static void rs232input(Rs232*); +static void rs232timer(Alarm*); +static void rs232kproc(void*); +static void rs232open(Queue*, Stream*); +static void rs232close(Queue*); +static void rs232oput(Queue*, Block*); +Qinfo rs232info = { nullput, rs232oput, rs232open, rs232close, "rs232" }; + void printinit(void) { @@ -57,10 +93,6 @@ printinit(void) kbdq.in = kbdq.buf; kbdq.out = kbdq.buf; - rs232iq.in = rs232iq.buf; - rs232iq.out = rs232iq.buf; - rs232oq.in = rs232oq.buf; - rs232oq.out = rs232oq.buf; klogq.in = klogq.buf; klogq.out = klogq.buf; lineq.in = lineq.buf; @@ -69,10 +101,6 @@ printinit(void) qunlock(&kbdq); lock(&lineq); /* allocate lock */ unlock(&lineq); - lock(&rs232iq); /* allocate lock */ - unlock(&rs232iq); - lock(&rs232oq); /* allocate lock */ - unlock(&rs232oq); lock(&klogq); /* allocate lock */ unlock(&klogq); lock(&klogq.put); /* allocate lock */ @@ -311,25 +339,6 @@ kbdclock(void) kbdchar(kbdq.c); } -void -rs232ichar(int c) -{ - putc(&rs232iq, c); - wakeup(&rs232iq.r); -} - -int -getrs232o(void) -{ - int c; - - c = getc(&rs232oq); - if(c == -1) - rs232oq.state = 0; - wakeup(&rs232oq.r); - return c; -} - int consactive(void) { @@ -348,13 +357,13 @@ enum{ Qpid, Qppid, Qrcons, - Qrs232, Qrs232ctl, Qtime, Quser, Qklog, Qmsec, Qclock, + Qrs232 = STREAMQID(1, Sdataqid), }; Dirtab consdir[]={ @@ -383,10 +392,6 @@ consgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) return -1; tab += i; devdir(c, tab->qid, tab->name, tab->length, tab->perm, dp); - switch(dp->qid){ - case Qrs232: - dp->length = cangetc(&rs232iq); break; - } return 1; } @@ -459,7 +464,14 @@ conswalk(Chan *c, char *name) void consstat(Chan *c, char *dp) { - devstat(c, dp, consdir, NCONS, consgen); + switch(c->qid){ + case Qrs232: + streamstat(c, dp, "rs232"); + break; + default: + devstat(c, dp, consdir, NCONS, consgen); + break; + } } Chan* @@ -484,6 +496,8 @@ consopen(Chan *c, int omode) } unlock(&lineq); } + if(c->qid == Qrs232) + streamopen(c, &rs232info); return devopen(c, omode, consdir, NCONS, consgen); } @@ -498,6 +512,8 @@ consclose(Chan *c) { if(c->qid==Qrcons && (c->flag&COPEN)) decref(&raw); + if(c->qid == Qrs232) + streamclose(c); } long @@ -566,21 +582,7 @@ consread(Chan *c, void *buf, long n) return i; case Qrs232: - qlock(&rs232iq); - if(waserror()){ - qunlock(&rs232iq); - nexterror(); - } - while(!cangetc(&rs232iq)) - sleep(&rs232iq.r, cangetc, &rs232iq); - for(i=0; ioffset) @@ -686,33 +688,13 @@ conswrite(Chan *c, void *va, long n) break; case Qrs232: - qlock(&rs232oq); - if(waserror()){ - qunlock(&rs232oq); - nexterror(); - } - l = n; - while(--l >= 0) { - while (putc(&rs232oq, *a) < 0) - sleep(&rs232oq.r, canputc, &rs232oq); - a++; - if(rs232oq.state == 0){ - splhi(); - if(rs232oq.state == 0){ - rs232oq.state = 1; - duartstartrs232o(); - } - spllo(); - } - } - poperror(); - qunlock(&rs232oq); + n = streamwrite(c, va, n, 1); break; case Qrs232ctl: - qlock(&rs232oq); + qlock(&rs232); if(waserror()){ - qunlock(&rs232oq); + qunlock(&rs232); nexterror(); } if(n<=2 || n>=sizeof buf) @@ -730,7 +712,7 @@ conswrite(Chan *c, void *va, long n) default: error(0, Ebadarg); } - qunlock(&rs232oq); + qunlock(&rs232); break; case Qtime: @@ -791,3 +773,185 @@ consuserstr(Error *e, char *buf) { strcpy(buf, u->p->pgrp->user); } + +/* + * rs232 stream routines + */ +static void +rs232output(Rs232 *r) +{ + int next; + Queue *q; + Block *bp; + + qlock(&r->outlock); + q = r->wq; + + /* + * free emptied blocks + */ + for(; r->out.f != r->out.r; r->out.f = NEXT(r->out.f)){ + freeb(r->out.bp[r->out.f]); + r->out.bp[r->out.f] = 0; + } + + /* + * stage new blocks + */ + bp = getq(q); + for(next = NEXT(r->out.w); bp && next!=r->out.r; next = NEXT(next)){ + r->out.bp[r->out.w] = bp; + bp = getq(q); + r->out.w = next; + } + + /* + * start output + */ + if(r->txenabled == 0){ + r->txenabled = 1; + duartstartrs232o(); + } + qunlock(&r->outlock); +} + +static void +rs232input(Rs232 *r) +{ + Queue *q; + char c; + Block *bp; + + q = RD(r->wq); + bp = 0; + while((c = getc(&r->in)) >= 0){ + if(bp == 0){ + bp->flags |= S_DELIM; + bp = allocb(64); + } + *bp->wptr++ = c; + if(bp->wptr == bp->lim){ + if(QFULL(q->next)) + freeb(bp); + else + PUTNEXT(q, bp); + bp = 0; + } + } + if(bp){ + if(QFULL(q->next)) + freeb(bp); + else + PUTNEXT(q, bp); + } +} + +static int +rs232stuff(void *arg) +{ + Rs232 *r; + + r = arg; + return (r->in.in != r->in.out) || (r->out.r != r->out.w) + || (r->out.f != r->out.r); +} + +static void +rs232kproc(void *a) +{ + Rs232 *r; + + r = a; + for(;;){ + qlock(r); + if(r->wq != 0){ + rs232output(r); + rs232input(r); + } + qunlock(r); + sleep(&r->r, rs232stuff, r); + } +} + +static void +rs232open(Queue *q, Stream *c) +{ + Rs232 *r; + + r = &rs232; + + RD(q)->ptr = r; + WR(q)->ptr = r; + r->wq = WR(q); + + if(r->kstarted == 0){ + r->in.in = r->in.out = r->in.buf; + kproc("rs232", rs232kproc, r); + r->kstarted = 1; + } +} + +static void +rs232close(Queue *q) +{ + Rs232 *r; + + r = q->ptr; + qlock(r); + r->wq = 0; + qunlock(r); +} + +static void +rs232oput(Queue *q, Block *bp) +{ + if(bp->rptr == bp->wptr) + freeb(bp); + else + putq(q, bp); + rs232output(q->ptr); +} + +static void +rs232timer(Alarm *a) +{ + Rs232 *r; + + r = a->arg; + cancel(a); + r->a = 0; + wakeup(&r->r); +} + +void +rs232ichar(int c) +{ + Rs232 *r; + + r = &rs232; + putc(&r->in, c); + if(r->a == 0) + alarm(125, rs232timer, r); +} + +int +getrs232o(void) +{ + int c; + Rs232 *r; + Block *bp; + + r = &rs232; + if(r->out.r == r->out.w){ + r->txenabled = 0; + return -1; + } + bp = r->out.bp[r->out.r]; + c = *bp->rptr++; + if(bp->rptr >= bp->wptr){ + r->out.r = NEXT(r->out.r); + if(r->out.r==r->out.w || NEXT(r->out.r)==r->out.w) + wakeup(&r->r); + } + return c; +}