From fd28a4fb7a6fb29d64ef108a8acdecb77589a776 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 16 Nov 1994 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1994-11-16 --- pc/clock.c | 1 + pc/devastar.c | 144 +++++++++++++++++++++++++++++++------------------- port/qio.c | 49 +++++++++-------- 3 files changed, 117 insertions(+), 77 deletions(-) diff --git a/pc/clock.c b/pc/clock.c index 0c0a486235d87924ce68d06d029591e2658fc156..6a67a377dee24dc79061303436b748ff3eb1e4ff 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -97,6 +97,7 @@ X86type x86type[] = { 4, 0, 24, "Intel486DX", }, { 4, 1, 24, "Intel486DX", }, { 4, 2, 24, "Intel486SX", }, + { 4, 3, 24, "Intel486DX2", }, { 4, 4, 24, "Intel486DX2", }, { 4, 5, 24, "Intel486SL", }, { 4, 8, 24, "IntelDX4", }, diff --git a/pc/devastar.c b/pc/devastar.c index e36001f1755597fd33cda163bf1f1ff8ae2b365b..cd78e3b2456ac1602fea88a4b6364da741d3db47 100644 --- a/pc/devastar.c +++ b/pc/devastar.c @@ -57,6 +57,9 @@ enum #define APAGE(x) ((x)>>Pageshift) +#define LOCKPAGE(a, o) if((a)->needpage){ilock(&(a)->pagelock);setpage(a, o);} +#define UNLOCKPAGE(a) if((a)->needpage)iunlock(&(a)->pagelock) + /* IRQ codes */ static int isairqcode[16] = { @@ -242,10 +245,10 @@ struct Astar Astarchan *c; /* channels */ int ramsize; /* 16k or 256k */ int memsize; /* size of memory currently mapped */ + int needpage; GCB *gcb; /* global board comm area */ uchar *addr; /* base of memory area */ int running; - }; /* host per channel info */ @@ -258,6 +261,7 @@ struct Astarchan CCB *ccb; /* channel control block */ int perm; int opens; + int baud; Queue *iq; Queue *oq; @@ -282,6 +286,7 @@ enum static int astarsetup(Astar*); static void astarintr(Ureg*, void*); static void astarkick(Astarchan*); +static void astarkickin(Astarchan*); static void enable(Astarchan*); static void disable(Astarchan*); static void astarctl(Astarchan*, char*); @@ -526,8 +531,11 @@ astaropen(Chan *c, int omode) qunlock(ac); nexterror(); } - if(ac->opens++ == 0) + if(ac->opens++ == 0){ enable(ac); + qreopen(ac->iq); + qreopen(ac->oq); + } qunlock(ac); poperror(); break; @@ -598,11 +606,10 @@ memread(Astar *a, uchar *to, long n, ulong offset) * go via tmp to avoid pagefaults while ilock'd */ tp = tmp; - ilock(&a->pagelock); - setpage(a, offset); + LOCKPAGE(a, offset); for(e = tp + i; tp < e;) *tp++ = *from++; - iunlock(&a->pagelock); + UNLOCKPAGE(a); memmove(to, tmp, i); to += i; @@ -645,7 +652,7 @@ astarread(Chan *c, void *buf, long n, ulong offset) case Qdata: a = astar[BOARD(c->qid.path)]; ac = a->c + CHAN(c->qid.path); - return qread(ac->oq, buf, n); + return qread(ac->iq, buf, n); } return 0; @@ -684,11 +691,10 @@ memwrite(Astar *a, uchar *from, long n, ulong offset) */ memmove(tmp, from, i); tp = tmp; - ilock(&a->pagelock); - setpage(a, offset); + LOCKPAGE(a, offset); for(e = tp + i; tp < e;) *to++ = *tp++; - iunlock(&a->pagelock); + UNLOCKPAGE(a); from += i; offset += i; @@ -714,6 +720,11 @@ startcp(Astar *a) /* take board out of download mode and enable IRQ */ outb(a->port+ISActl1, ISAien|isairqcode[a->irq]|ISAnotdl); a->memsize = a->ramsize; + setpage(a, 0); + if(a->memsize <= Pagesize) + a->needpage = 0; + else + a->needpage = 1; /* wait for control program to signal life */ for(i = 0; i < 21; i++){ @@ -727,11 +738,10 @@ startcp(Astar *a) } if(waserror()){ - iunlock(&a->pagelock); + UNLOCKPAGE(a); poperror(); } - ilock(&a->pagelock); - setpage(a, 0); + LOCKPAGE(a, 0); i = LEUS(a->gcb->type); switch(i){ default: @@ -761,7 +771,8 @@ startcp(Astar *a) error(Eio); } } - iunlock(&a->pagelock); + + UNLOCKPAGE(a); poperror(); /* setup the channels */ @@ -773,13 +784,15 @@ startcp(Astar *a) ac->a = a; ac->ccb = (CCB*)x; ac->perm = 0660; - ac->iq = qopen(4*1024, 0, 0, 0); + ac->iq = qopen(4*1024, 0, astarkickin, ac); ac->oq = qopen(4*1024, 0, astarkick, ac); x += sz; } - /* reenable interrupts */ + /* enable control program interrupt generation */ + LOCKPAGE(a, 0); a->gcb->cmd2 = LEUS(Gintack); + UNLOCKPAGE(a); } static void @@ -801,9 +814,10 @@ bctlwrite(Astar *a, char *cmsg) c = inb(a->port+ISActl1); outb(a->port+ISActl1, c & ~ISAnotdl); a->memsize = Pramsize; + a->needpage = 1; /* enable ISA access to first 16k */ - outb(a->port+ISActl2, ISAmen); + setpage(a, 0); } else if(strncmp(cmsg, "sharedmem", 9) == 0){ /* map shared memory */ @@ -835,10 +849,9 @@ chancmddone(void *arg) Astarchan *ac = arg; int x; - ilock(&ac->a->pagelock); - setpage(ac->a, 0); + LOCKPAGE(ac->a, 0); x = ac->ccb->cmd; - iunlock(&ac->a->pagelock); + UNLOCKPAGE(ac->a); return !x; } @@ -850,19 +863,17 @@ chancmd(Astarchan *ac, int cmd) ccb = ac->ccb; - ilock(&ac->a->pagelock); - setpage(ac->a, 0); + LOCKPAGE(ac->a, 0); ccb->cmd = cmd; - iunlock(&ac->a->pagelock); + UNLOCKPAGE(ac->a); /* wait outside of lock */ tsleep(&ac->r, chancmddone, ac, 1000); - ilock(&ac->a->pagelock); - setpage(ac->a, 0); + LOCKPAGE(ac->a, 0); status = ccb->status; cmd = ccb->cmd; - iunlock(&ac->a->pagelock); + UNLOCKPAGE(ac->a); if(cmd){ print("astar%d cmd didn't terminate\n", ac->a->id); error(Eio); @@ -884,12 +895,11 @@ enable(Astarchan *ac) int n; /* make sure we control RTS, DTR and break */ - ilock(&a->pagelock); - setpage(a, 0); + LOCKPAGE(a, 0); n = LEUS(ac->ccb->proto) | Cmctl; ac->ccb->proto = LEUS(n); ac->ccb->outlow = 64; - iunlock(&a->pagelock); + UNLOCKPAGE(a); chancmd(ac, Cconfall); astarctl(ac, "b9600"); @@ -911,11 +921,6 @@ disable(Astarchan *ac) astarctl(ac, "d0"); astarctl(ac, "r0"); - ilock(&ac->a->pagelock); - setpage(ac->a, 0); - ac->ccb->intrigger = 0; - iunlock(&ac->a->pagelock); - chancmd(ac, Crcvdis|Cxmtdis|Cflushin|Cflushout|Cconfall); } @@ -943,12 +948,12 @@ astarctl(Astarchan *ac, char *cmd) i = atoi(cmd+1); a = ac->a; - ilock(&a->pagelock); - setpage(a, 0); + LOCKPAGE(a, 0); switch(*cmd){ case 'B': case 'b': + /* set baud rate (high rates are special - only 16 bits) */ switch(i){ case 76800: ccb->baud = LEUS(Cb76800); @@ -960,6 +965,15 @@ astarctl(Astarchan *ac, char *cmd) ccb->baud = LEUS(i); break; } + ac->baud = i; + + /* set trigger level to about 50 per second */ + n = i/500; + i = (LEUS(ccb->inlim) - LEUS(ccb->inbase))/2; + if(n > i) + n = i; + ccb->intrigger = LEUS(n); + command = Cconfall; break; case 'D': @@ -993,15 +1007,15 @@ astarctl(Astarchan *ac, char *cmd) case 'M': /* turn on cts */ n = LEUS(ccb->proto); - if(i) - n |= Cobeycts; - else - n &= ~Cobeycts; + if(i){ + n |= Cobeycts|Cgenrts; + n &= ~Cmctl; + } else { + n &= ~(Cobeycts|Cgenrts); + n |= Cmctl; + } ccb->proto = LEUS(n); - /* set fifo sizes */ - ccb->intrigger = 8; - command = Cconfall; break; case 'n': @@ -1031,12 +1045,11 @@ astarctl(Astarchan *ac, char *cmd) i = 250; n = LEUS(ccb->mctl) | Cbreakctl; ccb->mctl = LEUS(n); - iunlock(&a->pagelock); + UNLOCKPAGE(a); tsleep(&ac->r, return0, 0, i); - ilock(&a->pagelock); - setpage(a, 0); + LOCKPAGE(a, 0); n &= ~Cbreakctl; ccb->mctl = LEUS(n); break; @@ -1065,7 +1078,7 @@ astarctl(Astarchan *ac, char *cmd) command = Cconfall; break; } - iunlock(&a->pagelock); + UNLOCKPAGE(a); if(command) chancmd(ac, command); @@ -1160,7 +1173,8 @@ astarkick1(Astarchan *ac) uchar *rp, *wp, *bp, *ep, *p, *e; int n; - setpage(a, 0); + if(a->needpage) + setpage(a, 0); ep = a->addr; rp = ep + LEUS(ccb->outrp); wp = ep + LEUS(ccb->outwp); @@ -1177,14 +1191,16 @@ astarkick1(Astarchan *ac) n = qconsume(ac->oq, buf, n); if(n <= 0) break; - setpage(a, bp - a->addr); + if(a->needpage) + setpage(a, bp - a->addr); e = buf + n; for(p = buf; p < e;){ *wp++ = *p++; if(wp > ep) wp = bp; } - setpage(a, 0); + if(a->needpage) + setpage(a, 0); ccb->outwp = LEUS(wp - a->addr); } } @@ -1208,7 +1224,8 @@ astarinput(Astarchan *ac) uchar *rp, *wp, *bp, *ep, *p, *e; int n; - setpage(a, 0); + if(a->needpage) + setpage(a, 0); ep = a->addr; rp = ep + LEUS(ccb->inrp); wp = ep + LEUS(ccb->inwp); @@ -1222,17 +1239,33 @@ astarinput(Astarchan *ac) n += ep - bp + 1; if(n > sizeof(buf)) n = sizeof(buf); - setpage(a, bp - a->addr); + if(a->needpage) + setpage(a, bp - a->addr); e = buf + n; for(p = buf; p < e;){ *p++ = *rp++; if(rp > ep) rp = bp; } - qproduce(ac->iq, buf, n); + if(qroduce(ac->iq, buf, n) < 0) + break; /* flow controlled */ + if(a->needpage) + setpage(a, 0); + ccb->inrp = LEUS(rp - a->addr); } - setpage(a, 0); - ccb->inrp = LEUS(rp - a->addr); + if(a->needpage) + setpage(a, 0); +} + +/* + * get flow controlled input going again + */ +static void +astarkick(Astarchan *ac) +{ + ilock(&ac->a->pagelock); + astarinput(ac); + iunlock(&ac->a->pagelock); } /* @@ -1247,7 +1280,8 @@ astarintr(Ureg *ur, void *arg) USED(ur); lock(&a->pagelock); - setpage(a, 0); + if(a->needpage) + setpage(a, 0); /* get causes */ invec = LEUS(xchgw(&a->gcb->inserv, 0)); diff --git a/port/qio.c b/port/qio.c index d5b0b2fc3fe636cfd91ba3455372eca194059a57..601f9641e63e2b698e4794523daa87bb9136a480 100644 --- a/port/qio.c +++ b/port/qio.c @@ -294,6 +294,7 @@ qproduce(Queue *q, void *vp, int len) /* no waiting receivers, room in buffer? */ if(q->len >= q->limit){ + q->state |= Qflow; unlock(q); return -1; } @@ -301,6 +302,7 @@ qproduce(Queue *q, void *vp, int len) /* save in buffer */ b = iallocb(len); if(b == 0){ + q->state |= Qflow; unlock(q); return -2; } @@ -375,31 +377,11 @@ long qread(Queue *q, void *vp, int len) { Block *b; - int n, dowakeup, syncwait; + int n, dowakeup; uchar *p = vp; qlock(&q->rlock); - syncwait = 0; if(waserror()){ - /* can't let go if the buffer is in use */ - if(syncwait){ - qlock(&q->wlock); - ilock(q); - if(q->syncbuf == 0){ - /* we got some data before the interrupt, queue it */ - b = allocb(q->synclen); - memmove(b->wp, vp, q->synclen); - b->wp += q->synclen; - b->next = q->bfirst; - if(q->bfirst == 0) - q->blast = b; - q->bfirst = b; - q->len += q->synclen; - } - q->syncbuf = 0; - iunlock(q); - qunlock(&q->wlock); - } qunlock(&q->rlock); nexterror(); } @@ -427,8 +409,28 @@ qread(Queue *q, void *vp, int len) q->synclen = len; q->syncbuf = vp; iunlock(q); - syncwait = 1; USED(syncwait); + if(waserror()){ + /* sync with qwrite() & qproduce() */ + qlock(&q->wlock); + ilock(q); + if(q->syncbuf == 0){ + /* we got some data before the interrupt */ + b = allocb(q->synclen); + memmove(b->wp, vp, q->synclen); + b->wp += q->synclen; + b->next = q->bfirst; + if(q->bfirst == 0) + q->blast = b; + q->bfirst = b; + q->len += q->synclen; + } + q->syncbuf = 0; + iunlock(q); + qunlock(&q->wlock); + nexterror(); + } sleep(&q->rr, filled, q); + poperror(); len = q->synclen; qunlock(&q->rlock); poperror(); @@ -461,12 +463,15 @@ qread(Queue *q, void *vp, int len) b->rp += n; QDEBUG checkb(b, "qread 2"); + /* free it or put what's left on the queue */ if(b->rp >= b->wp || (q->state&Qmsg)) { freeb(b); } else { ilock(q); b->next = q->bfirst; + if(q->bfirst == 0) + q->blast = b; q->bfirst = b; q->len += BLEN(b); iunlock(q);