From ab29c2601af861cdfa1457c4050fb5d5d6fe9da5 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 5 Jun 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-06-05 --- gnot/dat.h | 42 +++ gnot/devcons.c | 719 ++++++++++--------------------------- gnot/devduart.c | 914 ++++++++++++++++++++++++++++++++++++++++++++++++ gnot/fns.h | 20 +- gnot/main.c | 18 + gnot/mem.h | 3 +- gnot/screen.c | 496 +------------------------- port/devbit.c | 8 + port/devproc.c | 6 +- port/fault.c | 4 +- port/portdat.h | 11 +- port/portfns.h | 4 - port/sturp.c | 14 +- port/sysproc.c | 35 ++ power/lock.c | 43 ++- power/mem.h | 21 +- ss/fns.h | 4 + ss/mem.h | 3 +- 18 files changed, 1301 insertions(+), 1064 deletions(-) create mode 100644 gnot/devduart.c diff --git a/gnot/dat.h b/gnot/dat.h index c565f0d004c2b2b7385bfe7206e897a1e8e0921b..1b883fc76ab3a468f6bbee6aba3d7fd2fef7dbe6 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -1,6 +1,8 @@ typedef struct Conf Conf; typedef struct FFrame FFrame; typedef struct FPsave FPsave; +typedef struct IOQ IOQ; +typedef struct KIOQ KIOQ; typedef struct KMap KMap; typedef struct Label Label; typedef struct Lock Lock; @@ -118,6 +120,38 @@ struct KMap }; #define VA(k) ((k)->va) +/* + * character based IO (mouse, keyboard, console screen) + */ +#define NQ 4096 +struct IOQ +{ + Lock; + uchar buf[NQ]; + uchar *in; + uchar *out; + int state; + Rendez r; + union{ + void (*puts)(IOQ*, void*, int); /* output */ + int (*putc)(IOQ*, int); /* input */ + }; + void *ptr; +}; +struct KIOQ +{ + QLock; + IOQ; + int repeat; + int c; + int count; +}; + +extern IOQ lineq; +extern IOQ printq; +extern IOQ mouseq; +extern KIOQ kbdq; + struct Mach { int machno; /* physical id of processor */ @@ -130,6 +164,7 @@ struct Mach void *alarm; /* alarms bound to this clock */ int fpstate; /* state of fp registers on machine */ + int tlbpurge; int tlbfault; int pfault; int cs; @@ -229,5 +264,12 @@ struct User MMUCache mc; }; +struct +{ + Lock; + short machs; + short exiting; +}active; + extern Mach *m; extern User *u; diff --git a/gnot/devcons.c b/gnot/devcons.c index 6fceb9c12a7dfc633668c0ddc6b333ff06d58032..616ea30b61237fe4c2aaaceacf1f017516241c0a 100644 --- a/gnot/devcons.c +++ b/gnot/devcons.c @@ -8,157 +8,89 @@ #include "devtab.h" -typedef struct IOQ IOQ; +struct { + IOQ; /* lock to klogputs */ + QLock; /* qlock to getc */ +} klogq; -static struct -{ - Lock; - int printing; - int c; -}printq; - -#define NQ 2048 -struct IOQ{ - union{ - Lock; - QLock; - }; - uchar buf[NQ]; - uchar *in; - uchar *out; - int state; - Rendez r; -}; - -IOQ lineq; - -struct{ - IOQ; - Lock put; -}klogq; - -struct{ - IOQ; /* qlock to getc; interrupt putc's */ - int c; - int repeat; - int count; -}kbdq; +IOQ lineq; /* lock to getc; interrupt putc's */ +IOQ printq; +IOQ mouseq; +KIOQ kbdq; Ref raw; /* whether kbd i/o is raw (rcons is open) */ /* - * rs232 stream module + * init the queues and set the output routine */ -typedef struct Rs232 Rs232; -typedef struct IOBQ IOBQ; - -#define NBQ 6 -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 started; /* true if output interrupt pending */ - int delay; /* between character input and waking kproc */ - Rendez r; - Rendez rempty; -}; - -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) { - screeninit(); - - lock(&printq); /* allocate lock */ - unlock(&printq); - - kbdq.in = kbdq.buf; - kbdq.out = kbdq.buf; - klogq.in = klogq.buf; - klogq.out = klogq.buf; - lineq.in = lineq.buf; - lineq.out = lineq.buf; - rs232.in.in = rs232.in.buf; - rs232.in.out = rs232.in.buf; - rs232.delay = 64; /* msec */ - qlock(&kbdq); /* allocate qlock */ - qunlock(&kbdq); - lock(&lineq); /* allocate lock */ - unlock(&lineq); - lock(&klogq); /* allocate lock */ - unlock(&klogq); - lock(&klogq.put); /* allocate lock */ - unlock(&klogq.put); + initq(&printq); + initq(&lineq); + initq(&kbdq); + initq(&klogq); + initq(&mouseq); + mouseq.putc = mouseputc; } /* - * Print a string on the console. + * Print a string on the console. Convert \n to \r\n */ void -putstrn(char *str, long n) -{ - int s; - - s = splhi(); - lock(&printq); - printq.printing = 1; - while(--n >= 0) - screenputc(*str++); - printq.printing = 0; - unlock(&printq); - splx(s); +putstrn(char *str, int n) +{ + int s, c, m; + char *t; + + while(n > 0){ + if(printq.puts && *str=='\n') + (*printq.puts)(&printq, "\r", 1); + m = n; + t = memchr(str+1, '\n', m-1); + if(t) + if(t-str < m) + m = t - str; + if(printq.puts) + (*printq.puts)(&printq, str, m); + screenputs(str, m); + n -= m; + str += m; + } } -int -cangetc(void *arg) +/* + * Print a string in the kernel log. Ignore overflow. + */ +void +klogputs(char *str, long n) { - IOQ *q = (IOQ *)arg; - int n = q->in - q->out; - if (n < 0) - n += sizeof(q->buf); - return n; -} + int s, m; + uchar *nextin; -int -canputc(void *arg) -{ - IOQ *q = (IOQ *)arg; - return sizeof(q->buf)-cangetc(q)-1; + s = splhi(); + lock(&klogq); + while(n){ + m = &klogq.buf[NQ] - klogq.in; + if(m > n) + m = n; + memmove(klogq.in, str, m); + n -= m; + str += m; + nextin = klogq.in + m; + if(nextin >= &klogq.buf[NQ]) + klogq.in = klogq.buf; + else + klogq.in = nextin; + } + unlock(&klogq); + splx(s); + wakeup(&klogq.r); } int -isbrkc(void *arg) +isbrkc(KIOQ *q) { - IOQ *q = (IOQ *)arg; uchar *p; for(p=q->out; p!=q->in; ){ @@ -173,51 +105,6 @@ isbrkc(void *arg) return 0; } -int -getc(IOQ *q) -{ - int c; - - if(q->in == q->out) - return -1; - c = *q->out++; - if(q->out == q->buf+sizeof(q->buf)) - q->out = q->buf; - return c; -} - -int -putc(IOQ *q, int c) -{ - uchar *nextin; - if(q->in >= &q->buf[sizeof(q->buf)-1]) - nextin = q->buf; - else - nextin = q->in+1; - if(nextin == q->out) - return -1; - *q->in = c; - q->in = nextin; - return 0; -} - -void -putstrk(char *str, long n) -{ - int s; - - s = splhi(); - lock(&klogq.put); - while(--n >= 0){ - *klogq.in++ = *str++; - if(klogq.in == klogq.buf+sizeof(klogq.buf)) - klogq.in = klogq.buf; - } - unlock(&klogq.put); - splx(s); - wakeup(&klogq.r); -} - int sprint(char *s, char *fmt, ...) { @@ -242,7 +129,7 @@ kprint(char *fmt, ...) int n; n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; - putstrk(buf, n); + klogputs(buf, n); return n; } @@ -257,8 +144,9 @@ panic(char *fmt, ...) buf[n] = '\n'; putstrn(buf, n+1); dumpstack(); - exit(); + for(;;); } + int pprint(char *fmt, ...) { @@ -286,8 +174,7 @@ pprint(char *fmt, ...) void prflush(void) { - while(printq.printing) - delay(100); + while(printq.in != printq.out) ; } void @@ -295,7 +182,6 @@ echo(int c) { char ch; static int ctrlt; - extern void DEBUG(void), dumpqueues(void), mntdump(void); /* * ^t hack BUG @@ -305,6 +191,9 @@ echo(int c) switch(c){ case 0x14: break; /* pass it on */ + case 'm': + mntdump(); + return; case 'p': DEBUG(); return; @@ -312,14 +201,8 @@ echo(int c) dumpqueues(); return; case 'r': - panic("you asked for it"); + firmware(); break; - case 'm': - mntdump(); - return; - case 'i': - incontoggle(); - return; } }else if(c == 0x14){ ctrlt++; @@ -340,43 +223,44 @@ echo(int c) * Put character into read queue at interrupt time. * Always called splhi from proc 0. */ - -void -kbdchar(int c) +int +kbdputc(IOQ *q, int ch) { - if(kbdq.repeat == 1){ - kbdq.c = c; - kbdq.count = 0; - kbdq.repeat = 2; - } - echo(c); - *kbdq.in++ = c; + echo(ch); + kbdq.c = ch; + *kbdq.in++ = ch; if(kbdq.in == kbdq.buf+sizeof(kbdq.buf)) kbdq.in = kbdq.buf; - if(raw.ref || c=='\n' || c==0x04) + if(raw.ref || ch=='\n' || ch==0x04) wakeup(&kbdq.r); + return 0; } void kbdrepeat(int rep) { - if(rep) - kbdq.repeat = 1; - else - kbdq.repeat = 0; + kbdq.repeat = rep; + kbdq.count = 0; } void kbdclock(void) { - if(kbdq.repeat==2 && (++kbdq.count&1)) - kbdchar(kbdq.c); + if(kbdq.repeat == 0) + return; + if(kbdq.repeat==1 && ++kbdq.count>HZ){ + kbdq.repeat = 2; + kbdq.count = 0; + return; + } + if(++kbdq.count&1) + kbdputc(&kbdq, kbdq.c); } int consactive(void) { - return printq.printing; + return printq.in != printq.out; } /* @@ -386,6 +270,8 @@ enum{ Qdir, Qcons, Qcputime, + Qlights, + Qnoise, Qnull, Qpgrpid, Qpid, @@ -396,39 +282,29 @@ enum{ Qklog, Qmsec, Qclock, - Qrs232ctl = STREAMQID(1, Sctlqid), - Qrs232 = STREAMQID(1, Sdataqid), + Qsysstat, }; Dirtab consdir[]={ "cons", {Qcons}, 0, 0600, "cputime", {Qcputime}, 6*NUMSIZE, 0600, + "lights", {Qlights}, 0, 0600, + "noise", {Qnoise}, 0, 0600, "null", {Qnull}, 0, 0600, "pgrpid", {Qpgrpid}, NUMSIZE, 0600, "pid", {Qpid}, NUMSIZE, 0600, "ppid", {Qppid}, NUMSIZE, 0600, "rcons", {Qrcons}, 0, 0600, - "rs232", {Qrs232}, 0, 0600, - "rs232ctl", {Qrs232ctl}, 0, 0600, "time", {Qtime}, NUMSIZE, 0600, "user", {Quser}, 0, 0600, "klog", {Qklog}, 0, 0400, "msec", {Qmsec}, NUMSIZE, 0400, "clock", {Qclock}, 2*NUMSIZE, 0400, + "sysstat", {Qsysstat}, 0, 0600, }; #define NCONS (sizeof consdir/sizeof(Dirtab)) -static int -consgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) -{ - if(tab==0 || i>=ntab) - return -1; - tab += i; - devdir(c, tab->qid, tab->name, tab->length, tab->perm, dp); - return 1; -} - ulong boottime; /* seconds since epoch at boot */ long @@ -492,20 +368,13 @@ consclone(Chan *c, Chan *nc) int conswalk(Chan *c, char *name) { - return devwalk(c, name, consdir, NCONS, consgen); + return devwalk(c, name, consdir, NCONS, devgen); } void consstat(Chan *c, char *dp) { - switch(c->qid.path){ - case Qrs232: - streamstat(c, dp, "rs232"); - break; - default: - devstat(c, dp, consdir, NCONS, consgen); - break; - } + devstat(c, dp, consdir, NCONS, devgen); } Chan* @@ -534,12 +403,8 @@ consopen(Chan *c, int omode) unlock(&lineq); } break; - case Qrs232: - case Qrs232ctl: - streamopen(c, &rs232info); - break; } - return devopen(c, omode, consdir, NCONS, consgen); + return devopen(c, omode, consdir, NCONS, devgen); } void @@ -553,26 +418,26 @@ consclose(Chan *c) { if(c->qid.path==Qrcons && (c->flag&COPEN)) decref(&raw); - if(c->stream) - streamclose(c); } + long consread(Chan *c, void *buf, long n, ulong offset) { - int ch, i, j, k; + int ch, i, j, k, id; ulong l; uchar *out; char *cbuf = buf; char *user; int userlen; - char tmp[6*NUMSIZE]; + char tmp[6*NUMSIZE], xbuf[1024]; + Mach *mp; if(n <= 0) return n; - switch(c->qid.path&~CHDIR){ + switch(c->qid.path & ~CHDIR){ case Qdir: - return devdirread(c, buf, n, consdir, NCONS, consgen); + return devdirread(c, buf, n, consdir, NCONS, devgen); case Qrcons: case Qcons: @@ -603,9 +468,11 @@ consread(Chan *c, void *buf, long n, ulong offset) break; Default: default: - *lineq.in++ = ch; - if(lineq.in == lineq.buf+sizeof(lineq.buf)) + *lineq.in = ch; + if(lineq.in >= lineq.buf+sizeof(lineq.buf)-1) lineq.in = lineq.buf; + else + lineq.in++; } unlock(&lineq); }while(raw.ref==0 && ch!='\n' && ch!=0x04); @@ -622,15 +489,6 @@ consread(Chan *c, void *buf, long n, ulong offset) qunlock(&kbdq); return i; - case Qrs232: - return streamread(c, buf, n); - - case Qrs232ctl: - if(offset) - return 0; - *(char *)buf = duartinputport(); - return 1; - case Qcputime: k = offset; if(k >= sizeof tmp) @@ -658,10 +516,8 @@ consread(Chan *c, void *buf, long n, ulong offset) return readnum(offset, buf, n, u->p->parentpid, NUMSIZE); case Qtime: - return readnum(offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), NUMSIZE); + return readnum(offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), 12); - case Qmsec: - return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE); case Qclock: k = offset; if(k >= 2*NUMSIZE) @@ -696,12 +552,69 @@ consread(Chan *c, void *buf, long n, ulong offset) qunlock(&klogq); return i; + case Qmsec: + return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE); + + case Qsysstat: + j = 0; + for(id = 0; id < 32; id++) { + if(active.machs & (1<cs, mp->intr, mp->syscall, mp->pfault, + mp->tlbfault, mp->tlbpurge, m->spinlock); + } + } + return readstr(offset, buf, n, xbuf); + default: - panic("consread %lux\n", c->qid.path); + panic("consread %lux\n", c->qid); return 0; } } +void +conslights(char *a, int n) +{ + int l; + char line[128]; + char *lp; + int c; + + lp = line; + while(n--){ + *lp++ = c = *a++; + if(c=='\n' || n==0 || lp==&line[sizeof(line)-1]) + break; + } + *lp = 0; + lights(strtoul(line, 0, 0)); +} + +void +consnoise(char *a, int n) +{ + int freq; + int duration; + char line[128]; + char *lp; + int c; + + lp = line; + while(n--){ + *lp++ = c = *a++; + if(c=='\n' || n==0 || lp==&line[sizeof(line)-1]){ + *lp = 0; + freq = strtoul(line, &lp, 0); + while(*lp==' ' || *lp=='\t') + lp++; + duration = strtoul(lp, &lp, 0); + buzz(freq, duration); + lp = line; + } + } +} + long conswrite(Chan *c, void *va, long n, ulong offset) { @@ -709,10 +622,12 @@ conswrite(Chan *c, void *va, long n, ulong offset) char buf[256]; long l, m; char *a = va; + Mach *mp; + int id; switch(c->qid.path){ - case Qcons: case Qrcons: + case Qcons: /* * Damn. Can't page fault in putstrn, so copy the data locally. */ @@ -728,11 +643,6 @@ conswrite(Chan *c, void *va, long n, ulong offset) } break; - case Qrs232: - case Qrs232ctl: - n = streamwrite(c, va, n, 1); - break; - case Qtime: if(n<=0 || boottime!=0) /* only one write please */ return 0; @@ -762,6 +672,30 @@ conswrite(Chan *c, void *va, long n, ulong offset) case Qnull: break; + + case Qnoise: + consnoise(a, n); + break; + + case Qlights: + conslights(a, n); + break; + + case Qsysstat: + for(id = 0; id < 32; id++) { + if(active.machs & (1<cs = 0; + mp->intr = 0; + mp->syscall = 0; + mp->pfault = 0; + mp->tlbfault = 0; + mp->tlbpurge = 0; + mp->spinlock = 0; + } + } + break; + default: error(Egreg); } @@ -779,270 +713,3 @@ conswstat(Chan *c, char *dp) { error(Eperm); } - -/* - * rs232 stream routines - * - * A kernel process, rs232kproc, stages blocks to be output and - * packages input bytes into stream blocks to send upstream. - * The process is awakened whenever the interrupt side is almost - * out of bytes to xmit or 1/16 second has elapsed since a byte - * was input. - */ -static int -rs232empty(void *a) -{ - Rs232 *r; - - r = a; - return r->out.w == r->out.r; -} - -static void -rs232output(Rs232 *r) -{ - int next; - Queue *q; - Block *bp; - long l; - - qlock(&r->outlock); - q = r->wq; - - /* - * free old blocks - */ - for(next = r->out.f; next != r->out.r; next = NEXT(next)){ - freeb(r->out.bp[next]); - r->out.bp[next] = 0; - } - r->out.f = next; - - if(q==0){ - kprint("rs232output: null q\n"); - qunlock(&r->outlock); - return; - } - - /* - * stage new blocks - * - * if we run into a control block, wait till the queue - * is empty before doing the control. - */ - for(next = NEXT(r->out.w); next != r->out.f; next = NEXT(next)){ - bp = getq(q); - if(bp == 0) - break; - if(bp->type == M_CTL){ - if(waserror()){ - freeb(bp); - qunlock(&r->outlock); - nexterror(); - } - while(!rs232empty(r)) - sleep(&r->rempty, rs232empty, r); - l = strtoul((char *)(bp->rptr+1), 0, 0); - switch(*bp->rptr){ - case 'B': - case 'b': - duartbaud(l); - break; - case 'D': - case 'd': - duartdtr(l); - break; - case 'K': - case 'k': - duartbreak(l); - break; - case 'W': - case 'w': - if(l>=0 && l<1000) - r->delay = l; - break; - } - poperror(); - freeb(bp); - break; - } - r->out.bp[r->out.w] = bp; - r->out.w = next; - } - - /* - * start output, the spl's sync with interrupt level - * this wouldn't work on a multi-processor - */ - if(r->started == 0) - duartstartrs232o(); - qunlock(&r->outlock); -} - -static void -rs232input(Rs232 *r) -{ - Queue *q; - int c; - Block *bp; - - q = RD(r->wq); - bp = 0; - while((c = getc(&r->in)) >= 0){ - if(bp == 0){ - bp = allocb(64); - bp->flags |= S_DELIM; - } - *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); - - kprint("rs232open: q=0x%ux, inuse=%d, type=%d, dev=%d, id=%d\n", - q, c->inuse, c->type, c->dev, c->id); - if(r->kstarted == 0){ - r->in.in = r->in.out = r->in.buf; - kproc("rs232", rs232kproc, r); - r->kstarted = 1; - }else - wakeup(&r->r); /* pick up any input characters */ -} - -static void -rs232close(Queue *q) -{ - Rs232 *r; - - kprint("rs232close: q=0x%ux\n", q); - r = q->ptr; - qlock(&r->outlock); - while(!rs232empty(r)) - sleep(&r->rempty, rs232empty, r); - qunlock(&r->outlock); - kprint("rs232close: emptied\n"); - rs232output(r); /* reclaim blocks written */ - 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); -} - -/* - * called by input interrupt. runs splhi - */ -void -rs232ichar(int c) -{ - Rs232 *r; - - r = &rs232; - if(putc(&r->in, c) < 0) - /*screenputc('^')*/; - - /* - * pass upstream within r->delay milliseconds - */ - if(r->a==0){ - if(r->delay == 0) - wakeup(&r->r); - else - r->a = alarm(r->delay, rs232timer, r); - } -} - -/* - * called by output interrupt. runs spl5 - */ -int -getrs232o(void) -{ - uchar c; - Rs232 *r; - Block *bp; - - r = &rs232; - if(r->out.r == r->out.w){ - wakeup(&r->rempty); - r->started = 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); - } - r->started = 1; - return c; -} diff --git a/gnot/devduart.c b/gnot/devduart.c new file mode 100644 index 0000000000000000000000000000000000000000..4b40000d2f7d8127c81dd6cd01868f279a413598 --- /dev/null +++ b/gnot/devduart.c @@ -0,0 +1,914 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "errno.h" + +#include "devtab.h" + +int duartacr; +int duartimr; +void (*kprofp)(ulong); + +/* + * Register set for half the duart. There are really two sets. + */ +struct Duart{ + uchar mr1_2; /* Mode Register Channels 1 & 2 */ + uchar sr_csr; /* Status Register/Clock Select Register */ + 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, + CBITS8 =0x03, + CBITS7 =0x02, + CBITS6 =0x01, + CBITS5 =0x00, + NORM_OP =0x00, /* MR2x - Mode Register 2 */ + TWOSTOPB =0x0F, + ONESTOPB =0x07, + ENB_RX =0x01, /* CRx - Command Register */ + DIS_RX =0x02, + ENB_TX =0x04, + DIS_TX =0x08, + RESET_MR =0x10, + RESET_RCV =0x20, + RESET_TRANS =0x30, + RESET_ERR =0x40, + RESET_BCH =0x50, + STRT_BRK =0x60, + STOP_BRK =0x70, + RCV_RDY =0x01, /* SRx - Channel Status Register */ + FIFOFULL =0x02, + XMT_RDY =0x04, + XMT_EMT =0x08, + OVR_ERR =0x10, + PAR_ERR =0x20, + FRM_ERR =0x40, + RCVD_BRK =0x80, + BD38400 =0xCC|0x0000, + BD19200 =0xCC|0x0100, + BD9600 =0xBB|0x0000, + BD4800 =0x99|0x0000, + BD2400 =0x88|0x0000, + BD1200 =0x66|0x0000, + BD300 =0x44|0x0000, + IM_IPC =0x80, /* IMRx/ISRx - Interrupt Mask/Interrupt Status */ + IM_DBB =0x40, + IM_RRDYB =0x20, + IM_XRDYB =0x10, + IM_CRDY =0x08, + IM_DBA =0x04, + IM_RRDYA =0x02, + IM_XRDYA =0x01, +}; + +/* + * software info for a serial duart interface + */ +typedef struct Duartport Duartport; +struct Duartport +{ + QLock; + int printing; /* true if printing */ + + /* console interface */ + int nostream; /* can't use the stream interface */ + IOQ *iq; /* input character queue */ + IOQ *oq; /* output character queue */ + + /* stream interface */ + Queue *wq; /* write queue */ + Rendez r; /* kproc waiting for input */ + Alarm *a; /* alarm for waking the kernel process */ + int delay; /* between character input and waking kproc */ + int kstarted; /* kproc started */ + uchar delim[256]; /* characters that act as delimiters */ +}; +Duartport duartport[1]; + +uchar keymap[]={ +/*80*/ 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x8e, 0x58, +/*90*/ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x58, 0x58, 0x58, 0x58, +/*A0*/ 0x58, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xae, 0xaf, +/*B0*/ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0x00, 0xbb, 0x1e, 0xbd, 0x60, 0x1f, +/*C0*/ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0x58, 0xc6, 0x0a, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, +/*D0*/ 0x09, 0x08, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x58, +/*E0*/ 0x58, 0x58, 0xe2, 0x1b, 0x0d, 0xe5, 0x58, 0x0a, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, +/*F0*/ 0x09, 0x08, 0xb2, 0x1b, 0x0d, 0xf5, 0x81, 0x58, + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x80, +}; + +void +duartinit(void) +{ + Duart *duart; + static int already; + + if(already) + return; + already = 1; + + 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; + + /* + * RS232 + */ + 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 = BD9600; + + /* + * Output port + */ + duart[0].ipc_acr = duartacr = 0xB7; /* 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 = duartimr = IM_IPC|IM_RRDYB|IM_XRDYB|IM_RRDYA|IM_XRDYA; + 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 +duartbaud(int b) +{ + int x = 0; + Duart *duart = DUARTREG; + + switch(b){ + case 38400: + x = BD38400; + break; + case 19200: + x = BD19200; + break; + case 9600: + x = BD9600; + break; + case 4800: + x = BD4800; + break; + case 2400: + x = BD2400; + break; + case 1200: + x = BD1200; + break; + case 300: + x = BD300; + break; + default: + error(Ebadarg); + } + if(x & 0x0100) + duart[0].ipc_acr = duartacr |= 0x80; + else + duart[0].ipc_acr = duartacr &= ~0x80; + duart[1].sr_csr = x; +} + +void +duartdtr(int val) +{ + Duart *duart = DUARTREG; + if (val) + duart[1].scc_ropbc=0x01; + else + duart[1].scc_sopbc=0x01; +} + +void +duartbreak(int ms) +{ + static QLock brk; + Duart *duart = DUARTREG; + if (ms<=0 || ms >20000) + error(Ebadarg); + qlock(&brk); + duart[0].is_imr = duartimr &= ~IM_XRDYB; + duart[1].cmnd = STRT_BRK|ENB_TX; + tsleep(&u->p->sleep, return0, 0, ms); + duart[1].cmnd = STOP_BRK|ENB_TX; + duart[0].is_imr = duartimr |= IM_XRDYB; + qunlock(&brk); +} + +enum{ + Kptime=200 +}; +void +duartstarttimer(void) +{ + Duart *duart; + char x; + + duart = DUARTREG; + duart[0].ctur = (Kptime)>>8; + duart[0].ctlr = (Kptime)&255; + duart[0].is_imr = duartimr |= IM_CRDY; + x = duart[1].scc_sopbc; + USED(x); +} + +void +duartstoptimer(void) +{ + Duart *duart; + char x; + + duart = DUARTREG; + x = duart[1].scc_ropbc; + USED(x); + duart[0].is_imr = duartimr &= ~IM_CRDY; +} + +struct latin +{ + uchar l; + char c[2]; +}latintab[] = { + '€', "!!", /* spanish initial ! */ + '€', "c|", /* cent */ + '€', "c$", /* cent */ + '€', "l$", /* pound sterling */ + '€', "g$", /* general currency */ + '€', "y$", /* yen */ + '€', "j$", /* yen */ + '€', "||", /* broken vertical bar */ + '€', "SS", /* section symbol */ + '€', "\"\"", /* dieresis */ + '€', "cr", /* copyright */ + '€', "cO", /* copyright */ + '€', "sa", /* super a, feminine ordinal */ + '€', "<<", /* left angle quotation */ + '€', "no", /* not sign, hooked overbar */ + '€', "--", /* soft hyphen */ + '€', "rg", /* registered trademark */ + '€', "__", /* macron */ + '€', "s0", /* degree (sup o) */ + '€', "+-", /* plus-minus */ + '€', "s2", /* sup 2 */ + '€', "s3", /* sup 3 */ + '€', "''", /* grave accent */ + '€', "mu", /* mu */ + '€', "pg", /* paragraph (pilcrow) */ + '€', "..", /* centered . */ + '€', ",,", /* cedilla */ + '€', "s1", /* sup 1 */ + '€', "so", /* sup o */ + '€', ">>", /* right angle quotation */ + '€', "14", /* 1/4 */ + '€', "12", /* 1/2 */ + '€', "34", /* 3/4 */ + '€', "??", /* spanish initial ? */ + '€', "A`", /* A grave */ + '€', "A'", /* A acute */ + '€', "A^", /* A circumflex */ + '€', "A~", /* A tilde */ + '€', "A\"", /* A dieresis */ + '€', "A:", /* A dieresis */ + '€', "Ao", /* A circle */ + '€', "AO", /* A circle */ + '€', "Ae", /* AE ligature */ + '€', "AE", /* AE ligature */ + '€', "C,", /* C cedilla */ + '€', "E`", /* E grave */ + '€', "E'", /* E acute */ + '€', "E^", /* E circumflex */ + '€', "E\"", /* E dieresis */ + '€', "E:", /* E dieresis */ + '€', "I`", /* I grave */ + '€', "I'", /* I acute */ + '€', "I^", /* I circumflex */ + '€', "I\"", /* I dieresis */ + '€', "I:", /* I dieresis */ + '€', "D-", /* Eth */ + '€', "N~", /* N tilde */ + '€', "O`", /* O grave */ + '€', "O'", /* O acute */ + '€', "O^", /* O circumflex */ + '€', "O~", /* O tilde */ + '€', "O\"", /* O dieresis */ + '€', "O:", /* O dieresis */ + '€', "OE", /* O dieresis */ + '€', "Oe", /* O dieresis */ + '€', "xx", /* times sign */ + '€', "O/", /* O slash */ + '€', "U`", /* U grave */ + '€', "U'", /* U acute */ + '€', "U^", /* U circumflex */ + '€', "U\"", /* U dieresis */ + '€', "U:", /* U dieresis */ + '€', "UE", /* U dieresis */ + '€', "Ue", /* U dieresis */ + '€', "Y'", /* Y acute */ + '€', "P|", /* Thorn */ + '€', "Th", /* Thorn */ + '€', "TH", /* Thorn */ + '€', "ss", /* shadp s */ + '€', "a`", /* a grave */ + '€', "a'", /* a acute */ + '€', "a^", /* a circumflex */ + '€', "a~", /* a tilde */ + '€', "a\"", /* a dieresis */ + '€', "a:", /* a dieresis */ + '€', "ao", /* a circle */ + '€', "ae", /* ae ligature */ + '€', "c,", /* c cedilla */ + '€', "e`", /* e grave */ + '€', "e'", /* e acute */ + '€', "e^", /* e circumflex */ + '€', "e\"", /* e dieresis */ + '€', "e:", /* e dieresis */ + '€', "i`", /* i grave */ + '€', "i'", /* i acute */ + '€', "i^", /* i circumflex */ + '€', "i\"", /* i dieresis */ + '€', "i:", /* i dieresis */ + '€', "d-", /* eth */ + '€', "n~", /* n tilde */ + '€', "o`", /* o grave */ + '€', "o'", /* o acute */ + '€', "o^", /* o circumflex */ + '€', "o~", /* o tilde */ + '€', "o\"", /* o dieresis */ + '€', "o:", /* o dieresis */ + '€', "oe", /* o dieresis */ + '€', "-:", /* divide sign */ + '€', "o/", /* o slash */ + '€', "u`", /* u grave */ + '€', "u'", /* u acute */ + '€', "u^", /* u circumflex */ + '€', "u\"", /* u dieresis */ + '€', "u:", /* u dieresis */ + '€', "ue", /* u dieresis */ + '€', "y'", /* y acute */ + '€', "th", /* thorn */ + '€', "p|", /* thorn */ + '€', "y\"", /* y dieresis */ + '€', "y:", /* y dieresis */ + 0, 0, +}; + +int +latin1(int k1, int k2) +{ + int i; + struct latin *l; + + for(l=latintab; l->l; l++) + if(k1==l->c[0] && k2==l->c[1]) + return l->l; + return 0; +} + +/* + * a serial line input interrupt + */ +void +duartrintr(char ch) +{ + IOQ *cq; + Duartport *dp = duartport; + + cq = dp->iq; + if(cq->putc) + (*cq->putc)(cq, ch); + else { + putc(cq, ch); + if(dp->delim[ch]) + wakeup(&cq->r); + } +} + +/* + * a serial line output interrupt + */ +void +duartxintr(void) +{ + int ch; + IOQ *cq; + Duartport *dp = duartport; + Duart *duart; + + cq = dp->oq; + lock(cq); + ch = getc(cq); + duart = DUARTREG; + if(ch < 0){ + dp->printing = 0; + wakeup(&cq->r); + duart[1].cmnd = DIS_TX; + } else + duart[1].data = ch; + unlock(cq); +} + + +void +duartintr(Ureg *ur) +{ + int cause, status, c; + Duart *duart; + static int kbdstate, k1, k2; + + duart = DUARTREG; + cause = duart->is_imr; + /* + * I can guess your interrupt. + */ + /* + * Is it 0? + */ + if(cause & IM_CRDY){ + if(kprofp) + (*kprofp)(ur->pc); + c = duart[1].scc_ropbc; + USED(c); + duart[0].ctur = (Kptime)>>8; + duart[0].ctlr = (Kptime)&255; + c = duart[1].scc_sopbc; + USED(c); + return; + } + /* + * Is it 1? + */ + if(cause & IM_RRDYA){ /* keyboard input */ + status = duart->sr_csr; + c = duart->data; + if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) + duart->cmnd = RESET_ERR; + if(status & PAR_ERR) /* control word: caps lock (0x4) or repeat (0x10) */ + kbdrepeat((c&0x10) == 0); + else{ + if(c == 0x7F) /* VIEW key (bizarre) */ + c = 0xFF; + if(c == 0xB6) /* NUM PAD */ + kbdstate = 1; + else{ + if(c & 0x80) + c = keymap[c&0x7F]; + switch(kbdstate){ + case 1: + k1 = c; + kbdstate = 2; + break; + case 2: + k2 = c; + c = latin1(k1, k2); + if(c == 0){ + kbdputc(&kbdq, k1); + c = k2; + } + /* fall through */ + default: + kbdstate = 0; + kbdputc(&kbdq, c); + } + } + } + } + /* + * Is it 2? + */ + while(cause & IM_RRDYB){ /* duart input */ + status = duart[1].sr_csr; + c = duart[1].data; + if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) + duart[1].cmnd = RESET_ERR; + else + duartrintr(c); + cause = duart->is_imr; + } + /* + * Is it 3? + */ + if(cause & IM_XRDYB) /* duart output */ + duartxintr(); + /* + * Is it 4? + */ + if(cause & IM_XRDYA) + duart[0].cmnd = DIS_TX; + /* + * Is it 5? + */ + if(cause & IM_IPC) + mousebuttons((~duart[0].ipc_acr) & 7); +} + + +/* + * Queue n characters for output; if queue is full, we lose characters. + * Get the output going if it isn't already. + */ +void +duartputs(IOQ *cq, char *s, int n) +{ + int ch, x; + Duartport *dp = duartport; + Duart *duart; + + x = splduart(); + lock(cq); + puts(cq, s, n); + if(dp->printing == 0){ + ch = getc(cq); + if(ch >= 0){ + dp->printing = 1; + duart = DUARTREG; + duart[1].cmnd = ENB_TX; + while(!(duart[1].sr_csr & (XMT_RDY|XMT_EMT))) + ; + duart[1].data = ch; + } + } + unlock(cq); + splx(x); +} + +void +duartdevice(Duartport *dp) +{ + /* + * set up i/o routines + */ + if(dp->oq){ + dp->oq->puts = duartputs; + dp->oq->ptr = dp; + } + if(dp->iq) + dp->iq->ptr = dp; +} + +/* + * set up an duart port as something other than a stream + */ +void +duartspecial(int port, IOQ *oq, IOQ *iq, int baud) +{ + Duartport *dp = &duartport[port]; + + dp->nostream = 1; + dp->oq = oq; + dp->iq = iq; + duartdevice(dp); + duartbaud(baud); +} + +static void duarttimer(Alarm*); +static int duartputc(IOQ *, int); +static void duartstopen(Queue*, Stream*); +static void duartstclose(Queue*); +static void duartoput(Queue*, Block*); +static void duartkproc(void *); +Qinfo duartinfo = +{ + nullput, + duartoput, + duartstopen, + duartstclose, + "duart" +}; + +/* + * wakeup the helper process to do input + */ +static void +duarttimer(Alarm *a) +{ + Duartport *dp = a->arg; + + cancel(a); + dp->a = 0; + wakeup(&dp->iq->r); +} + +static int +duartputc(IOQ *cq, int ch) +{ + Duartport *dp = cq->ptr; int r; + + r = putc(cq, ch); + + /* + * pass upstream within dp->delay milliseconds + */ + if(dp->a==0){ + if(dp->delay == 0) + wakeup(&cq->r); + else + dp->a = alarm(dp->delay, duarttimer, dp); + } + return r; +} + +static void +duartstopen(Queue *q, Stream *s) +{ + Duartport *dp; + char name[NAMELEN]; + + if(s->id > 0) + panic("duartstopen"); + dp = &duartport[s->id]; + + qlock(dp); + dp->wq = WR(q); + WR(q)->ptr = dp; + RD(q)->ptr = dp; + dp->delay = 64; + dp->iq->putc = duartputc; + qunlock(dp); + + /* start with all characters as delimiters */ + memset(dp->delim, 1, sizeof(dp->delim)); + + if(dp->kstarted == 0){ + dp->kstarted = 1; + sprint(name, "duart%d", s->id); + kproc(name, duartkproc, dp); + } +} + +static void +duartstclose(Queue *q) +{ + Duartport *dp = q->ptr; + + qlock(dp); + dp->wq = 0; + dp->iq->putc = 0; + WR(q)->ptr = 0; + RD(q)->ptr = 0; + qunlock(dp); +} + +static void +duartoput(Queue *q, Block *bp) +{ + Duartport *dp = q->ptr; + IOQ *cq; + int n, m; + + if(dp == 0){ + freeb(bp); + return; + } + cq = dp->oq; + if(waserror()){ + freeb(bp); + nexterror(); + } + if(bp->type == M_CTL){ + while (cangetc(cq)) /* let output drain */ + sleep(&cq->r, cangetc, cq); + n = strtoul((char *)(bp->rptr+1), 0, 0); + switch(*bp->rptr){ + case 'B': + case 'b': + duartbaud(n); + break; + case 'D': + case 'd': + duartdtr(n); + break; + case 'K': + case 'k': + duartbreak(n); + break; + case 'R': + case 'r': + /* can't control? */ + break; + case 'W': + case 'w': + if(n>=0 && n<1000) + dp->delay = n; + break; + } + }else while((m = BLEN(bp)) > 0){ + while ((n = canputc(cq)) == 0){ + kprint(" duartoput: sleeping\n"); + sleep(&cq->r, canputc, cq); + } + if(n > m) + n = m; + (*cq->puts)(cq, bp->rptr, n); + bp->rptr += n; + } + freeb(bp); + poperror(); +} + +/* + * process to send bytes upstream for a port + */ +static void +duartkproc(void *a) +{ + Duartport *dp = a; + IOQ *cq = dp->iq; + Block *bp; + int n; + +loop: + while ((n = cangetc(cq)) == 0) + sleep(&cq->r, cangetc, cq); + qlock(dp); + if(dp->wq == 0){ + cq->out = cq->in; + }else{ + bp = allocb(n); + bp->flags |= S_DELIM; + bp->wptr += gets(cq, bp->wptr, n); + PUTNEXT(RD(dp->wq), bp); + } + qunlock(dp); + goto loop; +} + +enum{ + Qdir= 0, + Qtty0= STREAMQID(0, Sdataqid), + Qtty0ctl= STREAMQID(0, Sctlqid), +}; + +Dirtab duartdir[]={ + "tty0", {Qtty0}, 0, 0666, + "tty0ctl", {Qtty0ctl}, 0, 0666, +}; + +#define NDuartport (sizeof duartdir/sizeof(Dirtab)) + +/* + * allocate the queues if no one else has + */ +void +duartreset(void) +{ + Duartport *dp = duartport; + + if(dp->nostream) + return; + dp->iq = ialloc(sizeof(IOQ), 0); + initq(dp->iq); + dp->oq = ialloc(sizeof(IOQ), 0); + initq(dp->oq); + duartdevice(dp); +} + +Chan* +duartattach(char *spec) +{ + return devattach('t', spec); +} + +Chan* +duartclone(Chan *c, Chan *nc) +{ + return devclone(c, nc); +} + +int +duartwalk(Chan *c, char *name) +{ + return devwalk(c, name, duartdir, NDuartport, devgen); +} + +void +duartstat(Chan *c, char *dp) +{ + switch(c->qid.path){ + case Qtty0: + streamstat(c, dp, "tty0"); + break; + default: + devstat(c, dp, duartdir, NDuartport, devgen); + break; + } +} + +Chan* +duartopen(Chan *c, int omode) +{ + Duartport *dp; + + switch(c->qid.path){ + case Qtty0: + case Qtty0ctl: + dp = &duartport[0]; + break; + default: + dp = 0; + break; + } + + if(dp && dp->nostream) + errors("in use"); + + if((c->qid.path & CHDIR) == 0) + streamopen(c, &duartinfo); + return devopen(c, omode, duartdir, NDuartport, devgen); +} + +void +duartcreate(Chan *c, char *name, int omode, ulong perm) +{ + error(Eperm); +} + +void +duartclose(Chan *c) +{ + if(c->stream) + streamclose(c); +} + +long +duartread(Chan *c, void *buf, long n, ulong offset) +{ + int s; + Duart *duart = DUARTREG; + + switch(c->qid.path&~CHDIR){ + case Qdir: + return devdirread(c, buf, n, duartdir, NDuartport, devgen); + case Qtty0ctl: + if(offset) + return 0; + s = splhi(); + *(uchar *)buf = duart[1].ip_opcr; + splx(s); + return 1; + } + return streamread(c, buf, n); +} + +long +duartwrite(Chan *c, void *va, long n, ulong offset) +{ + return streamwrite(c, va, n, 0); +} + +void +duartremove(Chan *c) +{ + error(Eperm); +} + +void +duartwstat(Chan *c, char *dp) +{ + error(Eperm); +} diff --git a/gnot/fns.h b/gnot/fns.h index 795569e328ed288fc7f6f8d68069c1e7c7200bfe..5fa12999dea6e48bae07bec98f5e7f5dd0b04bc2 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -7,12 +7,16 @@ #define P_write(sel, addr, val, type) P_oper(sel, *(type *)(PORT+addr) = val) void addportintr(int (*)(void)); +int cangetc(void*); +int canputc(void*); void clearmmucache(void); void duartbaud(int); void duartbreak(int); void duartdtr(int); int duartinputport(void); -void duartstartrs232o(void); +void duartrs232start(char); +void duartrs232stop(void); +void duartrs232xmit(char); void duartstarttimer(void); void duartstoptimer(void); #define evenaddr(x) /* 68020 doesn't care */ @@ -26,9 +30,11 @@ void fpregrestore(char*); void fpregsave(char*); void fprestore(FPsave*); void fpsave(FPsave*); -int getrs232o(void); +int getc(IOQ*); +int gets(IOQ*, void*, int); void incontoggle(void); -void kbdchar(int); +void initq(IOQ*); +int kbdputc(IOQ*, int); void kbdclock(void); void kbdrepeat(int); KMap* kmap(Page*); @@ -38,19 +44,25 @@ void kunmap(KMap*); void mmuinit(void); void mousebuttons(int); void mouseclock(void); +int mouseputc(IOQ*, int); int portprobe(char*, int, int, int, long); void printinit(void); void procrestore(Proc*, uchar*); void procsave(uchar*, int); void procsetup(Proc*); +int putc(IOQ*, int); +void puts(IOQ*, void*, int); void putkmmu(ulong, ulong); void putstr(char*); void putstrn(char*, long); void restartprint(Alarm*); void restfpregs(FPsave*); -void rs232ichar(int); +void rs232puts(IOQ*, char*, int); +void rs232rintr(char); +void rs232xintr(void); void screeninit(void); void screenputc(int); +void screenputs(char*, int); int scsicap(int, uchar *); Scsi* scsicmd(int, int, long); void scsictrlintr(void); diff --git a/gnot/main.c b/gnot/main.c index e194e11c8df30785f2eabde444b66dd48587c5a6..97463580f05aef8729b694d85652052b33b29b07 100644 --- a/gnot/main.c +++ b/gnot/main.c @@ -40,6 +40,8 @@ main(void) mmuinit(); confinit(); kmapinit(); + duartinit(); + screeninit(); printinit(); print("bank 0: %dM bank 1: %dM\n", bank[0], bank[1]); flushmmu(); @@ -410,3 +412,19 @@ procrestore(Proc *p, uchar *state) if(balu->cr0 != 0xFFFFFFFF) /* balu busy */ memmove(BALU, balu, sizeof balu); } + +void +buzz(int f, int d) +{ +} + +void +lights(int val) +{ +} + +void +firmware(void) +{ + panic("you asked for it"); +} diff --git a/gnot/mem.h b/gnot/mem.h index e223d2af5e555b518cc47801dca5795b87a4c76e..dbd149f76a6a3b54313466493ff5eed43f5d0bae 100644 --- a/gnot/mem.h +++ b/gnot/mem.h @@ -97,9 +97,8 @@ #define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */ #define KZERO KSEG /* base of kernel address space */ #define KTZERO (KZERO+BY2PG) /* first address in kernel text */ -#define USTACKSIZE (4*1024*1024) /* size of user stack */ +#define USTKSIZE (4*1024*1024) /* size of user stack */ -#define NSEG 5 #define MACHSIZE 4096 diff --git a/gnot/screen.c b/gnot/screen.c index 906a8b7d73f4705544501ba70c6c592038c47fef..2945007b296abe8336e3e5907be1b2e0f6c9cde8 100644 --- a/gnot/screen.c +++ b/gnot/screen.c @@ -20,12 +20,6 @@ struct{ int bwid; }out; -void duartinit(void); -int duartacr; -int duartimr; - -void (*kprofp)(ulong); - GBitmap gscreen = { (ulong*)((4*1024*1024-256*1024)|KZERO), /* BUG */ @@ -39,7 +33,6 @@ GBitmap gscreen = void screeninit(void) { - duartinit(); /* * Read HEX switch to set ldepth */ @@ -84,492 +77,9 @@ screenputc(int c) } } -/* - * Register set for half the duart. There are really two sets. - */ -struct Duart{ - uchar mr1_2; /* Mode Register Channels 1 & 2 */ - uchar sr_csr; /* Status Register/Clock Select Register */ - 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, - CBITS8 =0x03, - CBITS7 =0x02, - CBITS6 =0x01, - CBITS5 =0x00, - NORM_OP =0x00, /* MR2x - Mode Register 2 */ - TWOSTOPB =0x0F, - ONESTOPB =0x07, - ENB_RX =0x01, /* CRx - Command Register */ - DIS_RX =0x02, - ENB_TX =0x04, - DIS_TX =0x08, - RESET_MR =0x10, - RESET_RCV =0x20, - RESET_TRANS =0x30, - RESET_ERR =0x40, - RESET_BCH =0x50, - STRT_BRK =0x60, - STOP_BRK =0x70, - RCV_RDY =0x01, /* SRx - Channel Status Register */ - FIFOFULL =0x02, - XMT_RDY =0x04, - XMT_EMT =0x08, - OVR_ERR =0x10, - PAR_ERR =0x20, - FRM_ERR =0x40, - RCVD_BRK =0x80, - BD38400 =0xCC|0x0000, - BD19200 =0xCC|0x0100, - BD9600 =0xBB|0x0000, - BD4800 =0x99|0x0000, - BD2400 =0x88|0x0000, - BD1200 =0x66|0x0000, - BD300 =0x44|0x0000, - IM_IPC =0x80, /* IMRx/ISRx - Interrupt Mask/Interrupt Status */ - IM_DBB =0x40, - IM_RRDYB =0x20, - IM_XRDYB =0x10, - IM_CRDY =0x08, - IM_DBA =0x04, - IM_RRDYA =0x02, - IM_XRDYA =0x01, -}; - -uchar keymap[]={ -/*80*/ 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, - 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x8e, 0x58, -/*90*/ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x58, 0x58, 0x58, 0x58, -/*A0*/ 0x58, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xae, 0xaf, -/*B0*/ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0x00, 0xbb, 0x1e, 0xbd, 0x60, 0x1f, -/*C0*/ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0x58, 0xc6, 0x0a, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, -/*D0*/ 0x09, 0x08, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x58, -/*E0*/ 0x58, 0x58, 0xe2, 0x1b, 0x0d, 0xe5, 0x58, 0x0a, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, -/*F0*/ 0x09, 0x08, 0xb2, 0x1b, 0x0d, 0xf5, 0x81, 0x58, - 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x80, -}; - -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; - - /* - * RS232 - */ - 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 = BD9600; - - /* - * Output port - */ - duart[0].ipc_acr = duartacr = 0xB7; /* 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 = duartimr = IM_IPC|IM_RRDYB|IM_XRDYB|IM_RRDYA|IM_XRDYA; - 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; -} - -int -duartinputport(void) -{ - Duart *duart = DUARTREG; - return duart[1].ip_opcr; -} -void -duartbaud(int b) -{ - int x = 0; - Duart *duart = DUARTREG; - - switch(b){ - case 38400: - x = BD38400; - break; - case 19200: - x = BD19200; - break; - case 9600: - x = BD9600; - break; - case 4800: - x = BD4800; - break; - case 2400: - x = BD2400; - break; - case 1200: - x = BD1200; - break; - case 300: - x = BD300; - break; - default: - error(Ebadarg); - } - if(x & 0x0100) - duart[0].ipc_acr = duartacr |= 0x80; - else - duart[0].ipc_acr = duartacr &= ~0x80; - duart[1].sr_csr = x; -} - -void -duartdtr(int val) -{ - Duart *duart = DUARTREG; - if (val) - duart[1].scc_ropbc=0x01; - else - duart[1].scc_sopbc=0x01; -} - -void -duartbreak(int ms) -{ - static QLock brk; - Duart *duart = DUARTREG; - if (ms<=0 || ms >20000) - error(Ebadarg); - qlock(&brk); - duart[0].is_imr = duartimr &= ~IM_XRDYB; - duart[1].cmnd = STRT_BRK|ENB_TX; - tsleep(&u->p->sleep, return0, 0, ms); - duart[1].cmnd = STOP_BRK|ENB_TX; - duart[0].is_imr = duartimr |= IM_XRDYB; - qunlock(&brk); -} - -enum{ - Kptime=200 -}; -void -duartstarttimer(void) -{ - Duart *duart; - char x; - - duart = DUARTREG; - duart[0].ctur = (Kptime)>>8; - duart[0].ctlr = (Kptime)&255; - duart[0].is_imr = duartimr |= IM_CRDY; - x = duart[1].scc_sopbc; -} - -void -duartstoptimer(void) -{ - Duart *duart; - char x; - - duart = DUARTREG; - x = duart[1].scc_ropbc; - duart[0].is_imr = duartimr &= ~IM_CRDY; -} - -void -duartrs232intr(void) -{ - int c; - Duart *duart; - - duart = DUARTREG; - c = getrs232o(); - if(c == -1) - duart[1].cmnd = DIS_TX; - else - duart[1].data = c; -} - -void -duartstartrs232o(void) -{ - int s; - Duart *duart; - - duart = DUARTREG; - s = splduart(); - duart[1].cmnd = ENB_TX; - if(duart[1].sr_csr & (XMT_RDY|XMT_EMT)) - duartrs232intr(); - splx(s); -} - -struct latin -{ - uchar l; - char c[2]; -}latintab[] = { - '€', "!!", /* spanish initial ! */ - '€', "c|", /* cent */ - '€', "c$", /* cent */ - '€', "l$", /* pound sterling */ - '€', "g$", /* general currency */ - '€', "y$", /* yen */ - '€', "j$", /* yen */ - '€', "||", /* broken vertical bar */ - '€', "SS", /* section symbol */ - '€', "\"\"", /* dieresis */ - '€', "cr", /* copyright */ - '€', "cO", /* copyright */ - '€', "sa", /* super a, feminine ordinal */ - '€', "<<", /* left angle quotation */ - '€', "no", /* not sign, hooked overbar */ - '€', "--", /* soft hyphen */ - '€', "rg", /* registered trademark */ - '€', "__", /* macron */ - '€', "s0", /* degree (sup o) */ - '€', "+-", /* plus-minus */ - '€', "s2", /* sup 2 */ - '€', "s3", /* sup 3 */ - '€', "''", /* grave accent */ - '€', "mu", /* mu */ - '€', "pg", /* paragraph (pilcrow) */ - '€', "..", /* centered . */ - '€', ",,", /* cedilla */ - '€', "s1", /* sup 1 */ - '€', "so", /* sup o */ - '€', ">>", /* right angle quotation */ - '€', "14", /* 1/4 */ - '€', "12", /* 1/2 */ - '€', "34", /* 3/4 */ - '€', "??", /* spanish initial ? */ - '€', "A`", /* A grave */ - '€', "A'", /* A acute */ - '€', "A^", /* A circumflex */ - '€', "A~", /* A tilde */ - '€', "A\"", /* A dieresis */ - '€', "A:", /* A dieresis */ - '€', "Ao", /* A circle */ - '€', "AO", /* A circle */ - '€', "Ae", /* AE ligature */ - '€', "AE", /* AE ligature */ - '€', "C,", /* C cedilla */ - '€', "E`", /* E grave */ - '€', "E'", /* E acute */ - '€', "E^", /* E circumflex */ - '€', "E\"", /* E dieresis */ - '€', "E:", /* E dieresis */ - '€', "I`", /* I grave */ - '€', "I'", /* I acute */ - '€', "I^", /* I circumflex */ - '€', "I\"", /* I dieresis */ - '€', "I:", /* I dieresis */ - '€', "D-", /* Eth */ - '€', "N~", /* N tilde */ - '€', "O`", /* O grave */ - '€', "O'", /* O acute */ - '€', "O^", /* O circumflex */ - '€', "O~", /* O tilde */ - '€', "O\"", /* O dieresis */ - '€', "O:", /* O dieresis */ - '€', "OE", /* O dieresis */ - '€', "Oe", /* O dieresis */ - '€', "xx", /* times sign */ - '€', "O/", /* O slash */ - '€', "U`", /* U grave */ - '€', "U'", /* U acute */ - '€', "U^", /* U circumflex */ - '€', "U\"", /* U dieresis */ - '€', "U:", /* U dieresis */ - '€', "UE", /* U dieresis */ - '€', "Ue", /* U dieresis */ - '€', "Y'", /* Y acute */ - '€', "P|", /* Thorn */ - '€', "Th", /* Thorn */ - '€', "TH", /* Thorn */ - '€', "ss", /* sharp s */ - '€', "a`", /* a grave */ - '€', "a'", /* a acute */ - '€', "a^", /* a circumflex */ - '€', "a~", /* a tilde */ - '€', "a\"", /* a dieresis */ - '€', "a:", /* a dieresis */ - '€', "ao", /* a circle */ - '€', "ae", /* ae ligature */ - '€', "c,", /* c cedilla */ - '€', "e`", /* e grave */ - '€', "e'", /* e acute */ - '€', "e^", /* e circumflex */ - '€', "e\"", /* e dieresis */ - '€', "e:", /* e dieresis */ - '€', "i`", /* i grave */ - '€', "i'", /* i acute */ - '€', "i^", /* i circumflex */ - '€', "i\"", /* i dieresis */ - '€', "i:", /* i dieresis */ - '€', "d-", /* eth */ - '€', "n~", /* n tilde */ - '€', "o`", /* o grave */ - '€', "o'", /* o acute */ - '€', "o^", /* o circumflex */ - '€', "o~", /* o tilde */ - '€', "o\"", /* o dieresis */ - '€', "o:", /* o dieresis */ - '€', "oe", /* o dieresis */ - '€', "-:", /* divide sign */ - '€', "o/", /* o slash */ - '€', "u`", /* u grave */ - '€', "u'", /* u acute */ - '€', "u^", /* u circumflex */ - '€', "u\"", /* u dieresis */ - '€', "u:", /* u dieresis */ - '€', "ue", /* u dieresis */ - '€', "y'", /* y acute */ - '€', "th", /* thorn */ - '€', "p|", /* thorn */ - '€', "y\"", /* y dieresis */ - '€', "y:", /* y dieresis */ - 0, 0, -}; - -int -latin1(int k1, int k2) -{ - int i; - struct latin *l; - - for(l=latintab; l->l; l++) - if(k1==l->c[0] && k2==l->c[1]) - return l->l; - return 0; -} - void -duartintr(Ureg *ur) +screenputs(char *s, int n) { - int cause, status, c; - Duart *duart; - static int kbdstate, k1, k2; - - duart = DUARTREG; - cause = duart->is_imr; - /* - * I can guess your interrupt. - */ - /* - * Is it 0? - */ - if(cause & IM_CRDY){ - if(kprofp) - (*kprofp)(ur->pc); - c = duart[1].scc_ropbc; - duart[0].ctur = (Kptime)>>8; - duart[0].ctlr = (Kptime)&255; - c = duart[1].scc_sopbc; - return; - } - /* - * Is it 1? - */ - if(cause & IM_RRDYA){ /* keyboard input */ - status = duart->sr_csr; - c = duart->data; - if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) - duart->cmnd = RESET_ERR; - if(status & PAR_ERR) /* control word: caps lock (0x4) or repeat (0x10) */ - kbdrepeat((c&0x10) == 0); - else{ - if(c == 0x7F) /* VIEW key (bizarre) */ - c = 0xFF; - if(c == 0xB6) /* NUM PAD */ - kbdstate = 1; - else{ - if(c & 0x80) - c = keymap[c&0x7F]; - switch(kbdstate){ - case 1: - k1 = c; - kbdstate = 2; - break; - case 2: - k2 = c; - c = latin1(k1, k2); - if(c == 0){ - kbdchar(k1); - c = k2; - } - /* fall through */ - default: - kbdstate = 0; - kbdchar(c); - } - } - } - } - /* - * Is it 2? - */ - while(cause & IM_RRDYB){ /* rs232 input */ - status = duart[1].sr_csr; - c = duart[1].data; - if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) - duart[1].cmnd = RESET_ERR; - else - rs232ichar(c); - cause = duart->is_imr; - } - /* - * Is it 3? - */ - if(cause & IM_XRDYB) /* rs232 output */ - duartrs232intr(); - /* - * Is it 4? - */ - if(cause & IM_XRDYA) - duart[0].cmnd = DIS_TX; - /* - * Is it 5? - */ - if(cause & IM_IPC) - mousebuttons((~duart[0].ipc_acr) & 7); + while(n-- > 0) + screenputc(*s++); } diff --git a/port/devbit.c b/port/devbit.c index 9a2e0c00bfc553ddf56bd3ef72eb3ee5f5cb0669..64f5794aa86dd22a84412a6d2052214754d4b7ff 100644 --- a/port/devbit.c +++ b/port/devbit.c @@ -1145,6 +1145,14 @@ mousetry(Ureg *ur) } } +int +mouseputc(IOQ *q, int c) +{ + /* + * put your favorite serial mouse code here + */ +} + void mouseupdate(int dolock) { diff --git a/port/devproc.c b/port/devproc.c index 6ee99317128caa505c9bdb5967cda42b615ee6d4..4d86b365725c47f281e9203e1f38764706cfa2a5 100644 --- a/port/devproc.c +++ b/port/devproc.c @@ -130,11 +130,13 @@ procopen(Chan *c, int omode) switch(QID(c->qid)){ case Qtext: o = p->seg[TSEG].o; - if(o==0 || p->state==Dead) + if(o==0 || p->state==Dead) goto Died; + tc = o->chan; if(tc == 0) goto Died; + if(incref(tc) == 0){ Close: close(tc); @@ -142,8 +144,10 @@ procopen(Chan *c, int omode) } if(!(tc->flag&COPEN) || tc->mode!=OREAD) goto Close; + if(p->pid != PID(c->qid)) goto Close; + qlock(&tc->rdl); tc->offset = 0; qunlock(&tc->rdl); diff --git a/port/fault.c b/port/fault.c index e6423d7473635ce3b75a76908b59e44536fda9da..8dc8ff67a57d5ac807ff506f8819a4b2cdc37e8a 100644 --- a/port/fault.c +++ b/port/fault.c @@ -25,7 +25,7 @@ fault(ulong addr, int read) if(addr > USTKTOP) return -1; s = &u->p->seg[SSEG]; - if(s->o==0 || addrmaxva-USTACKSIZE || addr>=s->maxva) + if(s->o==0 || addrmaxva-USTKSIZE || addr>=s->maxva) return -1; /* grow stack */ o = s->o; @@ -220,7 +220,7 @@ validaddr(ulong addr, ulong len, int write) s = seg(u->p, addr); if(s==0){ s = &u->p->seg[SSEG]; - if(s->o==0 || addrmaxva-USTACKSIZE || addr>=s->maxva) + if(s->o==0 || addrmaxva-USTKSIZE || addr>=s->maxva) goto Err; } if(write && (s->o->flag&OWRPERM)==0) diff --git a/port/portdat.h b/port/portdat.h index 98834a6a62e44586a360d9589dacdec40231999f..df67f63225b89855323eb9f6a5d5d0f25ff8a26f 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -283,13 +283,12 @@ enum /* Argument to forkpgrp call */ }; /* - * process memory segments + * process memory segments - NSEG always last ! */ -#define SSEG 0 -#define TSEG 1 -#define DSEG 2 -#define BSEG 3 -#define ESEG 4 /* used by exec to build new stack */ +enum +{ + SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, NSEG +}; struct Seg { diff --git a/port/portfns.h b/port/portfns.h index f020ff7c548b7761980375460c996474d411a116..59ed6298cc3f8cf1086ad210a2bfe7181b92d02c 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -128,10 +128,6 @@ void resched(char*); int return0(void*); Proc* runproc(void); void savefpregs(FPsave*); -void sccintr(void); -void sccputs(IOQ*, char*, int); -void sccsetup(void*); -void sccspecial(int, IOQ*, IOQ*, int); void schedinit(void); void sched(void); long seconds(void); diff --git a/port/sturp.c b/port/sturp.c index 429bda7ee49670e57d8c1b3a2cbe1c8aa1271c36..35e69162e7e0f45dc0508c4c7abb56f173736f31 100644 --- a/port/sturp.c +++ b/port/sturp.c @@ -157,10 +157,12 @@ urpopen(Queue *q, Stream *s) * find a free urp structure */ for(up = urp; up < &urp[conf.nurp]; up++){ - qlock(up); - if(up->state == 0) - break; - qunlock(up); + if(up->state == 0){ + qlock(up); + if(up->state == 0) + break; + qunlock(up); + } } if(up == &urp[conf.nurp]){ q->ptr = 0; @@ -265,6 +267,8 @@ urpciput(Queue *q, Block *bp) int ctl; up = (Urp *)q->ptr; + if(up == 0) + return; if(bp->type != M_DATA){ urpctliput(up, q, bp); return; @@ -364,6 +368,8 @@ urpiput(Queue *q, Block *bp) int ctl; up = (Urp *)q->ptr; + if(up == 0) + return; if(bp->type != M_DATA){ urpctliput(up, q, bp); return; diff --git a/port/sysproc.c b/port/sysproc.c index 7921d4592e0fc9d33dd8414b4ee539c194838eac..6f048e0845a8004e8e3f2ce2e3002239134e4bfa 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -545,3 +545,38 @@ sysbrk_(ulong *arg) u->p->bssend = addr; return 0; } +/* +long +syslkbrk(ulong *arg) +{ + ulong addr; + Orig *o; + Seg *s; + + addr = arg[0]; + s = &u->p->seg[LSEG]; + if(addr < LKSEGBASE) + error(Esegaddr); + + /* If we have never seen a lock segment create one */ + if(s->o == 0) { + s->proc = u->p; + s->minva = LKSEGBASE; + s->maxva = addr; + o = neworig(s->minva, (addr-LKSEGBASE)>>PGSHIFT, OWRPERM, 0); + o->minca = 0; + o->maxca = 0; + s->o = o; + s->mod = 0; + } + if(addr < s->maxva) + return 0; + if(segaddr(&u->p->seg[LSEG], s->minva, addr) == 0) { + pprint("bad segaddr in brk\n"); + pexit("Suicide", 0); + error(Esegaddr); + + } + return 0; +} +*/ diff --git a/power/lock.c b/power/lock.c index 2e68f3ea9f6992859c57e2b663784cf3b1837308..c4f2a25f02f3dc5b77ef83943bd80798e93de2d9 100644 --- a/power/lock.c +++ b/power/lock.c @@ -13,29 +13,58 @@ */ #define SEMPERPG 64 /* hardware semaphores per page */ -#define NONSEMPERPG (WD2PG-64) /* words of non-semaphore per page */ +#define NSEMPG 1024 struct { Lock lock; /* lock to allocate */ ulong *nextsem; /* next one to allocate */ int nsem; /* at SEMPERPG, jump to next page */ + uchar bmap[NSEMPG]; /* allocation map */ }semalloc; void lockinit(void) { + memset(semalloc.bmap, 0, sizeof(semalloc.bmap)); + semalloc.bmap[0] = 1; semalloc.lock.sbsem = SBSEM; semalloc.nextsem = SBSEM+1; semalloc.nsem = 1; unlock(&semalloc.lock); } +/* return the address of the next free page of locks */ +ulong* +lkpgalloc(void) +{ + uchar *p, *top; + + top = &semalloc.bmap[NSEMPG]; + for(p = semalloc.bmap; *p && p < top; p++) + ; + if(p == top) + panic("lkpgalloc"); + + *p = 1; + return (p-semalloc.bmap)*WD2PG + SBSEM; +} + +void +lkpgfree(ulong *lpa) +{ + uchar *p; + + p = &semalloc.bmap[(lpa-SBSEM)/WD2PG]; + if(!*p) + panic("lkpgfree"); + *p = 0; +} + #define PCOFF -9 /* * If l->sbsem is zero, allocate a hardware semaphore first. - * There is no way to free a semaphore. */ void lock(Lock *ll) @@ -49,9 +78,7 @@ lock(Lock *ll) lock(&semalloc.lock); if(semalloc.nsem == SEMPERPG){ semalloc.nsem = 0; - semalloc.nextsem += NONSEMPERPG; - if(semalloc.nextsem == SBSEMTOP) - panic("sem"); + semalloc.nextsem = lkpgalloc(); } l->sbsem = semalloc.nextsem; semalloc.nextsem++; @@ -74,7 +101,7 @@ lock(Lock *ll) } *sbsem = 0; print("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&ll)[PCOFF], l->pc); -dumpstack(); + dumpstack(); } int @@ -87,9 +114,7 @@ canlock(Lock *l) lock(&semalloc.lock); if(semalloc.nsem == SEMPERPG){ semalloc.nsem = 0; - semalloc.nextsem += NONSEMPERPG; - if(semalloc.nextsem == SBSEMTOP) - panic("sem"); + semalloc.nextsem = lkpgalloc(); } l->sbsem = semalloc.nextsem; semalloc.nextsem++; diff --git a/power/mem.h b/power/mem.h index a8e711a844cf29dcba7b5b492e6633e1b203e5fd..b18aa20a04fbff2512a06b8ac3ae7276b6d3c69f 100644 --- a/power/mem.h +++ b/power/mem.h @@ -98,7 +98,6 @@ #define PTEPID(n) ((n)<<6) #define TLBPID(n) (((n)>>6)&0x3F) -/* N.B. MUST CHANGE l.s utlbmiss if you want to change this */ #define STLBLOG 11 #define STLBSIZE (1<