From 1a3a798a350908cbeee28e3fbce55d514ae40240 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 7 Jun 1991 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1991-06-07 --- gnot/dat.h | 34 -- gnot/fns.h | 23 -- port/devcons.c | 579 +++++++++++++++----------------- port/devscc.c | 3 - port/fault.c | 32 +- port/page.c | 8 +- port/portdat.h | 38 ++- port/portfns.h | 21 +- port/sysproc.c | 14 +- power/clock.c | 2 +- power/devduart.c | 836 +++++++++++++++++++++++++++++++++++++++++++++++ power/duart.c | 220 ------------- power/fns.h | 18 +- power/l.s | 3 - power/lock.c | 22 +- power/main.c | 20 +- power/mem.h | 2 +- ss/dat.h | 35 -- ss/fns.h | 32 +- ss/mem.h | 1 + 20 files changed, 1240 insertions(+), 703 deletions(-) create mode 100644 power/devduart.c delete mode 100644 power/duart.c diff --git a/gnot/dat.h b/gnot/dat.h index 1b883fc76ab3a468f6bbee6aba3d7fd2fef7dbe6..ef8f4216056beeb588923a6eddef0f182e7f08e5 100644 --- a/gnot/dat.h +++ b/gnot/dat.h @@ -1,8 +1,6 @@ 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; @@ -120,38 +118,6 @@ 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 */ diff --git a/gnot/fns.h b/gnot/fns.h index 16566c8a2312b0d4e7976dd88ee80b3a1108245f..88b22b7ffb6fb9700640029eb6727c4cc48be31c 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -57,26 +57,3 @@ int splduart(void); int tas(char*); void touser(void); #define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1])) - -/* - * for queues (to go into portfns.h) - */ -int cangetc(void*); -int canputc(void*); -int getc(IOQ*); -int gets(IOQ*, void*, int); -void initq(IOQ*); -int putc(IOQ*, int); -void puts(IOQ*, void*, int); - -/* - * for devcons (to go into portfns.h) - */ -void kbdclock(void); -void kbdrepeat(int); -int kbdputc(IOQ*, int); -int kprint(char*, ...); -int mouseputc(IOQ*, int); -void printinit(void); -void putstr(char*); -void putstrn(char*, long); diff --git a/port/devcons.c b/port/devcons.c index dc86b13d1bb99cd3746a298626e76bb43f61bb67..1c0a461f64bb6745092095d5ed34c2090175b740 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -8,90 +8,35 @@ #include "devtab.h" -static struct -{ - Lock; - uchar buf[4000]; - uchar *in; - uchar *out; - int printing; - int c; -}printq; - -typedef struct IOQ IOQ; - -#define NQ 4096 -struct IOQ{ - union{ - Lock; - QLock; - }; - uchar buf[NQ]; - uchar *in; - uchar *out; - int state; - Rendez r; -}; - -IOQ kbdq; /* qlock to getc; interrupt putc's */ -IOQ lineq; /* lock to getc; interrupt putc's */ - -#define SYSLOGMAGIC 0xdeadbeaf -#define SYSLOG ((Syslog *)(UNCACHED | 0x1B00)) -typedef struct Syslog Syslog; -struct Syslog -{ - ulong magic; - int wrapped; - char *next; - char buf[2*1024]; -}; - - -void -printinit(void) -{ - - printq.in = printq.buf; - printq.out = printq.buf; - lock(&printq); /* allocate lock */ - unlock(&printq); +struct { + IOQ; /* lock to klogputs */ + QLock; /* qlock to getc */ +} klogq; - kbdq.in = kbdq.buf; - kbdq.out = kbdq.buf; - lineq.in = lineq.buf; - lineq.out = lineq.buf; - qlock(&kbdq); /* allocate qlock */ - qunlock(&kbdq); - lock(&lineq); /* allocate lock */ - unlock(&lineq); +IOQ lineq; /* lock to getc; interrupt putc's */ +IOQ printq; +IOQ mouseq; +KIOQ kbdq; - duartinit(); -} +Ref raw; /* whether kbd i/o is raw (rcons is open) */ /* - * Put a string on the console. - * n bytes of s are guaranteed to fit in the buffer and is ready to print. - * Must be called splhi() and with printq locked. + * init the queues and set the output routine */ void -puts(char *s, int n) +printinit(void) { - if(!printq.printing){ - printq.printing = 1; - printq.c = *s++; - n--; - } - memmove(printq.in, s, n); - printq.in += n; - if(printq.in >= printq.buf+sizeof(printq.buf)) - printq.in = printq.buf; + initq(&printq); + initq(&lineq); + initq(&kbdq); + kbdq.putc = kbdputc; + initq(&klogq); + initq(&mouseq); + mouseq.putc = mouseputc; } /* - * Print a string on the console. This is the high level routine - * with a queue to the interrupt handler. BUG: There is no check against - * overflow. + * Print a string on the console. Convert \n to \r\n */ void putstrn(char *str, int n) @@ -99,39 +44,59 @@ putstrn(char *str, int n) int s, c, m; char *t; - s = splhi(); - lock(&printq); - syslog(str, n); while(n > 0){ - if(*str == '\n') - puts("\r", 1); - m = printq.buf+sizeof(printq.buf) - printq.in; - if(n < m) - m = n; + 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; - puts(str, m); + if(printq.puts) + (*printq.puts)(&printq, str, m); + screenputs(str, m); n -= m; str += m; } - unlock(&printq); - splx(s); } -int -cangetc(IOQ *q) +/* + * Print a string in the kernel log. Ignore overflow. + */ +void +klogputs(char *str, long n) { - return q->in != q->out; + int s, m; + uchar *nextin; + + 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(IOQ *q) +isbrkc(KIOQ *q) { uchar *p; for(p=q->out; p!=q->in; ){ + if(raw.ref) + return 1; if(*p==0x04 || *p=='\n') return 1; p++; @@ -141,19 +106,6 @@ isbrkc(IOQ *q) 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 sprint(char *s, char *fmt, ...) { @@ -171,6 +123,17 @@ print(char *fmt, ...) return n; } +int +kprint(char *fmt, ...) +{ + char buf[PRINTSIZE]; + int n; + + n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; + klogputs(buf, n); + return n; +} + void panic(char *fmt, ...) { @@ -212,55 +175,50 @@ pprint(char *fmt, ...) void prflush(void) { - while(printq.printing) - delay(100); -} - -/* - * Get character to print at interrupt time. - * Always called splhi from proc 0. - */ -int -conschar(void) -{ - uchar *p; - int c; - - lock(&printq); - p = printq.out; - if(p == printq.in){ - printq.printing = 0; - c = -1; - }else{ - c = *p++; - if(p >= printq.buf+sizeof(printq.buf)) - p = printq.buf; - printq.out = p; - } - unlock(&printq); - return c; + while(printq.in != printq.out) ; } void echo(int c) { char ch; + static int ctrlt; /* - * ^t hack BUG + * ^p hack */ if(c == 0x10) panic("^p"); - if(c == 0x14) - DEBUG(); + /* + * ^t hack BUG + */ + if(ctrlt == 2){ + ctrlt = 0; + switch(c){ + case 0x14: + break; /* pass it on */ + case 'm': + mntdump(); + return; + case 'p': + DEBUG(); + return; + case 'q': + dumpqueues(); + return; + case 'r': + exit(); + break; + } + }else if(c == 0x14){ + ctrlt++; + return; + } + ctrlt = 0; + if(raw.ref) + return; if(c == 0x15) putstrn("^U\n", 3); - if(c == 0x16) - dumpqueues(); - if(c == 0xe) - nonettoggle(); - if(c == 0xc) - lancetoggle(); else{ ch = c; putstrn(&ch, 1); @@ -271,31 +229,38 @@ 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(c == 0) /* NULs cause trouble */ - return; - if(c == '\r') - c = '\n'; - 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(c=='\n' || c==0x04) + if(raw.ref || ch=='\n' || ch==0x04) wakeup(&kbdq.r); + return 0; } void -printslave(void) +kbdrepeat(int rep) { - int c; + kbdq.repeat = rep; + kbdq.count = 0; +} - c = printq.c; - if(c){ - printq.c = 0; - duartxmit(c); +void +kbdclock(void) +{ + 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 @@ -311,31 +276,37 @@ enum{ Qdir, Qcons, Qcputime, - Qlog, + Qlights, + Qnoise, Qnull, -/* Qpanic, /**/ Qpgrpid, Qpid, Qppid, + Qrcons, Qtime, Quser, - Qvmereset, + Qklog, + Qmsec, + Qclock, Qsysstat, }; Dirtab consdir[]={ - "cons", {Qcons}, 0, 0600, - "cputime", {Qcputime}, 72, 0600, - "log", {Qlog}, BY2PG-8, 0600, - "null", {Qnull}, 0, 0600, -/* "panic", {Qpanic}, 0, 0666, /**/ - "pgrpid", {Qpgrpid}, 12, 0600, - "pid", {Qpid}, 12, 0600, - "ppid", {Qppid}, 12, 0600, - "time", {Qtime}, 12, 0600, - "user", {Quser}, 0, 0600, - "vmereset", {Qvmereset}, 0, 0600, - "sysstat", {Qsysstat}, 0, 0600, + "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, + "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)) @@ -415,12 +386,29 @@ consstat(Chan *c, char *dp) Chan* consopen(Chan *c, int omode) { - if(c->qid.path==Quser && omode==(OWRITE|OTRUNC)){ - /* truncate? */ - if(strcmp(u->p->pgrp->user, "bootes") == 0) /* BUG */ - u->p->pgrp->user[0] = 0; - else - error(Eperm); + int ch; + + switch(c->qid.path){ + case Quser: + if(omode==(OWRITE|OTRUNC)){ + /* truncate? */ + if(strcmp(u->p->pgrp->user, "bootes") == 0) /* BUG */ + u->p->pgrp->user[0] = 0; + else + error(Eperm); + } + break; + case Qrcons: + if(incref(&raw) == 1){ + lock(&lineq); + while((ch=getc(&kbdq)) != -1){ + *lineq.in++ = ch; + if(lineq.in == lineq.buf+sizeof(lineq.buf)) + lineq.in = lineq.buf; + } + unlock(&lineq); + } + break; } return devopen(c, omode, consdir, NCONS, devgen); } @@ -434,8 +422,11 @@ conscreate(Chan *c, char *name, int omode, ulong perm) void consclose(Chan *c) { + if(c->qid.path==Qrcons && (c->flag&COPEN)) + decref(&raw); } + long consread(Chan *c, void *buf, long n, ulong offset) { @@ -445,7 +436,7 @@ consread(Chan *c, void *buf, long n, ulong offset) char *cbuf = buf; char *user; int userlen; - char tmp[6*NUMSIZE], xbuf[512]; + char tmp[6*NUMSIZE], xbuf[1024]; Mach *mp; if(n <= 0) @@ -454,6 +445,7 @@ consread(Chan *c, void *buf, long n, ulong offset) case Qdir: return devdirread(c, buf, n, consdir, NCONS, devgen); + case Qrcons: case Qcons: qlock(&kbdq); if(waserror()){ @@ -461,9 +453,14 @@ consread(Chan *c, void *buf, long n, ulong offset) nexterror(); } while(!cangetc(&lineq)){ - sleep(&kbdq.r, (int(*)(void*))isbrkc, &kbdq); + sleep(&kbdq.r, isbrkc, &kbdq); do{ + lock(&lineq); ch = getc(&kbdq); + if(raw.ref){ + unlock(&lineq); + goto Default; + } switch(ch){ case '\b': if(lineq.in != lineq.out){ @@ -475,17 +472,21 @@ consread(Chan *c, void *buf, long n, ulong offset) case 0x15: lineq.in = lineq.out; break; + Default: default: - *lineq.in++ = ch; - if(lineq.in == lineq.buf+sizeof(lineq.buf)) - lineq.in = lineq.buf; + *lineq.in = ch; + if(lineq.in >= lineq.buf+sizeof(lineq.buf)-1) + lineq.in = lineq.buf; + else + lineq.in++; } - }while(ch!='\n' && ch!=0x04); + unlock(&lineq); + }while(raw.ref==0 && ch!='\n' && ch!=0x04); } i = 0; - while(n>0){ + while(n > 0){ ch = getc(&lineq); - if(ch == 0x04 || ch == -1) + if(ch==-1 || (raw.ref==0 && ch==0x04)) break; i++; *cbuf++ = ch; @@ -523,11 +524,42 @@ consread(Chan *c, void *buf, long n, ulong offset) case Qtime: return readnum(offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), 12); + case Qclock: + k = offset; + if(k >= 2*NUMSIZE) + return 0; + if(k+n > 2*NUMSIZE) + n = 2*NUMSIZE - k; + readnum(0, tmp, NUMSIZE, MACHP(0)->ticks, NUMSIZE); + readnum(0, tmp+NUMSIZE, NUMSIZE, HZ, NUMSIZE); + memmove(buf, tmp+k, n); + return n; + case Quser: return readstr(offset, buf, n, u->p->pgrp->user); - case Qlog: - return readlog(offset, buf, n); + case Qnull: + return 0; + + case Qklog: + qlock(&klogq); + if(waserror()){ + qunlock(&klogq); + nexterror(); + } + while(!cangetc(&klogq)) + sleep(&klogq.r, cangetc, &klogq); + for(i=0; iticks), NUMSIZE); case Qsysstat: j = 0; @@ -536,13 +568,10 @@ consread(Chan *c, void *buf, long n, ulong offset) mp = MACHP(id); j += sprint(&xbuf[j], "%d %d %d %d %d %d %d %d\n", id, mp->cs, mp->intr, mp->syscall, mp->pfault, - mp->tlbfault, mp->tlbpurge, mp->spinlock); + mp->tlbfault, mp->tlbpurge, m->spinlock); } } - return readstr(offset, buf, n, xbuf); - case Qnull: - return 0; default: panic("consread %lux\n", c->qid); @@ -550,17 +579,60 @@ consread(Chan *c, void *buf, long n, ulong offset) } } +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) { char cbuf[64]; char buf[256]; long l, m; - int id; char *a = va; Mach *mp; + int id; switch(c->qid.path){ + case Qrcons: case Qcons: /* * Damn. Can't page fault in putstrn, so copy the data locally. @@ -607,11 +679,14 @@ conswrite(Chan *c, void *va, long n, ulong offset) case Qnull: break; - case Qvmereset: - if(strcmp(u->p->pgrp->user, "bootes") != 0) - error(Eperm); - vmereset(); + case Qnoise: + consnoise(a, n); break; + + case Qlights: + conslights(a, n); + break; + case Qsysstat: for(id = 0; id < 32; id++) { if(active.machs & (1<spinlock = 0; } } - break; + default: error(Egreg); } @@ -644,119 +719,3 @@ conswstat(Chan *c, char *dp) { error(Eperm); } - -/* - * kernel based system log, passed between crashes - */ -void -sysloginit(void) -{ - Syslog *s; - int i; - - s = SYSLOG; - if(s->magic!=SYSLOGMAGIC || s->next>=&s->buf[sizeof(s->buf)] || s->nextbuf){ - s->wrapped = 0; - s->next = s->buf; - s->magic = SYSLOGMAGIC; - } -} - -void -syslog(char *p, int n) -{ - Syslog *s; - char *end; - int m; - - sysloginit(); - s = SYSLOG; - end = &s->buf[sizeof(s->buf)]; - while(n){ - if(s->next + n > end) - m = end - s->next; - else - m = n; - memmove(s->next, p, m); - s->next += m; - p += m; - n -= m; - if(s->next >= end){ - s->wrapped = 1; - s->next = s->buf; - } - } - wbflush(); -} - -long -readlog(ulong off, char *buf, ulong len) -{ - Syslog *s; - char *end; - char *start; - int n, m; - char *p; - - n = len; - p = buf; - - sysloginit(); - s = SYSLOG; - end = &s->buf[sizeof(s->buf)]; - - if(s->wrapped){ - start = s->next; - m = sizeof(s->buf); - } else { - start = s->buf; - m = s->next - start; - } - - if(off > m) - return 0; - if(off + n > m) - n = m - off; - start += off; - if(start > end) - start -= sizeof(s->buf); - - while(n > 0){ - if(start + n > end) - m = end - start; - else - m = n; - memmove(p, start, m); - start += m; - p += m; - n -= m; - if(start >= end) - start = s->buf; - } - - return p-buf; -} - -/* - * Read and write every byte of the log. This seems to ensure that - * on reboot, the bytes will really be in memory. I don't understand -- presotto - */ -void -flushsyslog(void) -{ - Syslog *s; - char *p, *end; - int x; - - s = SYSLOG; - end = &s->buf[sizeof(s->buf)]; - - x = splhi(); - lock(&printq); - for(p = s->buf; p < end; p++) - *p = *p; - unlock(&printq); - splx(x); - - wbflush(); -} diff --git a/port/devscc.c b/port/devscc.c index e72c9abd2702e3a5115935366e937a37d4d43931..3de80800f63589e97821752a34792ef2c6ccd02d 100644 --- a/port/devscc.c +++ b/port/devscc.c @@ -284,7 +284,6 @@ sccintr0(SCC *sp, uchar x) IOQ *cq; if(x & ExtPendB){ - /*kprint("scc %d: %2.2ux\n", sp-scc, *sp->ptr);*/ sccwrreg(sp, 0, ResExtPend); } if(x & RxPendB){ @@ -305,10 +304,8 @@ sccintr0(SCC *sp, uchar x) cq = sp->oq; lock(cq); ch = getc(cq); - /*kprint("<%2.2ux>", ch);*/ onepointseven(); if(ch < 0){ - /*kprint("", ch);*/ sccwrreg(sp, 0, ResTxPend); sp->printing = 0; wakeup(&cq->r); diff --git a/port/fault.c b/port/fault.c index 115b0b5db92332054afe36d9a4c913104ed9bb4b..3a9c145887a794f82eb8c513a3534f5e7e6d7402 100644 --- a/port/fault.c +++ b/port/fault.c @@ -9,7 +9,7 @@ int fault(ulong addr, int read) { - ulong mmuvirt, mmuphys = 0, n; + ulong mmuvirt, mmuphys, uncache = 0, n; Seg *s; PTE *opte, *pte, *npte; Orig *o; @@ -67,7 +67,11 @@ fault(ulong addr, int read) /* Make a new bss or lock segment page */ if(s - u->p->seg == LSEG) { pte->page = lkpage(o, addr); - mmuphys = PTEUNCACHE; + if(pte->page == 0) { + unlock(o); + return -1; + } + uncache = PTEUNCACHED; } else pte->page = newpage(0, o, addr); @@ -115,9 +119,12 @@ fault(ulong addr, int read) /* * Copy on reference (conf.copymode==1) or write (conf.copymode==0) */ - if((o->flag & OWRPERM) && (conf.copymode || !read) + if((o->flag & (OWRPERM|OSHARED))==OWRPERM && (conf.copymode || !read) && ((head && ((o->flag&OPURE) || o->nproc>1)) || (!head && pte->page->ref>1))){ + + if(!(o->flag&OISMEM)) + panic("copy on ref/wr to non memory"); touched = 1; /* * Look for the easy way out: are we the last non-modified? @@ -163,6 +170,7 @@ fault(ulong addr, int read) * increment on the mod list which must be removed */ if(zeroed){ + pg->ref--; o->npage--; opte->page = 0; }else{ /* copy page */ @@ -174,25 +182,27 @@ fault(ulong addr, int read) kunmap(k1); if(pg->ref <= 1) panic("pg->ref <= 1"); + pg->ref--; } - pg->ref--; easy: - mmuphys |= PTEWRITE; + mmuphys = PTEWRITE; }else{ - mmuphys |= PTERONLY; + mmuphys = PTERONLY; if(o->flag & OWRPERM) if(o->flag & OPURE){ if(!head && pte->page->ref==1) - mmuphys |= PTEWRITE; + mmuphys = PTEWRITE; }else if((head && o->nproc==1) || (!head && pte->page->ref==1)) - mmuphys |= PTEWRITE; + mmuphys = PTEWRITE; } mmuvirt = addr; - mmuphys |= PPN(pte->page->pa) | PTEVALID; - usepage(pte->page, 1); + mmuphys |= PPN(pte->page->pa) | PTEVALID | uncache; + if(o->flag&OISMEM) + usepage(pte->page, 1); + if(pte->page->va != addr) panic("wrong addr in tail %lux %lux", pte->page->va, addr); if(pte->proc && pte->proc != u->p){ @@ -200,9 +210,11 @@ fault(ulong addr, int read) print("u->p %lux pte->proc %lux\n", u->p, pte->proc); panic("addr %lux seg %d wrong proc in tail", addr, s-u->p->seg); } + unlock(o); if(touched == 0) m->tlbfault++; + putmmu(mmuvirt, mmuphys); return 0; } diff --git a/port/page.c b/port/page.c index 4f531e52e65e3d002dde22c2ad56391073e39f6c..6ddccac1eb015b1fb98232058d46866e6235b9e1 100644 --- a/port/page.c +++ b/port/page.c @@ -334,6 +334,7 @@ loop: o->nproc = 1; o->npage = 0; o->chan = c; + o->freepg = unusepage; if(c){ o->type = c->type; o->qid = c->qid; @@ -428,8 +429,6 @@ forkmod(Seg *old, Seg *new, Proc *p) ppte = 0; pte = old->mod; while(pte){ -if(pte->page==0) panic("forkmod zero page"); -if(pte->proc != u->p) panic("forkmod wrong page"); npte = newmod(o); npte->proc = p; npte->page = pte->page; @@ -579,15 +578,16 @@ freepage(Orig *o, int dolock) int i; pte = o->pte; - for(i=0; inpte; i++,pte++) + for(i=0; inpte; i++,pte++) { if(pg = pte->page){ /* assign = */ if(pg->ref == 1){ - unusepage(pg, dolock); + (*o->freepg)(pg, dolock); pte->page = 0; pg->o = 0; } pg->ref--; } + } o->npage = 0; } diff --git a/port/portdat.h b/port/portdat.h index 0fdb221294db423c5ec004890d2938f6c75a821d..08123baa09d8c1768e8b17223a4c21238411af47 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -9,6 +9,8 @@ typedef struct Env Env; typedef struct Envp Envp; typedef struct Envval Envval; typedef struct Etherpkt Etherpkt; +typedef struct IOQ IOQ; +typedef struct KIOQ KIOQ; typedef struct List List; typedef struct Mount Mount; typedef struct Mtab Mtab; @@ -199,6 +201,37 @@ struct Etherpkt { #define ETHERMAXTU 1514 /* maximum transmit size */ #define ETHERHDRSIZE 14 /* size of an ethernet header */ +/* + * 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 Mount { Ref; /* also used as a lock when playing lists */ @@ -229,6 +262,8 @@ struct Note #define OWRPERM 0x01 /* write permission */ #define OPURE 0x02 /* original data mustn't be written */ #define OCACHED 0x04 /* cached; don't discard on exit */ +#define OISMEM 0x08 /* origin contains real memory */ +#define OSHARED 0x10 /* origin does not copy on ref/wr */ struct Orig { @@ -247,6 +282,8 @@ struct Orig Qid mqid; ulong minca; /* base of region in chan */ ulong maxca; /* end of region in chan */ + void (*freepg)(Page*, int); /* how to free pages for this origin */ + Page (*allocpg)(int, Orig*, ulong); }; struct Page @@ -298,7 +335,6 @@ struct Seg ulong maxva; /* va of last pte */ PTE *mod; /* list of modified pte's */ ulong endseg; /* segments end */ - ulong pad[2]; /**/ }; /* diff --git a/port/portfns.h b/port/portfns.h index 580d811fa8d3630bc989445275c88c95f5964882..35e914d54010a565e9de02cc4edda9c764c76ce2 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -10,8 +10,10 @@ int blen(Block *); int bround(Block *, int); void buzz(int, int); void cancel(Alarm*); +int cangetc(void*); int canlock(Lock*); int canqlock(QLock*); +int canputc(void*); void chandevinit(void); void chandevreset(void); void chaninit(void); @@ -65,19 +67,27 @@ void freepage(Orig*, int); void freepte(Orig*); void freesegs(int); Block* getb(Blist*); +int getc(IOQ*); int getfields(char*, char**, int, char); Block* getq(Queue*); +int gets(IOQ*, void*, int); void gotolabel(Label*); void growpte(Orig*, ulong); void* ialloc(ulong, int); long ibrk(ulong, int); int incref(Ref*); +void initq(IOQ*); void insert(List**, List*, List*); void invalidateu(void); void isdir(Chan*); +void kbdclock(void); +void kbdrepeat(int); +int kbdputc(IOQ*, int); +int kprint(char*, ...); void kproc(char*, void(*)(void*), void*); void lights(int); Page* lkpage(Orig*, ulong); +void lkpgfree(Page*, int); void lock(Lock*); void lockinit(void); Orig* lookorig(ulong, ulong, int, Chan*); @@ -86,6 +96,7 @@ void mapstack(Proc*); void mklockseg(Seg*); void mmurelease(Proc*); int mount(Chan*, Chan*, int); +int mouseputc(IOQ*, int); Chan* namec(char*, int, int, ulong); Alarm* newalarm(void); Chan* newchan(void); @@ -112,7 +123,11 @@ Pgrp* pgrptab(int); #define poperror() u->nerrlab-- int postnote(Proc*, int, char*, int); int pprint(char*, ...); -void printslave(void); +void printinit(void); +int putc(IOQ*, int); +void putstr(char*); +void putstrn(char*, long); +void puts(IOQ*, void*, int); ulong procalarm(ulong); void procinit0(void); Proc* proctab(int); @@ -131,6 +146,10 @@ 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/sysproc.c b/port/sysproc.c index b82782ccb56b8d19371a6d8c30e9104706866e29..9ca1d3b1d2855aa42f4345a1e9ccd3e960ffdd93 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -66,7 +66,7 @@ sysfork(ulong *arg) usp = s->minva & (BY2PG-1); /* just low bits */ s->maxva = USTKTOP; n = (s->maxva-s->minva)>>PGSHIFT; - s->o = neworig(s->minva, n, OWRPERM, 0); + s->o = neworig(s->minva, n, OWRPERM|OISMEM, 0); lock(s->o); /* * Only part of last stack page @@ -250,7 +250,7 @@ sysexec(ulong *arg) s = &p->seg[ESEG]; s->proc = p; - s->o = neworig(TSTKTOP-(spage<o = neworig(TSTKTOP-(spage<minva = s->o->va; s->maxva = TSTKTOP; @@ -295,9 +295,9 @@ sysexec(ulong *arg) */ s = &p->seg[TSEG]; s->proc = p; - o = lookorig(UTZERO, (t-UTZERO)>>PGSHIFT, OCACHED, tc); + o = lookorig(UTZERO, (t-UTZERO)>>PGSHIFT, OCACHED|OISMEM, tc); if(o == 0){ - o = neworig(UTZERO, (t-UTZERO)>>PGSHIFT, OCACHED, tc); + o = neworig(UTZERO, (t-UTZERO)>>PGSHIFT, OCACHED|OISMEM, tc); o->minca = 0; o->maxca = sizeof(Exec)+exec.text; } @@ -311,9 +311,9 @@ sysexec(ulong *arg) */ s = &p->seg[DSEG]; s->proc = p; - o = lookorig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED, tc); + o = lookorig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED|OISMEM, tc); if(o == 0){ - o = neworig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED, tc); + o = neworig(t, (d-t)>>PGSHIFT, OWRPERM|OPURE|OCACHED|OISMEM, tc); o->minca = p->seg[TSEG].o->maxca; o->maxca = o->minca + exec.data; } @@ -327,7 +327,7 @@ sysexec(ulong *arg) */ s = &p->seg[BSEG]; s->proc = p; - o = neworig(d, (b-d)>>PGSHIFT, OWRPERM, 0); + o = neworig(d, (b-d)>>PGSHIFT, OWRPERM|OISMEM, 0); o->minca = 0; o->maxca = 0; s->o = o; diff --git a/power/clock.c b/power/clock.c index 91088cdb6c958ec80f9eac20b89be7851b076a0c..9e38d1fb79d2dd7e6164595318fb0e671de2ec5f 100644 --- a/power/clock.c +++ b/power/clock.c @@ -101,8 +101,8 @@ clock(Ureg *ur) p->time[p->insyscall]++; } } - printslave(); } + duartslave(); if(active.exiting && active.machs&(1<machno)){ print("someone's exiting\n"); exit(); diff --git a/power/devduart.c b/power/devduart.c new file mode 100644 index 0000000000000000000000000000000000000000..b50981f9b3c775a7a17eb92a263c55740ba23240 --- /dev/null +++ b/power/devduart.c @@ -0,0 +1,836 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +int duartacr; +int duartimr; + +void duartputs(IOQ*, char*, int); +void iprint(char*, ...); + +#define PAD 15 /* registers are well-spaced */ + +/* + * Register set for half the duart. There are really two sets. + */ +struct Duart{ + uchar mr1_2, /* Mode Register Channels 1 & 2 */ + pad0[PAD]; + uchar sr_csr, /* Status Register/Clock Select Register */ + pad1[PAD]; + uchar cmnd, /* Command Register */ + pad2[PAD]; + uchar data, /* RX Holding / TX Holding Register */ + pad3[PAD]; + uchar ipc_acr, /* Input Port Change/Aux. Control Register */ + pad4[PAD]; + uchar is_imr, /* Interrupt Status/Interrupt Mask Register */ + pad5[PAD]; + uchar ctur, /* Counter/Timer Upper Register */ + pad6[PAD]; + uchar ctlr, /* Counter/Timer Lower Register */ + pad7[PAD]; +}; +#define ppcr is_imr /* in the second register set */ + +#define DBD75 0 +#define DBD110 1 +#define DBD38400 2 +#define DBD150 3 +#define DBD300 4 +#define DBD600 5 +#define DBD1200 6 +#define DBD2000 7 +#define DBD2400 8 +#define DBD4800 9 +#define DBD1800 10 +#define DBD9600 11 +#define DBD19200 12 + +enum{ + CHAR_ERR =0x00, /* MR1x - Mode Register 1 */ + 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, + 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, + BD38400 =0xCC|0x0000, + BD19200 =0xCC|0x0100, + BD9600 =0xBB|0x0000, + BD4800 =0x99|0x0000, + BD2400 =0x88|0x0000, + BD1200 =0x66|0x0000, + BD300 =0x44|0x0000, + + Maxport =8, +}; + +/* + * requests to perform on a duart + */ +enum { + Dnone= 0, + Dbaud, + Dbreak, + Ddtr, + Dprint, + Dena, + Dstate, +}; + +/* + * software info for a serial duart interface + */ +typedef struct Duartport Duartport; +struct Duartport +{ + QLock; + int printing; /* true if printing */ + Duart *duart; /* device */ + int inited; + int c; /* character to restart output */ + int op; /* operation requested */ + int val; /* value of operation */ + Rendez opr; /* waiot here for op to complete */ + + /* 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/8]; /* characters that act as delimiters */ +}; +Duartport duartport[Maxport]; /* max possible */ + +/* + * configure a duart port, default is 9600 baud, 8 bits/char, 1 stop bit, + * no parity + */ +void +duartsetup(Duartport *dp) +{ + Duart *duart; + + duart = dp->duart; + + duart->cmnd = RESET_RCV|DIS_TX|DIS_RX; + duart->cmnd = RESET_TRANS; + duart->cmnd = RESET_ERR; + duart->cmnd = STOP_BRK; + + duart->ipc_acr = 0x80; /* baud-rate set 2 */ + duart->cmnd = RESET_MR; + duart->mr1_2 = NO_PAR|CBITS8; + duart->mr1_2 = ONESTOPB; + duart->sr_csr = (DBD9600<<4)|DBD9600; + duart->is_imr = IM_RRDYA|IM_XRDYA; + duart->cmnd = ENB_TX|ENB_RX; +} + +/* + * init the duart on the current processor + */ +void +duartinit(void) +{ + Duartport *dp; + + dp = &duartport[2*m->machno]; + if(dp->inited) + return; + dp->inited = 1; + + dp->duart = DUARTREG; + duartsetup(dp); + dp++; + dp->duart = DUARTREG+1; + duartsetup(dp); +} + +/* + * enable a duart port + */ +void +duartenable(Duartport *dp) +{ + dp->duart->cmnd = ENB_TX|ENB_RX; +} + +void +duartenable0(void) +{ + DUARTREG->cmnd = ENB_TX|ENB_RX; +} + +void +duartbaud(Duartport *dp, int b) +{ + int x = 0; + + 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: + errors("bad baud rate"); + } + if(x & 0x0100) + dp->duart->ipc_acr = duartacr |= 0x80; + else + dp->duart->ipc_acr = duartacr &= ~0x80; + dp->duart->sr_csr = x; +} + +void +duartdtr(Duartport *dp, int val) +{ + if (val) + dp->duart->ctlr=0x01; + else + dp->duart->ctur=0x01; +} + +void +duartbreak(Duartport *dp, int val) +{ + Duart *duart; + + duart = dp->duart; + if (val){ + duart->is_imr = duartimr &= ~IM_XRDYB; + duart->cmnd = STRT_BRK|ENB_TX; + } else { + duart->cmnd = STOP_BRK|ENB_TX; + duart->is_imr = duartimr |= IM_XRDYB; + } +} + +/* + * do anything requested for this CPU's duarts + */ +void +duartslave0(Duartport *dp) +{ + switch(dp->op){ + case Ddtr: + duartbaud(dp, dp->val); + break; + case Dbaud: + duartdtr(dp, dp->val); + break; + case Dbreak: + duartbreak(dp, dp->val); + break; + case Dprint: + dp->duart->cmnd = ENB_TX; + dp->duart->data = dp->val; + break; + case Dena: + duartenable(dp); + break; + case Dstate: + dp->val = dp->duart->is_imr; + break; + } + dp->op = Dnone; + wakeup(&dp->opr); +} +void +duartslave(void) +{ + Duartport *dp; + + dp = &duartport[2*m->machno]; + if(dp->op != Dnone) + duartslave0(dp); + dp++; + if(dp->op != Dnone) + duartslave0(dp); +} + +duartrintr(Duartport *dp) +{ + Duart *duart; + IOQ *cq; + int status; + char ch; + + duart = dp->duart; + status = duart->sr_csr; + ch = duart->data; + if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) + duart->cmnd = RESET_ERR; + + cq = dp->iq; + if(cq->putc) + (*cq->putc)(cq, ch); + else { + putc(cq, ch); + if(dp->delim[ch/8] & (1<<(ch&7)) ) + wakeup(&cq->r); + } +} + +duartxintr(Duartport *dp) +{ + Duart *duart; + IOQ *cq; + char ch; + + cq = dp->oq; + lock(cq); + ch = getc(cq); + duart = dp->duart; + if(ch < 0){ + dp->printing = 0; + wakeup(&cq->r); + duart->cmnd = DIS_TX; + } else + duart->data = ch; + unlock(cq); +} + +void +duartintr(void) +{ + int cause, status, c; + Duart *duart; + Duartport *dp; + + dp = &duartport[2*m->machno]; + duart = dp->duart; + cause = duart->is_imr; + /* + * I can guess your interrupt. + */ + /* + * Is it 1? + */ + if(cause & IM_RRDYA) + duartrintr(dp); + /* + * Is it 2? + */ + if(cause & IM_XRDYA) + duartxintr(dp); + /* + * Is it 3? + */ + if(cause & IM_RRDYB) + duartrintr(dp+1); + /* + * Is it 4? + */ + if(cause & IM_XRDYB) + duartxintr(dp+1); +} + +/* + * processor 0 only + */ +int +duartrawputc(int c) +{ + Duart *duart; + int i; + + duart = DUARTREG; + if(c == '\n') + duartrawputc('\r'); + duart->cmnd = ENB_TX; + i = 0; + while((duart->sr_csr&XMT_RDY) == 0) + if(++i >= 1000000){ + duartsetup(&duartport[0]); + for(i=0; i<100000; i++) + ; + break; + } + duart->data = c; + if(c == '\n') + for(i=0; i<100000; i++) + ; + return c; +} +void +duartrawputs(char *s) +{ + int i; + while(*s){ + duartrawputc(*s++); + } + for(i=0; i < 1000000; i++) + ; +} +void +iprint(char *fmt, ...) +{ + char buf[1024]; + long *arg; + + arg = (long*)(&fmt+1); + sprint(buf, fmt, *arg, *(arg+1), *(arg+2), *(arg+3)); + duartrawputs(buf); +} + +/* + * 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; + Duart *duart; + + x = splhi(); + lock(cq); + puts(cq, s, n); + dp = cq->ptr; + if(dp->printing == 0){ + ch = getc(cq); + if(ch >= 0){ + dp->printing = 1; + dp->val = ch; + dp->op = Dprint; + } + } + unlock(cq); + splx(x); +} + +/* + * 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; + if(oq){ + dp->oq = oq; + dp->oq->puts = duartputs; + dp->oq->ptr = dp; + } + if(iq){ + dp->iq = iq; + dp->iq->ptr = dp; + } + duartenable(dp); + duartbaud(dp, 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]; + + 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 int +opdone(void *x) +{ + Duartport *dp = x; + + return dp->op == Dnone; +} +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){ + qlock(dp); + 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': + dp->val = n; + dp->op = Dbaud; + sleep(&dp->opr, opdone, dp); + break; + case 'D': + case 'd': + dp->val = n; + dp->op = Ddtr; + sleep(&dp->opr, opdone, dp); + break; + case 'K': + case 'k': + dp->val = 1; + dp->op = Dbreak; + sleep(&dp->opr, opdone, dp); + tsleep(&dp->opr, return0, 0, n); + dp->val = 0; + dp->op = Dbreak; + sleep(&dp->opr, opdone, dp); + break; + case 'R': + case 'r': + /* can't control? */ + break; + case 'W': + case 'w': + if(n>=0 && n<1000) + dp->delay = n; + break; + } + qunlock(dp); + }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; +} + +Dirtab *duartdir; +int nduartport; + +/* + * allocate the queues if no one else has + */ +void +duartreset(void) +{ + Duartport *dp; + int i; + + /* + * allocate the directory and fill it in + */ + nduartport = 2*conf.nmach; + duartdir = ialloc(nduartport*2*sizeof(Dirtab), 0); + for(i = 0; i < nduartport; i++){ + sprint(duartdir[2*i].name, "tty%d", i); + sprint(duartdir[2*i+1].name, "tty%dctl", i); + duartdir[2*i].length = duartdir[2*i+1].length = 0; + duartdir[2*i].perm = duartdir[2*i+1].perm = 0666; + duartdir[2*i].qid.path = STREAMQID(i, Sdataqid); + duartdir[2*i+1].qid.path = STREAMQID(i, Sctlqid); + } + + /* + * allocate queues for any stream interfaces + */ + for(dp = duartport; dp < &duartport[nduartport]; dp++){ + if(dp->nostream) + continue; + + dp->iq = ialloc(sizeof(IOQ), 0); + initq(dp->iq); + dp->iq->ptr = dp; + + dp->oq = ialloc(sizeof(IOQ), 0); + initq(dp->oq); + dp->oq->ptr = dp; + dp->oq->puts = duartputs; + } +} + +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, 2*nduartport, devgen); +} + +void +duartstat(Chan *c, char *dp) +{ + switch(STREAMTYPE(c->qid.path)){ + case Sdataqid: + streamstat(c, dp, "tty0"); + break; + default: + devstat(c, dp, duartdir, 2*nduartport, devgen); + break; + } +} + +Chan* +duartopen(Chan *c, int omode) +{ + Duartport *dp; + + switch(STREAMTYPE(c->qid.path)){ + case Sdataqid: + case Sctlqid: + dp = &duartport[STREAMID(c->qid.path)]; + 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, 2*nduartport, devgen); +} + +void +duartcreate(Chan *c, char *name, int omode, ulong perm) +{ + errors("only God can create a tty"); +} + +void +duartclose(Chan *c) +{ + if(c->stream) + streamclose(c); +} + +long +duartread(Chan *c, void *buf, long n, ulong offset) +{ + Duartport *dp; + + if(c->qid.path&CHDIR) + return devdirread(c, buf, n, duartdir, 2*nduartport, devgen); + + switch(STREAMTYPE(c->qid.path)){ + case Sdataqid: + return streamread(c, buf, n); + case Sctlqid: + if(offset) + return 0; + dp = &duartport[STREAMID(c->qid.path)]; + qlock(dp); + dp->op = Dstate; + sleep(&dp->opr, opdone, dp); + *(uchar *)buf = dp->val; + qunlock(dp); + return 1; + } + + errors("no such duart type"); +} + +long +duartwrite(Chan *c, void *va, long n, ulong offset) +{ + return streamwrite(c, va, n, 0); +} + +void +duartremove(Chan *c) +{ + errors("can't remove a duart"); +} + +void +duartwstat(Chan *c, char *dp) +{ + errors("can't write a duart"); +} + +int +duartactive(void) +{ + int i; + + for(i = 0; i < nduartport; i++) + if(duartport[i].printing) + return 1; + return 0; } diff --git a/power/duart.c b/power/duart.c deleted file mode 100644 index ae385da90d2049a86434be1681f9b797da7ca40b..0000000000000000000000000000000000000000 --- a/power/duart.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "u.h" -#include "lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#define PAD 15 /* registers are well-spaced */ - -/* - * Register set for half the duart. There are really two sets. - */ -struct Duart{ - uchar mr1_2, /* Mode Register Channels 1 & 2 */ - pad0[PAD]; - uchar sr_csr, /* Status Register/Clock Select Register */ - pad1[PAD]; - uchar cmnd, /* Command Register */ - pad2[PAD]; - uchar data, /* RX Holding / TX Holding Register */ - pad3[PAD]; - uchar ipc_acr, /* Input Port Change/Aux. Control Register */ - pad4[PAD]; - uchar is_imr, /* Interrupt Status/Interrupt Mask Register */ - pad5[PAD]; - uchar ctur, /* Counter/Timer Upper Register */ - pad6[PAD]; - uchar ctlr, /* Counter/Timer Lower Register */ - pad7[PAD]; -}; -#define ppcr is_imr /* in the second register set */ - -#define DBD75 0 -#define DBD110 1 -#define DBD38400 2 -#define DBD150 3 -#define DBD300 4 -#define DBD600 5 -#define DBD1200 6 -#define DBD2000 7 -#define DBD2400 8 -#define DBD4800 9 -#define DBD1800 10 -#define DBD9600 11 -#define DBD19200 12 - -enum{ - CHAR_ERR =0x00, /* MR1x - Mode Register 1 */ - 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, - 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, -}; - -void -duartinit(void) -{ - Duart *duart; - - duart = DUARTREG; - - duart->cmnd = RESET_RCV|DIS_TX|DIS_RX; - duart->cmnd = RESET_TRANS; - duart->cmnd = RESET_ERR; - duart->cmnd = STOP_BRK; - - duart->ipc_acr = 0x80; /* baud-rate set 2 */ - duart->cmnd = RESET_MR; - duart->mr1_2 = NO_PAR|CBITS8; - duart->mr1_2 = ONESTOPB; - duart->sr_csr = (DBD9600<<4)|DBD9600; - duart->is_imr = IM_RRDYA|IM_XRDYA; - duart->cmnd = ENB_TX|ENB_RX; -} - -void -duartreset(void) -{ - DUARTREG->cmnd = ENB_TX|ENB_RX; -} - -void -duartintr(void) -{ - int cause, status, c; - Duart *duart; - - duart = DUARTREG; - cause = duart->is_imr; - /* - * I can guess your interrupt. - */ - /* - * Is it 1? - */ - if(cause & IM_RRDYA){ - /* keyboard input interrupt */ - status = duart->sr_csr; - c = duart->data; - if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) - duart->cmnd = RESET_ERR; - kbdchar(c); - } - /* - * Is it 2? - */ - if(cause & IM_XRDYA){ - c = conschar(); - if(c == -1) - duart->cmnd = DIS_TX; - else - duart->data = c; - } -} -/* -int -duartgetc(void) -{ - Duart *duart; - int c; - - duart = DUARTREG; - do; while ((duart->sr_csr & RCV_RDY) == 0); - c = duart->data&0177; - consputc(c); - if(c == '\r'){ - c = '\n'; - consputc(c); - } - return c; -} -*/ - -int -duartputc(int c) -{ - Duart *duart; - int i; - - duart = DUARTREG; - if(c == '\n') - duartputc('\r'); - duart->cmnd = ENB_TX; - i = 0; - while((duart->sr_csr&XMT_RDY) == 0) - if(++i >= 1000000){ - duartinit(); - for(i=0; i<100000; i++) - ; - break; - } - duart->data = c; - if(c == '\n') - for(i=0; i<100000; i++) - ; - return c; -} - -void -duartxmit(int c) -{ - Duart *duart; - - duart = DUARTREG; - duart->cmnd = ENB_TX; - duart->data = c; -} - -void -duartputs(char *s) -{ - int i; - while(*s){ - duartputc(*s++); - } - for(i=0; i < 1000000; i++) - ; -} - -void -iprint(char *s, void *a, void *b, void *c, void *d) -{ - char buf[1024]; - - sprint(buf, s, a, b, c, d); - duartputs(buf); -} diff --git a/power/fns.h b/power/fns.h index 0d27c45f084aa9cf4e579c679cad0b72df941f00..5ce367a15d056663a26745aacafed0cf3ce83b00 100644 --- a/power/fns.h +++ b/power/fns.h @@ -7,16 +7,12 @@ ulong confeval(char*); void confread(void); void confprint(void); void confset(char*); -int consactive(void); -int conschar(void); -void consoff(void); -int consputc(int); +void duartspecial(int, IOQ*, IOQ*, int); +int duartactive(void); +void duartenable0(void); void duartinit(void); void duartintr(void); -int duartputc(int); -void duartputs(char*); -void duartreset(void); -void duartxmit(int); +void duartslave(void); void evenaddr(ulong); void faultmips(Ureg*, int, int); ulong fcr31(void); @@ -28,19 +24,16 @@ ulong gettlbvirt(int); void gotopc(ulong); void icflush(void *, int); void ioboardinit(void); -void kbdchar(int); void intr(Ureg*); void lanceintr(void); void lanceparity(void); void lancesetup(Lance*); void launchinit(void); void launch(int); -void lights(int); void newstart(void); int newtlbpid(Proc*); void novme(int); void online(void); -void printinit(void); Block* prepend(Block*, int); void prflush(void); #define procsetup(p) ((p)->fpstate = FPinit) @@ -53,12 +46,11 @@ void puttlb(ulong, ulong); void puttlbx(int, ulong, ulong); int readlog(ulong, char*, ulong); void restfpregs(FPsave*, ulong); +#define screenputs void setvmevec(int, void (*)(int)); void sinit(void); uchar* smap(int, uchar*); void sunmap(int, uchar*); -void syslog(char*, int); -void sysloginit(void); void tlbinit(void); Block* tolance(Block*, int); void touser(void*); diff --git a/power/l.s b/power/l.s index f7557fb8e2c6a671814f37f8595d927cc5c64eed..b761d443f2b384888a094388866bb4270be45b53 100644 --- a/power/l.s +++ b/power/l.s @@ -160,10 +160,8 @@ TEXT gotopc(SB), $8 TEXT puttlb(SB), $4 - JAL splhi(SB) MOVW 0(FP), R2 MOVW 4(FP), R3 - MOVW R1, 4(SP) MOVW R2, M(TLBVIRT) MOVW R3, M(TLBPHYS) NOOP @@ -173,7 +171,6 @@ TEXT puttlb(SB), $4 BGEZ R4, index TLBWR NOOP - JAL splx(SB) RET index: diff --git a/power/lock.c b/power/lock.c index f9d49db6712e569240554a63c5e0b61b8ce12e36..924a76197b68a4a488df3f6d8817e2ea9d1b0d7b 100644 --- a/power/lock.c +++ b/power/lock.c @@ -15,6 +15,7 @@ #define SEMPERPG 64 /* hardware semaphores per page */ #define NSEMPG 1024 +#define ULOCKPG 512 struct { @@ -22,6 +23,7 @@ struct ulong *nextsem; /* next one to allocate */ int nsem; /* at SEMPERPG, jump to next page */ uchar bmap[NSEMPG]; /* allocation map */ + int ulockpg; /* count of user lock available */ }semalloc; Page lkpgheader[NSEMPG]; @@ -32,6 +34,7 @@ lockinit(void) memset(semalloc.bmap, 0, sizeof(semalloc.bmap)); semalloc.bmap[0] = 1; + semalloc.ulockpg = ULOCKPG; semalloc.lock.sbsem = SBSEM; semalloc.nextsem = SBSEM+1; semalloc.nsem = 1; @@ -63,6 +66,11 @@ lkpage(Orig *o, ulong va) int i; lock(&semalloc.lock); + if(--semalloc.ulockpg < 0) { + semalloc.ulockpg++; + unlock(&semalloc.lock); + return 0; + } top = &semalloc.bmap[NSEMPG]; for(p = semalloc.bmap; *p && p < top; p++) ; @@ -72,23 +80,28 @@ lkpage(Orig *o, ulong va) *p = 1; i = p-semalloc.bmap; pg = &lkpgheader[i]; - pg->pa = (ulong)((i*WD2PG) + SBSEM); + pg->pa = (ulong)((i*WD2PG) + SBSEM) & ~UNCACHED; pg->va = va; pg->o = o; + pg->ref = 1; unlock(&semalloc.lock); return pg; } void -lkpgfree(ulong *lpa) +lkpgfree(Page *pg, int dolock) { uchar *p; - p = &semalloc.bmap[(lpa-SBSEM)/WD2PG]; + lock(&semalloc.lock); + p = &semalloc.bmap[((pg->pa|UNCACHED)-(ulong)SBSEM)/BY2PG]; if(!*p) panic("lkpgfree"); *p = 0; + + semalloc.ulockpg++; + unlock(&semalloc.lock); } #define PCOFF -9 @@ -171,9 +184,10 @@ mklockseg(Seg *s) Orig *o; s->proc = u->p; - o = neworig(LKSEGBASE, 0, OWRPERM|OPURE, 0); + o = neworig(LKSEGBASE, 0, OWRPERM|OSHARED, 0); o->minca = 0; o->maxca = 0; + o->freepg = lkpgfree; s->o = o; s->minva = LKSEGBASE; s->maxva = LKSEGBASE; diff --git a/power/main.c b/power/main.c index c1862a6c89023ac0f3e11fe5a075c9b1428c7535..a44adeed67bf95f3b0c35533bdb3cb355e185e26 100644 --- a/power/main.c +++ b/power/main.c @@ -57,6 +57,7 @@ main(void) arginit(); lockinit(); printinit(); + duartspecial(0, &printq, &kbdq, 9600); tlbinit(); vecinit(); procinit0(); @@ -83,6 +84,7 @@ machinit(void) memset(m, 0, sizeof(Mach)); m->machno = n; m->stb = &stlb[n][0]; + duartinit(); } void @@ -370,13 +372,13 @@ exit(void) unlock(&active); spllo(); print("cpu %d exiting\n", m->machno); - while(active.machs || consactive()) + while(active.machs || duartactive()) for(i=0; i<1000; i++) ; splhi(); for(i=0; i<2000000; i++) ; - duartreset(); + duartenable0(); firmware(); } @@ -819,3 +821,17 @@ lanceparity(void) MODEREG->promenet &= ~4; MODEREG->promenet |= 4; } + +/* + * for the sake of a single devcons.c + */ +void +buzz(int f, int d) +{ +} +int +mouseputc(IOQ *q, int c) +{ + return 0; +} + diff --git a/power/mem.h b/power/mem.h index 8f8a6539c82099911bdf437c0542699014d35c39..0ad5851aaf2e4407a598ff0dea27eee780d7086e 100644 --- a/power/mem.h +++ b/power/mem.h @@ -96,7 +96,7 @@ #define PTEGLOBL (1<<8) #define PTEVALID (1<<9) #define PTEWRITE (1<<10) -#define PTEUNCACHE (1<<11) +#define PTEUNCACHED (1<<11) #define PTERONLY 0 #define PTEPID(n) ((n)<<6) #define TLBPID(n) (((n)>>6)&0x3F) diff --git a/ss/dat.h b/ss/dat.h index d1ea0affa1cb320f5c17b7284414b85d712b08fd..13e9bc1fcdd2aa9bca9ec2721dbbf7ad24605f22 100644 --- a/ss/dat.h +++ b/ss/dat.h @@ -212,38 +212,3 @@ struct short machs; short exiting; }active; - -/* - * character based IO (mouse, keyboard, console screen) - */ -typedef struct IOQ IOQ; -typedef struct KIOQ KIOQ; -#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; - diff --git a/ss/fns.h b/ss/fns.h index f6c924e76d376b84d5d3b8fcbe4bd6df0c918181..facfb778572ce38ff4ca15929498cdcd9c8abd62 100644 --- a/ss/fns.h +++ b/ss/fns.h @@ -59,6 +59,7 @@ void restartprint(Alarm*); void restfpregs(FPsave*); void screeninit(void); void screenputc(int); +void screenputs(char*, int); void spldone(void); ulong swap1(ulong*); void touser(ulong); @@ -66,34 +67,3 @@ void trap(Ureg*); void trapinit(void); #define wbflush() /* mips compatibility */ #define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1])) - -/* - * for queues (to go into portfns.h) - */ -int cangetc(void*); -int canputc(void*); -int getc(IOQ*); -int gets(IOQ*, void*, int); -void initq(IOQ*); -int putc(IOQ*, int); -void puts(IOQ*, void*, int); - -/* - * for the scc (to go into portfns.h) - */ -void sccintr(void); -void sccputs(IOQ*, char*, int); -void sccsetup(void*); -void sccspecial(int, IOQ*, IOQ*, int); - -/* - * for devcons (to go into portfns.h) - */ -void kbdclock(void); -void kbdrepeat(int); -int kbdputc(IOQ*, int); -int kprint(char*, ...); -int mouseputc(IOQ*, int); -void printinit(void); -void putstr(char*); -void putstrn(char*, long); diff --git a/ss/mem.h b/ss/mem.h index ff2f9ea5a3e2ea78d7778c41630bf4c10aaee0a3..1dc0cb0f2d9769c1694b7ff5b49dd044032aea28 100644 --- a/ss/mem.h +++ b/ss/mem.h @@ -92,6 +92,7 @@ #define PTEIO (1<<26) #define PTEACCESS (1<<25) #define PTEMODIFY (1<<24) +#define PTEUNCACHED 0 #define INVALIDPTE 0 #define PPN(pa) ((pa>>12)&0xFFFF)