ref: 702ddcd8846c7c9b64e95e93e035003d1cab38d8
parent: d820cecf3f0e00f02da03d85f6db118d989e140b
author: 9ferno <gophone2015@gmail.com>
date: Sat Aug 7 01:45:30 EDT 2021
going for kbdfs
--- a/os/pc64/dat.h
+++ b/os/pc64/dat.h
@@ -37,6 +37,10 @@
u32 sr;
uintptr pc;
u32 pri;
+ void *p; /* Proc */
+ Mach *m;
+ u16 isilock;
+ u32 lockcycles;
};
struct Label
--- a/os/pc64/fns.h
+++ b/os/pc64/fns.h
@@ -158,7 +158,6 @@
void (*_pcmspecialclose)(int);
void pcmunmap(int, PCMmap*);
void pmap(uintptr, u64, s64);
-void poolinit(void);
void poolsizeinit(void);
void procsave(Proc*);
void procsetup(Proc*);
@@ -183,7 +182,6 @@
void setconfenv(void);
void* sigsearch(char*, int);
s32 segflush(void*, u32);
-void setpanic(void);
void showframe(void*, void*);
void syncclock(void);
uvlong tscticks(uvlong*);
--- a/os/pc64/main.c
+++ b/os/pc64/main.c
@@ -135,7 +135,6 @@
meminit(); /* builds the conf.mem entries */
confinit();
xinit();
- kbdinit();
i8253init();
/* TODO 9front if(i8237alloc != nil)
i8237alloc(); */
@@ -157,8 +156,6 @@
timersinit();
doc("mathinit");
mathinit();
- doc("kbdenable");
- kbdenable();
if(arch->clockenable){
doc("clockinit");
arch->clockenable();
--- a/os/pc64/mkfile
+++ b/os/pc64/mkfile
@@ -30,7 +30,6 @@
i8253.$O\
i8259.$O\
main.$O\
- kbd.$O\
memmap.$O\
memory.$O\
mmu.$O\
--- a/os/pc64/pc64
+++ b/os/pc64/pc64
@@ -13,14 +13,16 @@
ssl
cap
+ ether netif netaux ethermedium
+# bridge netif log
+ ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum iprouter plan9 nullmedium pktmedium
+
draw screen vga vgax cga
+# mouse mouse
pointer
+ kbd
vga pci
- ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum iprouter plan9 nullmedium pktmedium
- ether netif netaux ethermedium
-# bridge netif log
-
# ata
audio dma
uart
@@ -27,8 +29,6 @@
sd
# floppy dma
tinyfs
-# kbd
-# mouse mouse
# dbg x86break
ip
--- a/os/port/alloc.c
+++ b/os/port/alloc.c
@@ -918,7 +918,6 @@
static void
_poolfault(void *v, char *msg, uintptr c)
{
- setpanic();
auditmemloc(msg, v);
panic("%s %p (from %p/%zux)", msg, v, getcallerpc(&v), c);
}
@@ -1078,8 +1077,10 @@
return r;
}
+/*
void
poolinit(void)
{
debugkey('m', "memory pools", poolsummary, 0);
}
+*/
\ No newline at end of file
--- a/os/port/devcons.c
+++ b/os/port/devcons.c
@@ -14,37 +14,16 @@
void (*serwrite)(char *, int);
-Queue* kscanq; /* keyboard raw scancodes (when needed) */
-char* kscanid; /* name of raw scan format (if defined) */
-Queue* kbdq; /* unprocessed console input */
-Queue* lineq; /* processed console input */
-Queue* printq; /* console output */
-Queue* klogq; /* kernel print (log) output */
+void (*consdebug)(void) = nil;
+void (*screenputs)(char*, int) = nil;
+
+Queue* serialoq; /* serial console output */
+Queue* kprintoq; /* console output, for /dev/kprint */
+ulong kprintinuse; /* test and set whether /dev/kprint is open */
int iprintscreenputs = 1;
+
int panicking;
-static struct
-{
- RWlock;
- Queue* q;
-} kprintq;
-
-static struct
-{
- QLock;
-
- int raw; /* true if we shouldn't process input */
- int ctl; /* number of opens to the control file */
- int kbdr; /* number of open reads to the keyboard */
- int scan; /* true if reading raw scancodes */
- int x; /* index into line */
- char line[1024]; /* current input line */
-
- char c;
- int count;
- int repeat;
-} kbd;
-
char* sysname;
char* eve;
@@ -71,10 +50,6 @@
void
printinit(void)
{
- lineq = qopen(2*1024, 0, nil, nil);
- if(lineq == nil)
- panic("printinit");
- qnoblock(lineq, 1);
}
/*
@@ -92,8 +67,8 @@
static int
consactive(void)
{
- if(printq)
- return qlen(printq) > 0;
+ if(serialoq)
+ return qlen(serialoq) > 0;
return 0;
}
@@ -103,7 +78,7 @@
ulong now;
now = m->ticks;
- while(serwrite==nil && consactive())
+ while(consactive())
if(m->ticks - now >= HZ)
break;
}
@@ -148,7 +123,7 @@
{
int m;
char *t;
- char buf[PRINTSIZE+2];
+ int (*wq)(Queue*, void*, int);
/*
* how many different output devices do we need?
@@ -156,62 +131,35 @@
kmesgputs(str, n);
/*
- * if kprint is open, put the message there, otherwise
- * if there's an attached bit mapped display,
+ * if someone is reading /dev/kprint,
* put the message there.
- */
- m = consoleprint;
- if(canrlock(&kprintq)){
- if(kprintq.q != nil){
- if(waserror()){
- runlock(&kprintq);
- nexterror();
- }
- if(usewrite)
- qwrite(kprintq.q, str, n);
- else
- qiwrite(kprintq.q, str, n);
- poperror();
- m = 0;
- }
- runlock(&kprintq);
- }
- if(m && screenputs != nil){
- screenputs(str, n);
- }
-
- /*
+ * if not and there's an attached bit mapped display,
+ * put the message there.
+ *
* if there's a serial line being used as a console,
* put the message there.
*/
- if(serwrite != nil) {
- serwrite(str, n);
+ wq = usewrite && islo() ? qwrite : qiwrite;
+ if(kprintoq != nil && !qisclosed(kprintoq))
+ (*wq)(kprintoq, str, n);
+ else if(screenputs != nil)
+ screenputs(str, n);
+
+ if(serialoq == nil){
+ uartputs(str, n);
return;
}
- if(printq == 0)
- return;
-
while(n > 0) {
t = memchr(str, '\n', n);
- if(t && !kbd.raw) {
- m = t - str;
- if(m > sizeof(buf)-2)
- m = sizeof(buf)-2;
- memmove(buf, str, m);
- buf[m] = '\r';
- buf[m+1] = '\n';
- if(usewrite)
- qwrite(printq, buf, m+2);
- else
- qiwrite(printq, buf, m+2);
- str = t + 1;
- n -= m + 1;
+ if(t != nil) {
+ m = t-str;
+ (*wq)(serialoq, str, m);
+ (*wq)(serialoq, "\r\n", 2);
+ n -= m+1;
+ str = t+1;
} else {
- if(usewrite)
- qwrite(printq, str, n);
- else
- qiwrite(printq, str, n);
+ (*wq)(serialoq, str, n);
break;
}
}
@@ -279,25 +227,32 @@
return n;
}
-int
-kprint(char *fmt, ...)
+/*
+ * Want to interlock iprints to avoid interlaced output on
+ * multiprocessor, but don't want to deadlock if one processor
+ * dies during print and another has something important to say.
+ * Make a good faith effort.
+ */
+static Lock iprintlock;
+static int
+iprintcanlock(Lock *l)
{
- va_list arg;
- char buf[PRINTSIZE];
- int n;
-
- va_start(arg, fmt);
- n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- if(qfull(klogq))
- qflush(klogq);
- return qproduce(klogq, buf, n);
+ int i;
+
+ for(i=0; i<1000; i++){
+ if(canlock(l))
+ return 1;
+ if(l->m == MACHP(m->machno))
+ return 0;
+ microdelay(100);
+ }
+ return 0;
}
int
iprint(char *fmt, ...)
{
- int n, s;
+ int n, s, locked;
va_list arg;
char buf[PRINTSIZE];
@@ -305,9 +260,12 @@
va_start(arg, fmt);
n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
va_end(arg);
+ locked = iprintcanlock(&iprintlock);
if(screenputs != nil && iprintscreenputs)
screenputs(buf, n);
uartputs(buf, n);
+ if(locked)
+ unlock(&iprintlock);
splx(s);
return n;
@@ -314,36 +272,44 @@
}
void
-setpanic(void)
-{
- panicking = 1;
-}
-
-void
panic(char *fmt, ...)
{
- int n;
+ int s;
va_list arg;
char buf[PRINTSIZE];
- setpanic();
- kprintq.q = nil;
+ kprintoq = nil; /* don't try to write to /dev/kprint */
+
+ if(panicking)
+ for(;;);
+ panicking = 1;
+
+ s = splhi();
strcpy(buf, "panic: ");
va_start(arg, fmt);
- n = vseprint(buf+strlen(buf), buf+sizeof(buf)-1, fmt, arg) - buf;
+ vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
va_end(arg);
- buf[n] = '\n';
- putstrn(buf, n+1);
- spllo();
+ iprint("%s\n", buf);
+ if(consdebug)
+ (*consdebug)();
+ splx(s);
+ prflush();
dumpstack();
- exit(1);
+ /* reboot cpu servers and headless machines when not debugging */
+ if(getconf("*debug") == nil)
+ if(!conf.monitor)
+ exit(1);
+
+ /* otherwise, just hang */
+ while(islo()) idlehands();
+ for(;;);
}
void
_assert(char *fmt)
{
- panic("assert failed: %s", fmt);
+ panic("assert failed at %#p: %s", getcallerpc(&fmt), fmt);
}
/*
@@ -352,13 +318,13 @@
void
sysfatal(char *fmt, ...)
{
+ char err[256];
va_list arg;
- char buf[64];
va_start(arg, fmt);
- vsnprint(buf, sizeof(buf), fmt, arg);
+ vseprint(err, err + sizeof err, fmt, arg);
va_end(arg);
- error(buf);
+ panic("sysfatal: %s", err);
}
int
@@ -366,30 +332,22 @@
{
int n;
Chan *c;
- Osenv *o;
va_list arg;
char buf[2*PRINTSIZE];
- n = sprint(buf, "%s %d: ", up->text, up->pid);
+ if(up == nil || up->env->fgrp == nil)
+ return 0;
+
+ c = up->env->fgrp->fd[2];
+ if(c==nil || (c->flag&CMSG)!=0 || (c->mode!=OWRITE && c->mode!=ORDWR))
+ return 0;
+ n = snprint(buf, sizeof buf, "%s %ud: ", up->text, up->pid);
va_start(arg, fmt);
n = vseprint(buf+n, buf+sizeof(buf), fmt, arg) - buf;
va_end(arg);
- o = up->env;
- if(o->fgrp == 0) {
- print("%s", buf);
+ if(waserror())
return 0;
- }
- c = o->fgrp->fd[2];
- if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) {
- print("%s", buf);
- return 0;
- }
-
- if(waserror()) {
- print("%s", buf);
- return 0;
- }
devtab[c->type]->write(c, buf, n, c->offset);
poperror();
@@ -400,260 +358,6 @@
return n;
}
-void
-echo(Rune r, char *buf, int n)
-{
- if(kbd.raw)
- return;
-
- if(r == '\n'){
- if(printq)
- qiwrite(printq, "\r", 1);
- } else if(r == 0x15){
- buf = "^U\n";
- n = 3;
- }
- if(consoleprint && screenputs != nil)
- screenputs(buf, n);
- if(printq)
- qiwrite(printq, buf, n);
-}
-
-/*
- * Debug key support. Allows other parts of the kernel to register debug
- * key handlers, instead of devcons.c having to know whatever's out there.
- * A kproc is used to invoke most handlers, rather than tying up the CPU at
- * splhi, which can choke some device drivers (eg softmodem).
- */
-typedef struct {
- Rune r;
- char *m;
- void (*f)(Rune);
- int i; /* function called at interrupt time */
-} Dbgkey;
-
-static struct {
- Rendez;
- Dbgkey *work;
- Dbgkey keys[50];
- int nkeys;
- int on;
-} dbg;
-
-static Dbgkey *
-finddbgkey(Rune r)
-{
- int i;
- Dbgkey *dp;
-
- for(dp = dbg.keys, i = 0; i < dbg.nkeys; i++, dp++)
- if(dp->r == r)
- return dp;
- return nil;
-}
-
-static int
-dbgwork(void *)
-{
- return dbg.work != 0;
-}
-
-static void
-dbgproc(void *)
-{
- Dbgkey *dp;
-
- setpri(PriRealtime);
- for(;;) {
- do {
- sleep(&dbg, dbgwork, 0);
- dp = dbg.work;
- } while(dp == nil);
- dp->f(dp->r);
- dbg.work = nil;
- }
-}
-
-void
-debugkey(Rune r, char *msg, void (*fcn)(), int iflag)
-{
- Dbgkey *dp;
-
- if(dbg.nkeys >= nelem(dbg.keys))
- return;
- if(finddbgkey(r) != nil)
- return;
- for(dp = &dbg.keys[dbg.nkeys++] - 1; dp >= dbg.keys; dp--) {
- if(strcmp(dp->m, msg) < 0)
- break;
- dp[1] = dp[0];
- }
- dp++;
- dp->r = r;
- dp->m = msg;
- dp->f = fcn;
- dp->i = iflag;
-}
-
-static int
-isdbgkey(Rune r)
-{
- static int ctrlt;
- Dbgkey *dp;
- int echoctrlt = ctrlt;
-
- /*
- * ^t hack BUG
- */
- if(dbg.on || (ctrlt >= 2)) {
- if(r == 0x14 || r == 0x05) {
- ctrlt++;
- return 0;
- }
- if(dp = finddbgkey(r)) {
- if(dp->i || ctrlt > 2)
- dp->f(r);
- else {
- dbg.work = dp;
- wakeup(&dbg);
- }
- ctrlt = 0;
- return 1;
- }
- ctrlt = 0;
- }
- else if(r == 0x14){
- ctrlt++;
- return 1;
- }
- else
- ctrlt = 0;
- if(echoctrlt){
- char buf[UTFmax];
-
- buf[0] = 0x14;
- while(--echoctrlt >= 0){
- echo(buf[0], buf, 1);
- qproduce(kbdq, buf, 1);
- }
- }
- return 0;
-}
-
-static void
-dbgtoggle(Rune)
-{
- dbg.on = !dbg.on;
- print("Debug keys %s\n", dbg.on ? "HOT" : "COLD");
-}
-
-static void
-dbghelp(void)
-{
- int i;
- Dbgkey *dp;
- Dbgkey *dp2;
- static char fmt[] = "%c: %-22s";
-
- dp = dbg.keys;
- dp2 = dp + (dbg.nkeys + 1)/2;
- for(i = dbg.nkeys; i > 1; i -= 2, dp++, dp2++) {
- print(fmt, dp->r, dp->m);
- print(fmt, dp2->r, dp2->m);
- print("\n");
- }
- if(i)
- print(fmt, dp->r, dp->m);
- print("\n");
-}
-
-static void
-debuginit(void)
-{
- kproc("consdbg", dbgproc, nil, 0);
- debugkey('|', "HOT|COLD keys", dbgtoggle, 0);
- debugkey('?', "help", dbghelp, 0);
-}
-
-/*
- * Called by a uart interrupt for console input.
- *
- * turn '\r' into '\n' before putting it into the queue.
- */
-int
-kbdcr2nl(Queue *q, int ch)
-{
- if(ch == '\r')
- ch = '\n';
- return kbdputc(q, ch);
-}
-
-/*
- * Put character, possibly a rune, into read queue at interrupt time.
- * Performs translation for compose sequences
- * Called at interrupt time to process a character.
- */
-int
-kbdputc(Queue *q, int ch)
-{
- int n;
- char buf[UTFmax];
- Rune r;
- static Rune kc[15];
- static int nk, collecting = 0;
-
- r = ch;
- if(r == Latin) {
- collecting = 1;
- nk = 0;
- return 0;
- }
- if(collecting) {
- int c;
- nk += runetochar((char*)&kc[nk], &r);
- c = latin1(kc, nk);
- if(c < -1) /* need more keystrokes */
- return 0;
- collecting = 0;
- if(c == -1) { /* invalid sequence */
- echo(kc[0], (char*)kc, nk);
- qproduce(q, kc, nk);
- return 0;
- }
- r = (Rune)c;
- }
- kbd.c = r;
- n = runetochar(buf, &r);
- if(n == 0)
- return 0;
- if(!isdbgkey(r)) {
- echo(r, buf, n);
- qproduce(q, buf, n);
- }
- return 0;
-}
-
-void
-kbdrepeat(int rep)
-{
- kbd.repeat = rep;
- kbd.count = 0;
-}
-
-void
-kbdclock(void)
-{
- if(kbd.repeat == 0)
- return;
- if(kbd.repeat==1 && ++kbd.count>HZ){
- kbd.repeat = 2;
- kbd.count = 0;
- return;
- }
- if(++kbd.count&1)
- kbdputc(kbdq, kbd.c);
-}
-
enum{
Qdir,
Qcons,
@@ -662,8 +366,8 @@
Qdrivers,
Qhostowner,
Qkeyboard,
- Qklog,
- Qkprint,
+ Qklog, /* same as 9front's kmesg */
+ Qkprint, /* tail of kprint's and cons. Why not just a tail of klog? Why is this needed? */
Qscancode,
Qmemory,
Qmsec,
@@ -680,7 +384,6 @@
{
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
"cons", {Qcons}, 0, 0660,
- "consctl", {Qconsctl}, 0, 0220,
"sysctl", {Qsysctl}, 0, 0644,
"drivers", {Qdrivers}, 0, 0444,
"hostowner", {Qhostowner}, 0, 0644,
@@ -787,12 +490,13 @@
static void
consinit(void)
{
+ todinit();
randominit();
- debuginit();
+/*
debugkey('f', "files/6", fddump, 0);
debugkey('q', "panic", qpanic, 1);
debugkey('r', "exit", rexit, 1);
- klogq = qopen(128*1024, 0, 0, 0);
+*/
}
static Chan*
@@ -813,111 +517,43 @@
return devstat(c, dp, n, consdir, nelem(consdir), devgen);
}
-static void
-flushkbdline(Queue *q)
-{
- if(kbd.x){
- qwrite(q, kbd.line, kbd.x);
- kbd.x = 0;
- }
-}
-
static Chan*
consopen(Chan *c, u32 omode)
{
- c->aux = 0;
+ c->aux = nil;
+ c = devopen(c, omode, consdir, nelem(consdir), devgen);
switch((u64)c->qid.path){
- case Qconsctl:
- if(!iseve())
- error(Eperm);
- qlock(&kbd);
- kbd.ctl++;
- qunlock(&kbd);
- break;
-
- case Qkeyboard:
- if((omode & 3) != OWRITE) {
- qlock(&kbd);
- kbd.kbdr++;
- flushkbdline(kbdq);
- kbd.raw = 1;
- qunlock(&kbd);
- }
- break;
-
- case Qscancode:
- qlock(&kbd);
- if(kscanq || !kscanid) {
- qunlock(&kbd);
+ case Qkprint:
+ if(tas(&kprintinuse) != 0){
c->flag &= ~COPEN;
- if(kscanq)
- error(Einuse);
- else
- error(Ebadarg);
+ error(Einuse);
}
- kscanq = qopen(256, 0, nil, nil);
- qunlock(&kbd);
- break;
-
- case Qkprint:
- if((omode & 3) != OWRITE) {
- wlock(&kprintq);
- if(kprintq.q != nil){
- wunlock(&kprintq);
- error(Einuse);
- }
- kprintq.q = qopen(32*1024, Qcoalesce, nil, nil);
- if(kprintq.q == nil){
- wunlock(&kprintq);
+ if(kprintoq == nil){
+ kprintoq = qopen(8*1024, Qcoalesce, 0, 0);
+ if(kprintoq == nil){
+ c->flag &= ~COPEN;
error(Enomem);
}
- qnoblock(kprintq.q, 1);
- wunlock(&kprintq);
- c->iounit = qiomaxatomic;
- }
+ qnoblock(kprintoq, 1);
+ }else
+ qreopen(kprintoq);
+ c->iounit = qiomaxatomic;
break;
}
- return devopen(c, omode, consdir, nelem(consdir), devgen);
+ return c;
}
static void
consclose(Chan *c)
{
- if((c->flag&COPEN) == 0)
- return;
-
switch((u64)c->qid.path){
- case Qconsctl:
- /* last close of control file turns off raw */
- qlock(&kbd);
- if(--kbd.ctl == 0)
- kbd.raw = 0;
- qunlock(&kbd);
- break;
-
- case Qkeyboard:
- if(c->mode != OWRITE) {
- qlock(&kbd);
- --kbd.kbdr;
- qunlock(&kbd);
+ /* close of kprint allows other opens */
+ case Qkprint:
+ if(c->flag & COPEN){
+ kprintinuse = 0;
+ qhangup(kprintoq, nil);
}
break;
-
- case Qscancode:
- qlock(&kbd);
- if(kscanq) {
- qfree(kscanq);
- kscanq = 0;
- }
- qunlock(&kbd);
- break;
-
- case Qkprint:
- wlock(&kprintq);
- qfree(kprintq.q);
- kprintq.q = nil;
- wunlock(&kprintq);
- break;
}
}
@@ -926,9 +562,8 @@
{
int l;
Osenv *o;
- int ch, eol, i;
+ int i;
char *p, tmp[128];
- char *cbuf = buf;
if(n <= 0)
return n;
@@ -939,63 +574,8 @@
case Qsysctl:
return readstr(offset, buf, n, VERSION);
case Qcons:
- case Qkeyboard:
- qlock(&kbd);
- if(waserror()) {
- qunlock(&kbd);
- nexterror();
- }
- if(kbd.raw || kbd.kbdr) {
- if(qcanread(lineq))
- n = qread(lineq, buf, n);
- else {
- /* read as much as possible */
- do {
- i = qread(kbdq, cbuf, n);
- cbuf += i;
- n -= i;
- } while(n>0 && qcanread(kbdq));
- n = cbuf - (char*)buf;
- }
- } else {
- while(!qcanread(lineq)) {
- qread(kbdq, &kbd.line[kbd.x], 1);
- ch = kbd.line[kbd.x];
- eol = 0;
- switch(ch){
- case '\b':
- if(kbd.x)
- kbd.x--;
- break;
- case 0x15:
- kbd.x = 0;
- break;
- case '\n':
- case 0x04:
- eol = 1;
- default:
- kbd.line[kbd.x++] = ch;
- break;
- }
- if(kbd.x == sizeof(kbd.line) || eol) {
- if(ch == 0x04)
- kbd.x--;
- qwrite(lineq, kbd.line, kbd.x);
- kbd.x = 0;
- }
- }
- n = qread(lineq, buf, n);
- }
- qunlock(&kbd);
- poperror();
- return n;
+ error(Egreg);
- case Qscancode:
- if(offset == 0)
- return readstr(0, buf, n, kscanid);
- else
- return qread(kscanq, buf, n);
-
case Qtime:
snprint(tmp, sizeof(tmp), "%.lld", (vlong)mseconds()*1000);
return readstr(offset, buf, n, tmp);
@@ -1048,19 +628,24 @@
return n;
case Qklog:
- return qread(klogq, buf, n);
-
- case Qkprint:
- rlock(&kprintq);
- if(waserror()){
- runlock(&kprintq);
- nexterror();
+ /*
+ * This is unlocked to avoid tying up a process
+ * that's writing to the buffer. kmesg.n never
+ * gets smaller, so worst case the reader will
+ * see a slurred buffer.
+ */
+ if(offset >= kmesg.n)
+ n = 0;
+ else{
+ if(offset+n > kmesg.n)
+ n = kmesg.n - offset;
+ memmove(buf, kmesg.buf+offset, n);
}
- n = qread(kprintq.q, buf, n);
- poperror();
- runlock(&kprintq);
return n;
+ case Qkprint:
+ return qread(kprintoq, buf, n);
+
default:
print("consread %llud\n", c->qid.path);
error(Egreg);
@@ -1097,34 +682,7 @@
break;
case Qconsctl:
- if(n >= sizeof(buf))
- n = sizeof(buf)-1;
- strncpy(buf, a, n);
- buf[n] = 0;
- for(a = buf; a;){
- if(strncmp(a, "rawon", 5) == 0){
- qlock(&kbd);
- flushkbdline(kbdq);
- kbd.raw = 1;
- qunlock(&kbd);
- } else if(strncmp(a, "rawoff", 6) == 0){
- qlock(&kbd);
- kbd.raw = 0;
- kbd.x = 0;
- qunlock(&kbd);
- }
- if(a = strchr(a, ' '))
- a++;
- }
- break;
-
- case Qkeyboard:
- for(x=0; x<n; ) {
- Rune r;
- x += chartorune(&r, &a[x]);
- kbdputc(kbdq, r);
- }
- break;
+ error(Egreg);
case Qtime:
if(n >= sizeof(buf))
--- a/os/port/devuart.c
+++ b/os/port/devuart.c
@@ -5,6 +5,7 @@
#include "fns.h"
#include "io.h"
#include "../port/error.h"
+
#include "../port/netif.h"
enum
@@ -22,6 +23,7 @@
static int uartnuart;
static Dirtab *uartdir;
static int uartndir;
+static Timer *uarttimer;
struct Uartalloc {
Lock;
@@ -34,19 +36,21 @@
/*
* enable/disable uart and add/remove to list of enabled uarts
*/
-static Uart*
+Uart*
uartenable(Uart *p)
{
Uart **l;
+ if(p->enabled)
+ return p;
if(p->iq == nil){
- if((p->iq = qopen(4*1024, 0, uartflow, p)) == nil)
+ if((p->iq = qopen(8*1024, Qcoalesce, uartflow, p)) == nil)
return nil;
}
else
qreopen(p->iq);
if(p->oq == nil){
- if((p->oq = qopen(4*1024, 0, uartkick, p)) == nil){
+ if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
qfree(p->iq);
p->iq = nil;
return nil;
@@ -78,7 +82,11 @@
uartctl(p, "b9600");
(*p->phys->enable)(p, 1);
- lock(&uartalloc);
+ /*
+ * use ilock because uartclock can otherwise interrupt here
+ * and would hang on an attempt to lock uartalloc.
+ */
+ ilock(&uartalloc);
for(l = &uartalloc.elist; *l; l = &(*l)->elist){
if(*l == p)
break;
@@ -88,7 +96,7 @@
uartalloc.elist = p;
}
p->enabled = 1;
- unlock(&uartalloc);
+ iunlock(&uartalloc);
return p;
}
@@ -98,9 +106,11 @@
{
Uart **l;
+ if(!p->enabled)
+ return;
(*p->phys->disable)(p);
- lock(&uartalloc);
+ ilock(&uartalloc);
for(l = &uartalloc.elist; *l; l = &(*l)->elist){
if(*l == p){
*l = p->elist;
@@ -108,7 +118,7 @@
}
}
p->enabled = 0;
- unlock(&uartalloc);
+ iunlock(&uartalloc);
}
static Uart*
@@ -204,6 +214,8 @@
uartndir = 1 + 3*uartnuart;
uartdir = xalloc(uartndir * sizeof(Dirtab));
+ if(uartnuart && uart == nil || uartdir == nil)
+ panic("uartreset: no memory");
dp = uartdir;
strcpy(dp->name, ".");
mkqid(&dp->qid, 0, 0, QTDIR);
@@ -213,15 +225,15 @@
p = uartlist;
for(i = 0; i < uartnuart; i++){
/* 3 directory entries per port */
- sprint(dp->name, "eia%d", i);
+ snprint(dp->name, sizeof dp->name, "eia%d", i);
dp->qid.path = NETQID(i, Ndataqid);
dp->perm = 0660;
dp++;
- sprint(dp->name, "eia%dctl", i);
+ snprint(dp->name, sizeof dp->name, "eia%dctl", i);
dp->qid.path = NETQID(i, Nctlqid);
dp->perm = 0660;
dp++;
- sprint(dp->name, "eia%dstatus", i);
+ snprint(dp->name, sizeof dp->name, "eia%dstatus", i);
dp->qid.path = NETQID(i, Nstatqid);
dp->perm = 0444;
dp++;
@@ -231,9 +243,7 @@
if(p->console || p->special){
if(uartenable(p) != nil){
if(p->console){
- kbdq = p->iq;
- printq = p->oq;
- p->putc = kbdcr2nl;
+ serialoq = p->oq;
}
p->opens++;
}
@@ -244,9 +254,9 @@
if(uartnuart){
/*
* at 115200 baud, the 1024 char buffer takes 56 ms to process,
- * processing it every 22 ms should be fine
+ * processing it every 22 ms should be fine.
*/
- addclock0link(uartclock, 22);
+ uarttimer = addclock0link(uartclock, 22);
}
}
@@ -258,13 +268,13 @@
}
static Walkqid*
-uartwalk(Chan *c, Chan *nc, char **name, int nname)
+uartwalk(Chan *c, Chan *nc, char **name, s32 nname)
{
return devwalk(c, nc, name, nname, uartdir, uartndir, devgen);
}
-static int
-uartstat(Chan *c, uchar *dp, int n)
+static s32
+uartstat(Chan *c, uchar *dp, s32 n)
{
if(NETTYPE(c->qid.path) == Ndataqid)
setlength(NETID(c->qid.path));
@@ -308,9 +318,8 @@
static void
uartdrainoutput(Uart *p)
{
- if(!p->enabled)
+ if(!p->enabled || up == nil || !islo())
return;
-
p->drain = 1;
if(waserror()){
p->drain = 0;
@@ -336,7 +345,9 @@
qlock(p);
if(--(p->opens) == 0){
qclose(p->iq);
+ ilock(&p->rlock);
p->ir = p->iw = p->istage;
+ iunlock(&p->rlock);
/*
*/
@@ -474,22 +485,18 @@
if((*p->phys->stop)(p, n) < 0)
return -1;
break;
- case 'T':
- case 't':
- p->dcdts = n;
- break;
case 'W':
case 'w':
- /* TODO 9front manages the timer here */
- /* obsolete */
+ if(uarttimer == nil || n < 1)
+ return -1;
+ uarttimer->tns = (vlong)n * 100000LL;
break;
case 'X':
case 'x':
- if(p->enabled){
- ilock(&p->tlock);
- p->xonoff = n;
- iunlock(&p->tlock);
- }
+ ilock(&p->tlock);
+ p->xonoff = n;
+ p->blocked = 0;
+ iunlock(&p->tlock);
break;
}
}
@@ -521,7 +528,7 @@
poperror();
break;
case Nctlqid:
- cmd = malloc(n+1);
+ cmd = smalloc(n+1);
memmove(cmd, buf, n);
cmd[n] = 0;
qlock(p);
@@ -544,8 +551,8 @@
return n;
}
-static int
-uartwstat(Chan *c, uchar *dp, int n)
+static s32
+uartwstat(Chan *c, uchar *dp, s32 n)
{
Dir d;
Dirtab *dt;
@@ -567,7 +574,7 @@
}
void
-uartpower(int on)
+uartpower(s32 on)
{
Uart *p;
@@ -637,7 +644,7 @@
{
Uart *p = v;
- if(p->blocked)
+ if(!p->enabled || p->blocked)
return;
ilock(&p->tlock);
@@ -651,6 +658,35 @@
}
/*
+ * Move data from the interrupt staging area to
+ * the input Queue.
+ */
+static void
+uartstageinput(Uart *p)
+{
+ int n;
+ uchar *ir, *iw;
+
+ while(p->ir != p->iw){
+ ir = p->ir;
+ if(p->ir > p->iw){
+ iw = p->ie;
+ p->ir = p->istage;
+ }
+ else{
+ iw = p->iw;
+ p->ir = p->iw;
+ }
+ if((n = qproduce(p->iq, ir, iw - ir)) < 0){
+ p->serr++;
+ (*p->phys->rts)(p, 0);
+ }
+ else if(n == 0)
+ p->berr++;
+ }
+}
+
+/*
* receive a character at interrupt time
*/
void
@@ -671,14 +707,18 @@
/* receive the character */
if(p->putc)
p->putc(p->iq, ch);
- else{
+ else if (p->iw) { /* maybe the line isn't enabled yet */
+ ilock(&p->rlock);
next = p->iw + 1;
if(next == p->ie)
next = p->istage;
+ if(next == p->ir)
+ uartstageinput(p);
if(next != p->ir){
*p->iw = ch;
p->iw = next;
}
+ iunlock(&p->rlock);
}
}
@@ -690,22 +730,15 @@
uartclock(void)
{
Uart *p;
- uchar *iw;
+ ilock(&uartalloc);
for(p = uartalloc.elist; p; p = p->elist){
- /* this amortizes cost of qproduce to many chars */
+ /* this hopefully amortizes cost of qproduce to many chars */
if(p->iw != p->ir){
- iw = p->iw;
- if(iw < p->ir){
- if(qproduce(p->iq, p->ir, p->ie-p->ir) < 0)
- (*p->phys->rts)(p, 0);
- p->ir = p->istage;
- }
- if(iw > p->ir)
- if(qproduce(p->iq, p->ir, iw-p->ir) < 0)
- (*p->phys->rts)(p, 0);
- p->ir = iw;
+ ilock(&p->rlock);
+ uartstageinput(p);
+ iunlock(&p->rlock);
}
/* hang up if requested */
@@ -725,6 +758,7 @@
iunlock(&p->tlock);
}
}
+ iunlock(&uartalloc);
}
/*
--- a/os/port/portdat.h
+++ b/os/port/portdat.h
@@ -575,11 +575,12 @@
extern Dev* devtab[];
extern char* eve;
extern int hwcurs;
+extern Queue* kprintoq;
extern Queue *kbdq;
extern Queue *kscanq;
extern Ref noteidalloc;
-extern Queue *printq;
extern uint qiomaxatomic;
+extern Queue* serialoq;
extern char* statename[];
extern char* sysname;
extern Talarm talarm;
--- a/os/port/proc.c
+++ b/os/port/proc.c
@@ -306,7 +306,7 @@
p->qnext = p+1;
p->qnext = 0;
- debugkey('p', "processes", procdump, 0);
+ /* debugkey('p', "processes", procdump, 0); */
}
void
--- a/os/port/qio.c
+++ b/os/port/qio.c
@@ -1524,6 +1524,6 @@
qdump(Queue *q)
{
if(q)
- kprint("q=%p bfirst=%p blast=%p len=%d dlen=%d limit=%d state=#%x\n",
+ iprint("q=%p bfirst=%p blast=%p len=%d dlen=%d limit=%d state=#%x\n",
q, q->bfirst, q->blast, q->len, q->dlen, q->limit, q->state);
}
--- a/os/port/taslock.c
+++ b/os/port/taslock.c
@@ -12,7 +12,6 @@
if(panicking)
return;
- setpanic();
panic("lock loop 0x%p key 0x%ux pc 0x%zux held by pc 0x%zux\n", l, l->key, pc, l->pc);
panic("lockloop");
}
@@ -36,6 +35,9 @@
}
}
l->pc = pc;
+ l->p = up;
+ l->m = MACHP(m->machno);
+ l->isilock = 0;
return;
}
@@ -54,6 +56,9 @@
l->pri = up->pri;
up->pri = PriLock;
l->pc = pc;
+ l->p = up;
+ l->m = MACHP(m->machno);
+ l->isilock = 0;
}
void
@@ -68,6 +73,9 @@
if(_tas((int*)&l->key) == 0) {
l->sr = x;
l->pc = pc;
+ l->p = up;
+ l->m = MACHP(m->machno);
+ l->isilock = 1;
return;
}
if(conf.nmach < 2)
@@ -94,6 +102,9 @@
up->pri = PriLock;
}
l->pc = getcallerpc(&l);
+ l->p = up;
+ l->m = MACHP(m->machno);
+ l->isilock = 0;
return 1;
}
@@ -104,10 +115,17 @@
if(l->key == 0)
print("unlock: not locked: pc %zux\n", getcallerpc(&l));
+ if(l->isilock)
+ print("unlock(%#p) of ilock: pc %#p, held by %#p\n",
+ l, getcallerpc(&l), l->pc);
+ if(l->p != up)
+ print("unlock(%#p): up changed: pc %#p, acquired at pc %#p, lock p %#p, unlock up %#p\n",
+ l, getcallerpc(&l), l->pc, l->p, up);
p = l->pri;
+ l->m = nil;
+ coherence();
l->key = 0;
l->pc = 0;
- coherence();
if(up && islo()){
/*
* Call sched if the need arose while locks were held
@@ -122,13 +140,14 @@
void
iunlock(Lock *l)
{
- ulong sr;
+ u32 sr;
if(l->key == 0)
print("iunlock: not locked: pc %zux\n", getcallerpc(&l));
sr = l->sr;
+ l->m = nil;
+ coherence();
l->pc = 0;
l->key = 0;
- coherence();
splx(sr);
}
--- a/os/port/xalloc.c
+++ b/os/port/xalloc.c
@@ -67,7 +67,7 @@
xhole(cm->base, cm->npage*BY2PG);
}
- debugkey('x', "xalloc/ialloc", ixprt, 0);
+ /* debugkey('x', "xalloc/ialloc", ixprt, 0); */
xsummary();
}