M gnot/dat.h => gnot/dat.h +42 -0
@@ 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;
M gnot/devcons.c => gnot/devcons.c +193 -526
@@ 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; ){
@@ 174,51 106,6 @@ isbrkc(void *arg)
}
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, ...)
{
return doprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s;
@@ 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<<id)) {
+ 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, 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<<id)) {
+ mp = MACHP(id);
+ mp->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;
-}
A gnot/devduart.c => gnot/devduart.c +914 -0
@@ 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);
+}
M gnot/fns.h => gnot/fns.h +16 -4
@@ 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);
M gnot/main.c => gnot/main.c +18 -0
@@ 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");
+}
M gnot/mem.h => gnot/mem.h +1 -2
@@ 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
M gnot/screen.c => gnot/screen.c +3 -493
@@ 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++);
}
M port/devbit.c => port/devbit.c +8 -0
@@ 1145,6 1145,14 @@ mousetry(Ureg *ur)
}
}
+int
+mouseputc(IOQ *q, int c)
+{
+ /*
+ * put your favorite serial mouse code here
+ */
+}
+
void
mouseupdate(int dolock)
{
M port/devproc.c => port/devproc.c +5 -1
@@ 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);
M port/fault.c => port/fault.c +2 -2
@@ 25,7 25,7 @@ fault(ulong addr, int read)
if(addr > USTKTOP)
return -1;
s = &u->p->seg[SSEG];
- if(s->o==0 || addr<s->maxva-USTACKSIZE || addr>=s->maxva)
+ if(s->o==0 || addr<s->maxva-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 || addr<s->maxva-USTACKSIZE || addr>=s->maxva)
+ if(s->o==0 || addr<s->maxva-USTKSIZE || addr>=s->maxva)
goto Err;
}
if(write && (s->o->flag&OWRPERM)==0)
M port/portdat.h => port/portdat.h +5 -6
@@ 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
{
M port/portfns.h => port/portfns.h +0 -4
@@ 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);
M port/sturp.c => port/sturp.c +10 -4
@@ 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;
M port/sysproc.c => port/sysproc.c +35 -0
@@ 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;
+}
+*/
M power/lock.c => power/lock.c +34 -9
@@ 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++;
M power/mem.h => power/mem.h +10 -11
@@ 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<<STLBLOG)
@@ 110,14 109,16 @@
* Address spaces
*/
-#define UZERO KUSEG /* base of user address space */
-#define UTZERO (UZERO+BY2PG) /* first address in user text */
-#define USTKTOP KZERO /* byte just beyond user stack */
-#define TSTKTOP (USERADDR+TSTKSIZ*BY2PG)/* top of temporary stack */
-#define TSTKSIZ 100
-#define KZERO KSEG0 /* base of kernel address space */
-#define KTZERO (KZERO+0x20000) /* first address in kernel text */
-#define USTACKSIZE (4*1024*1024) /* size of user stack */
+#define UZERO KUSEG /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define USTKTOP KZERO /* byte just beyond user stack */
+#define TSTKTOP (USERADDR+TSTKSIZ*BY2PG)/* top of temporary stack */
+#define TSTKSIZ 100
+#define KZERO KSEG0 /* base of kernel address space */
+#define KTZERO (KZERO+0x20000) /* first address in kernel text */
+#define USTKSIZE (4*1024*1024) /* size of user stack */
+#define LKSEGSIZE (25*BY2PG)
+#define LKSEGBASE (USTKTOP-USTKSIZE-LKSEGSIZE)
/*
* Exception codes
*/
@@ 138,6 139,4 @@
#define CUNK14 14 /* undefined 14 */
#define CUNK15 15 /* undefined 15 */
-#define NSEG 5
-
#define isphys(x) ((ulong)(x) & KZERO)
M ss/fns.h => ss/fns.h +4 -0
@@ 77,6 77,10 @@ void reset(void);
void restartprint(Alarm*);
void restfpregs(FPsave*);
void rs232ichar(int);
+void sccintr(void);
+void sccputs(IOQ*, char*, int);
+void sccsetup(void*);
+void sccspecial(int, IOQ*, IOQ*, int);
void screeninit(void);
void screenputc(int);
void spldone(void);
M ss/mem.h => ss/mem.h +1 -2
@@ 128,9 128,8 @@
#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
#define KZERO 0xE0000000 /* base of kernel address space */
#define KTZERO (KZERO+4*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
#define isphys(x) (((ulong)(x)&0xF0000000) == KZERO)