A bitsy/devpenmouse.c => bitsy/devpenmouse.c +447 -0
@@ 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 <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#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<<i;
+ }
+ else if(map[i] == '2'){
+ if(two)
+ error(Ebadarg);
+ two = 1<<i;
+ }
+ else if(map[i] == '3'){
+ if(three)
+ error(Ebadarg);
+ three = 1<<i;
+ }
+ else
+ error(Ebadarg);
+ }
+ if(map[i])
+ error(Ebadarg);
+
+ memset(buttonmap, 0, 8);
+ for(i = 0; i < 8; i++){
+ x = 0;
+ if(i & 1)
+ x |= one;
+ if(i & 2)
+ x |= two;
+ if(i & 4)
+ x |= three;
+ buttonmap[x] = i;
+ }
+}
+
+static long
+penmousewrite(Chan *c, void *va, long n, vlong)
+{
+ char *p;
+ Point pt;
+ char buf[64], *field[3];
+ int nf, b;
+
+ p = va;
+ switch(c->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;
+}
A bitsy/devµc.c => bitsy/devµc.c +352 -0
@@ 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<<b);
+ }
+ break;
+ case BLtouch:
+ if(len == 4)
+ pentrackxy((p[0]<<8)|p[1], (p[2]<<8)|p[3]);
+ else
+ pentrackxy(-1, -1);
+ break;
+ case BLled:
+ wakeup(&ctlr.r);
+ break;
+ case BLbattery:
+ if(len >= 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,
+};
M bitsy/fns.h => bitsy/fns.h +4 -0
@@ 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*);
M bitsy/sa1110uart.c => bitsy/sa1110uart.c +20 -1
@@ 353,6 353,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
*/
static void
@@ 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);
}
M bitsy/screen.c => bitsy/screen.c +4 -6
@@ 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)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
lcd->lccr1 = (Wid-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
-
}
void
@@ 185,14 184,12 @@ screeninit(void)
/* map the lcd regs into the kernel's virtual space */
lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;
- framebuf = xspanalloc(sizeof *framebuf, 0x10, 0);
+ framebuf = xspanalloc(sizeof *framebuf, 0x20, 0);
/* the following works because main memory is direct mapped */
framebuf->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;
M bitsy/screen.h => bitsy/screen.h +7 -1
@@ 1,3 1,9 @@
+typedef struct Cursorinfo Cursorinfo;
+typedef struct Cursor Cursor;
+
+struct Cursorinfo {
+ Lock;
+};
+
extern void blankscreen(int);
extern void flushmemscreen(Rectangle);
-
M boot/aux.c => boot/aux.c +2 -8
@@ 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);
}
M boot/bootip.c => boot/bootip.c +2 -2
@@ 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");
M carrera/screen.c => carrera/screen.c +2 -2
@@ 8,7 8,7 @@
#include "../port/error.h"
#define Image IMAGE
-#include <draw.h>
+#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
@@ 63,7 63,7 @@ static Memimage xgscreen =
0, /* zero */
512, /* width */
0, /* layer */
- Frepl, /* flags */
+ 0, /* flags */
};
Memimage *gscreen;
M pc/devi82365.c => pc/devi82365.c +19 -9
@@ 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<nv && l<link; l++)
+ for(l=0; l<nv && l<n; l++)
if(readc(&cis, p++) != 1)
break;
pcmunmap(slotno, m);
@@ 1137,14 1147,14 @@ xcistuple(int slotno, int tuple, void *v, int nv, int attr)
}
int
-pcmcistuple(int slotno, int tuple, void *v, int nv)
+pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
{
int n;
/* try attribute space, then memory */
- if((n = xcistuple(slotno, tuple, v, nv, 1)) >= 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;
M pc/ether589.c => pc/ether589.c +1 -1
@@ 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];
A pc/ethersmc.c => pc/ethersmc.c +779 -0
@@ 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);
+}
M pc/fns.h => pc/fns.h +1 -1
@@ 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);
M port/devcons.c => port/devcons.c +58 -28
@@ 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);
}
/*
M port/devdraw.c => port/devdraw.c +1 -1
@@ 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;