M boot/boot.c => boot/boot.c +13 -0
@@ 25,6 25,18 @@ static void recover(Method*);
static Method *rootserver(char*);
void
+intest(void)
+{
+ int n;
+ char buf[128];
+
+ print(">");
+ n = read(0, buf, sizeof(buf)-1);
+print("read %d bytes\n", n);
+ write(1, buf, n);
+}
+
+void
pipetest(void)
{
int i, n, p[2];
@@ 178,6 190,7 @@ boot(int argc, char *argv[])
print("\n");
#endif DEBUG
+ intest();
pipetest();
pipetest2();
ethertest();
M port/devcons.c => port/devcons.c +94 -168
@@ 8,35 8,34 @@
#include "devtab.h"
-struct {
- IOQ; /* lock to klogputs */
- QLock; /* qlock to getc */
-}klogq;
+Queue *mouseq;
+Queue *kbdq; /* unprocessed console input */
+Queue *lineq; /* processed console input */
+Queue *printq; /* console output */
+Queue *klogq;
-IOQ mouseq;
-IOQ lineq; /* lock to getc; interrupt putc's */
-IOQ printq;
-KIOQ kbdq;
+static struct
+{
+ QLock;
+
+ int raw; /* true if we shouldn't process input */
+ int ctl; /* number of opens to the control file */
+ int x; /* index into line */
+ char line[1024]; /* current input line */
+
+ char c;
+ int count;
+ int repeat;
+} kbd;
-static Ref ctl; /* number of opens to the control file */
-static int raw; /* true if ctl file is raw */
char sysname[NAMELEN];
-/*
- * init the queues and set the output routine
- */
void
printinit(void)
{
- initq(&printq);
- printq.puts = 0;
- initq(&lineq);
- initq(&kbdq);
- kbdq.putc = kbdputc;
- initq(&klogq);
- initq(&mouseq);
- mouseq.putc = mouseputc;
+ klogq = qopen(32*1024, 0, 0, 0);
+ lineq = qopen(2*1024, 0, 0, 0);
}
/*
@@ 65,7 64,7 @@ putstrn(char *str, int n)
* put the message there. Tack a carriage return
* before new lines.
*/
- if(printq.puts == 0)
+ if(printq == 0)
return;
while(n > 0){
t = memchr(str, '\n', n);
@@ 74,62 73,16 @@ putstrn(char *str, int n)
memmove(buf, str, m);
buf[m] = '\r';
buf[m+1] = '\n';
- (*printq.puts)(&printq, buf, m+2);
+ qwrite(printq, buf, m+2, 1);
str = t + 1;
n -= m + 1;
} else {
- (*printq.puts)(&printq, str, n);
+ qwrite(printq, str, n, 1);
break;
}
}
}
-/*
- * Print a string in the kernel log. Ignore overflow.
- */
-void
-klogputs(char *str, long n)
-{
- 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(KIOQ *q)
-{
- uchar *p;
-
- for(p=q->out; p!=q->in; ){
- if(raw)
- return 1;
- if(*p==0x04 || *p=='\n')
- return 1;
- p++;
- if(p >= q->buf+sizeof(q->buf))
- p = q->buf;
- }
- return 0;
-}
-
int
sprint(char *s, char *fmt, ...)
{
@@ 154,7 107,7 @@ kprint(char *fmt, ...)
int n;
n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf;
- klogputs(buf, n);
+ qwrite(klogq, buf, n, 1);
return n;
}
@@ 202,7 155,7 @@ pprint(char *fmt, ...)
void
prflush(void)
{
- while(printq.in != printq.out) ;
+ while(qlen(printq) > 0) ;
}
void
@@ 245,8 198,12 @@ echo(Rune r, char *buf, int n)
return;
}
ctrlt = 0;
- if(raw)
+ if(kbd.raw)
return;
+
+ /*
+ * finally, the actual echoing
+ */
if(r == 0x15)
putstrn("^U\n", 3);
else
@@ 254,10 211,12 @@ echo(Rune r, char *buf, int n)
}
/*
- * turn '\r' into '\n' before putting it into the queue
+ * Called by a uart interrupt for console input.
+ *
+ * turn '\r' into '\n' before putting it into the queue.
*/
int
-kbdcr2nl(IOQ *q, int ch)
+kbdcr2nl(Queue *q, int ch)
{
if(ch == '\r')
ch = '\n';
@@ 267,11 226,13 @@ kbdcr2nl(IOQ *q, int ch)
/*
* Put character, possibly a rune, into read queue at interrupt time.
* Always called splhi from processor 0.
+ *
+ * Called at interrupt time to process a character.
*/
int
-kbdputc(IOQ *q, int ch)
+kbdputc(Queue *q, int ch)
{
- int i, n;
+ int n;
char buf[3];
Rune r;
@@ 281,42 242,35 @@ kbdputc(IOQ *q, int ch)
if(n == 0)
return 0;
echo(r, buf, n);
- kbdq.c = r;
- for(i=0; i<n; i++){
- *kbdq.in++ = buf[i];
- if(kbdq.in == kbdq.buf+sizeof(kbdq.buf))
- kbdq.in = kbdq.buf;
- }
- if(raw || r=='\n' || r==0x04)
- wakeup(&kbdq.r);
+ qproduce(kbdq, buf, n);
return 0;
}
void
kbdrepeat(int rep)
{
- kbdq.repeat = rep;
- kbdq.count = 0;
+ kbd.repeat = rep;
+ kbd.count = 0;
}
void
kbdclock(void)
{
- if(kbdq.repeat == 0)
+ if(kbd.repeat == 0)
return;
- if(kbdq.repeat==1 && ++kbdq.count>HZ){
- kbdq.repeat = 2;
- kbdq.count = 0;
+ if(kbd.repeat==1 && ++kbd.count>HZ){
+ kbd.repeat = 2;
+ kbd.count = 0;
return;
}
- if(++kbdq.count&1)
- kbdputc(&kbdq, kbdq.c);
+ if(++kbd.count&1)
+ kbdputc(kbdq, kbd.c);
}
int
consactive(void)
{
- return printq.in != printq.out;
+ return qlen(printq) > 0;
}
enum{
@@ 456,7 410,9 @@ consopen(Chan *c, int omode)
case Qconsctl:
if(!iseve())
error(Eperm);
- incref(&ctl);
+ qlock(&kbd);
+ kbd.ctl++;
+ qunlock(&kbd);
break;
}
return devopen(c, omode, consdir, NCONS, devgen);
@@ 476,10 432,10 @@ consclose(Chan *c)
switch(c->qid.path){
case Qconsctl:
if(c->flag&COPEN){
- lock(&ctl);
- if(--ctl.ref == 0)
- raw = 0;
- unlock(&ctl);
+ qlock(&kbd);
+ if(--kbd.ctl == 0)
+ kbd.raw = 0;
+ qunlock(&kbd);
}
case Qauth:
case Qauthcheck:
@@ 504,52 460,41 @@ consread(Chan *c, void *buf, long n, ulong offset)
return devdirread(c, buf, n, consdir, NCONS, devgen);
case Qcons:
- qlock(&kbdq);
+ qlock(&kbd);
if(waserror()){
- qunlock(&kbdq);
+ qunlock(&kbd);
nexterror();
}
- while(!cangetc(&lineq)){
- sleep(&kbdq.r, isbrkc, &kbdq);
- do{
- lock(&lineq);
- ch = getc(&kbdq);
- if(raw)
- goto Default;
- switch(ch){
- case '\b':
- if(lineq.in != lineq.out){
- if(lineq.in == lineq.buf)
- lineq.in = lineq.buf+sizeof(lineq.buf);
- lineq.in--;
- }
- break;
- case 0x15:
- lineq.in = lineq.out;
- break;
- Default:
- default:
- *lineq.in = ch;
- if(lineq.in >= lineq.buf+sizeof(lineq.buf)-1)
- lineq.in = lineq.buf;
- else
- lineq.in++;
- }
- unlock(&lineq);
- }while(raw==0 && ch!='\n' && ch!=0x04);
- }
- i = 0;
- while(n > 0){
- ch = getc(&lineq);
- if(ch==-1 || (raw==0 && ch==0x04))
+ while(!qcanread(lineq)){
+ qread(kbdq, &kbd.line[kbd.x], 1);
+ ch = kbd.line[kbd.x];
+ if(kbd.raw){
+ i = splhi();
+ qproduce(lineq, &kbd.line[kbd.x], 1);
+ splx(i);
+ continue;
+ }
+ switch(ch){
+ case '\b':
+ if(kbd.x)
+ kbd.x--;
+ break;
+ case 0x15:
+ kbd.x = 0;
+ break;
+ default:
+ kbd.line[kbd.x++] = ch;
break;
- i++;
- *cbuf++ = ch;
- --n;
+ }
+ if(kbd.x == sizeof(kbd.line) || ch == '\n' || ch == 0x04){
+ if(ch == 0x04)
+ kbd.x--;
+ qwrite(lineq, kbd.line, kbd.x, 1);
+ }
}
- poperror();
- qunlock(&kbdq);
- return i;
+ n = qread(lineq, buf, n);
+ qunlock(&kbd);
+ return n;
case Qcputime:
k = offset;
@@ 613,21 558,7 @@ consread(Chan *c, void *buf, long n, ulong offset)
return 0;
case Qklog:
- qlock(&klogq);
- if(waserror()){
- qunlock(&klogq);
- nexterror();
- }
- while(!cangetc(&klogq))
- sleep(&klogq.r, cangetc, &klogq);
- for(i=0; i<n; i++){
- if((ch=getc(&klogq)) == -1)
- break;
- *cbuf++ = ch;
- }
- poperror();
- qunlock(&klogq);
- return i;
+ return qread(klogq, buf, n);
case Qmsec:
return readnum(offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE);
@@ 730,7 661,7 @@ conswrite(Chan *c, void *va, long n, ulong offset)
long l, bp;
char *a = va;
Mach *mp;
- int id, fd, ch;
+ int id, fd;
Chan *swc;
switch(c->qid.path){
@@ 757,20 688,15 @@ conswrite(Chan *c, void *va, long n, ulong offset)
buf[n] = 0;
for(a = buf; a;){
if(strncmp(a, "rawon", 5) == 0){
- lock(&lineq);
- while((ch=getc(&kbdq)) != -1){
- *lineq.in++ = ch;
- if(lineq.in == lineq.buf+sizeof(lineq.buf))
- lineq.in = lineq.buf;
+ qlock(&kbd);
+ if(kbd.x){
+ qwrite(kbdq, kbd.line, kbd.x, 1);
+ kbd.x = 0;
}
- unlock(&lineq);
- lock(&ctl);
- raw = 1;
- unlock(&ctl);
+ kbd.raw = 1;
+ qunlock(&kbd);
} else if(strncmp(a, "rawoff", 6) == 0){
- lock(&ctl);
- raw = 0;
- unlock(&ctl);
+ kbd.raw = 0;
}
if(a = strchr(a, ' '))
a++;
M port/devpipe.c => port/devpipe.c +2 -2
@@ 301,9 301,9 @@ pipewrite(Chan *c, void *va, long n, ulong offset)
switch(NETTYPE(c->qid.path)){
case Qdata0:
- return qwrite(p->q[1], va, n);
+ return qwrite(p->q[1], va, n, 0);
case Qdata1:
- return qwrite(p->q[0], va, n);
+ return qwrite(p->q[0], va, n, 0);
default:
panic("piperead");
}
M port/portdat.h => port/portdat.h +3 -34
@@ 218,36 218,6 @@ struct Scsi
uchar cmdblk[16];
};
-/* 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 */
- };
- union{
- int (*gets)(IOQ*, void*, int); /* input */
- int (*getc)(IOQ*); /* output */
- };
- void *ptr;
-};
-
-struct KIOQ
-{
- QLock;
- IOQ;
- int repeat;
- int c;
- int count;
-};
-
enum
{
NSMAX = 1000,
@@ 654,13 624,12 @@ extern char eve[];
extern char hostdomain[];
extern uchar initcode[];
extern FPsave initfp;
-extern KIOQ kbdq;
-extern IOQ lineq;
-extern IOQ mouseq;
+extern Queue *kbdq;
+extern Queue *mouseq;
extern Ref noteidalloc;
extern int nrdy;
extern Palloc palloc;
-extern IOQ printq;
+extern Queue *printq;
extern char* statename[];
extern Image swapimage;
extern char sysname[NAMELEN];
M port/portfns.h => port/portfns.h +7 -14
@@ 77,10 77,8 @@ void freechan(Chan*);
void freepte(Segment*, Pte*);
void freesegs(int);
void freesession(Session*);
-int getc(IOQ*);
void getcolor(ulong, ulong*, ulong*, ulong*);
int getfields(char*, char**, int, char);
-int gets(IOQ*, void*, int);
void gotolabel(Label*);
int haswaitq(void*);
int hwcursmove(int, int);
@@ 88,15 86,14 @@ int hwcursset(uchar*, uchar*, int, int);
void iallocinit(void);
long ibrk(ulong, int);
int incref(Ref*);
-void initq(IOQ*);
void initscsi(void);
void initseg(void);
void invalidateu(void);
void isdir(Chan*);
int ispages(void*);
void kbdclock(void);
-int kbdcr2nl(IOQ*, int);
-int kbdputc(IOQ*, int);
+int kbdcr2nl(Queue*, int);
+int kbdputc(Queue*, int);
void kbdrepeat(int);
void kickpager(void);
int kprint(char*, ...);
@@ 109,7 106,6 @@ void lights(int);
void lock(Lock*);
void lockinit(void);
Page* lookpage(Image*, ulong);
-int m3mouseputc(IOQ*, int);
void machinit(void);
void* malloc(ulong);
void mmuswitch(Proc*);
@@ 123,7 119,6 @@ void mountfree(Mount*);
void mousebuttons(int);
void mousectl(char*);
void mouseclock(void);
-int mouseputc(IOQ*, int);
void mousescreenupdate(void);
int msize(void*);
Chan* namec(char*, int, int, ulong);
@@ 159,28 154,27 @@ void procinit0(void);
Proc* proctab(int);
Pte* ptealloc(void);
Pte* ptecpy(Pte*);
-int putc(IOQ*, int);
void putimage(Image*);
void putmmu(ulong, ulong, Page*);
void putpage(Page*);
-void puts(IOQ*, void*, int);
void putseg(Segment*);
void putstr(char*);
void putstr(char*);
void putstrn(char*, long);
void putswap(Page*);
ulong pwait(Waitmsg*);
+int qcanread(Queue*);
void qclose(Queue*);
-int qconsume(Queue*, uchar*, int);
+int qconsume(Queue*, void*, int);
void qhangup(Queue*);
int qlen(Queue*);
void qlock(QLock*);
Queue* qopen(int, int, void (*)(void*), void*);
-int qproduce(Queue*, uchar*, int);
-long qread(Queue*, char*, int);
+int qproduce(Queue*, void*, int);
+long qread(Queue*, void*, int);
void qreopen(Queue*);
void qunlock(QLock*);
-long qwrite(Queue*, char*, int);
+long qwrite(Queue*, void*, int, int);
int readnum(ulong, char*, ulong, ulong, int);
int readstr(ulong, char*, ulong, char*);
void ready(Proc*);
@@ 197,7 191,6 @@ void savefpregs(FPsave*);
void sccclock(void);
int sccintr(void);
void sccsetup(void*, ulong, int);
-void sccspecial(int, IOQ*, IOQ*, int);
void sched(void);
void schedinit(void);
int screenbits(void);
M port/qio.c => port/qio.c +34 -8
@@ 253,10 253,11 @@ allocb(int size)
* set, any bytes left in a block afer a consume are discarded.
*/
int
-qconsume(Queue *q, uchar *p, int len)
+qconsume(Queue *q, void *vp, int len)
{
Block *b;
int n, dowakeup;
+ uchar *p = vp;
/* sync with qwrite */
lock(q);
@@ 298,10 299,11 @@ qconsume(Queue *q, uchar *p, int len)
}
int
-qproduce(Queue *q, uchar *p, int len)
+qproduce(Queue *q, void *vp, int len)
{
Block *b;
int dowakeup;
+ uchar *p = vp;
/* sync with qread */
lock(q);
@@ 340,8 342,11 @@ qproduce(Queue *q, uchar *p, int len)
dowakeup = 0;
unlock(q);
- if(dowakeup)
+ if(dowakeup){
+ if(q->kick)
+ (*q->kick)(q->arg);
wakeup(&q->rr);
+ }
return len;
}
@@ 363,6 368,7 @@ qopen(int limit, int msg, void (*kick)(void*), void *arg)
q->kick = kick;
q->arg = arg;
q->state = msg ? Qmsg : 0;
+ q->state |= Qstarve;
return q;
}
@@ 380,10 386,11 @@ notempty(void *a)
* and wait on its Rendez.
*/
long
-qread(Queue *q, char *p, int len)
+qread(Queue *q, void *vp, int len)
{
Block *b;
int x, n, dowakeup;
+ uchar *p = vp;
qlock(&q->rlock);
if(waserror()){
@@ 467,10 474,11 @@ qnotfull(void *a)
* queue the data.
*/
long
-qwrite(Queue *q, char *p, int len)
+qwrite(Queue *q, void *vp, int len, int nowait)
{
int x, dowakeup;
Block *b;
+ uchar *p = vp;
b = allocb(len);
memmove(b->wp, p, len);
@@ 478,6 486,8 @@ qwrite(Queue *q, char *p, int len)
/* flow control */
while(!qnotfull(q)){
+ if(nowait)
+ return len;
qlock(&q->wlock);
q->state |= Qflow;
sleep(&q->wr, qnotfull, q);
@@ 493,8 503,11 @@ qwrite(Queue *q, char *p, int len)
error(Ehungup);
}
- b->next = q->bfirst;
- q->bfirst = b;
+ if(q->bfirst)
+ q->blast->next = b;
+ else
+ q->bfirst = b;
+ q->blast = b;
q->len += len;
if(q->state & Qstarve){
@@ 506,8 519,11 @@ qwrite(Queue *q, char *p, int len)
unlock(q);
splx(x);
- if(dowakeup)
+ if(dowakeup){
+ if(q->kick)
+ (*q->kick)(q->arg);
wakeup(&q->rr);
+ }
return len;
}
@@ 570,6 586,7 @@ void
qreopen(Queue *q)
{
q->state &= ~Qclosed;
+ q->state |= Qstarve;
}
/*
@@ 580,3 597,12 @@ qlen(Queue *q)
{
return q->len;
}
+
+/*
+ * return true if we can read without blocking
+ */
+int
+qcanread(Queue *q)
+{
+ return q->bfirst!=0;
+}