From d2a20e0abc18e86bac9e72d3c9749604aba60e19 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 21 Oct 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-10-21 --- bitsy/devpenmouse.c | 447 +++++++++++++++++++++++ "bitsy/dev\302\265c.c" | 352 +++++++++++++++++++ bitsy/fns.h | 4 + bitsy/sa1110uart.c | 21 +- bitsy/screen.c | 10 +- bitsy/screen.h | 8 +- boot/aux.c | 10 +- boot/bootip.c | 4 +- carrera/screen.c | 4 +- pc/devi82365.c | 28 +- pc/ether589.c | 2 +- pc/ethersmc.c | 779 +++++++++++++++++++++++++++++++++++++++++ pc/fns.h | 2 +- port/devcons.c | 86 +++-- port/devdraw.c | 2 +- 15 files changed, 1699 insertions(+), 60 deletions(-) create mode 100644 bitsy/devpenmouse.c create mode 100644 "bitsy/dev\302\265c.c" create mode 100644 pc/ethersmc.c diff --git a/bitsy/devpenmouse.c b/bitsy/devpenmouse.c new file mode 100644 index 0000000000000000000000000000000000000000..324ac12019956b559cea22a2f380563a8108cb89 --- /dev/null +++ b/bitsy/devpenmouse.c @@ -0,0 +1,447 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +typedef struct Mouseinfo Mouseinfo; +typedef struct Mousestate Mousestate; +typedef struct Calibration Calibration; + +struct Calibration +{ + long scalex; + long scaley; + long transx; + long transy; +} calibration = { + -0x10000*0x400/320, + -0x10000*0x400/240, + 320, + 240 +}; + +struct Mousestate +{ + Point xy; /* mouse.xy */ + int buttons; /* mouse.buttons */ + ulong counter; /* increments every update */ + ulong msec; /* time of last event */ +}; + +struct Mouseinfo +{ + Mousestate; + ulong lastcounter; /* value when /dev/mouse read */ + Rendez r; + Ref; + QLock; + int open; + int inopen; + Mousestate queue[16]; /* circular buffer of click events */ + int ri; /* read index into queue */ + int wi; /* write index into queue */ + uchar qfull; /* queue is full */ +}; + +Mouseinfo mouse; +int mouseshifted; + +int penmousechanged(void*); +static void penmousetrack(int b, int x, int y); + +enum{ + Qdir, + Qmouse, + Qmousein, + Qmousectl, +}; + +static Dirtab mousedir[]={ + "mouse", {Qmouse}, 0, 0666, + "mousein", {Qmousein}, 0, 0220, + "mousectl", {Qmousectl}, 0, 0220, +}; + +static uchar buttonmap[8] = { + 0, 1, 2, 3, 4, 5, 6, 7, +}; +static int mouseswap; + +extern Memimage* gscreen; + +void +penbutton(int up, int b) { + if (up) + mouse.buttons &= ~ (1 << b); + else + mouse.buttons |= 1 << b; + penmousetrack(mouse.buttons, -1, -1); +} + +void +pentrackxy(int x, int y) { + if (x == -1) { + /* pen up. associate with button 1, 2, 3 up */ + if (mouse.buttons & 0x7) + mouse.buttons &= ~0x7; + } else { + x = (x<<16)/calibration.scalex + calibration.transx; + y = (y<<16)/calibration.scaley + calibration.transy; + } + penmousetrack(mouse.buttons, x, y); +} + +static void +penmousereset(void) +{ + if(!conf.monitor) + return; +} + +static void +penmouseinit(void) +{ + if(!conf.monitor) + return; +} + +static Chan* +penmouseattach(char *spec) +{ + if(!conf.monitor) + error(Egreg); + return devattach('m', spec); +} + +static Chan* +penmouseclone(Chan *c, Chan *nc) +{ + nc = devclone(c, nc); + if(c->qid.path != CHDIR) + incref(&mouse); + return nc; +} + +static int +penmousewalk(Chan *c, char *name) +{ + return devwalk(c, name, mousedir, nelem(mousedir), devgen); +} + +static void +penmousestat(Chan *c, char *db) +{ + devstat(c, db, mousedir, nelem(mousedir), devgen); +} + +static Chan* +penmouseopen(Chan *c, int omode) +{ + switch(c->qid.path){ + case CHDIR: + if(omode != OREAD) + error(Eperm); + break; + case Qmouse: + lock(&mouse); + if(mouse.open){ + unlock(&mouse); + error(Einuse); + } + mouse.open = 1; + mouse.ref++; + unlock(&mouse); + break; + case Qmousein: + /* error("disabled"); */ + lock(&mouse); + if(mouse.inopen){ + unlock(&mouse); + error(Einuse); + } + mouse.inopen = 1; + unlock(&mouse); + break; + default: + incref(&mouse); + } + c->mode = openmode(omode); + c->flag |= COPEN; + c->offset = 0; + return c; +} + +static void +penmousecreate(Chan*, char*, int, ulong) +{ + if(!conf.monitor) + error(Egreg); + error(Eperm); +} + +static void +penmouseclose(Chan *c) +{ + if(c->qid.path!=CHDIR && (c->flag&COPEN)){ + lock(&mouse); + if(c->qid.path == Qmouse) + mouse.open = 0; + else if(c->qid.path == Qmousein){ + mouse.inopen = 0; + unlock(&mouse); + return; + } + --mouse.ref; + unlock(&mouse); + } +} + + +static long +penmouseread(Chan *c, void *va, long n, vlong) +{ + char buf[4*12+1]; + static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; + Mousestate m; + int b; + + switch(c->qid.path){ + case CHDIR: + return devdirread(c, va, n, mousedir, nelem(mousedir), devgen); + + case Qmouse: + while(penmousechanged(0) == 0) + sleep(&mouse.r, penmousechanged, 0); + + mouse.qfull = 0; + + /* + * No lock of the indicies is necessary here, because ri is only + * updated by us, and there is only one mouse reader + * at a time. I suppose that more than one process + * could try to read the fd at one time, but such behavior + * is degenerate and already violates the calling + * conventions for sleep above. + */ + if(mouse.ri != mouse.wi) { + m = mouse.queue[mouse.ri]; + if(++mouse.ri == nelem(mouse.queue)) + mouse.ri = 0; + } else { + m = mouse.Mousestate; + } + + b = buttonmap[m.buttons&7]; + /* put buttons 4 and 5 back in */ + b |= m.buttons & (3<<3); + sprint(buf, "m%11d %11d %11d %11lud", + m.xy.x, m.xy.y, + b, + m.msec); + mouse.lastcounter = m.counter; + if(n > 1+4*12) + n = 1+4*12; + memmove(va, buf, n); + return n; + } + return 0; +} + +static void +setbuttonmap(char* map) +{ + int i, x, one, two, three; + + one = two = three = 0; + for(i = 0; i < 3; i++){ + if(map[i] == 0) + error(Ebadarg); + if(map[i] == '1'){ + if(one) + error(Ebadarg); + one = 1<qid.path){ + case CHDIR: + error(Eisdir); + + case Qmousectl: + if(n >= sizeof(buf)) + n = sizeof(buf)-1; + strncpy(buf, va, n); + if(buf[n - 1] == '\n') + buf[n-1] = 0; + else + buf[n] = 0; + nf = getfields(buf, field, 3, 1, " "); + if(strcmp(field[0], "swap") == 0){ + if(mouseswap) + setbuttonmap("123"); + else + setbuttonmap("321"); + mouseswap ^= 1; + } + else if(strcmp(field[0], "calibrate") == 0){ + if (nf == 1) { + calibration.scalex = 1; + calibration.scaley = 1; + calibration.transx = 0; + calibration.transy = 0; + } else if (nf == 5) { + calibration.scalex = strtol(field[1], nil, 0); + calibration.scaley = strtol(field[2], nil, 0); + calibration.transx = strtol(field[3], nil, 0); + calibration.transy = strtol(field[4], nil, 0); + } + } + return n; + + case Qmousein: + if(n > sizeof buf-1) + n = sizeof buf -1; + memmove(buf, va, n); + buf[n] = 0; + p = 0; + pt.x = strtol(buf+1, &p, 0); + if(p == 0) + error(Eshort); + pt.y = strtol(p, &p, 0); + if(p == 0) + error(Eshort); + b = strtol(p, &p, 0); + penmousetrack(b, pt.x, pt.y); + return n; + + case Qmouse: + if(n > sizeof buf-1) + n = sizeof buf -1; + memmove(buf, va, n); + buf[n] = 0; + p = 0; + pt.x = strtoul(buf+1, &p, 0); + if(p == 0) + error(Eshort); + pt.y = strtoul(p, 0, 0); + qlock(&mouse); + if(ptinrect(pt, gscreen->r)) + penmousetrack(mouse.buttons, pt.x, pt.y); + qunlock(&mouse); + return n; + } + + error(Egreg); + return -1; +} + +Dev penmousedevtab = { + 'm', + "penmouse", + + penmousereset, + penmouseinit, + penmouseattach, + penmouseclone, + penmousewalk, + penmousestat, + penmouseopen, + penmousecreate, + penmouseclose, + penmouseread, + devbread, + penmousewrite, + devbwrite, + devremove, + devwstat, +}; + +/* + * called at interrupt level to update the structure and + * awaken any waiting procs. + */ +static void +penmousetrack(int b, int x, int y) +{ + int lastb; + + if(gscreen==nil) + return; + + if (x >= 0) { + mouse.xy = Pt(x, y); + } + lastb = mouse.buttons; + mouse.buttons = b; + mouse.counter++; + mouse.msec = TK2MS(MACHP(0)->ticks); + + /* + * if the queue fills, we discard the entire queue and don't + * queue any more events until a reader polls the mouse. + */ + if(!mouse.qfull && lastb != b) { /* add to ring */ + mouse.queue[mouse.wi] = mouse.Mousestate; + if(++mouse.wi == nelem(mouse.queue)) + mouse.wi = 0; + if(mouse.wi == mouse.ri) + mouse.qfull = 1; + } + wakeup(&mouse.r); +} + +int +penmousechanged(void*) +{ + return mouse.lastcounter != mouse.counter; +} + +Point +penmousexy(void) +{ + return mouse.xy; +} diff --git "a/bitsy/dev\302\265c.c" "b/bitsy/dev\302\265c.c" new file mode 100644 index 0000000000000000000000000000000000000000..848c3e775d688b5ccb31a5528bb09b20661c8020 --- /dev/null +++ "b/bitsy/dev\302\265c.c" @@ -0,0 +1,352 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +enum{ + Qbacklight = 1, + Qbattery, + Qbuttons, + Qled, + Qversion, + + /* command types */ + BLversion= 0, + BLbuttons= 2, /* button events */ + BLtouch= 3, /* read touch screen events */ + BLled= 8, /* turn LED on/off */ + BLbattery= 9, /* read battery status */ + BLbacklight= 0xd, /* backlight control */ + + SOF= 0x2, /* start of frame */ + + /* key definitions */ + Up= 0xFF0E, + Left= 0xFF11, + Right= 0xFF12, + Down= 0x8000, +}; + +Dirtab µcdir[]={ + "backlight", { Qbacklight, 0 }, 0, 0664, + "battery", { Qbattery, 0 }, 0, 0664, + "buttons", { Qbuttons, 0 }, 0, 0664, + "led", { Qled, 0 }, 0, 0664, + "version", { Qversion, 0 }, 0, 0664, +}; + +static struct µcontroller +{ + /* message being rcvd */ + int state; + uchar buf[16+4]; + uchar n; + + /* for messages that require acks */ + QLock; + Rendez r; + + /* battery */ + uchar acstatus; + uchar voltage; + ushort batstatus; + uchar batchem; + + /* version string */ + char version[16+2]; +} ctlr; + +/* button map */ +Rune bmap[4] = +{ + Up, Right, Down, Left +}; + +int +µcputc(Queue*, int ch) +{ + int i, len, b, up; + uchar cksum; + uchar *p; + + if(ctlr.n > sizeof(ctlr.buf)) + panic("µcputc"); + + ctlr.buf[ctlr.n++] = (uchar)ch; + + for(;;){ + /* message hasn't started yet */ + if(ctlr.buf[0] != SOF){ + ctlr.n = 0; + break; + } + + /* if it's too short, wait */ + len = ctlr.buf[1] & 0xf; + if(ctlr.n < 3 || ctlr.n < len+3) + break; + + /* check the sum */ + ctlr.buf[0] = ~SOF; + cksum = 0; + for(i = 1; i < len+2; i++) + cksum += ctlr.buf[i]; + + /* ignore bad checksums */ + if(ctlr.buf[len+2] != cksum){ + p = memchr(ctlr.buf+1, SOF, ctlr.n); + if(p == nil){ + ctlr.n = 0; + break; + } else { + ctlr.n -= p-ctlr.buf; + memmove(ctlr.buf, p, ctlr.n); + continue; + } + } + + /* parse resulting message */ + p = ctlr.buf+2; + switch(ctlr.buf[1] >> 4){ + case BLversion: + strncpy(ctlr.version, (char*)p, len); + ctlr.version[len] = '0'; + strcat(ctlr.version, "\n"); + wakeup(&ctlr.r); + break; + case BLbuttons: + if(len < 1) + break; + b = p[0] & 0x7f; + up = p[0] & 80; + + if(b > 5){ + /* rocker panel acts like arrow keys */ + if(b < 10) + kbdputc(kbdq, bmap[b-6]); + } else { + /* the rest like mouse buttons */ + if(--b == 0) + b = 5; + penbutton(up, 1<= 5){ + ctlr.acstatus = p[0]; + ctlr.voltage = (p[3]<<8)|p[2]; + ctlr.batstatus = p[4]; + ctlr.batchem = p[1]; + } + wakeup(&ctlr.r); + break; + case BLbacklight: + wakeup(&ctlr.r); + break; + } + + /* remove the message */ + ctlr.n -= len+3; + memmove(ctlr.buf, &ctlr.buf[len+3], ctlr.n); + } + return 0; +} + +static void +_sendmsg(uchar id, uchar *data, int len) +{ + uchar buf[20]; + uchar cksum; + uchar c; + uchar *p = buf; + int i; + + /* create the message */ + if(sizeof(buf) < len+4) + return; + cksum = (id<<4) | len; + *p++ = SOF; + *p++ = cksum; + for(i = 0; i < len; i++){ + c = data[i]; + cksum += c; + *p++ = c; + } + *p++ = cksum; + + /* send the message - there should be a more generic way to do this */ + serialµcputs(buf, p-buf); +} + +static void +sendmsgwithack(uchar id, uchar *data, int len) +{ + if(waserror()){ + qunlock(&ctlr); + nexterror(); + } + qlock(&ctlr); + _sendmsg(id, data, len); + tsleep(&ctlr.r, return0, 0, 100); + qunlock(&ctlr); + poperror(); +} + +static void +sendmsg(uchar id, uchar *data, int len) +{ + if(waserror()){ + qunlock(&ctlr); + nexterror(); + } + qlock(&ctlr); + _sendmsg(id, data, len); + qunlock(&ctlr); + poperror(); +} + +void +µcinit(void) +{ +} + +static Chan* +µcattach(char* spec) +{ + return devattach('r', spec); +} + +static int +µcwalk(Chan* c, char* name) +{ + return devwalk(c, name, µcdir, nelem(µcdir), devgen); +} + +static void +µcstat(Chan* c, char* dp) +{ + devstat(c, dp, µcdir, nelem(µcdir), devgen); +} + +static Chan* +µcopen(Chan* c, int omode) +{ + omode = openmode(omode); + if(strcmp(up->user, eve)!=0) + error(Eperm); + return devopen(c, omode, µcdir, nelem(µcdir), devgen); +} + +static void +µcclose(Chan*) +{ +} + +char* +acstatus(int x) +{ + if(x) + return "attached"; + else + return "detached"; +} + +char* +batstatus(int x) +{ + switch(x){ + case 1: return "high"; + case 2: return "low"; + case 4: return "critical"; + case 8: return "charging"; + case 0x80: return "none"; + } + return "ok"; +} + +static long +µcread(Chan* c, void* a, long n, vlong off) +{ + char buf[64]; + + if(c->qid.path & CHDIR) + return devdirread(c, a, n, µcdir, nelem(µcdir), devgen); + + switch(c->qid.path){ + case Qbattery: + sendmsgwithack(BLbattery, nil, 0); /* send a battery request */ + sprint(buf, "voltage: %d\nac: %s\nstatus: %s\n", ctlr.voltage, + acstatus(ctlr.acstatus), + batstatus(ctlr.batstatus)); + return readstr(off, a, n, buf); + case Qversion: + sendmsgwithack(BLversion, nil, 0); /* send a battery request */ + return readstr(off, a, n, ctlr.version); + } + error(Ebadarg); + return 0; +} + +#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4) + +static long +µcwrite(Chan* c, void* a, long n, vlong off) +{ + Cmdbuf *cmd; + uchar data[16]; + int i; + + if(off != 0) + error(Ebadarg); + + cmd = parsecmd(a, n); + if(cmd->nf > 15) + error(Ebadarg); + for(i = 0; i < cmd->nf; i++) + data[i] = atoi(cmd->f[i]); + + switch(c->qid.path){ + case Qled: + sendmsgwithack(BLled, data, cmd->nf); + break; + case Qbacklight: + sendmsgwithack(BLbacklight, data, cmd->nf); + break; + default: + error(Ebadarg); + } + return n; +} + +Dev µcdevtab = { + 'r', + "µc", + + devreset, + µcinit, + µcattach, + devclone, + µcwalk, + µcstat, + µcopen, + devcreate, + µcclose, + µcread, + devbread, + µcwrite, + devbwrite, + devremove, + devwstat, +}; diff --git a/bitsy/fns.h b/bitsy/fns.h index fcc8d7154b05ecff10220df4297cc0f2bb13b264..2ef3dd31fb4853d366c790cde64d716620fbc89f 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -33,8 +33,11 @@ void mmuenable(void); void mmudisable(void); void mmuinvalidate(void); void mmuinvalidateaddr(ulong); +int µcputc(Queue*, int); void noted(Ureg*, ulong); int notify(Ureg*); +void penbutton(int, int); +void pentrackxy(int x, int y); #define procrestore(p) void procsave(Proc*); void procsetup(Proc*); @@ -50,6 +53,7 @@ void sa1100_uartsetup(int); void screeninit(void); int screenprint(char*, ...); /* debugging */ void screenputs(char*, int); +void serialµcputs(uchar *str, int n); void setr13(int, ulong*); uchar* tarlookup(uchar*, char*, int*); void touser(void*); diff --git a/bitsy/sa1110uart.c b/bitsy/sa1110uart.c index 3bc1325e1f71b40b5ef580e80aa5c227427a6f0b..8052761a5445ca4683912b8433f60f80602b41d8 100644 --- a/bitsy/sa1110uart.c +++ b/bitsy/sa1110uart.c @@ -352,6 +352,25 @@ serialputs(char *str, int n) ; } +/* + * for iprint, just write it + */ +void +serialµcputs(uchar *str, int n) +{ + Uartregs *ur; + + ur = uart1regs; + while(n-- > 0){ + /* wait for output ready */ + while((ur->status[1] & Tnotfull) == 0) + ; + ur->data = *str++; + } + while((ur->status[1] & Tbusy)) + ; +} + /* * take an interrupt */ @@ -433,6 +452,6 @@ sa1100_uartsetup(int console) gpclkregs->r0 = Gpclk_sus; /* set uart mode */ uart1regs = mapspecial(UART1REGS, 64); p = uartsetup(&sa1100_uart, uart1regs, ClockFreq, "serialport1"); - sa1100_uartbaud(p, 115200); + uartspecial(p, 115200, 0, 0, µcputc); intrenable(IRQuart1b, sa1100_uartintr, p, p->name); } diff --git a/bitsy/screen.c b/bitsy/screen.c index 330ebb7320cfcd73e10346fb966a4b1d9596958b..29f0c1809e68638684e25998baa92b45bcc99a4f 100644 --- a/bitsy/screen.c +++ b/bitsy/screen.c @@ -123,14 +123,14 @@ static Memimage xgscreen = { 0, 0, Wid, Ht }, /* r */ { 0, 0, Wid, Ht }, /* clipr */ 16, /* depth */ - 1, /* nchan */ + 3, /* nchan */ RGB16, /* chan */ nil, /* cmap */ &xgdata, /* data */ 0, /* zero */ Wid/2, /* width */ 0, /* layer */ - Frepl, /* flags */ + 0, /* flags */ }; Memimage *gscreen; @@ -174,7 +174,6 @@ lcdinit(void) lcd->lccr2 = (Ht-1)<lccr1 = (Wid-16)<lccr0 = 1<palette[0] = Pal0; - iprint("LCD power up\n"); lcdpower(1); - lcdinit(); gscreen = &xgscreen; @@ -335,6 +332,7 @@ screenputc(char *buf) Rectangle r; static int *xp; static int xbuf[256]; +return; if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) xp = xbuf; diff --git a/bitsy/screen.h b/bitsy/screen.h index 60c5240452fae1d36a8c1fde1d13da0d38035841..09e6ef90babd6a70bed4466e16b7f579bf7519fc 100644 --- a/bitsy/screen.h +++ b/bitsy/screen.h @@ -1,3 +1,9 @@ +typedef struct Cursorinfo Cursorinfo; +typedef struct Cursor Cursor; + +struct Cursorinfo { + Lock; +}; + extern void blankscreen(int); extern void flushmemscreen(Rectangle); - diff --git a/boot/aux.c b/boot/aux.c index 68fde824930ddbd2c7408e6fcacc883afe4772af..7a2a7ed59a2f675f67ec4c77cd0f4e15b698cb41 100644 --- a/boot/aux.c +++ b/boot/aux.c @@ -54,19 +54,13 @@ sendmsg(int fd, char *msg) void warning(char *s) { - char buf[ERRLEN]; - - errstr(buf); - fprint(2, "boot: %s: %s\n", s, buf); + fprint(2, "boot: %s: %r\n", s); } void fatal(char *s) { - char buf[ERRLEN]; - - errstr(buf); - fprint(2, "boot: %s: %s\n", s, buf); + fprint(2, "boot fatal: %s: %r\n", s); exits(0); } diff --git a/boot/bootip.c b/boot/bootip.c index e60750b41066a83901c2413b702aa5c7f80c3d1e..b376fed47e069daf318450e9bc9526563dfc93da 100644 --- a/boot/bootip.c +++ b/boot/bootip.c @@ -27,7 +27,7 @@ configip(void) arg = malloc((bargc+1) * sizeof(char*)); if(arg == nil) - fatal("%r"); + fatal("malloc"); memmove(arg, bargv, (bargc+1) * sizeof(char*)); argc = bargc; @@ -56,7 +56,7 @@ configip(void) /* let ipconfig configure the ip interface */ switch(pid = fork()){ case -1: - fatal("configuring ip: %r"); + fatal("configuring ip"); case 0: exec("/ipconfig", arg); fatal("execing /ipconfig"); diff --git a/carrera/screen.c b/carrera/screen.c index f432a9b4ea0a52ac26abe7aea1f52adbc3fb594c..f3cb49f38667453c55eeaaffa2eab7eadb32ded3 100644 --- a/carrera/screen.c +++ b/carrera/screen.c @@ -8,7 +8,7 @@ #include "../port/error.h" #define Image IMAGE -#include +#include #include #include #include "screen.h" @@ -63,7 +63,7 @@ static Memimage xgscreen = 0, /* zero */ 512, /* width */ 0, /* layer */ - Frepl, /* flags */ + 0, /* flags */ }; Memimage *gscreen; diff --git a/pc/devi82365.c b/pc/devi82365.c index 4a7b24aa2c114092b9b6b12cdefc254ab5849679..b24d980dfc5cc28d057c7f918bf27c5c0ce8564c 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -1093,14 +1093,14 @@ readc(Cisdat *pp, uchar *x) } static int -xcistuple(int slotno, int tuple, void *v, int nv, int attr) +xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr) { PCMmap *m; Cisdat cis; int i, l; uchar *p; - uchar type, link; - int this; + uchar type, link, n, c; + int this, subtype; m = pcmmap(slotno, 0, 0, attr); if(m == 0) @@ -1122,9 +1122,19 @@ xcistuple(int slotno, int tuple, void *v, int nv, int attr) break; if(link == 0xFF) break; - if(type == tuple) { + + n = link; + if (link > 1 && subtuple != -1) { + if (readc(&cis, &c) != 1) + break; + subtype = c; + n--; + } else + subtype = -1; + + if(type == tuple && subtype == subtuple) { p = v; - for(l=0; l= 0) + if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0) return n; - return xcistuple(slotno, tuple, v, nv, 0); + return xcistuple(slotno, tuple, subtuple, v, nv, 0); } static void @@ -1161,7 +1171,7 @@ cisread(Slot *pp) pp->nctab = 0; for(i = 0; i < nelem(cistab); i++) { - if((nv = pcmcistuple(pp->slotno, cistab[i].n, v, sizeof(v))) >= 0) { + if((nv = pcmcistuple(pp->slotno, cistab[i].n, -1, v, sizeof(v))) >= 0) { cis.cisbase = v; cis.cispos = 0; cis.cisskip = 1; diff --git a/pc/ether589.c b/pc/ether589.c index f45483efd34b4baa00e7a79e64173912f8c91a8a..ef19093f9a19997763f287b19d075e4b3946b6fc 100644 --- a/pc/ether589.c +++ b/pc/ether589.c @@ -152,7 +152,7 @@ reset(Ether* ether) */ memset(ea, 0, sizeof ea); if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) { - if(pcmcistuple(slot, 0x88, ea, 6) == 6) { + if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) { for(i = 0; i < 6; i += 2){ t = ea[i]; ea[i] = ea[i+1]; diff --git a/pc/ethersmc.c b/pc/ethersmc.c new file mode 100644 index 0000000000000000000000000000000000000000..86f2276f1690a142b1c964cc385b3cb60989f78f --- /dev/null +++ b/pc/ethersmc.c @@ -0,0 +1,779 @@ +/* + * SMC EtherEZ (SMC91cXX chip) PCMCIA card support. + */ + +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" +#include "etherif.h" + +enum { + IoSize = 0x10, /* port pool size */ + TxTimeout = 150, +}; + +enum { /* PCMCIA related */ + TupleFunce = 0x22, + TfNodeId = 0x04, +}; + +enum { /* bank 0 registers */ + Tcr = 0x0000, /* transmit control */ + Eph = 0x0002, /* ethernet protocol handler */ + Rcr = 0x0004, /* receiver control */ + Counter = 0x0006, /* statistics counter */ + MemInfo = 0x0008, + MemCfg = 0x000A, +}; + +enum { /* bank 1 registers */ + Config = 0x0000, + BaseAddr = 0x0002, + Addr0 = 0x0004, /* ethernet address */ + Addr1 = 0x0006, + Addr2 = 0x0008, + General = 0x000A, + Control = 0x000C, +}; + +enum { /* bank 2 registers */ + MmuCmd = 0x0000, + PktNo = 0x0002, + AllocRes = 0x0003, + FifoPorts = 0x0004, + Pointer = 0x0006, + Data1 = 0x0008, + Interrupt = 0x000C, + IntrMask = 0x000D, +}; + +enum { /* bank 3 registers */ + Mcast0 = 0x0000, + Mcast2 = 0x0002, + Mcast4 = 0x0004, + Mcast6 = 0x0006, + Revision = 0x000A, +}; + +enum { + BankSelect = 0x000E /* bank select register */ +}; + +enum { + BsrMask = 0xFF00, /* mask for chip identification */ + BsrId = 0x3300, +}; + + +enum { /* Tcr values */ + TcrClear = 0x0000, + TcrEnable = 0x0001, /* enable transmit */ + TcrLoop = 0x0002, /* enable internal analogue loopback */ + TcrForceCol = 0x0004, /* force collision on next tx */ + TcrPadEn = 0x0080, /* pad short packets to 64 bytes */ + TcrNoCrc = 0x0100, /* do not append CRC */ + TcrMonCns = 0x0400, /* monitor carrier status */ + TcrFduplx = 0x0800, + TcrStpSqet = 0x1000, + TcrEphLoop = 0x2000, + TcrNormal = TcrEnable, +}; + +enum { /* Eph values */ + EphTxOk = 0x0001, + Eph1Col = 0x0002, /* single collision */ + EphMCol = 0x0004, /* multiple collisions */ + EphTxMcast = 0x0008, /* multicast transmit */ + Eph16Col = 0x0010, /* 16 collisions, tx disabled */ + EphSqet = 0x0020, /* SQE test failed, tx disabled */ + EphTxBcast = 0x0040, /* broadcast tx */ + EphDefr = 0x0080, /* deffered tx */ + EphLatCol = 0x0200, /* late collision, tx disabled */ + EphLostCarr = 0x0400, /* lost carrier, tx disabled */ + EphExcDefr = 0x0800, /* excessive defferals */ + EphCntRol = 0x1000, /* ECR counter(s) rolled over */ + EphRxOvrn = 0x2000, /* receiver overrun, packets dropped */ + EphLinkOk = 0x4000, + EphTxUnrn = 0x8000, /* tx underrun */ +}; + +enum { /* Rcr values */ + RcrClear = 0x0000, + RcrPromisc = 0x0002, + RcrAllMcast = 0x0004, + RcrEnable = 0x0100, + RcrStripCrc = 0x0200, + RcrSoftReset = 0x8000, + RcrNormal = RcrStripCrc | RcrEnable, +}; + +enum { /* Counter value masks */ + CntColMask = 0x000F, /* collisions */ + CntMColMask = 0x00F0, /* multiple collisions */ + CntDtxMask = 0x0F00, /* deferred transmits */ + CntExDtxMask = 0xF000, /* excessively deferred transmits */ + + CntColShr = 1, + CntMColShr = 4, + CntDtxShr = 8, +}; + +enum { /* MemInfo value masks */ + MirTotalMask = 0x00FF, + MirFreeMask = 0xFF00, +}; + +enum { /* Config values */ + CfgIrqSel0 = 0x0002, + CfgIrqSel1 = 0x0004, + CfgDisLink = 0x0040, /* disable 10BaseT link test */ + Cfg16Bit = 0x0080, + CfgAuiSelect = 0x0100, + CfgSetSqlch = 0x0200, + CfgFullStep = 0x0400, + CfgNoWait = 0x1000, + CfgMiiSelect = 0x8000, +}; + +enum { /* Control values */ + CtlStore = 0x0001, /* store to EEPROM */ + CtlReload = 0x0002, /* reload EEPROM into registers */ + CtlEeSelect = 0x0004, /* select registers for reload/store */ + CtlTeEnable = 0x0020, /* tx error detection via eph irq */ + CtlCrEnable = 0x0040, /* counter rollover via eph irq */ + CtlLeEnable = 0x0080, /* link error detection via eph irq*/ + CtlAutoRls = 0x0800, /* auto release mode */ + CtlPowerDn = 0x2000, +}; + +enum { /* MmuCmd values */ + McBusy = 0x0001, + McAlloc = 0x0020, /* | with number of 256 byte packets - 1 */ + McReset = 0x0040, + McRelease = 0x0080, /* dequeue (but not free) current rx packet */ + McFreePkt = 0x00A0, /* dequeue and free current rx packet */ + McEnqueue = 0x00C0, /* enqueue the packet for tx */ + McTxReset = 0x00E0, /* reset transmit queues */ +}; + +enum { /* AllocRes values */ + ArFailed = 0x80, +}; + +enum { /* FifoPorts values */ + FpTxEmpty = 0x0080, + FpRxEmpty = 0x8000, + FpTxMask = 0x007F, + FpRxMask = 0x7F00, +}; + +enum { /* Pointer values */ + PtrRead = 0x2000, + PtrAutoInc = 0x4000, + PtrRcv = 0x8000, +}; + +enum { /* Interrupt values */ + IntRcv = 0x0001, + IntTxError = 0x0002, + IntTxEmpty = 0x0004, + IntAllo = 0x0008, + IntRxOvrn = 0x0010, + IntEph = 0x0020, +}; + +enum { /* transmit status bits */ + TsSuccess = 0x0001, + Ts16Col = 0x00A0, + TsLatCol = 0x0200, + TsLostCar = 0x0400, +}; + +enum { /* receive status bits */ + RsMcast = 0x0001, + RsTooShort = 0x0400, + RsTooLong = 0x0800, + RsOddFrame = 0x1000, + RsBadCrc = 0x2000, + RsAlgnErr = 0x8000, + RsError = RsAlgnErr | RsBadCrc | RsTooLong | RsTooShort, +}; + +enum { + RxLenMask = 0x07FF, /* significant rx len bits */ + HdrSize = 6, /* packet header length */ + PageSize = 256, /* page length */ +}; + +typedef struct { + Lock; + ushort rev; + int attached; + Block *txbp; + ulong txtime; + + ulong rovrn; + ulong lcar; + ulong col; + ulong scol; + ulong mcol; + ulong lcol; + ulong dfr; +} Smc91xx; + +#define SELECT_BANK(x) outs(port + BankSelect, x) + +static int +readnodeid(int slot, Ether* ether) +{ + uchar data[Eaddrlen + 1]; + int len; + + len = sizeof(data); + if (pcmcistuple(slot, TupleFunce, TfNodeId, data, len) != len) + return -1; + + if (data[0] != Eaddrlen) + return -1; + + memmove(ether->ea, &data[1], Eaddrlen); + return 0; +} + +static void +chipreset(Ether* ether) +{ + int port; + int i; + + port = ether->port; + + /* reset the chip */ + SELECT_BANK(0); + outs(port + Rcr, RcrSoftReset); + delay(1); + outs(port + Rcr, RcrClear); + outs(port + Tcr, TcrClear); + SELECT_BANK(1); + outs(port + Control, CtlAutoRls | CtlTeEnable | + CtlCrEnable); + + for(i = 0; i < 6; i++) { + outb(port + Addr0 + i, ether->ea[i]); + } + + SELECT_BANK(2); + outs(port + MmuCmd, McReset); +} + +static void +chipenable(Ether* ether) +{ + int port; + + port = ether->port; + SELECT_BANK(0); + outs(port + Tcr, TcrNormal); + outs(port + Rcr, RcrNormal); + SELECT_BANK(2); + outb(port + IntrMask, IntEph | IntRxOvrn | IntRcv); +} + +static void +attach(Ether *ether) +{ + Smc91xx* ctlr; + + ctlr = ether->ctlr; + ilock(ctlr); + + if (ctlr->attached) { + iunlock(ctlr); + return; + } + + chipenable(ether); + ctlr->attached = 1; + iunlock(ctlr); +} + +static void +txstart(Ether* ether) +{ + int port; + Smc91xx* ctlr; + Block* bp; + int len, npages; + int pno; + + /* assumes ctlr is locked and bank 2 is selected */ + /* leaves bank 2 selected on return */ + port = ether->port; + ctlr = ether->ctlr; + + if (ctlr->txbp) { + bp = ctlr->txbp; + ctlr->txbp = 0; + } else { + bp = qget(ether->oq); + if (bp == 0) + return; + + len = BLEN(bp); + npages = (len + HdrSize) / PageSize; + outs(port + MmuCmd, McAlloc | npages); + } + + pno = inb(port + AllocRes); + if (pno & ArFailed) { + outb(port + IntrMask, inb(port + IntrMask) | IntAlloc); + ctlr->txbp = bp; + ctlr->txtime = MACHP(0)->ticks; + return; + } + + outb(port + PktNo, pno); + outs(port + Pointer, PtrAutoInc); + + len = BLEN(bp); + outs(port + Data1, 0); + outb(port + Data1, (len + HdrSize) & 0xFF); + outb(port + Data1, (len + HdrSize) >> 8); + outss(port + Data1, bp->rp, len / 2); + if ((len & 1) == 0) { + outs(port + Data1, 0); + } else { + outb(port + Data1, bp->rp[len - 1]); + outb(port + Data1, 0x20); /* no info what 0x20 means */ + } + + outb(port + IntrMask, inb(port + IntrMask) | + IntTxError | IntTxEmpty); + + outs(port + MmuCmd, McEnqueue); + freeb(bp); +} + +static void +receive(Ether* ether) +{ + int port; + Block* bp; + int pktno, status, len; + + /* assumes ctlr is locked and bank 2 is selected */ + /* leaves bank 2 selected on return */ + port = ether->port; + + pktno = ins(port + FifoPorts); + if (pktno & FpRxEmpty) { + return; + } + + outs(port + Pointer, PtrRead | PtrRcv | PtrAutoInc); + status = ins(port + Data1); + len = ins(port + Data1) & RxLenMask - HdrSize; + + if (status & RsOddFrame) + len++; + + if ((status & RsError) || (bp = iallocb(len)) == 0) { + + if (status & RsAlgnErr) + ether->frames++; + if (status & (RsTooShort | RsTooLong)) + ether->buffs++; + if (status & RsBadCrc) + ether->crcs++; + + outs(port + MmuCmd, McRelease); + return; + } + + /* packet length is padded to word */ + inss(port + Data1, bp->rp, len / 2); + bp->wp = bp->rp + (len & ~1); + + if (len & 1) { + *bp->wp = inb(port + Data1); + bp->wp++; + } + + etheriq(ether, bp, 1); + ether->inpackets++; + outs(port + MmuCmd, McRelease); +} + +static void +txerror(Ether* ether) +{ + int port; + Smc91xx* ctlr; + int save_pkt; + int pktno, status; + + /* assumes ctlr is locked and bank 2 is selected */ + /* leaves bank 2 selected on return */ + port = ether->port; + ctlr = ether->ctlr; + + save_pkt = inb(port + PktNo); + + pktno = ins(port + FifoPorts) & FpTxMask; + outb(port + PktNo, pktno); + outs(port + Pointer, PtrAutoInc | PtrRead); + status = ins(port + Data1); + + if (status & TsLostCar) + ctlr->lcar++; + + if (status & TsLatCol) + ctlr->lcol++; + + if (status & Ts16Col) + ctlr->scol++; + + ether->oerrs++; + + SELECT_BANK(0); + outs(port + Tcr, ins(port + Tcr) | TcrEnable); + + SELECT_BANK(2); + outs(port + MmuCmd, McFreePkt); + + outb(port + PktNo, save_pkt); +} + +static void +eph_irq(Ether* ether) +{ + int port; + Smc91xx* ctlr; + ushort status; + int n; + + /* assumes ctlr is locked and bank 2 is selected */ + /* leaves bank 2 selected on return */ + port = ether->port; + ctlr = ether->ctlr; + + SELECT_BANK(0); + status = ins(port + Eph); + + if (status & EphCntRol) { + /* read the counter register even if we don't need it */ + /* otherwise we will keep getting this interrupt */ + n = ins(port + Counter); + ctlr->col += (n & CntColMask) >> CntColShr; + ctlr->mcol += (n & CntMColMask) >> CntMColShr; + ctlr->dfr += (n & CntDtxMask) >> CntDtxShr; + } + + /* if there was a transmit error, Tcr is disabled */ + outs(port + Tcr, ins(port + Tcr) | TcrEnable); + + /* clear a link error interrupt */ + SELECT_BANK(1); + outs(port + Control, CtlAutoRls); + outs(port + Control, CtlAutoRls | CtlTeEnable | CtlCrEnable); + + SELECT_BANK(2); +} + +static void +transmit(Ether* ether) +{ + Smc91xx* ctlr; + int port, n; + + ctlr = ether->ctlr; + port = ether->port; + ilock(ctlr); + + if (ctlr->txbp) { + n = TK2MS(MACHP(0)->ticks - ctlr->txtime); + if (n > TxTimeout) { + chipreset(ether); + chipenable(ether); + freeb(ctlr->txbp); + ctlr->txbp = 0; + } + iunlock(ctlr); + return; + } + + SELECT_BANK(2); + txstart(ether); + iunlock(ctlr); +} + +static void +interrupt(Ureg*, void *arg) +{ + int port; + Smc91xx* ctlr; + Ether* ether; + int save_bank; + int save_pointer; + int mask, status; + + ether = arg; + port = ether->port; + ctlr = ether->ctlr; + + ilock(ctlr); + save_bank = ins(port + BankSelect); + SELECT_BANK(2); + save_pointer = ins(port + Pointer); + + mask = inb(port + IntrMask); + outb(port + IntrMask, 0); + + while ((status = inb(port + Interrupt) & mask) != 0) { + if (status & IntRcv) { + receive(ether); + } + + if (status & IntTxError) { + txerror(ether); + } + + if (status & IntTxEmpty) { + outb(port + Interrupt, IntTxEmpty); + outb(port + IntrMask, mask & ~IntTxEmpty); + txstart(ether); + mask = inb(port + IntrMask); + } + + if (status & IntAlloc) { + outb(port + IntrMask, mask & ~IntAlloc); + txstart(ether);; + mask = inb(port + IntrMask); + } + + if (status & IntRxOvrn) { + ctlr->rovrn++; + ether->misses++; + outb(port + Interrupt,IntRxOvrn); + } + + if (status & IntEph) + eph_irq(ether); + } + + outb(port + IntrMask, mask); + outs(port + Pointer, save_pointer); + outs(port + BankSelect, save_bank); + iunlock(ctlr); +} + +static void +promiscuous(void* arg, int on) +{ + int port; + Smc91xx *ctlr; + Ether* ether; + ushort x; + + ether = arg; + port = ether->port; + ctlr = ether->ctlr; + + ilock(ctlr); + SELECT_BANK(0); + x = ins(port + Rcr); + if (on) + x |= RcrPromisc; + else + x &= ~RcrPromisc; + + outs(port + Rcr, x); + iunlock(ctlr); +} + +static void +multicast(void* arg, uchar *addr, int on) +{ + int port; + Smc91xx*ctlr; + Ether *ether; + ushort x; + + USED(addr, on); + + ether = arg; + port = ether->port; + ctlr = ether->ctlr; + ilock(ctlr); + + SELECT_BANK(0); + x = ins(port + Rcr); + + if (ether->nmaddr) + x |= RcrAllMcast; + else + x &= ~RcrAllMcast; + + outs(port + Rcr, x); + iunlock(ctlr); +} + +static long +ifstat(Ether* ether, void* a, long n, ulong offset) +{ + static char *chiprev[] = { + [3] "92", + [5] "95", + [7] "100", + [8] "100-FD", + [9] "110", + }; + + Smc91xx* ctlr; + char* p; + int r, len; + char* s; + + if (n == 0) + return 0; + + ctlr = ether->ctlr; + p = malloc(READSTR); + + s = 0; + if (ctlr->rev > 0) { + r = ctlr->rev >> 4; + if (r < nelem(chiprev)) + s = chiprev[r]; + + if (r == 4) { + if ((ctlr->rev & 0x0F) >= 6) + s = "96"; + else + s = "94"; + } + } + + len = snprint(p, READSTR, "rev: 91c%s\n", (s) ? s : "???"); + len += snprint(p + len, READSTR - len, "rxovrn: %uld\n", ctlr->rovrn); + len += snprint(p + len, READSTR - len, "lcar: %uld\n", ctlr->lcar); + len += snprint(p + len, READSTR - len, "col: %uld\n", ctlr->col); + len += snprint(p + len, READSTR - len, "16col: %uld\n", ctlr->scol); + len += snprint(p + len, READSTR - len, "mcol: %uld\n", ctlr->mcol); + len += snprint(p + len, READSTR - len, "lcol: %uld\n", ctlr->lcol); + len += snprint(p + len, READSTR - len, "dfr: %uld\n", ctlr->dfr); + USED(len); + + n = readstr(offset, a, n, p); + free(p); + + return n; +} + +static int +reset(Ether* ether) +{ + int port; + int i, x; + char* type; + Smc91xx* ctlr; + int slot; + uchar ea[Eaddrlen]; + + if (ether->irq == 0) + ether->irq = 9; + + if (ether->port == 0) + ether->port = 0x100; + + type = "8020"; + for(i = 0; i < ether->nopt; i++) { + if (cistrncmp(ether->opt[i], "id=", 3)) + continue; + type = ðer->opt[i][3]; + break; + } + + if ((slot = pcmspecial(type, ether)) < 0) + return -1; + + if (ioalloc(ether->port, IoSize, 0, "smc91cXX") < 0) { + pcmspecialclose(slot); + return -1; + } + + ether->ctlr = malloc(sizeof(Smc91xx)); + ctlr = ether->ctlr; + if (ctlr == 0) { + iofree(ether->port); + pcmspecialclose(slot); + } + + ilock(ctlr); + ctlr->rev = 0; + ctlr->txbp = nil; + ctlr->attached = 0; + ctlr->rovrn = 0; + ctlr->lcar = 0; + ctlr->col = 0; + ctlr->scol = 0; + ctlr->mcol = 0; + ctlr->lcol = 0; + ctlr->dfr = 0; + + port = ether->port; + + SELECT_BANK(1); + if ((ins(port + BankSelect) & BsrMask) != BsrId) { + outs(port + Control, 0); /* try powering up the chip */ + delay(55); + } + + outs(port + Config, ins(port + Config) | Cfg16Bit); + x = ins(port + BaseAddr); + + if (((ins(port + BankSelect) & BsrMask) != BsrId) || + ((x >> 8) == (x & 0xFF))) { + iunlock(ctlr); + iofree(port); + pcmspecialclose(slot); + return -1; + } + + SELECT_BANK(3); + ctlr->rev = ins(port + Revision) & 0xFF; + + memset(ea, 0, Eaddrlen); + if (memcmp(ea, ether->ea, Eaddrlen) == 0) { + if (readnodeid(slot, ether) < 0) { + print("Smc91cXX: cannot find ethernet address\n"); + iunlock(ctlr); + iofree(port); + pcmspecialclose(slot); + return -1; + } + } + + chipreset(ether); + + ether->attach = attach; + ether->transmit = transmit; + ether->interrupt = interrupt; + ether->ifstat = ifstat; + ether->promiscuous = promiscuous; + ether->multicast = multicast; + ether->arg = ether; + iunlock(ctlr); + return 0; +} + +void +ethersmclink(void) +{ + addethercard("smc91cXX", reset); +} diff --git a/pc/fns.h b/pc/fns.h index a4bef2c02507cb5300330a7d4dbc6f7c10d017ea..e812a5ee4052d39bdbc2f8cbac4ed65321161187 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -95,7 +95,7 @@ Pcidev* pcimatch(Pcidev*, int, int); Pcidev* pcimatchtbdf(int); void pcireset(void); void pcisetbme(Pcidev*); -int pcmcistuple(int, int, void*, int); +int pcmcistuple(int, int, int, void*, int); PCMmap* pcmmap(int, ulong, int, int); int pcmspecial(char*, ISAConf*); void pcmspecialclose(int); diff --git a/port/devcons.c b/port/devcons.c index 6ade99292bbb743d4d4ca47c66d84b32250b0a1f..942ef6540a83eac053d586edbe0ce7ea4ad8fd01 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -256,6 +256,62 @@ pprint(char *fmt, ...) return n; } +static void +echoscreen(char *buf, int n) +{ + char *e, *p; + char ebuf[128]; + int x; + + p = ebuf; + e = ebuf + sizeof(ebuf) - 4; + while(n-- > 0){ + if(p >= e){ + screenputs(ebuf, p - ebuf); + p = ebuf; + } + x = *buf++; + if(x == 0x15){ + *p++ = '^'; + *p++ = 'U'; + *p++ = '\n'; + } else + *p++ = x; + } + if(p != ebuf) + screenputs(ebuf, p - ebuf); +} + +static void +echoprintq(char *buf, int n) +{ + char *e, *p; + char ebuf[128]; + int x; + + p = ebuf; + e = ebuf + sizeof(ebuf) - 4; + while(n-- > 0){ + if(p >= e){ + qiwrite(printq, ebuf, p - ebuf); + p = ebuf; + } + x = *buf++; + if(x == '\n'){ + *p++ = '\r'; + *p++ = '\n'; + } else if(x == 0x15){ + *p++ = '^'; + *p++ = 'U'; + *p++ = '\n'; + } else + *p++ = x; + } + if(p != ebuf) + qiwrite(printq, ebuf, p - ebuf); +} + + void echo(char *buf, int n) { @@ -263,7 +319,6 @@ echo(char *buf, int n) extern ulong etext; int x; char *e, *p; - char ebuf[128]; e = buf+n; for(p = buf; p < e; p++){ @@ -330,34 +385,9 @@ echo(char *buf, int n) if(kbd.raw) return; - /* - * finally, the actual echoing - */ - p = ebuf; - e = ebuf + sizeof(ebuf) - 4; - while(n-- > 0){ - if(p >= e){ - screenputs(ebuf, p - ebuf); - if(printq) - qiwrite(printq, ebuf, p - ebuf); - p = ebuf; - } - x = *buf++; - if(x == '\n'){ - *p++ = '\r'; - *p++ = '\n'; - } else if(x == 0x15){ - *p++ = '^'; - *p++ = 'U'; - *p++ = '\n'; - } else - *p++ = x; - } - if(p == ebuf) - return; - screenputs(ebuf, p - ebuf); + echoscreen(buf, n); if(printq) - qiwrite(printq, ebuf, p - ebuf); + echoprintq(buf, n); } /* diff --git a/port/devdraw.c b/port/devdraw.c index f0eba384e7e92ae291554e2c6d26a5d06ae07d2f..4b27dd695f1861d64db67541bc411c226cbb221f 100644 --- a/port/devdraw.c +++ b/port/devdraw.c @@ -1225,7 +1225,7 @@ printmesg(char *fmt, uchar *a, int plsprnt) char *p, *q; int s; - if(1|| plsprnt==0){ + if(1 || plsprnt==0){ SET(s,q,p); USED(fmt, a, buf, p, q, s); return;