## diffname pc/devether.c 1992/0403
## diff -e /dev/null /n/bootesdump/1992/0403/sys/src/9/safari/devether.c
0a
/*
* Western Digital ethernet adapter
* BUGS:
* more than one controller
* fix for different controller types
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.h"
typedef struct Ctlr Ctlr;
typedef struct Pktype Pktype;
enum {
IObase = 0x360,
EA = 0x08, /* Ethernet Address in ROM */
ID = 0x0E, /* interface type */
NIC = 0x10, /* National DP8390 Chip */
Cr = NIC+0x00, /* Page [01] */
Clda0 = NIC+0x01, /* read */
Pstart = Clda0, /* write */
Clda1 = NIC+0x02, /* read */
Pstop = Clda1, /* write */
Bnry = NIC+0x03, /* Page 0 */
Tsr = NIC+0x04, /* read */
Tpsr = Tsr, /* write */
Ncr = NIC+0x05,
Isr = NIC+0x07,
Rbcr0 = NIC+0x0A,
Rbcr1 = NIC+0x0B,
Rsr = NIC+0x0C, /* read */
Rcr = Rsr, /* write */
Cntr0 = NIC+0x0D, /* read */
Tcr = Cntr0, /* write */
Cntr1 = NIC+0x0E, /* read */
Dcr = Cntr1, /* write */
Cntr2 = NIC+0x0F, /* read */
Imr = Cntr2, /* write */
Par0 = NIC+0x01, /* Page 1 */
Curr = NIC+0x07,
Mar0 = NIC+0x08,
Mar1 = NIC+0x09,
Mar2 = NIC+0x0A,
Mar3 = NIC+0x0B,
Mar4 = NIC+0x0C,
Mar5 = NIC+0x0D,
Mar6 = NIC+0x0E,
Mar7 = NIC+0x0F,
RAMbase = 0xC8000,
Nctlr = 1,
NPktype = 9, /* types/interface */
};
/*
* one per ethernet packet type
*/
struct Pktype {
QLock;
int type; /* ethernet type */
int prom; /* promiscuous mode */
Queue *q;
int inuse;
Ctlr *ctlr;
};
/*
* per ethernet
*/
struct Ctlr {
QLock;
Rendez rr; /* rendezvous for an input buffer */
Queue rq;
Qlock xl;
Rendez xr;
int iobase; /* I/O base address */
Pktype pktype[NPktype];
uchar ea[6];
uchar ba[6];
uchar prom; /* true if promiscuous mode */
uchar kproc; /* true if kproc started */
char name[NAMELEN]; /* name of kproc */
Network net;
Netprot prot[NPktype];
int inpackets;
int outpackets;
int crcs; /* input crc errors */
int oerrs; /* output errors */
int frames; /* framing errors */
int overflows; /* packet overflows */
int buffs; /* buffering errors */
};
static Ctlr ctlr[Nctlr];
static void
etheroput(Queue *q, Block *bp)
{
Ctlr *c;
int len, n;
Pktype *t;
Etherpkt *p;
Block *nbp;
c = ((Pktype *)q->ptr)->ctlr;
if(bp->type == M_CTL){
t = q->ptr;
if(streamparse("connect", bp))
t->type = strtol((char *)bp->rptr, 0, 0);
else if(streamparse("promiscuous", bp)) {
t->prom = 1;
qlock(c);
c->prom++;
if(c->prom == 1)
outb(c->iobase+Rcr, 0x14); /* PRO|AB */
qunlock(c);
}
freeb(bp);
return;
}
/*
* give packet a local address, return upstream if destined for
* this machine.
*/
if(BLEN(bp) < ETHERHDRSIZE){
bp = pullup(bp, ETHERHDRSIZE);
if(bp == 0)
return;
}
p = (Etherpkt *)bp->rptr;
memmove(p->s, c->ea, sizeof(c->ea));
if(memcmp(c->ea, p->d, sizeof(c->ea)) == 0){
len = blen(bp);
bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU);
if(bp){
putq(&c->rq, bp);
wakeup(&c->rr);
}
return;
}
if(memcmp(c->ba, p->d, sizeof(c->ba)) == 0){
len = blen(bp);
nbp = copyb(bp, len);
nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU);
if(nbp){
nbp->wptr = nbp->rptr+len;
putq(&c->rq, nbp);
wakeup(&c->rr);
}
}
/*
* only one transmitter at a time
*/
qlock(&c->xl);
if(waserror()){
qunlock(&c->xl);
nexterror();
}
/*
* Wait till we get an output buffer
*/
sleep(&c->xr, isobuf, c);
p = enet.xn;
/*
* copy message into buffer
*/
len = 0;
for(nbp = bp; nbp; nbp = nbp->next){
if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){
memmove(((uchar *)p)+len, nbp->rptr, n);
len += n;
} else
print("no room damn it\n");
if(bp->flags & S_DELIM)
break;
}
/*
* pad the packet (zero the pad)
*/
if(len < ETHERMINTU){
memset(((char*)p)+len, 0, ETHERMINTU-len);
len = ETHERMINTU;
}
enet.xn->len = len;
/*
* give packet a local address
*/
memmove(p->s, enet.ea, sizeof(enet.ea));
/*
* give to Chip
*/
splhi(); /* sync with interrupt routine */
enet.xn->owner = Chip;
if(enet.xmting == 0)
ethersend(enet.xn);
spllo();
/*
* send
*/
enet.xn = XSUCC(enet.xn);
freeb(bp);
qunlock(&enet.xl);
poperror();
enet.outpackets++;
}
/*
* open an ether line discipline
*
* the lock is to synchronize changing the ethertype with
* sending packets up the stream on interrupts.
*/
static void
etherstopen(Queue *q, Stream *s)
{
Ctlr *c = &ctlr[0];
Pktype *t;
t = &c->pktype[s->id];
qlock(t);
RD(q)->ptr = WR(q)->ptr = t;
t->type = 0;
t->q = RD(q);
t->inuse = 1;
t->ctlr = c;
qunlock(t);
}
/*
* close ether line discipline
*
* the lock is to synchronize changing the ethertype with
* sending packets up the stream on interrupts.
*/
static void
etherstclose(Queue *q)
{
Pktype *t;
t = (Pktype *)(q->ptr);
if(t->prom){
qlock(t->ctlr);
t->ctlr->prom--;
if(t->ctlr->prom == 0)
/* turn off promiscuous mode here */;
qunlock(t->ctlr);
}
qlock(t);
t->type = 0;
t->q = 0;
t->prom = 0;
t->inuse = 0;
netdisown(&t->ctlr->net, t - t->ctlr->pktype);
qunlock(t);
}
static Qinfo info = {
nullput,
etheroput,
etherstopen,
etherstclose,
"ether"
};
static int
clonecon(Chan *chan)
{
Ctlr *c = &ctlr[0];
Pktype *t;
for(t = c->pktype; t < &c->pktype[NPktype]; t++){
qlock(t);
if(t->inuse || t->q){
qunlock(t);
continue;
}
t->inuse = 1;
netown(&c->net, t - c->pktype, u->p->user, 0);
qunlock(t);
return t - c->pktype;
}
exhausted("ether channels");
}
static void
statsfill(Chan *chan, char *p, int n)
{
Ctlr *c = &ctlr[0];
char buf[256];
sprint(buf, "in: %d\nout: %d\ncrc errs %d\noverflows: %d\nframe errs %d\nbuff errs: %d\noerrs %d\naddr: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",
c->inpackets, c->outpackets, c->crcs,
c->overflows, c->frames, c->buffs, c->oerrs,
c->ea[0], c->ea[1], c->ea[2], c->ea[3], c->ea[4], c->ea[5]);
strncpy(p, buf, n);
}
static void
typefill(Chan *c, char *p, int n)
{
char buf[16];
Pktype *t;
t = &ctlr[0].pktype[STREAMID(c->qid.path)];
sprint(buf, "%d", t->type);
strncpy(p, buf, n);
}
static void
intr(Ureg *ur)
{
panic("ether intr\n");
}
/*
* the following initialisation procedure
* is mandatory
* after this, the chip is still offline
*/
static void
init(Ctlr *c)
{
int i;
outb(c->iobase+Cr, 0x21); /* Page0, RD2|STP */
outb(c->iobase+Dcr, 0x48); /* FT1|LS */
outb(c->iobase+Rbcr0, 0);
outb(c->iobase+Rbcr1, 0);
outb(c->iobase+Rcr, 0x04); /* AB */
outb(c->iobase+Tcr, 0);
outb(c->iobase+Bnry, 6);
outb(c->iobase+Pstart, 6); /* 6*256 */
outb(c->iobase+Pstop, 32); /* 8*1024/256 */
outb(c->iobase+Isr, 0xFF);
outb(c->iobase+Imr, 0x0F); /* TXEE|RXEE|PTXE|PRXE */
outb(c->iobase+Cr, 0x61); /* Page1, RD2|STP */
for(i = 0; i < sizeof(c->ea); i++)
outb(c->iobase+Par0+i, c->ea[i]);
outb(c->iobase+Curr, 6); /* 6*256 */
}
void
etherreset(void)
{
Ctlr *c = &ctlr[0];
int i;
c->iobase = IObase;
init(c);
setvec(Ethervec, intr);
for(i = 0; i < sizeof(c->ea); i++)
c->ea[i] = inb(c->iobase+EA+i);
memset(c->ba, 0xFF, sizeof(c->ba));
c->net.name = "ether";
c->net.nconv = NPktype;
c->net.devp = &info;
c->net.protop = 0;
c->net.listen = 0;
c->net.clone = clonecon;
c->net.ninfo = 2;
c->net.prot = c->prot;
c->net.info[0].name = "stats";
c->net.info[0].fill = statsfill;
c->net.info[1].name = "type";
c->net.info[1].fill = typefill;
}
static int
isinput(void *arg)
{
Ctlr *c = arg;
return 0;
}
static void
etherkproc(void *arg)
{
Ctlr *c = arg;
if(waserror()){
print("someone noted %s\n", c->name);
c->kproc = 0;
nexterror();
}
c->kproc = 1;
for(;;){
sleep(&c->rr, isinput, c);
}
}
void
etherinit(void)
{
int ctlrno = 0;
/*
* put the receiver online
* and start the kproc
*/
outb(c->iobase+Cr, 0x22); /* Page0, RD2|STA */
outb(c->iobase+Tpsr, 0);
if(ctlr[ctlrno].kproc == 0){
sprint(ctlr[ctlrno].name, "ether%dkproc", ctlrno);
kproc(ctlr[ctlrno].name, etherkproc, &ctlr[ctlrno]);
}
}
Chan *
etherattach(char *spec)
{
return devattach('l', spec);
}
Chan *
etherclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
etherwalk(Chan *c, char *name)
{
return netwalk(c, name, &ctlr[0].net);
}
void
etherstat(Chan *c, char *dp)
{
netstat(c, dp, &ctlr[0].net);
}
Chan *
etheropen(Chan *c, int omode)
{
return netopen(c, omode, &ctlr[0].net);
}
void
ethercreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
etherremove(Chan *c)
{
error(Eperm);
}
void
etherwstat(Chan *c, char *dp)
{
netwstat(c, dp, &ctlr[0].net);
}
void
etherclose(Chan *c)
{
if(c->stream)
streamclose(c);
}
long
etherread(Chan *c, void *a, long n, ulong offset)
{
return netread(c, a, n, offset, &ctlr[0].net);
}
long
etherwrite(Chan *c, char *a, long n, ulong offset)
{
return streamwrite(c, a, n, 0);
}
.
## diffname pc/devether.c 1992/0404
## diff -e /n/bootesdump/1992/0403/sys/src/9/safari/devether.c /n/bootesdump/1992/0404/sys/src/9/safari/devether.c
428,429c
outb(ctlr[ctlrno].iobase+Tcr, 0);
.
415c
sleep(&cp->rr, isinput, cp);
while(bp = getq(&cp->rq)){
cp->inpackets++;
etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp));
freeb(bp);
}
#ifdef foo
bnry = inb(cp->iobase+Bnry);
while(bnry != cp->curr){
rp = &((Ring *)RAMbase)[bnry];
}
#endif
.
413c
cp->kproc = 1;
.
409,410c
print("%s noted\n", cp->name);
init(cp);
cp->kproc = 0;
.
406c
Ctlr *cp = arg;
Block *bp;
uchar bnry, curr;
Ring *rp;
.
400c
return cp->bnry != cp->curr;
.
398c
Ctlr *cp = arg;
.
394a
static void
etherup(Ctlr *cp, Etherpkt *p, int len)
{
Block *bp;
Pktype *pp;
int t;
t = (p->type[0]<<8) | p->type[1];
for(pp = &cp->pktype[0]; pp < &cp->pktype[NPktype]; pp++){
/*
* check before locking just to save a lock
*/
if(pp->q == 0 || (t != pp->type && pp->type != -1))
continue;
/*
* only a trace channel gets packets destined for other machines
*/
if(pp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d)))
continue;
/*
* check after locking to make sure things didn't
* change under foot
*/
if(canqlock(pp) == 0)
continue;
if(pp->q == 0 || pp->q->next->len > Streamhi || (t != pp->type && pp->type != -1)){
qunlock(pp);
continue;
}
if(waserror() == 0){
bp = allocb(len);
memmove(bp->rptr, (uchar *)p, len);
bp->wptr += len;
bp->flags |= S_DELIM;
PUTNEXT(pp->q, bp);
}
poperror();
qunlock(pp);
}
}
.
381,392c
cp->net.name = "ether";
cp->net.nconv = NPktype;
cp->net.devp = &info;
cp->net.protop = 0;
cp->net.listen = 0;
cp->net.clone = clonecon;
cp->net.ninfo = 2;
cp->net.prot = cp->prot;
cp->net.info[0].name = "stats";
cp->net.info[0].fill = statsfill;
cp->net.info[1].name = "type";
cp->net.info[1].fill = typefill;
.
377,379c
for(i = 0; i < sizeof(cp->ea); i++)
cp->ea[i] = inb(cp->iobase+EA+i);
memset(cp->ba, 0xFF, sizeof(cp->ba));
.
373,374c
cp->iobase = IObase;
init(cp);
.
370c
Ctlr *cp = &ctlr[0];
.
361,364c
outb(cp->iobase+Cr, 0x61); /* Page1, RD2|STP */
for(i = 0; i < sizeof(cp->ea); i++)
outb(cp->iobase+Par0+i, cp->ea[i]);
outb(cp->iobase+Curr, 6); /* 6*256 */
cp->curr = 6;
outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */
outb(cp->iobase+Tpsr, 0);
.
349,359c
outb(cp->iobase+Cr, 0x21); /* Page0, RD2|STP */
outb(cp->iobase+Dcr, 0x48); /* FT1|LS */
outb(cp->iobase+Rbcr0, 0);
outb(cp->iobase+Rbcr1, 0);
outb(cp->iobase+Rcr, 0x04); /* AB */
outb(cp->iobase+Tcr, 0x20); /* LB0 */
outb(cp->iobase+Bnry, 6);
cp->bnry = 6;
outb(cp->iobase+Pstart, 6); /* 6*256 */
outb(cp->iobase+Pstop, 32); /* 8*1024/256 */
outb(cp->iobase+Isr, 0xFF);
outb(cp->iobase+Imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */
.
345c
init(Ctlr *cp)
.
342c
* we leave the chip idling on internal loopback
.
336c
Ctlr *cp = &ctlr[0];
uchar isr, curr;
outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */
while(isr = inb(cp->iobase+Isr)){
outb(cp->iobase+Isr, isr);
if(isr & Txe)
cp->oerrs++;
if(isr & Rxe){
cp->frames += inb(cp->iobase+Cntr0);
cp->crcs += inb(cp->iobase+Cntr1);
cp->buffs += inb(cp->iobase+Cntr2);
}
if(isr & Ptx)
cp->outpackets++;
if(isr & (Txe|Ptx)){
panic("tx intr\n");
}
/*
* the receive ring is full.
* put the NIC into loopback mode to give
* kproc a chance to process some packets.
*/
if(isr & Ovw){
outb(cp->iobase+Cr, 0x21); /* Page0, RD2|STP */
outb(cp->iobase+Rbcr0, 0);
outb(cp->iobase+Rbcr1, 0);
while((inb(cp->iobase+Isr) & Rst) == 0)
delay(1);
outb(cp->iobase+Tcr, 0x20); /* LB0 */
outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */
cp->ovw = 1;
}
/*
* we have received packets.
* this is the only place, other than the init code,
* where we set the controller to Page1.
* we must be careful to reset it back to Page0 in case
* we interrupted some other part of this driver.
*/
if(isr & (Ovw|Prx)){
outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */
cp->curr = inb(cp->iobase+Curr);
outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */
wakeup(&cp->rr);
}
}
.
328,329c
pp = &ctlr[0].pktype[STREAMID(c->qid.path)];
sprint(buf, "%d", pp->type);
.
326c
Pktype *pp;
.
316,318c
cp->inpackets, cp->outpackets, cp->crcs,
cp->overflows, cp->frames, cp->buffs, cp->oerrs,
cp->ea[0], cp->ea[1], cp->ea[2], cp->ea[3], cp->ea[4], cp->ea[5]);
.
312c
Ctlr *cp = &ctlr[0];
.
310c
statsfill(Chan *c, char *p, int n)
.
301,304c
pp->inuse = 1;
netown(&cp->net, pp - cp->pktype, u->p->user, 0);
qunlock(pp);
return pp - cp->pktype;
.
295,298c
for(pp = cp->pktype; pp < &cp->pktype[NPktype]; pp++){
qlock(pp);
if(pp->inuse || pp->q){
qunlock(pp);
.
292,293c
Ctlr *cp = &ctlr[0];
Pktype *pp;
.
290c
clonecon(Chan *c)
.
272,278c
qlock(pp);
pp->type = 0;
pp->q = 0;
pp->prom = 0;
pp->inuse = 0;
netdisown(&pp->ctlr->net, pp - pp->ctlr->pktype);
qunlock(pp);
.
264,270c
pp = (Pktype *)(q->ptr);
if(pp->prom){
qlock(pp->ctlr);
pp->ctlr->prom--;
if(pp->ctlr->prom == 0){
outb(pp->ctlr->iobase+Cr, 0x22);/* Page0, RD2|STA */
outb(pp->ctlr->iobase+Rcr, 0x04);/* AB */
}
qunlock(pp->ctlr);
.
262c
Pktype *pp;
.
243,250c
pp = &cp->pktype[s->id];
qlock(pp);
RD(q)->ptr = WR(q)->ptr = pp;
pp->type = 0;
pp->q = RD(q);
pp->inuse = 1;
pp->ctlr = cp;
qunlock(pp);
.
240,241c
Ctlr *cp = &ctlr[0];
Pktype *pp;
.
228a
#endif
.
130a
}
.
129c
if(c->prom == 1){
outb(t->ctlr->iobase+Cr, 0x22); /* Page0, RD2|STA */
.
119a
panic("etheroput\n");
#ifdef notdef
.
86c
QLock xl;
.
83a
uchar bnry;
uchar curr;
uchar ovw;
.
61,62c
struct Ring {
uchar status;
uchar next;
ushort len;
uchar data[BUFsize-4];
.
59c
/*
* some register bits
*/
enum {
Prx = 0x01, /* Isr: packet received */
Ptx = 0x02, /* packet transmitted */
Rxe = 0x04, /* receive error */
Txe = 0x08, /* transmit error */
Ovw = 0x10, /* overwrite warning */
Rst = 0x80, /* reset status */
};
.
50,57c
};
.
35c
Tbcr0 = NIC+0x05, /* write */
Tbcr1 = NIC+0x06, /* write */
.
28,32c
Pstart = NIC+0x01, /* write */
Pstop = NIC+0x02, /* write */
Bnry = NIC+0x03,
.
21a
Nctlr = 1,
NPktype = 9, /* types/interface */
};
/*
* register offsets from IObase
*/
enum {
.
20a
RAMbase = 0xC8000,
RAMsize = 8*1024,
BUFsize = 256,
.
17a
typedef struct Ring Ring;
.
4c
* no more than one controller
.
## diffname pc/devether.c 1992/0405
## diff -e /n/bootesdump/1992/0404/sys/src/9/safari/devether.c /n/bootesdump/1992/0405/sys/src/9/safari/devether.c
415a
* and pointing to Page0.
.
414c
* is mandatory.
.
400c
* we must be sure to reset it back to Page0 in case
.
366d
296d
293,294c
if(pp->ctlr->prom == 0)
.
154d
151,152c
if(c->prom == 1)
.
## diffname pc/devether.c 1992/0406
## diff -e /n/bootesdump/1992/0405/sys/src/9/safari/devether.c /n/bootesdump/1992/0406/sys/src/9/safari/devether.c
542,547c
/*
* process any received packets
*/
bnry = inb(cp->iobase+Bnry);
while(bnry != cp->curr){
rp = &((Ring*)RAMbase)[bnry];
printpkt(bnry, rp->len, (Etherpkt*)rp->data);
cp->inpackets++;
etherup(cp, (Etherpkt*)rp->data, rp->len-4);
bnry = rp->next;
outb(cp->iobase+Bnry, bnry);
}
/*
* if we idled input because of overflow,
* restart
*/
if(cp->ovw){
cp->ovw = 0;
outb(cp->iobase+Tcr, 0);
}
.
536a
/*
* process any internal loopback packets
*/
.
511a
static void
printpkt(uchar bnry, ushort len, Etherpkt *p)
{
int i;
print("%.2ux: %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)\n",
bnry, len,
p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5],
p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5],
p->type[0], p->type[1]);
}
.
189a
panic("etheroput\n");
#ifdef notdef
.
185,186c
putq(&cp->rq, nbp);
wakeup(&cp->rr);
.
182,183c
if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){
.
179c
if(memcmp(cp->ba, p->d, sizeof(cp->ba)) == 0){
.
172,175c
if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){
putq(&cp->rq, bp);
wakeup(&cp->rr);
.
169,170c
memmove(p->s, cp->ea, sizeof(cp->ea));
if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){
.
163,167c
if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0)
return;
.
148,153c
pp->prom = 1;
qlock(cp);
cp->prom++;
if(cp->prom == 1)
outb(cp->iobase+Rcr, 0x14); /* PRO|AB */
qunlock(cp);
.
146c
pp->type = strtol((char *)bp->rptr, 0, 0);
.
144c
pp = q->ptr;
.
140,142c
cp = ((Pktype *)q->ptr)->ctlr;
.
136c
Pktype *pp;
.
134c
Ctlr *cp;
.
5a
* output
* deal with stalling and restarting output on input overflow
* fix magic ring constants
.
4a
* TODO:
.
## diffname pc/devether.c 1992/0407
## diff -e /n/bootesdump/1992/0406/sys/src/9/safari/devether.c /n/bootesdump/1992/0407/sys/src/9/safari/devether.c
574a
wakeup(&cp->xr);
.
564,566c
etherup(cp, (Etherpkt*)rp->data, ((rp->len1<<8)+rp->len0)-4);
cp->bnry = rp->next;
outb(cp->iobase+Bnry, cp->bnry);
.
559,562c
cp->bnry = inb(cp->iobase+Bnry);
while(cp->bnry != cp->curr){
rp = &cp->ring[cp->bnry];
.
437a
cp->xpkt = (Etherpkt*)(KZERO|RAMbase);
.
424a
cp->ring = (Ring*)(KZERO|RAMbase);
.
373c
cp->xbusy = 0;
wakeup(&cp->xr);
.
248,250d
246c
qunlock(&cp->xl);
.
241,244d
235,239c
outb(cp->iobase+Tbcr0, len & 0xFF);
outb(cp->iobase+Tbcr1, (len>>8) & 0xFF);
outb(cp->iobase+Cr, 0x26); /* Page0|TXP|STA */
cp->xbusy = 1;
.
233c
* start the transmission
.
230c
memmove(p->s, cp->ea, sizeof(cp->ea));
.
228c
* give packet a local address
.
225d
219c
* pad the packet (zero the pad)
.
201,202c
sleep(&cp->xr, isxfree, cp);
p = cp->xpkt;
.
199c
* Wait till we get an output buffer
.
194c
qunlock(&cp->xl);
.
192c
qlock(&cp->xl);
.
187,188d
134a
static int
isxfree(void *arg)
{
Ctlr *cp = arg;
return cp->xbusy == 0 && cp->ovw == 0;
}
.
111a
uchar xbusy;
.
109a
Etherpkt *xpkt;
.
108d
104a
Queue rq;
.
103a
Ring *ring;
.
82c
uchar len0;
uchar len1;
.
9a
* rewrite per SMC doc
.
## diffname pc/devether.c 1992/0408
## diff -e /n/bootesdump/1992/0407/sys/src/9/safari/devether.c /n/bootesdump/1992/0408/sys/src/9/safari/devether.c
571a
.
569c
bnry = rp->next;
cp->bnry = PREV(bnry, 32);
.
564,566c
bnry = NEXT(cp->bnry, 32);
while(bnry != cp->curr){
rp = &cp->ring[bnry];
.
560a
.
533c
return NEXT(cp->bnry, 32) != cp->curr;
.
456a
init(cp);
setvec(Ethervec, intr);
.
452,454d
437,438c
cp->curr = cp->bnry+1;
outb(cp->iobase+Curr, cp->curr);
.
427a
outb(cp->iobase+Bnry, cp->bnry);
.
426d
391a
cp->overflows++;
.
34a
#define NEXT(x, l) ((((x)+1)%(l)) == 0 ? 6: (((x)+1)%(l)))
#define PREV(x, l) (((x)-1) == 5 ? (l-1): ((x)-1))
.
## diffname pc/devether.c 1992/0409
## diff -e /n/bootesdump/1992/0408/sys/src/9/safari/devether.c /n/bootesdump/1992/0409/sys/src/9/safari/devether.c
670a
}
void
etherdump(void)
{
Ctlr *cp = &ctlr[0];
uchar bnry, curr, isr;
int s;
s = splhi();
bnry = inb(cp->iobase+Bnry);
outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */
curr = inb(cp->iobase+Curr);
outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */
isr = inb(cp->iobase+Isr);
print("b%d c%d x%d B%d C%d I%ux",
cp->bnry, cp->curr, cp->xbusy, bnry, curr, isr);
print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->opackets,
cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs);
splx(s);
.
577,586d
455a
msr = 0x40|inb(cp->iobase);
outb(cp->iobase, msr);
for(i = 0; i < 0x10; i++)
print("#%2.2ux ", inb(cp->iobase+i));
print("\n");
.
453a
uchar msr;
.
406a
if(cp->curr == 0)
print("C0: b%d i%ux\n", cp->bnry, isr);
.
396d
381,394c
if(isr & Ovw)
.
148c
return cp->xbusy == 0;
.
114d
## diffname pc/devether.c 1992/0410
## diff -e /n/bootesdump/1992/0409/sys/src/9/safari/devether.c /n/bootesdump/1992/0410/sys/src/9/safari/devether.c
671c
print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->outpackets,
.
663a
debug++;
.
567c
cp->bnry = PREV(bnry, RINGsize);
.
565c
len0 = ((rp->len1<<8)+rp->len0)-4;
len1 = 0;
if(rp->data+len0 >= (uchar*)&cp->ring[RINGsize]){
len1 = rp->data+len0 - (uchar*)&cp->ring[RINGsize];
len0 = (uchar*)&cp->ring[RINGsize] - rp->data;
}
etherup(cp, rp->data, len0, (uchar*)&cp->ring[RINGbase], len1);
if(debug)
print("K%d/%d/%d|", bnry, rp->next, PREV(rp->next, RINGsize));
.
561c
bnry = NEXT(cp->bnry, RINGsize);
.
554c
etherup(cp, bp->rptr, BLEN(bp), 0, 0);
.
538a
int len0, len1;
.
529c
return NEXT(cp->bnry, RINGsize) != cp->curr;
.
508c
qunlock(tp);
.
505c
PUTNEXT(tp->q, bp);
.
501,503c
bp = allocb(len0+len1);
memmove(bp->rptr, d0, len0);
if(len1)
memmove(bp->rptr+len0, d1, len1);
bp->wptr += len0+len1;
.
496,497c
if(tp->q == 0 || tp->q->next->len > Streamhi || (t != tp->type && tp->type != -1)){
qunlock(tp);
.
494c
if(canqlock(tp) == 0)
.
487c
if(tp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d)))
.
481c
if(tp->q == 0 || (t != tp->type && tp->type != -1))
.
476,477c
p = (Etherpkt*)d0;
t = (p->type[0]<<8)|p->type[1];
for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){
.
473c
Type *tp;
.
471a
Etherpkt *p;
.
470c
etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1)
.
456c
cp->net.nconv = NType;
.
448a
msr=0x40|inb(cp->iobase+0x05);
outb(cp->iobase+0x05, msr);
.
445a
msr=0x40|inb(cp->iobase+0x05);
outb(cp->iobase+0x05, msr);
.
420,421c
outb(cp->iobase+Pstart, RINGbase);
outb(cp->iobase+Pstop, RINGsize);
.
417c
cp->bnry = RINGbase;
.
394a
if(debug)
print("I%d/%d/%d|", isr, cp->curr, cp->bnry);
.
392,393d
389c
if(isr & (Rxe|Prx)){
.
380,381c
if(isr & Ovw){
bnry = inb(cp->iobase+Bnry);
outb(cp->iobase+bnry, bnry);
cp->buffs++;
}
.
372c
cp->overflows += inb(cp->iobase+Cntr2);
.
363c
uchar isr, bnry, curr;
.
354,355c
tp = &ctlr[0].type[STREAMID(c->qid.path)];
sprint(buf, "%d", tp->type);
.
352c
Type *tp;
.
327,330c
tp->inuse = 1;
netown(&cp->net, tp - cp->type, u->p->user, 0);
qunlock(tp);
return tp - cp->type;
.
321,324c
for(tp = cp->type; tp < &cp->type[NType]; tp++){
qlock(tp);
if(tp->inuse || tp->q){
qunlock(tp);
.
319c
Type *tp;
.
298,304c
qlock(tp);
tp->type = 0;
tp->q = 0;
tp->prom = 0;
tp->inuse = 0;
netdisown(&tp->ctlr->net, tp - tp->ctlr->type);
qunlock(tp);
.
290,296c
tp = (Type *)(q->ptr);
if(tp->prom){
qlock(tp->ctlr);
tp->ctlr->prom--;
if(tp->ctlr->prom == 0)
outb(tp->ctlr->iobase+Rcr, 0x04);/* AB */
qunlock(tp->ctlr);
.
288c
Type *tp;
.
269,276c
tp = &cp->type[s->id];
qlock(tp);
RD(q)->ptr = WR(q)->ptr = tp;
tp->type = 0;
tp->q = RD(q);
tp->inuse = 1;
tp->ctlr = cp;
qunlock(tp);
.
267c
Type *tp;
.
165c
tp->prom = 1;
.
163c
tp->type = strtol((char *)bp->rptr, 0, 0);
.
161c
tp = q->ptr;
.
159c
cp = ((Type *)q->ptr)->ctlr;
.
155c
Type *tp;
.
130c
Netprot prot[NType];
.
122c
Type type[NType];
.
94c
struct Type {
.
80d
35,36c
#define NEXT(x, l) ((((x)+1)%(l)) == 0 ? RINGbase: (((x)+1)%(l)))
#define PREV(x, l) (((x)-1) < RINGbase ? (l-1): ((x)-1))
.
32c
NType = 9, /* types/interface */
.
30a
RINGbase = 6, /* gak */
RINGsize = 32, /* gak */
.
27c
RAMbase = 0xD0000,
.
22c
typedef struct Type Type;
.
20a
static int debug;
.
## diffname pc/devether.c 1992/0411
## diff -e /n/bootesdump/1992/0410/sys/src/9/safari/devether.c /n/bootesdump/1992/0411/sys/src/9/safari/devether.c
686c
consdebug(void)
.
517c
xmemmove(bp->rptr+len0, d1, len1);
.
515c
xmemmove(bp->rptr, d0, len0);
.
458,459d
451,454c
reg = 0x40|inb(cp->iobase);
outb(cp->iobase, reg);
reg = 0x40|inb(cp->iobase+0x05);
outb(cp->iobase+0x05, reg);
.
448c
uchar reg;
.
246a
xmemmove(cp->xpkt, p, len);
.
218,219c
tsleep(&cp->xr, isxfree, cp, 1000);
if(isxfree(cp) == 0)
print("Tx wedged\n");
p = &txpkt;
.
210a
freeb(bp);
.
145a
static Etherpkt txpkt;
static void
xmemmove(void *to, void *from, long len)
{
ushort *t, *f;
int s;
Ctlr *cp = &ctlr[0];
uchar reg;
t = to;
f = from;
len = (len+1)/2;
s = splhi();
reg = inb(cp->iobase+0x05);
outb(cp->iobase+Imr, 0);
outb(cp->iobase+0x05, 0x80|reg);
while(len--)
*t++ = *f++;
outb(cp->iobase+0x05, reg);
outb(cp->iobase+Imr, 0x1F);
splx(s);
}
.
29c
RAMbase = 0xC8000,
.
## diffname pc/devether.c 1992/0424
## diff -e /n/bootesdump/1992/0411/sys/src/9/safari/devether.c /n/bootesdump/1992/0424/sys/src/9/safari/devether.c
714,729d
710a
static Hw wd8013 = {
0x360, /* I/O base address */
KZERO|0xC8000, /* shared memory address */
8*1024, /* shared memory size */
wd8013reset,
wd8013init,
wd8013mode,
wd8013online,
wd8013receive,
wd8013transmit,
wd8013intr,
};
.
708c
Ctlr *cp = &ctlr[0];
Hw *hw = cp->hw;
Buffer *tb;
uchar isr;
while(isr = IN(hw, r.isr)){
OUT(hw, w.isr, isr);
if(isr & 0x08) /* Txe - transmit error */
cp->oerrs++;
if(isr & 0x04){ /* Rxe - receive error */
cp->frames += IN(hw, r.cntr0);
cp->crcs += IN(hw, r.cntr1);
cp->buffs += IN(hw, r.cntr2);
}
if(isr & 0x02) /* Ptx - packet transmitted */
cp->outpackets++;
/*
* a packet completed transmission, successfully or
* not. start transmission on the next buffered packet,
* and wake the output routine.
*/
if(isr & (0x08|0x02)){
tb = &cp->tb[cp->ti];
tb->owner = Host;
tb->busy = 0;
cp->ti = NEXT(cp->ti, Ntb);
(*cp->hw->transmit)(cp);
wakeup(&cp->tr);
}
if(isr & 0x10) /* Ovw - overwrite warning */
cp->overflows++;
/*
* we have received packets.
*/
if(isr & (0x04|0x01)){ /* Rxe|Prx - packet received */
(*cp->hw->receive)(cp);
wakeup(&cp->rr);
}
}
.
705,706c
static void
wd8013intr(Ureg *ur)
.
702c
Hw *hw;
Buffer *tb;
int s;
print("transmit\n");
s = splhi();
tb = &cp->tb[cp->ti];
if(tb->busy == 0 && tb->owner == Interface){
hw = cp->hw;
print("transmit memove %lux %lux, %d\n", hw->ram, &tb->pkt, tb->len);
memmove(hw->ram, &tb->pkt, tb->len);
OUT(hw, w.tbcr0, tb->len & 0xFF);
OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF);
OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */
tb->busy = 1;
}
splx(s);
print("transmit done\n");
.
699,700c
static void
wd8013transmit(Ctlr *cp)
.
695,696c
Hw *hw = cp->hw;
Buffer *rb;
uchar bnry, curr, next;
typedef struct Ring {
uchar status;
uchar next;
uchar len0;
uchar len1;
uchar data[256-4];
} Ring;
Ring *p;
int len;
bnry = IN(hw, r.bnry);
next = NEXT(bnry, HOWMANY(hw->ramsz, 256));
if(next == 0)
next = HOWMANY(sizeof(Etherpkt), 256);
for(;;){
OUT(hw, w.cr, 0x62); /* Page1|RD2|STA */
curr = IN(hw, curr);
OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */
if(next == curr)
break;
cp->inpackets++;
p = &((Ring*)hw->ram)[next];
len = (p->len1<<8)|p->len0;
rb = &cp->rb[cp->ri];
if(rb->owner == Interface){
rb->len = len;
/*copy in packet*/
rb->owner = Host;
cp->ri = NEXT(cp->ri, Nrb);
}
next = p->next;
bnry = next-1;
if(bnry < HOWMANY(sizeof(Etherpkt), 256))
bnry = HOWMANY(hw->ramsz, 256)-1;
OUT(hw, w.bnry, bnry);
}
.
692,693c
static void
wd8013receive(Ctlr *cp)
.
689c
OUT(cp->hw, w.tcr, 0);
.
686,687c
static void
wd8013online(Ctlr *cp, int on)
.
683c
qlock(cp);
if(on){
cp->prom++;
if(cp->prom == 1)
OUT(cp->hw, w.rcr, 0x14);/* PRO|AB */
}
else {
cp->prom--;
if(cp->prom == 0)
OUT(cp->hw, w.rcr, 0x04);/* AB */
}
qunlock(cp);
.
681c
wd8013mode(Ctlr *cp, int on)
.
677c
Hw *hw = cp->hw;
int i;
uchar bnry;
print("init %d %d\n", HOWMANY(sizeof(Etherpkt), 256), HOWMANY(hw->ramsz, 256));
OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */
OUT(hw, w.dcr, 0x48); /* FT1|LS */
OUT(hw, w.rbcr0, 0);
OUT(hw, w.rbcr1, 0);
OUT(hw, w.rcr, 0x04); /* AB */
OUT(hw, w.tcr, 0x20); /* LB0 */
bnry = HOWMANY(sizeof(Etherpkt), 256);
OUT(hw, w.bnry, bnry);
OUT(hw, w.pstart, bnry);
OUT(hw, w.pstop, HOWMANY(hw->ramsz, 256));
OUT(hw, w.isr, 0xFF);
OUT(hw, w.imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */
OUT(hw, w.cr, 0x61); /* Page1|RD2|STP */
for(i = 0; i < sizeof(cp->ea); i++)
OUT(hw, par[i], cp->ea[i]);
OUT(hw, curr, bnry+1);
OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */
OUT(hw, w.tpsr, 0);
.
674,675c
/*
* we leave the chip idling on internal loopback
* and pointing to Page0.
*/
static void
wd8013init(Ctlr *cp)
.
672a
print("\n");
}
for(i = 0; i < sizeof(cp->ea); i++)
cp->ea[i] = IN(hw, lan[i]);
(*hw->init)(cp);
setvec(Ethervec, hw->intr);
}
.
671c
int addr = hw->addr;
for(i = 0; i < 16; i++){
print("#%2.2ux ", inb(addr));
addr++;
.
668,669c
print("reset\n");
cp->rb = ialloc(sizeof(Buffer)*Nrb, 0);
cp->nrb = Nrb;
cp->tb = ialloc(sizeof(Buffer)*Ntb, 0);
cp->ntb = Ntb;
msr = IN(hw, msr);
OUT(hw, msr, 0x40|msr);
.
665,666c
Hw *hw = cp->hw;
int i;
uchar msr;
.
662,663c
#define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m))
#define OUT(hw, m, x) outb((hw)->addr+OFFSETOF(Wd8013, m), (x))
/*
*/
static void
wd8013reset(Ctlr *cp)
.
656,660c
union { /* DP8390/83C690 LAN controller */
struct { /* Page0, read */
uchar cr;
uchar clda0;
uchar clda1;
uchar bnry;
uchar tsr;
uchar ncr;
uchar fifo;
uchar isr;
uchar crda0;
uchar crda1;
uchar pad0x0A;
uchar pad0x0B;
uchar rsr;
uchar cntr0;
uchar cntr1;
uchar cntr2;
} r;
struct { /* Page0, write */
uchar cr;
uchar pstart;
uchar pstop;
uchar bnry;
uchar tpsr;
uchar tbcr0;
uchar tbcr1;
uchar isr;
uchar rsar0;
uchar rsar1;
uchar rbcr0;
uchar rbcr1;
uchar rcr;
uchar tcr;
uchar dcr;
uchar imr;
} w;
struct { /* Page1, read/write */
uchar cr;
uchar par[6];
uchar curr;
uchar mar[8];
};
};
} Wd8013;
.
650,654c
typedef struct {
uchar msr; /* 83C584 bus interface */
uchar icr;
uchar iar;
uchar bio;
uchar irr;
uchar laar;
uchar ijr;
uchar gp2;
uchar lan[6];
uchar id;
uchar cksum;
.
642,646d
637,640c
(*cp->hw->online)(cp, 1);
if(cp->kproc == 0){
sprint(cp->name, "ether%dkproc", ctlrno);
kproc(cp->name, etherkproc, cp);
.
632a
cp->rh = 0;
cp->ri = 0;
for(i = 0; i < cp->nrb; i++)
cp->rb[i].owner = Interface;
cp->th = 0;
cp->ti = 0;
for(i = 0; i < cp->ntb; i++)
cp->tb[i].owner = Host;
.
631a
Ctlr *cp = &ctlr[ctlrno];
int i;
.
628,629c
Chan*
etherattach(char *spec)
.
619,625c
cp->net.name = "ether";
cp->net.nconv = NType;
cp->net.devp = &info;
cp->net.protop = 0;
cp->net.listen = 0;
cp->net.clone = clonecon;
cp->net.ninfo = 2;
cp->net.prot = cp->prot;
cp->net.info[0].name = "stats";
cp->net.info[0].fill = statsfill;
cp->net.info[1].name = "type";
cp->net.info[1].fill = typefill;
.
617a
memset(cp->ba, 0xFF, sizeof(cp->ba));
.
616a
cp->hw = &wd8013;
(*cp->hw->reset)(cp);
.
615c
void
etherreset(void)
{
Ctlr *cp = &ctlr[0];
.
610,613c
qunlock(&cp->rlock);
sleep(&cp->rr, isinput, cp);
}
}
.
607,608c
rb = &cp->rb[cp->rh];
etherup(cp, &rb->pkt, rb->len);
rb->owner = Interface;
cp->rh = NEXT(cp->rh, Nrb);
}
.
603,605c
while(cp->rb[cp->rh].owner == Host){
.
596c
etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp));
.
594c
while(bp = getq(&cp->lbq)){
.
590c
qlock(&cp->rlock);
.
584c
(*cp->hw->init)(cp);
.
578,580d
576a
Buffer *rb;
.
570c
return cp->lbq.first || cp->rb[cp->ri].owner == Host;
.
553,564d
540,544c
bp = allocb(len);
memmove(bp->rptr, p, len);
bp->wptr += len;
.
514d
394,509d
392c
etherup(Ctlr *cp, Etherpkt *p, int len)
.
323,329c
if(tp->prom)
(*tp->ctlr->hw->mode)(tp->ctlr, 0);
.
285c
qunlock(&cp->tlock);
print("oput done\n");
.
279,282c
cp->outpackets++;
tb->len = len;
tb->owner = Interface;
cp->th = NEXT(cp->th, cp->ntb);
(*cp->hw->transmit)(cp);
.
276a
* set up the transmit buffer and
.
274d
247a
tb = &cp->tb[cp->th];
p = &tb->pkt;
.
243,246c
print("oput sleep\n");
sleep(&cp->tr, isobuf, cp);
.
241c
* wait till we get an output buffer.
* should try to restart.
.
236c
qunlock(&cp->tlock);
.
233c
qlock(&cp->tlock);
.
225c
putq(&cp->lbq, nbp);
.
215c
putq(&cp->lbq, bp);
.
203a
cp = ((Type *)q->ptr)->ctlr;
.
194,198c
(*tp->ctlr->hw->mode)(tp->ctlr, 1);
.
187d
184a
Buffer *tb;
.
175c
cp->tb[cp->th].owner == Host;
.
171c
isobuf(void *arg)
.
169a
long
etherwrite(Chan *c, char *a, long n, ulong offset)
{
return streamwrite(c, a, n, 0);
}
void
etherremove(Chan *c)
{
error(Eperm);
}
void
etherwstat(Chan *c, char *dp)
{
netwstat(c, dp, &ctlr[0].net);
}
.
156,167c
int
etherwalk(Chan *c, char *name)
{
return netwalk(c, name, &ctlr[0].net);
}
void
etherstat(Chan *c, char *dp)
{
netstat(c, dp, &ctlr[0].net);
}
Chan*
etheropen(Chan *c, int omode)
{
return netopen(c, omode, &ctlr[0].net);
}
void
ethercreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
etherclose(Chan *c)
{
if(c->stream)
streamclose(c);
}
long
etherread(Chan *c, void *a, long n, ulong offset)
{
return netread(c, a, n, offset, &ctlr[0].net);
.
151,154c
return devclone(c, nc);
}
.
148,149c
Chan*
etherclone(Chan *c, Chan *nc)
.
146c
void
etherinit(void)
{
}
.
138,142c
int crcs; /* input crc errors */
int oerrs; /* output errors */
int frames; /* framing errors */
int overflows; /* packet overflows */
int buffs; /* buffering errors */
.
135a
Queue lbq; /* software loopback packet queue */
.
130,132c
Rendez tr; /* rendezvous for a transmit buffer */
QLock tlock; /* semaphore on tc */
ushort th; /* first transmit buffer belonging to host */
ushort ti; /* first transmit buffer belonging to interface */
Type type[NType];
uchar prom; /* true if promiscuous mode */
uchar kproc; /* true if kproc started */
char name[NAMELEN]; /* name of kproc */
.
126,128c
Rendez rr; /* rendezvous for a receive buffer */
QLock rlock; /* semaphore on rc */
ushort rh; /* first receive buffer belonging to host */
ushort ri; /* first receive buffer belonging to interface */
.
124c
uchar ea[6]; /* ethernet address */
uchar ba[6]; /* broadcast address */
.
119,122c
ushort nrb; /* number of software receive buffers */
ushort ntb; /* number of software transmit buffers */
Buffer *rb; /* software receive buffers */
Buffer *tb; /* software transmit buffers */
.
113,117c
Hw *hw;
.
108c
* per ethernet
.
87,94d
80,84c
Host = 0, /* buffer owned by host */
Interface = 1, /* buffer owned by interface */
.
76,78d
72,73c
struct Buffer {
uchar owner;
uchar busy;
ushort len;
Etherpkt pkt;
.
53,70c
#define NEXT(x, l) (((x)+1)%(l))
#define OFFSETOF(t, m) ((unsigned)&(((t*)0)->m))
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
.
50,51c
Nrb = 16, /* software receive buffers */
Ntb = 4, /* software transmit buffers */
};
.
47,48c
Nctlr = 1, /* even one of these is too many */
NType = 9, /* types/interface */
.
40,45d
38a
static Hw wd8013;
.
27,37c
struct Hw {
int addr; /* interface address */
void *ram; /* interface shared memory address */
int ramsz; /* interface shared memory size */
void (*reset)(Ctlr*);
void (*init)(Ctlr*);
void (*mode)(Ctlr*, int);
void (*online)(Ctlr*, int);
void (*receive)(Ctlr*);
void (*transmit)(Ctlr*);
void (*intr)(Ureg*);
.
25c
typedef struct Ctlr Ctlr;
.
21,23c
typedef struct Hw Hw;
typedef struct Buffer Buffer;
.
1,11d
## diffname pc/devether.c 1992/0425
## diff -e /n/bootesdump/1992/0424/sys/src/9/safari/devether.c /n/bootesdump/1992/0425/sys/src/9/safari/devether.c
727a
if(p->data+len0 >= (uchar*)hw->ram+hw->ramsz){
len1 = p->data+len0 - (uchar*)hw->ram+hw->ramsz;
len0 = (uchar*)hw->ram+hw->ramsz - p->data;
}
memmove((uchar*)&rb->pkt, p->data, len0);
if(len1)
memmove((uchar*)&rb->pkt+len0,
(uchar*)hw->ram+ROUNDUP(sizeof(Etherpkt), 256),
len1);
.
726c
rb->len = len0;
.
722c
len0 = (p->len1<<8)|p->len0-4;
len1 = 0;
.
708c
int len0, len1;
.
613d
539d
512,513c
void
etherinit(void)
.
294d
249d
182c
return cp->tb[cp->th].owner == Host;
.
113a
return devattach('l', spec);
.
111,112c
Chan*
etherattach(char *spec)
.
## diffname pc/devether.c 1992/0501
## diff -e /n/bootesdump/1992/0425/sys/src/9/safari/devether.c /n/bootesdump/1992/0501/sys/src/9/safari/devether.c
829a
Ctlr *cp = &ctlr[0];
Hw *hw = cp->hw;
Buffer *bp;
uchar bnry, curr;
print("th%d ti%d rh%d ri%d\n",
cp->th, cp->ti, cp->rh, cp->ri);
bp = &cp->tb[cp->ti];
print("t: owner %d busy %d len %d\n",
bp->owner, bp->busy, bp->len);
bnry = IN(hw, r.bnry);
OUT(hw, w.cr, 0x62);
curr = IN(hw, curr);
OUT(hw, w.cr, 0x22);
print("bnry %d, curr %d\n", bnry, curr);
print("in %d out %d crcs %d oerrs %d frames %d overflows %d buffs %d wraps %d\n",
cp->inpackets, cp->outpackets, cp->crcs, cp->oerrs, cp->frames,
cp->overflows, cp->buffs, wraps);
.
817c
8*1024,
0,
HOWMANY(sizeof(Etherpkt), 256),
HOWMANY(8*1024, 256),
.
767d
759,760c
tb->len = tb->len+1 & ~1;
memmove(hw->ram, tb->pkt, tb->len);
.
754d
741,742c
if(bnry < hw->pstart)
bnry = hw->pstop-1;
.
738a
p->status = 0;
.
730,734c
memmove(rb->pkt, p->data, len);
.
726,728c
if(p->data+len >= hw->ram+hw->size){
wraps++;
len = hw->ram+hw->size - p->data;
memmove(rb->pkt+len,
&((Ring*)hw->ram)[hw->pstart],
p->data+rb->len - hw->ram+hw->size);
.
724c
rb->len = len;
.
719,720c
len = (p->len1<<8)|p->len0-4;
if(len > sizeof(Etherpkt))
print("!");
.
708,710c
next = bnry+1;
if(next >= hw->pstop)
next = hw->pstart;
.
705c
int len;
.
697,703d
690a
static ulong wraps;
.
662c
OUT(hw, curr, hw->pstart+1);
.
652,655c
OUT(hw, w.bnry, hw->pstart);
OUT(hw, w.pstart, hw->pstart);
OUT(hw, w.pstop, hw->pstop);
.
644d
642d
628a
.
621,626d
618,619d
614a
cp->rb = ialloc(sizeof(Buffer)*Nrb, 1);
cp->nrb = Nrb;
.
611,613c
cp->tb = ialloc(sizeof(Buffer)*Ntb, 1);
.
601a
typedef struct {
uchar status;
uchar next;
uchar len0;
uchar len1;
uchar data[256-4];
} Ring;
.
531,532c
*/
.
477c
etherup(cp, rb->pkt, rb->len);
.
467c
etherup(cp, bp->rptr, BLEN(bp));
.
400a
p = data;
.
399a
Type *tp;
Block *bp;
.
397,398c
Etherpkt *p;
.
395c
etherup(Ctlr *cp, void *data, int len)
.
278,282d
273c
memset(tb->pkt+len, 0, ETHERMINTU-len);
.
261c
memmove(tb->pkt+len, nbp->rptr, n);
.
253d
46c
uchar pkt[sizeof(Etherpkt)];
.
17,18c
uchar *ram; /* interface shared memory address */
int size;
uchar tstart;
uchar pstart;
uchar pstop;
.
## diffname pc/devether.c 1992/0502
## diff -e /n/bootesdump/1992/0501/sys/src/9/safari/devether.c /n/bootesdump/1992/0502/sys/src/9/safari/devether.c
823,840d
788c
cp->ti = NEXT(cp->ti, cp->ntb);
.
750d
730c
p->status = 0;
.
727c
cp->ri = NEXT(cp->ri, cp->nrb);
.
723c
(p->data+rb->len) - (hw->ram+hw->size));
.
717,719c
if((p->data+len) >= (hw->ram+hw->size)){
.
711,712d
687,688d
620a
cp->tb = ialloc(sizeof(Buffer)*Ntb, 1);
cp->ntb = Ntb;
.
617,618d
478c
cp->rh = NEXT(cp->rh, cp->nrb);
.
## diffname pc/devether.c 1992/0503
## diff -e /n/bootesdump/1992/0502/sys/src/9/safari/devether.c /n/bootesdump/1992/0503/sys/src/9/safari/devether.c
714c
len = (hw->ram+hw->size) - p->data;
.
## diffname pc/devether.c 1992/0505
## diff -e /n/bootesdump/1992/0503/sys/src/9/safari/devether.c /n/bootesdump/1992/0505/sys/src/9/safari/devether.c
708c
len = ((p->len1<<8)|p->len0)-4;
if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){
print("%d: #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next,
p->status, p->next, p->len0, p->len1);
dp8390rinit(cp);
return;
}
.
631a
static void
dp8390rinit(Ctlr *cp)
{
Hw *hw = cp->hw;
OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */
OUT(hw, w.bnry, hw->pstart);
OUT(hw, w.cr, 0x61); /* Page1|RD2|STP */
OUT(hw, curr, hw->pstart+1);
OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */
}
.
480,482d
459c
sleep(&cp->rr, isinput, cp);
.
335a
tp->ctlr = 0;
.
91c
QLock tlock; /* semaphore on th */
.
86d
## diffname pc/devether.c 1992/0506
## diff -e /n/bootesdump/1992/0505/sys/src/9/safari/devether.c /n/bootesdump/1992/0506/sys/src/9/safari/devether.c
720a
panic("receive");
.
719c
print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len,
.
## diffname pc/devether.c 1992/0625
## diff -e /n/bootesdump/1992/0506/sys/src/9/safari/devether.c /n/bootesdump/1992/0625/sys/src/9/safari/devether.c
616c
cp->tb = xspanalloc(sizeof(Buffer)*Ntb, BY2PG, 0);
.
614c
cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0);
.
504a
for(i = 0; i < NType; i++)
netadd(&cp->net, &cp->type[i], i);
.
500d
487a
cp = &ctlr[0];
.
486c
int i;
Ctlr *cp;
.
360c
netown(tp, u->p->user, 0);
.
334c
netdisown(tp);
.
99d
61a
Netprot; /* stat info */
.
## diffname pc/devether.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devether.c /n/bootesdump/1992/0711/sys/src/9/safari/devether.c
779a
USED(ur);
.
695a
USED(on);
.
372a
USED(c);
.
364a
return 0;
.
352a
USED(c);
.
170a
USED(c);
.
164a
USED(offset);
.
145a
USED(c, name, omode, perm);
.
## diffname pc/devether.c 1992/0905
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devether.c /n/bootesdump/1992/0905/sys/src/9/pc/devether.c
839,843d
826c
KZERO|0xF0000, /* shared memory address */
.
770c
bmemmove(hw->ram, tb->pkt, tb->len);
.
756a
print(">");
.
751a
OUT(hw, laar, 0x01);
print("?");
.
745c
bmemmove(rb->pkt, p->data, len);
.
741c
bmemmove(rb->pkt+len,
.
733c
break;
.
731c
OUT(hw, laar, 0x01);
.
726a
{ int ii; for(ii = 0; ii < 30; ii++) print("%2.2ux ", p->data[ii]); for(;;); }
.
725a
print("*");
OUT(hw, laar, 0xC1);
print("!");
.
706a
bmemmove(void *a, void *b, int n)
{
uchar *to, *from;
to = a;
from = b;
while(n-- > 0)
*to++ = *from++;
}
static void
.
633a
/* get configuration info from card */
ram = (IN(hw, msr) & 0x3f) << 13;
ram |= KZERO|0x80000;
hw->ram = (uchar*)ram;
print("ether ram is at %lux\n", ram);
.
629c
OUT(hw, msr, MENB|msr);
.
621a
ulong ram;
.
613a
static void
wd8013dumpregs(Hw *hw)
{
print("msr=#%2.2ux\n", IN(hw, msr));
print("icr=#%2.2ux\n", IN(hw, icr));
print("iar=#%2.2ux\n", IN(hw, iar));
print("bio=#%2.2ux\n", IN(hw, bio));
print("irr=#%2.2ux\n", IN(hw, irr));
print("laar=#%2.2ux\n", IN(hw, laar));
print("ijr=#%2.2ux\n", IN(hw, ijr));
print("gp2=#%2.2ux\n", IN(hw, gp2));
print("lan0=#%2.2ux\n", IN(hw, lan[0]));
print("lan1=#%2.2ux\n", IN(hw, lan[1]));
print("lan2=#%2.2ux\n", IN(hw, lan[2]));
print("lan3=#%2.2ux\n", IN(hw, lan[3]));
print("lan4=#%2.2ux\n", IN(hw, lan[4]));
print("lan5=#%2.2ux\n", IN(hw, lan[5]));
print("id=#%2.2ux\n", IN(hw, id));
}
.
602a
enum {
MENB = 0x40, /* memory enable */
L16EN = 0x40, /* enable 16-bit LAN operation */
M16EN = 0x80, /* enable 16-bit memory access */
};
.
## diffname pc/devether.c 1992/0906
## diff -e /n/bootesdump/1992/0905/sys/src/9/pc/devether.c /n/bootesdump/1992/0906/sys/src/9/pc/devether.c
883c
0,
.
881a
0,
0,
0,
0,
.
879,880d
822,823c
memmove(hw->ram, tb->pkt, tb->len);
.
819a
hw = cp->hw;
.
809d
802,803d
795c
memmove(rb->pkt, p->data, len);
.
791c
memmove(rb->pkt+len,
.
781d
776d
772,774d
742,752d
696c
if(hw->bt16)
OUT(hw, w.dcr, 0x49); /* 16 bit interface, DMA burst size 8 */
else
OUT(hw, w.dcr, 0x48); /* FT1|LS */
.
670c
setvec(Int0vec + hw->lvl, hw->intr);
.
668a
/* interrupt level */
hw->lvl = intrmap[((irr>>5) & 0x3) | (icr & 0x4)];
/* ram size */
if(icr&(1<<3))
hw->size = 32*1024;
else
hw->size = 8*1024;
if(hw->bt16)
hw->size <<= 1;
hw->pstop = HOWMANY(hw->size, 256);
print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8,
hw->ram, hw->size, hw->lvl);
/* enable interface RAM, set interface width */
OUT(hw, msr, MENB|msr);
if(hw->bt16)
OUT(hw, laar, laar|L16EN|M16EN);
.
667d
663,665c
/* 16 bit operation? */
hw->bt16 = icr & 0x1;
/* address of interface RAM */
ram = KZERO | ((msr & 0x3f) << 13);
if(hw->bt16)
ram |= (laar & 0x3f)<<19;
else
ram |= 0x80000;
.
659a
/* ethernet address */
.
658c
icr = IN(hw, icr);
irr = IN(hw, irr);
laar = IN(hw, laar);
.
649a
uchar icr;
uchar laar;
uchar irr;
.
642a
* get configuration parameters, enable memory
.
641a
/* mapping from configuration bits to interrupt level */
int intrmap[] =
{
9, 3, 5, 7, 10, 11, 15, 4,
};
.
17a
int bt16; /* true if a 16 bit interface */
int lvl; /* interrupt level */
.
## diffname pc/devether.c 1992/0909
## diff -e /n/bootesdump/1992/0906/sys/src/9/pc/devether.c /n/bootesdump/1992/0909/sys/src/9/pc/devether.c
916a
wd8013tweek,
0x360, /* I/O base address */
.
911c
dp8390init,
.
901,909c
static Hw wd8013 =
{
.
898a
if(hw->bt16){
OUT(hw, laar, laar);
OUT(hw, w.imr, 0x1F);
}
.
863a
if(hw->bt16){
laar = IN(hw, laar);
OUT(hw, w.imr, 0x0);
OUT(hw, laar, laar|M16EN);
}
.
862c
uchar isr, laar;
.
851a
if(hw->bt16 && (laar&M16EN)==0){
OUT(hw, laar, laar);
OUT(hw, w.imr, 0x1F);
}
.
846a
if(hw->bt16){
OUT(hw, w.imr, 0x0);
laar = IN(hw, laar);
OUT(hw, laar, laar|M16EN);
}
.
841a
uchar laar;
.
808c
p->status, p->next, p->len0, p->len1);/**/
.
730c
dp8390init(Ctlr *cp)
.
713a
wd8013tweek(Ctlr *cp)
{
uchar laar, msr;
Hw *hw = cp->hw;
Buffer *tb;
int s;
s = splhi();
msr = IN(hw, msr);
if(msr & MENB){
splx(s);
return;
}
print("TWEEK\n");
delay(500);
/* reset the hardware */
OUT(hw, msr, MENB|msr);
laar = IN(hw, laar);
if(hw->bt16)
OUT(hw, laar, laar|L16EN);
(*hw->init)(cp);
(*cp->hw->online)(cp, 1);
/* retransmit the current packet */
tb = &cp->tb[cp->ti];
if(tb->owner == Interface){
tb->busy = 0;
(*cp->hw->transmit)(cp);
}
splx(s);
}
static void
.
707c
OUT(hw, laar, laar|L16EN);
.
698a
hw->pstart = HOWMANY(sizeof(Etherpkt), 256);
.
623d
467c
tsleep(&cp->rr, isinput, cp, 1000);
(*cp->hw->tweek)(cp);
.
24,30d
15a
void (*reset)(Ctlr*);
void (*init)(Ctlr*);
void (*mode)(Ctlr*, int);
void (*online)(Ctlr*, int);
void (*receive)(Ctlr*);
void (*transmit)(Ctlr*);
void (*intr)(Ureg*);
void (*tweek)(Ctlr*);
.
## diffname pc/devether.c 1992/0913
## diff -e /n/bootesdump/1992/0909/sys/src/9/pc/devether.c /n/bootesdump/1992/0913/sys/src/9/pc/devether.c
965d
716,749d
468,469c
sleep(&cp->rr, isinput, cp);
.
23d
## diffname pc/devether.c 1992/0915
## diff -e /n/bootesdump/1992/0913/sys/src/9/pc/devether.c /n/bootesdump/1992/0915/sys/src/9/pc/devether.c
928a
wd8013tweek,
.
914,917d
874,878d
872c
uchar isr;
.
858,861d
848,852d
842d
832a
break;
.
808a
delay(100);
.
807c
/* print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len,
.
784a
wd8013tweek(Ctlr *cp)
{
uchar msr;
Hw *hw = cp->hw;
int s;
s = splhi();
msr = IN(hw, msr);
if((msr & MENB) == 0){
/* board has reset itself, start again */
delay(100);
(*hw->reset)(cp);
etherinit();
wakeup(&cp->tr);
wakeup(&cp->rr);
}
splx(s);
}
static void
.
742c
if(cp->prom)
OUT(hw, w.rcr, 0x14); /* PRO|AB */
else
OUT(hw, w.rcr, 0x04); /* AB */
.
737c
OUT(hw, w.dcr, 0x61); /* 16 bit interface */
.
707c
OUT(hw, laar, laar|L16EN|M16EN);
.
701,702c
/* print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8,
hw->ram, hw->size, hw->lvl);/**/
.
663,666c
if(cp->rb == 0){
cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0);
cp->nrb = Nrb;
cp->tb = xspanalloc(sizeof(Buffer)*Ntb, BY2PG, 0);
cp->ntb = Ntb;
}
.
467c
tsleep(&cp->rr, isinput, cp, 500);
(*cp->hw->tweek)(cp);
.
22a
void (*tweek)(Ctlr*);
.
## diffname pc/devether.c 1992/0916
## diff -e /n/bootesdump/1992/0915/sys/src/9/pc/devether.c /n/bootesdump/1992/0916/sys/src/9/pc/devether.c
741c
OUT(hw, w.dcr, 0x01); /* 16 bit interface */
.
## diffname pc/devether.c 1992/0917
## diff -e /n/bootesdump/1992/0916/sys/src/9/pc/devether.c /n/bootesdump/1992/0917/sys/src/9/pc/devether.c
919,927d
897a
/*
* we have received packets.
*/
if(isr & (0x04|0x01)){ /* Rxe|Prx - packet received */
(*cp->hw->receive)(cp);
wakeup(&cp->rr);
}
if(isr & 0x10) /* Ovw - overwrite warning */
cp->overflows++;
.
881c
OUT(hw, w.cr, Page0|RD2|TXP|STA);
.
863d
856d
842d
838d
836c
/*print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len,
.
831a
waitfordma(hw);
.
829c
OUT(hw, w.cr, Page0|RD2|STA);
.
826,827c
for(i = 0; ; i++){
OUT(hw, w.cr, Page1|RD2|STA);
.
820c
int i, len;
.
812a
/*
* hack to keep away from the card's memory while it is receiving
* a packet. This is only a problem on the NCR 3170 safari.
*
* we peek at the DMA registers and, if they are changing, wait.
*/
void
waitfordma(Hw *hw)
{
uchar a,b,c;
for(;;delay(10)){
a = IN(hw, r.clda0);
b = IN(hw, r.clda0);
if(a != b)
continue;
c = IN(hw, r.clda0);
if(c != b)
continue;
break;
}
}
.
763c
OUT(hw, w.cr, Page0|RD2|STA);
.
758c
OUT(hw, w.cr, Page1|RD2|STP);
.
741c
OUT(hw, w.dcr, (1<<0)|(3<<5)); /* 16 bit interface, 12 byte DMA burst */
.
739c
OUT(hw, w.cr, Page0|RD2|STP);
.
726c
OUT(hw, w.cr, Page0|RD2|STA);
.
724c
OUT(hw, w.cr, Page1|RD2|STP);
.
722c
OUT(hw, w.cr, Page0|RD2|STP);
.
714a
return 0;
.
711c
OUT(hw, laar, laar|L16EN|M16EN|ZeroWS16);
.
672,676d
664a
msr = IN(hw, msr);
icr = IN(hw, icr);
irr = IN(hw, irr);
laar = IN(hw, laar);
if(msr == 0xff || icr == 0xff || irr == 0xff || laar == 0xff)
return -1;
.
654c
static int
.
650a
.
610,611c
/* bit definitions for laar */
ZeroWS16 = (1<<5), /* zero wait states for 16-bit ops */
L16EN = (1<<6), /* enable 16-bit LAN operation */
M16EN = (1<<7), /* enable 16-bit memory access */
/* bit defintitions for DP8390/83C690 cr */
Page0 = (0<<6),
Page1 = (1<<6),
Page2 = (2<<6),
RD2 = (4<<3),
TXP = (1<<2),
STA = (1<<1),
STP = (1<<0),
.
603a
struct { /* Page2, read */
uchar cr;
uchar pstart;
uchar pstop;
uchar dummy1[1];
uchar tstart;
uchar next;
uchar block;
uchar enh;
uchar dummy2[4];
uchar rcon;
uchar tcon;
uchar dcon;
uchar intmask;
} r2;
struct { /* Page2, write */
uchar cr;
uchar trincrl;
uchar trincrh;
uchar dummy1[2];
uchar next;
uchar block;
uchar enh;
} w2;
.
526a
if(cp->present == 0)
return;
.
501c
if((*cp->hw->reset)(cp) < 0){
cp->present = 0;
return;
}
cp->present = 1;
.
118a
if(ctlr[0].present == 0)
error(Enodev);
.
79a
int present;
.
16c
int (*reset)(Ctlr*);
.
## diffname pc/devether.c 1992/0918
## diff -e /n/bootesdump/1992/0917/sys/src/9/pc/devether.c /n/bootesdump/1992/0918/sys/src/9/pc/devether.c
1012d
905c
if(strcmp(machtype, "NCRD.0") == 0)
waitfordma(hw);
.
754c
print("elite at %lux width %d addr %lux size %d lvl %d\n", hw->addr, hw->bt16?16:8,
.
726,729d
716c
/* ethernet address */
for(i = 0; i < sizeof(cp->ea); i++)
cp->ea[i] = IN(hw, lan[i]);
/* look for an elite ether address */
if(cp->ea[0] == 0x00 && cp->ea[1] == 0x00 && cp->ea[2] == 0xC0)
break;
}
if(hw->addr >= 0x400)
.
711,714c
/* find the ineterface */
SET(msr, icr, irr, laar);
for(hw->addr = 0x200; hw->addr < 0x400; hw->addr += 0x20){
msr = IN(hw, msr);
icr = IN(hw, icr);
irr = IN(hw, irr);
laar = IN(hw, laar);
if((msr&0x80) || (icr&0xf0) || irr == 0xff || laar == 0xff)
continue; /* nothing there */
.
705,708c
uchar msr, icr, laar, irr;
.
696d
## diffname pc/devether.c 1992/0922
## diff -e /n/bootesdump/1992/0918/sys/src/9/pc/devether.c /n/bootesdump/1992/0922/sys/src/9/pc/devether.c
557,1018d
531c
EtherCtlr *cp = &ctlr[ctlrno];
.
508c
if(cp->present == 0)
return;
.
503,506c
for(hw = etherhw; *hw; hw++){
cp->hw = *hw;
if((*cp->hw->reset)(cp) == 0){
cp->present = 1;
setvec(Int0vec + cp->hw->irq, etherintr);
break;
}
.
500d
498a
EtherCtlr *cp;
EtherHw **hw;
.
495a
static void
etherintr(Ureg *ur)
{
EtherCtlr *cp = &ctlr[0];
USED(ur);
(*cp->hw->intr)(cp);
}
.
472c
if(cp->hw->tweak)
(*cp->hw->tweak)(cp);
.
465c
if(cp->hw->init)
(*cp->hw->init)(cp);
.
459,460c
EtherCtlr *cp = arg;
EtherBuf *rb;
.
451c
EtherCtlr *cp = arg;
.
408c
EtherType *tp;
.
404c
etherup(EtherCtlr *cp, void *data, int len)
.
396c
EtherType *tp;
.
381c
EtherCtlr *cp = &ctlr[0];
.
359,360c
EtherCtlr *cp = &ctlr[0];
EtherType *tp;
.
335c
tp = (EtherType*)(q->ptr);
.
333c
EtherType *tp;
.
311,312c
EtherCtlr *cp = &ctlr[0];
EtherType *tp;
.
227c
p = (Etherpkt*)bp->rptr;
.
219c
cp = ((EtherType*)q->ptr)->ctlr;
.
210c
tp->type = strtol((char*)bp->rptr, 0, 0);
.
204c
EtherBuf *tb;
int len, n;
.
200,202c
EtherCtlr *cp;
EtherType *tp;
.
192c
EtherCtlr *cp = arg;
.
48,116d
42a
static struct EtherCtlr ctlr[Nctlr];
.
36,40c
Nctlr = 1,
.
33d
15,31c
static EtherHw *etherhw[] = {
ðer509,
ðer80x3,
0
.
10,13c
/*
* Half-arsed attempt at a general top-level
* ethernet driver. Needs work:
* handle multiple controllers
* much tidying
* set ethernet address
*/
extern EtherHw ether509;
extern EtherHw ether80x3;
.
## diffname pc/devether.c 1992/0925
## diff -e /n/bootesdump/1992/0922/sys/src/9/pc/devether.c /n/bootesdump/1992/0925/sys/src/9/pc/devether.c
373c
return cp->lbq.first || cp->rb[cp->rh].owner == Host;
.
## diffname pc/devether.c 1992/1015
## diff -e /n/bootesdump/1992/0925/sys/src/9/pc/devether.c /n/bootesdump/1992/1015/sys/src/9/pc/devether.c
363d
361a
poperror();
.
356c
if(!waserror()){
.
## diffname pc/devether.c 1992/1222
## diff -e /n/bootesdump/1992/1015/sys/src/9/pc/devether.c /n/bootesdump/1992/1222/sys/src/9/pc/devether.c
491a
return devattach('l', spec);
.
487,490c
(*ctlr->board->attach)(ctlr);
if(ctlr->kproc == 0){
sprint(ctlr->name, "ether%dkproc", ctlrno);
ctlr->kproc = 1;
kproc(ctlr->name, etherkproc, ctlr);
.
484,485c
* Enable the interface
* and start the kproc.
.
482a
Chan*
etherattach(char *spec)
{
int ctlrno = 0;
Ctlr *ctlr = softctlr[ctlrno];
if(ctlr->present == 0)
error(Enodev);
.
478,481c
ctlr->th = 0;
ctlr->ti = 0;
for(i = 0; i < ctlr->ntb; i++)
ctlr->tb[i].owner = Host;
}
.
473,476c
ctlr->rh = 0;
ctlr->ri = 0;
for(i = 0; i < ctlr->nrb; i++)
ctlr->rb[i].owner = Interface;
.
470c
if(ctlr->present == 0)
.
467c
Ctlr *ctlr = softctlr[ctlrno];
.
460c
netadd(&ctlr->net, &ctlr->type[i], i);
.
448,458c
memset(ctlr->ba, 0xFF, sizeof(ctlr->ba));
ctlr->net.name = "ether";
ctlr->net.nconv = NType;
ctlr->net.devp = &info;
ctlr->net.protop = 0;
ctlr->net.listen = 0;
ctlr->net.clone = clonecon;
ctlr->net.ninfo = 2;
ctlr->net.info[0].name = "stats";
ctlr->net.info[0].fill = statsfill;
ctlr->net.info[1].name = "type";
ctlr->net.info[1].fill = typefill;
.
446c
if(ctlr->nrb == 0)
ctlr->nrb = Nrb;
ctlr->rb = xalloc(sizeof(RingBuf)*ctlr->nrb);
if(ctlr->ntb == 0)
ctlr->ntb = Ntb;
ctlr->tb = xalloc(sizeof(RingBuf)*ctlr->ntb);
.
444a
nctlr++;
.
443c
if(ctlr->present == 0)
.
434,439c
if(softctlr[nctlr] == 0)
softctlr[nctlr] = xalloc(sizeof(Ctlr));
ctlr = softctlr[nctlr];
for(board = boards; *board; board++){
ctlr->board = *board;
if((*ctlr->board->reset)(ctlr) == 0){
ctlr->present = 1;
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(ctlr->board->irq == 2)
ctlr->board->irq = 9;
setvec(Int0vec + ctlr->board->irq, etherintr);
.
430,431c
Ctlr *ctlr;
Board **board;
.
424c
(*ctlr->board->intr)(ctlr);
.
421c
Ctlr *ctlr = softctlr[0];
.
414a
/*
* Close Types requesting it.
*/
if(ctlr->clist){
lock(&ctlr->clock);
for(type = ctlr->clist; type; type = type->clist){
type->q = 0;
wakeup(&type->cr);
}
ctlr->clist = 0;
unlock(&ctlr->clock);
}
.
408,413c
while(ctlr->rb[ctlr->rh].owner == Host){
ctlr->inpackets++;
ring = &ctlr->rb[ctlr->rh];
etherup(ctlr, (Etherpkt*)ring->pkt, ring->len);
ring->owner = Interface;
ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
.
406c
* Process any received packets.
.
399,401c
while(bp = getq(&ctlr->lbq)){
ctlr->inpackets++;
etherup(ctlr, (Etherpkt*)bp->rptr, BLEN(bp));
.
397c
* Process any internal loopback packets.
.
392,394c
tsleep(&ctlr->rr, isinput, ctlr, 500);
if(ctlr->board->watch)
(*ctlr->board->watch)(ctlr);
.
390c
.
384,387c
print("%s noted\n", ctlr->name);
/* fix
if(ctlr->board->reset)
(*ctlr->board->reset)(ctlr);
*/
ctlr->kproc = 0;
.
381a
Type *type;
.
379,380c
Ctlr *ctlr = arg;
RingBuf *ring;
.
373c
return ctlr->lbq.first || ctlr->rb[ctlr->rh].owner == Host || ctlr->clist;
.
371c
Ctlr *ctlr = arg;
.
364d
361c
PUTNEXT(type->q, bp);
.
358c
memmove(bp->rptr, pkt, len);
.
352,356c
if(waserror() == 0){
.
350c
if(type->type != -1 && pkt->d[0] != 0xFF
&& (*pkt->d != *ctlr->ea || memcmp(pkt->d, ctlr->ea, sizeof(pkt->d))))
.
347,348c
* Only a trace channel gets packets destined for other machines.
.
344a
if(t != type->type && type->type != -1)
continue;
if(type->q->next->len > Streamhi)
continue;
.
343c
if(type->q == 0)
.
341c
* Check for open, the right type, and flow control.
.
331,338c
t = (pkt->type[0]<<8)|pkt->type[1];
for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){
.
328c
Type *type;
.
326d
324c
etherup(Ctlr *ctlr, Etherpkt *pkt, int len)
.
318,319c
type = &softctlr[0]->type[STREAMID(c->qid.path)];
sprint(buf, "%d", type->type);
.
316c
Type *type;
.
306,308c
ctlr->inpackets, ctlr->outpackets, ctlr->crcs,
ctlr->overflows, ctlr->frames, ctlr->buffs, ctlr->oerrs,
ctlr->ea[0], ctlr->ea[1], ctlr->ea[2],
ctlr->ea[3], ctlr->ea[4], ctlr->ea[5]);
.
301c
Ctlr *ctlr = softctlr[0];
.
289,292c
type->inuse = 1;
netown(type, u->p->user, 0);
qunlock(type);
return type - ctlr->type;
.
283,286c
for(type = ctlr->type; type < &ctlr->type[NType]; type++){
qlock(type);
if(type->inuse || type->q){
qunlock(type);
.
279,280c
Ctlr *ctlr = softctlr[0];
Type *type;
.
255,265c
if(type->prom){
qlock(ctlr);
ctlr->prom--;
if(ctlr->prom == 0)
(*ctlr->board->mode)(ctlr, 0);
qunlock(ctlr);
}
if(type->type == -1){
qlock(ctlr);
ctlr->all--;
qunlock(ctlr);
}
/*
* Mark as closing and wait for kproc
* to close us.
*/
lock(&ctlr->clock);
type->clist = ctlr->clist;
ctlr->clist = type;
unlock(&ctlr->clock);
wakeup(&ctlr->rr);
sleep(&type->cr, isclosed, type);
type->type = 0;
type->prom = 0;
type->inuse = 0;
netdisown(type);
type->ctlr = 0;
.
253c
Type *type = (Type*)(q->ptr);
Ctlr *ctlr = type->ctlr;
.
249a
static int
isclosed(void *arg)
{
return ((Type*)arg)->q == 0;
}
.
247,248c
* The locking is to synchronize changing the ethertype with
* sending packets up the stream on interrupts.
.
245c
* Close ether line discipline.
.
234,241c
type = &ctlr->type[s->id];
RD(q)->ptr = WR(q)->ptr = type;
type->type = 0;
type->q = RD(q);
type->inuse = 1;
type->ctlr = ctlr;
.
231,232c
Ctlr *ctlr = softctlr[0];
Type *type;
.
223,226c
* Open an ether line discipline.
.
218c
qunlock(&ctlr->tlock);
.
211,215c
ctlr->outpackets++;
ring->len = len;
ring->owner = Interface;
ctlr->th = NEXT(ctlr->th, ctlr->ntb);
(*ctlr->board->transmit)(ctlr);
.
208,209c
* Set up the transmit buffer and
* start the transmission.
.
203c
memset(ring->pkt+len, 0, ETHERMINTU-len);
.
200c
* Pad the packet (zero the pad).
.
193,194c
}
.
191c
memmove(ring->pkt+len, nbp->rptr, n);
.
186c
* Copy message into buffer.
.
183c
ring = &ctlr->tb[ctlr->th];
.
181c
sleep(&ctlr->tr, isobuf, ctlr);
.
178c
* Wait till we get an output buffer.
.
173c
qunlock(&ctlr->tlock);
.
170c
qlock(&ctlr->tlock);
.
168c
* Only one transmitter at a time.
.
162,163c
putq(&ctlr->lbq, nbp);
wakeup(&ctlr->rr);
.
157c
if(memcmp(ctlr->ba, pkt->d, sizeof(ctlr->ba)) == 0 || ctlr->prom || ctlr->all){
.
151,153c
if(bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){
putq(&ctlr->lbq, bp);
wakeup(&ctlr->rr);
.
147,149c
pkt = (Etherpkt*)bp->rptr;
memmove(pkt->s, ctlr->ea, sizeof(ctlr->ea));
if(memcmp(ctlr->ea, pkt->d, sizeof(ctlr->ea)) == 0){
.
142c
* Give packet a local address, return upstream if destined for
.
139,140d
134a
qunlock(ctlr);
.
132,133c
type->prom = 1;
ctlr->prom++;
if(ctlr->prom == 1)
(*ctlr->board->mode)(ctlr, 1);
.
128,130c
qlock(ctlr);
if(streamparse("connect", bp)){
if(type->type == -1)
ctlr->all--;
type->type = strtol((char*)bp->rptr, 0, 0);
if(type->type == -1)
ctlr->all++;
}
.
126a
type = q->ptr;
ctlr = type->ctlr;
.
120,123c
Ctlr *ctlr;
Type *type;
Etherpkt *pkt;
RingBuf *ring;
.
114c
return ctlr->tb[ctlr->th].owner == Host;
.
112c
Ctlr *ctlr = arg;
.
106c
netwstat(c, dp, &softctlr[0]->net);
.
86c
return netread(c, a, n, offset, &softctlr[0]->net);
.
66c
return netopen(c, omode, &softctlr[0]->net);
.
60c
netstat(c, dp, &softctlr[0]->net);
.
54c
return netwalk(c, name, &softctlr[0]->net);
.
38,45d
32,36d
30c
static struct Ctlr *softctlr[NCtlr];
static int nctlr;
.
27c
NCtlr = 1,
.
22d
20c
/*
* The ordering here is important for those boards
* using the DP8390 (WD8003, 3COM503 and NE2000) as
* attempting to determine if a board is a NE2000
* cannot be done passively, so it must be last to
* prevent scrogging one of the others.
*/
static Board *boards[] = {
ðer8003,
ðer503,
ðer2000,
.
17,18c
extern Board ether8003;
extern Board ether503;
extern Board ether2000;
extern Board ether509;
.
9a
#include "ether.h"
.
## diffname pc/devether.c 1993/0212
## diff -e /n/bootesdump/1992/1222/sys/src/9/pc/devether.c /n/bootesdump/1993/0212/sys/src/9/pc/devether.c
554c
(*ctlr->card.attach)(ctlr);
.
493a
print("ether%d: %s: I/O addr %lux width %d addr %lux size %d irq %d:",
nctlr, ctlr->card.id,
ctlr->card.io, ctlr->card.bit16 ? 16: 8, ctlr->card.ramstart,
ctlr->card.ramstop-ctlr->card.ramstart, ctlr->card.irq);
for(i = 0; i < sizeof(ctlr->ea); i++)
print(" %2.2ux", ctlr->ea[i]);
print("\n");
.
486,488c
if(ctlr->card.irq == 2)
ctlr->card.irq = 9;
setvec(Int0vec + ctlr->card.irq, etherintr);
.
476,478c
for(card = cards; *card; card++){
memset(ctlr, 0, sizeof(Ctlr));
ctlr->card = **card;
if((*ctlr->card.reset)(ctlr) == 0){
.
472a
if(nctlr >= NCtlr)
return;
.
470c
Card **card;
.
463c
(*ctlr->card.intr)(ctlr);
.
419,420c
if(ctlr->card.watch)
(*ctlr->card.watch)(ctlr);
.
410,411c
if(ctlr->card.reset)
(*ctlr->card.reset)(ctlr);
.
270c
(*ctlr->card.mode)(ctlr, 0);
.
227a
freeb(bp);
.
226d
224c
(*ctlr->card.transmit)(ctlr);
splx(s);
.
220c
s = splhi();
.
191c
if(isobuf(ctlr) == 0){
tsleep(&ctlr->tr, isobuf, ctlr, 3*1000);
if(isobuf(ctlr) == 0){
qunlock(&ctlr->tlock);
freeb(bp);
poperror();
return;
}
}
.
183a
freeb(bp);
.
182d
144c
(*ctlr->card.mode)(ctlr, 1);
.
126c
int len, n, s;
.
44c
/*static */struct Ctlr *softctlr[NCtlr];
.
31c
static Card *cards[] = {
.
25,27c
* The ordering here is important for those cards
* using the DP8390 (WD8003, 3Com503 and NE2000) as
* attempting to determine if a card is a NE2000
.
19,22c
extern Card ether8003, ether503, ether2000;
extern Card ether509;
.
17a
* need a ctl file passed down to card drivers
* so we can set options.
.
## diffname pc/devether.c 1993/1113
## diff -e /n/bootesdump/1993/0212/sys/src/9/pc/devether.c /n/fornaxdump/1993/1113/sys/src/brazil/pc/devether.c
581c
if(ctlr)
free(ctlr);
.
517,579c
ether[ctlrno] = ctlr;
ctlr = 0;
}
.
515c
netifinit(ctlr, "ether", Ntypes, 32*1024);
ctlr->alen = Eaddrlen;
memmove(ctlr->addr, ctlr->ea, sizeof(ctlr->ea));
memmove(ctlr->bcast, etherbcast, sizeof(etherbcast));
.
507,513c
print("ether%d: %s: port %lux irq %d addr %lux size %d:",
ctlrno, ctlr->type, ctlr->port, ctlr->irq, ctlr->mem, ctlr->size);
for(i = 0; i < sizeof(ctlr->ea); i++)
print(" %2.2ux", ctlr->ea[i]);
print("\n");
.
498,505c
if(ctlr->irq == 2)
ctlr->irq = 9;
if((irqmask & (1<<ctlr->irq)) == 0){
setvec(Int0vec+ctlr->irq, etherintr);
irqmask |= 1<<ctlr->irq;
}
.
496a
* If there are multiple controllers on the same IRQ, only
* call setvec() for one of them, etherintr() will scan through
* all the controllers looking for those at the IRQ it was
* called with. This is a hack, see the comments in etherintr().
.
482,491c
irqmask = 0;
for(ctlr = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ctlr == 0)
ctlr = malloc(sizeof(Ether));
memset(ctlr, 0, sizeof(Ether));
if(isaconfig("ether", ctlrno, ctlr) == 0)
continue;
for(n = 0; cards[n].type; n++){
if(strcmp(cards[n].type, ctlr->type))
continue;
if((*cards[n].reset)(ctlr))
break;
.
478,480c
Ether *ctlr;
int i, n, ctlrno;
ulong irqmask;
.
362,474d
357,359c
if(ncard == NCARD)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
.
354,355c
static int ncard;
.
342,352c
void
addethercard(char *t, int (*r)(Ether*))
.
336,340c
#define NCARD 32
static struct {
char *type;
int (*reset)(Ether*);
} cards[NCARD+1];
.
332,333d
292,330c
irq = ur->trap-Int0vec;
for(i = 0; i < MaxEther; i++){
if(ether[i] && ether[i]->irq == irq)
(*ether[i]->interrupt)(ether[i]);
.
289,290c
* Call all ethernet interrupt routines on this IRQ.
* Might be better if setvec() took an argument which
* was passed down to the interrupt routine when
* called. This would let us easily distinguish multiple
* controllers. A hack by any other name...
.
275,287d
272,273c
int i, irq;
.
270c
etherintr(Ureg *ur)
.
257,268d
240,254c
return n;
.
238c
qunlock(&ctlr->tlock);
.
186,236c
n = (*ctlr->write)(ctlr, buf, n);
.
183d
129,179d
119,127c
if(NETTYPE(c->qid.path) != Ndataqid)
return netifwrite(ctlr, c, buf, n);
.
116,117c
USED(offset);
if(n > ETHERMAXTU)
error(Ebadarg);
ctlr = ether[c->dev];
.
114c
Ether *ctlr;
.
111,112c
long
etherwrite(Chan *c, void *buf, long n, ulong offset)
.
108c
netifwstat(ether[c->dev], c, dp);
.
102d
91,97d
88c
return netifread(ether[c->dev], c, buf, n, offset);
.
86c
etherread(Chan *c, void *buf, long n, ulong offset)
.
81,82c
netifclose(ether[c->dev], c);
.
75d
68c
return netifopen(ether[c->dev], c, omode);
.
62c
netifstat(ether[c->dev], c, dp);
.
56c
return netifwalk(ether[c->dev], c, name);
.
44,45c
c = devattach('l', spec);
c->dev = ctlrno;
if(ether[ctlrno]->attach)
(*ether[ctlrno]->attach)(ether[ctlrno]);
return c;
}
.
40,42c
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if(ether[ctlrno] == 0)
error(Enodev);
.
36,38c
Chan*
etherattach(char *spec)
{
ulong ctlrno;
char *p;
Chan *c;
.
24,34c
void
etherinit(void)
{
}
.
12,22c
static Ether *ether[MaxEther];
.
10c
#include "etherif.h"
.
8c
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
.
6d
## diffname pc/devether.c 1993/1119
## diff -e /n/fornaxdump/1993/1113/sys/src/brazil/pc/devether.c /n/fornaxdump/1993/1119/sys/src/brazil/pc/devether.c
152c
if(ncard == MaxEther)
.
145c
} cards[MaxEther+1];
.
141d
## diffname pc/devether.c 1993/1120
## diff -e /n/fornaxdump/1993/1119/sys/src/brazil/pc/devether.c /n/fornaxdump/1993/1120/sys/src/brazil/pc/devether.c
206a
break;
.
109a
if(etherwloop(ctlr, buf, n))
return n;
.
96a
void
etherrloop(Ether *ctlr, Etherpkt *pkt, long len)
{
ushort type;
Netfile *f, **fp, **ep;
type = (pkt->type[0]<<8)|pkt->type[1];
ep = &ctlr->f[Ntypes];
for(fp = ctlr->f; fp < ep; fp++){
f = *fp;
if(f && (f->type == type || f->type < 0)){
switch(qproduce(f->in, pkt->d, len)){
case -1:
print("etherrloop overflow\n");
break;
case -2:
print("etherrloop memory\n");
break;
}
}
}
}
static int
etherwloop(Ether *ctlr, Etherpkt *pkt, long len)
{
int s, different;
different = memcmp(pkt->d, pkt->s, sizeof(pkt->s));
if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)))
return 0;
s = splhi();
etherrloop(ctlr, pkt, len);
splx(s);
return !different;
}
.
## diffname pc/devether.c 1993/1124
## diff -e /n/fornaxdump/1993/1120/sys/src/brazil/pc/devether.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devether.c
233c
setvec(Int0vec+ctlr->irq, ctlr->interrupt, ctlr);
.
225,228d
165,183d
## diffname pc/devether.c 1994/0202
## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0202/sys/src/brazil/pc/devether.c
106,118c
if((f = *fp) && (f->type == type || f->type < 0))
qproduce(f->in, pkt->d, len);
.
## diffname pc/devether.c 1994/0629
## diff -e /n/fornaxdump/1994/0202/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0629/sys/src/brazil/pc/devether.c
117c
if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d))
&& ctlr->prom==0 && ctlr->all==0)
.
## diffname pc/devether.c 1994/0702
## diff -e /n/fornaxdump/1994/0629/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0702/sys/src/brazil/pc/devether.c
124c
return tome;
.
122c
etherrloop(ctlr, pkt, len, tome||bcast);
.
116,118c
tome = memcmp(pkt->d, ctlr->ea, sizeof(pkt->d)) == 0;
bcast = memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) == 0;
if(!tome && !bcast && ctlr->prom==0 && ctlr->all==0)
.
114c
int s, tome, bcast;
.
106c
if((f = *fp) && ((tome && f->type==type) || f->type < 0))
.
98c
etherrloop(Ether *ctlr, Etherpkt *pkt, long len, int tome)
.
## diffname pc/devether.c 1994/0713
## diff -e /n/fornaxdump/1994/0702/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0713/sys/src/brazil/pc/devether.c
200,203c
setvec(Int0vec+ctlr->irq, ctlr->interrupt, ctlr);
.
180d
178d
## diffname pc/devether.c 1995/0108
## diff -e /n/fornaxdump/1994/0713/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devether.c
153a
}
long
etherbwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
.
84a
Block*
etherbread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
## diffname pc/devether.c 1995/0504
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0504/sys/src/brazil/pc/devether.c
212,213c
print("ether%d: %s: port 0x%lux irq %d",
ctlrno, ctlr->type, ctlr->port, ctlr->irq);
if(ctlr->mem)
print(" addr 0x%lux", ctlr->mem);
if(ctlr->mem)
print(" size %d", ctlr->size);
print(": ea");
.
## diffname pc/devether.c 1995/0505
## diff -e /n/fornaxdump/1995/0504/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0505/sys/src/brazil/pc/devether.c
218c
print(":");
.
216c
if(ctlr->size)
.
## diffname pc/devether.c 1995/0511
## diff -e /n/fornaxdump/1995/0505/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0511/sys/src/brazil/pc/devether.c
217c
print(" size 0x%lux", ctlr->size);
.
215c
print(" addr 0x%lux", ctlr->mem & ~KZERO);
.
## diffname pc/devether.c 1995/0513
## diff -e /n/fornaxdump/1995/0511/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0513/sys/src/brazil/pc/devether.c
220c
print(" %2.2uX", ctlr->ea[i]);
.
217c
print(" size 0x%luX", ctlr->size);
.
215c
print(" addr 0x%luX", ctlr->mem & ~KZERO);
.
212c
print("ether%d: %s: port 0x%luX irq %d",
.
## diffname pc/devether.c 1995/0711
## diff -e /n/fornaxdump/1995/0513/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0711/sys/src/brazil/pc/devether.c
113c
if(qproduce(f->in, pkt->d, len) < 0)
ctlr->soverflows++;
.
## diffname pc/devether.c 1995/0713
## diff -e /n/fornaxdump/1995/0711/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0713/sys/src/brazil/pc/devether.c
112,114c
if((f = *fp) && ((tome && f->type==type) || f->type < 0)){
if(f->type > -2){
if(qproduce(f->in, pkt->d, len) < 0)
ctlr->soverflows++;
} else {
if(qwindow(f->in) <= 0)
continue;
if(len > 60)
len = 60;
bp = iallocb(len);
if(bp == 0)
continue;
memmove(bp->wp, pkt->d, len);
i = TK2MS(m->ticks);
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
}
.
106a
int i;
.
105a
Block *bp;
.
## diffname pc/devether.c 1995/0721
## diff -e /n/fornaxdump/1995/0713/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0721/sys/src/brazil/pc/devether.c
153c
return different == 0;
.
150c
etherrloop(ctlr, pkt, len);
.
144,146c
different = memcmp(pkt->d, ctlr->ea, sizeof(pkt->d));
if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)))
.
142c
int s, different;
.
114c
if((f = *fp) && (f->type == type || f->type < 0)){
.
104c
etherrloop(Ether *ctlr, Etherpkt *pkt, long len)
.
## diffname pc/devether.c 1995/0725
## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0725/sys/src/brazil/pc/devether.c
248a
ctlr->ctlrno = ctlrno;
.
## diffname pc/devether.c 1995/0726
## diff -e /n/fornaxdump/1995/0725/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devether.c
70d
68c
ethercreate(Chan*, char*, int, ulong)
.
## diffname pc/devether.c 1995/0731
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0731/sys/src/brazil/pc/devether.c
144c
if(!ctlr->prom && different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)))
.
126a
bp->wp[58] = len>>8;
bp->wp[59] = len;
.
## diffname pc/devether.c 1995/0801
## diff -e /n/fornaxdump/1995/0731/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0801/sys/src/brazil/pc/devether.c
125c
memmove(bp->wp, pkt->d, n);
.
120,122c
if(len > 64)
n = 64;
else
n = len;
bp = iallocb(n);
.
107c
int i, n;
.
## diffname pc/devether.c 1995/0822
## diff -e /n/fornaxdump/1995/0801/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0822/sys/src/brazil/pc/devether.c
181a
poperror();
.
180d
163d
159c
etherwrite(Chan *c, void *buf, long n, ulong)
.
148c
if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)))
.
93d
91c
etherremove(Chan*)
.
## diffname pc/devether.c 1995/1004
## diff -e /n/fornaxdump/1995/0822/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/1004/sys/src/brazil/pc/devether.c
147c
if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) && ctlr->prom == 0)
.
## diffname pc/devether.c 1996/0601
## diff -e /n/fornaxdump/1995/1004/sys/src/brazil/pc/devether.c /n/fornaxdump/1996/0601/sys/src/brazil/pc/devether.c
250d
245c
if(ctlr->mbps == 100)
netifinit(ctlr, "ether", Ntypes, 100*1024);
else
netifinit(ctlr, "ether", Ntypes, 32*1024);
.
242c
print("%2.2uX", ctlr->ea[i]);
.
240c
print(": ");
.
234,235c
print("ether%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, ctlr->type, ctlr->mbps, ctlr->port, ctlr->irq);
.
216a
ctlr->ctlrno = ctlrno;
ctlr->mbps = 10;
.
## diffname pc/devether.c 1996/0607
## diff -e /n/fornaxdump/1996/0601/sys/src/brazil/pc/devether.c /n/fornaxdump/1996/0607/sys/src/brazil/pc/devether.c
248c
netifinit(ctlr, "ether", Ntypes, 128*1024);
.
236c
print("ether#%d: %s: %dMbps port 0x%luX irq %d",
.
81c
Ether *ctlr;
ctlr = ether[c->dev];
if((c->qid.path & CHDIR) == 0 && ctlr->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(c->qid.path) == Nifstatqid)
return (*ctlr->ifstat)(ctlr, buf, n, offset);
else if(NETTYPE(c->qid.path) == Nstatqid)
(*ctlr->ifstat)(ctlr, buf, 0, offset);
}
return netifread(ctlr, c, buf, n, offset);
.
## diffname pc/devether.c 1997/0327
## diff -e /n/fornaxdump/1996/0607/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devether.c
276a
Dev etherdevtab = {
etherreset,
devinit,
etherattach,
devclone,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
etherremove,
etherwstat,
};
.
274,275c
if(ether)
free(ether);
.
269,270c
etherxx[ctlrno] = ether;
ether = 0;
.
261,267c
snprint(name, sizeof(name), "ether%d", ctlrno);
if(ether->mbps == 100){
netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, 1, 0, 0);
}
else{
netifinit(ether, name, Ntypes, 32*1024);
if(ether->oq == 0)
ether->oq = qopen(64*1024, 1, 0, 0);
}
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
.
250,259c
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
if(ether->mem)
i += sprint(buf+i, " addr 0x%luX", ether->mem & ~KZERO);
if(ether->size)
i += sprint(buf+i, " size 0x%luX", ether->size);
i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
.
246,248c
if(ether->irq == 2)
ether->irq = 9;
intrenable(VectorPIC+ether->irq, ether->interrupt, ether, ether->tbdf);
.
238c
for(i = 0; i < ether->nopt; i++){
if(strncmp(ether->opt[i], "ea=", 3))
continue;
if(parseether(ether->ea, ðer->opt[i][3]) == -1)
memset(ether->ea, 0, Eaddrlen);
}
if(cards[n].reset(ether))
.
236c
if(cistrcmp(cards[n].type, ether->type))
.
227,233c
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN;
ether->mbps = 10;
if(isaconfig("ether", ctlrno, ether) == 0)
.
225a
char name[NAMELEN], buf[128];
.
224c
Ether *ether;
.
221c
int
parseether(uchar *to, char *from)
{
char nip[4];
char *p;
int i;
p = from;
for(i = 0; i < 6; i++){
if(*p == 0)
return -1;
nip[0] = *p++;
if(*p == 0)
return -1;
nip[1] = *p++;
nip[2] = 0;
to[i] = strtoul(nip, 0, 16);
if(*p == ':')
p++;
}
return 0;
}
static void
.
210c
addethercard(char* t, int (*r)(Ether*))
.
205c
char* type;
.
201c
Ether *ether;
long n;
n = BLEN(bp);
if(n > ETHERMAXTU){
freeb(bp);
error(Ebadarg);
}
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid){
n = netifwrite(ether, chan, bp->rp, n);
freeb(bp);
return n;
}
return etheroq(ether, bp);
.
198,199c
static long
etherbwrite(Chan* chan, Block* bp, ulong)
.
195c
return etheroq(ether, bp);
.
193a
bp->wp += n;
.
191,192c
memmove(bp->rp, buf, n);
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
.
188c
freeb(bp);
.
183,186c
bp = allocb(n);
.
180,181c
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid)
return netifwrite(ether, chan, buf, n);
.
178d
174c
Ether *ether;
Block *bp;
.
171,172c
static long
etherwrite(Chan* chan, void* buf, long n, ulong)
.
168c
if(!loopback){
qbwrite(ether->oq, bp);
ether->transmit(ether);
}
return len;
.
164,166c
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = !memcmp(pkt->d, ether->ea, sizeof(pkt->d));
if(loopback || !memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) || ether->prom){
s = splhi();
etheriq(ether, bp, loopback);
splx(s);
}
.
160,162c
ether->outpackets++;
.
158c
int len, loopback, s;
Etherpkt *pkt;
.
156c
etheroq(Ether* ether, Block* bp)
.
152a
if(fx){
qpass(fx->in, bp);
return 0;
}
if(freebp){
freeb(bp);
return 0;
}
return bp;
.
150a
else
etherrtrace(f, pkt, len);
.
136,149c
ether->soverflows++;
.
128,134c
if(freebp && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
qpass(f->in, xbp);
}
.
124,125c
fx = 0;
ep = ðer->f[Ntypes];
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (freebp != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
.
122a
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
.
120,121c
int len;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
.
118a
if(qwindow(f->in) <= 0)
return;
if(len > 64)
n = 64;
else
n = len;
bp = iallocb(n);
if(bp == 0)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(m->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int freebp)
{
Etherpkt *pkt;
.
117a
int i, n;
.
115,116c
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
.
112c
netifwstat(etherxx[chan->dev], chan, dp);
.
109,110c
static void
etherwstat(Chan* chan, char* dp)
.
104c
static void
.
101c
return netifbread(etherxx[chan->dev], chan, n, offset);
.
98,99c
static Block*
etherbread(Chan* chan, long n, ulong offset)
.
95c
return netifread(ether, chan, buf, n, offset);
.
89,92c
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
.
83,84c
ether = etherxx[chan->dev];
if((chan->qid.path & CHDIR) == 0 && ether->ifstat){
.
81c
Ether *ether;
.
78,79c
static long
etherread(Chan* chan, void* buf, long n, ulong offset)
.
75c
netifclose(etherxx[chan->dev], chan);
.
72,73c
static void
etherclose(Chan* chan)
.
61,67c
static void
.
58c
return netifopen(etherxx[chan->dev], chan, omode);
.
55,56c
static Chan*
etheropen(Chan* chan, int omode)
.
52c
netifstat(etherxx[chan->dev], chan, dp);
.
49,50c
static void
etherstat(Chan* chan, char* dp)
.
46c
return netifwalk(etherxx[chan->dev], chan, name);
.
43,44c
static int
etherwalk(Chan* chan, char* name)
.
36,40c
chan = devattach('l', spec);
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
return chan;
.
33c
if(etherxx[ctlrno] == 0)
.
25c
Chan *chan;
.
21c
etherattach(char* spec)
.
15,19d
13c
static Ether *etherxx[MaxEther];
.
## diffname pc/devether.c 1997/0404
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0404/sys/src/brazil/pc/devether.c
147a
/* check for valid multcast addresses */
if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(freebp){
freeb(bp);
bp = 0;
}
return bp;
}
}
.
## diffname pc/devether.c 1997/0408
## diff -e /n/emeliedump/1997/0404/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devether.c
388a
'l',
"ether",
.
## diffname pc/devether.c 1997/0415
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0415/sys/src/brazil/pc/devether.c
387a
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1);
if((crc^b) & 1)
crc ^= POLY;
b >>= 1;
}
}
return crc;
}
.
## diffname pc/devether.c 1997/0418
## diff -e /n/emeliedump/1997/0415/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0418/sys/src/brazil/pc/devether.c
401,403c
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
.
## diffname pc/devether.c 1997/0808
## diff -e /n/emeliedump/1997/0418/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0808/sys/src/brazil/pc/devether.c
212,213c
loopback = (memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0);
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
.
149c
if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
.
120c
i = TK2MS(MACHP(0)->ticks);
.
## diffname pc/devether.c 1997/1101
## diff -e /n/emeliedump/1997/0808/sys/src/brazil/pc/devether.c /n/emeliedump/1997/1101/sys/src/brazil/pc/devether.c
355c
i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
.
271a
if(n > ETHERMAXTU){
freeb(bp);
error(Ebadarg);
}
if(n < ETHERMINTU){
freeb(bp);
error(Etoosmall);
}
.
260,264d
239a
if(n > ETHERMAXTU)
error(Etoobig);
if(n < ETHERMINTU)
error(Etoosmall);
.
233,235d
## diffname pc/devether.c 1997/1105
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/devether.c /n/emeliedump/1997/1105/sys/src/brazil/pc/devether.c
380a
if(ether->oq == 0)
panic("etherreset %s", name);
.
## diffname pc/devether.c 1998/0218
## diff -e /n/emeliedump/1997/1105/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0218/sys/src/brazil/pc/devether.c
379c
ether->oq = qopen(65*1024, 1, 0, 0);
.
377c
netifinit(ether, name, Ntypes, 65*1024);
.
## diffname pc/devether.c 1998/0319
## diff -e /n/emeliedump/1998/0218/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devether.c
228c
etherwrite(Chan* chan, void* buf, long n, vlong)
.
70a
ulong offset = off;
.
68c
etherread(Chan* chan, void* buf, long n, vlong off)
.
## diffname pc/devether.c 1998/0825
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0825/sys/src/brazil/pc/devether.c
359c
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",
.
## diffname pc/devether.c 1998/0910
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0910/sys/src/brazil/pc/devether.c
357c
intrenable(ether->irq, ether->interrupt, ether, ether->tbdf);
.
## diffname pc/devether.c 1998/1013
## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/devether.c /n/emeliedump/1998/1013/sys/src/brazil/pc/devether.c
185c
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
.
## diffname pc/devether.c 1999/0316
## diff -e /n/emeliedump/1998/1013/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0316/sys/src/brazil/pc/devether.c
214a
mine = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
if(mine)
.
210a
* To enable bridging to work, only packets that were originated
* by this interface are feedback
.
200c
int len, loopback, s, mine;
.
167c
if((f = *fp) && (f->type == type || f->type < 0) && (forme || multi || f->prom)){
.
159a
// is it for me?
forme = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
.
150c
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
.
148a
multi = pkt->d[0] & 1;
.
137c
int len, multi, forme;
.
## diffname pc/devether.c 1999/0402
## diff -e /n/emeliedump/1999/0316/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0402/sys/src/brazil/pc/devether.c
216c
* by this interface are fed back.
.
## diffname pc/devether.c 1999/0625
## diff -e /n/emeliedump/1999/0402/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0625/sys/src/brazil/pc/devether.c
232c
} else
freeb(bp);
.
225c
etheriq(ether, bp, 0);
.
220,222c
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
.
204c
int len, loopback, s;
.
193c
if(fromwire){
.
171,173c
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear bridged packets */
if(f->bridge && !fromwire && !fromme)
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
.
166c
* If the packet is not to be used subsequently (fromwire != 0),
.
161,162c
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
.
153c
if(fromwire){
.
137c
int len, multi, tome, fromme;
.
133c
etheriq(Ether* ether, Block* bp, int fromwire)
.
## diffname pc/devether.c 1999/0819
## diff -e /n/emeliedump/1999/0625/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0819/sys/src/brazil/pc/devether.c
385d
371c
snprint(name, sizeof(name), "ether%d", ctlrno);
intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
.
## diffname pc/devether.c 2000/0713
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/devether.c /n/emeliedump/2000/0713/sys/src/9/pc/devether.c
117,118c
bp = iallocb(64);
if(bp == nil)
.
113,114c
if(len > 58)
n = 58;
.
## diffname pc/devether.c 2000/0817
## diff -e /n/emeliedump/2000/0713/sys/src/9/pc/devether.c /n/emeliedump/2000/0817/sys/src/9/pc/devether.c
372c
/* If ether->irq is less than 0, it is a hack to indicate no interrupt
* used for the seocnd logical ethernet for the wavelan card
*/
if(ether->irq >= 0)
intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
.
282a
ether = etherxx[chan->dev];
.
279c
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
.
277d
264d
258,261d
251a
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
.
249,250c
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
.
246a
int nn;
.
## diffname pc/devether.c 2000/0921
## diff -e /n/emeliedump/2000/0817/sys/src/9/pc/devether.c /n/emeliedump/2000/0921/sys/src/9/pc/devether.c
399c
if(ether->mbps >= 100){
.
357a
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
.
296c
if(n < ether->minmtu){
.
294c
error(Etoobig);
.
292c
if(n > ether->maxmtu){
.
286a
poperror();
.
263c
if(n < ether->minmtu)
.
261c
if(n > ether->maxmtu)
.
## diffname pc/devether.c 2000/1110
## diff -e /n/emeliedump/2000/0921/sys/src/9/pc/devether.c /n/emeliedump/2000/1110/sys/src/9/pc/devether.c
385c
* used for the second logical ethernet for the wavelan card
.
## diffname pc/devether.c 2001/0203
## diff -e /n/emeliedump/2000/1110/sys/src/9/pc/devether.c /n/emeliedump/2001/0203/sys/src/9/pc/devether.c
124,128c
bp->wp[60] = ts>>56;
bp->wp[61] = ts>>48;
bp->wp[62] = ts>>40;
bp->wp[63] = ts>>32;
bp->wp[64] = ts>>24;
bp->wp[65] = ts>>16;
bp->wp[66] = ts>>8;
bp->wp[67] = ts;
bp->wp += 68;
.
121c
ts = fastticks(nil);
.
117c
bp = iallocb(68);
.
109a
uvlong ts;
.
108c
int n;
.
## diffname pc/devether.c 2001/0504
## diff -e /n/emeliedump/2001/0203/sys/src/9/pc/devether.c /n/emeliedump/2001/0504/sys/src/9/pc/devether.c
273a
poperror();
.
271a
if(waserror()){
freeb(bp);
nexterror();
}
.
251c
Block *volatile bp;
.
## diffname pc/devether.c 2001/0527
## diff -e /n/emeliedump/2001/0504/sys/src/9/pc/devether.c /n/emeliedump/2001/0527/sys/src/9/pc/devether.c
464d
360c
char name[32], buf[128];
.
251c
Block *bp;
.
125,133c
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
.
122c
i = TK2MS(MACHP(0)->ticks);
.
118c
bp = iallocb(64);
.
110d
108c
int i, n;
.
102c
return netifwstat(etherxx[chan->dev], chan, dp, n);
.
99,100c
static int
etherwstat(Chan* chan, uchar* dp, int n)
.
74c
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
.
47c
return netifstat(etherxx[chan->dev], chan, dp, n);
.
44,45c
static int
etherstat(Chan* chan, uchar* dp, int n)
.
41c
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
.
38,39c
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
.
## diffname pc/devether.c 2001/0622
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devether.c /n/emeliedump/2001/0622/sys/src/9/pc/devether.c
356a
print("Searching for ethernet devices\n");
.
## diffname pc/devether.c 2001/0626
## diff -e /n/emeliedump/2001/0622/sys/src/9/pc/devether.c /n/emeliedump/2001/0626/sys/src/9/pc/devether.c
357d
## diffname pc/devether.c 2001/1130
## diff -e /n/emeliedump/2001/0626/sys/src/9/pc/devether.c /n/emeliedump/2001/1130/sys/src/9/pc/devether.c
392c
if(ether->irq > 0)
.
389,390c
/*
* If ether->irq is 0, it is a hack to indicate no interrupt
* used by ethersink.
.
## diffname pc/devether.c 2001/1204
## diff -e /n/emeliedump/2001/1130/sys/src/9/pc/devether.c /n/emeliedump/2001/1204/sys/src/9/pc/devether.c
469c
devremove,
.
94,98d
## diffname pc/devether.c 2002/0109
## diff -e /n/emeliedump/2001/1204/sys/src/9/pc/devether.c /n/emeliedump/2002/0109/sys/src/9/pc/devether.c
453a
ethershutdown,
.
427a
static void
ethershutdown(void)
{
Ether *ether;
int i;
for(i = 0; i < MaxEther; i++){
ether = etherxx[i];
if(ether == nil)
continue;
if(ether->shutdown == nil) {
print("#l%d: no shutdown fuction\n", i);
continue;
}
(*ether->shutdown)(ether);
}
}
.
## diffname pc/devether.c 2002/0314
## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devether.c /n/emeliedump/2002/0314/sys/src/9/pc/devether.c
179c
if(qpass(f->in, xbp) < 0)
ether->soverflows++;
.
## diffname pc/devether.c 2002/0403
## diff -e /n/emeliedump/2002/0314/sys/src/9/pc/devether.c /n/emeliedump/2002/0403/sys/src/9/pc/devether.c
425,426d
423a
if((ether = etherprobe(cardno, ctlrno)) == nil){
cardno++;
continue;
}
etherxx[ctlrno] = ether;
ctlrno++;
.
420,422c
if(ether->mbps >= 100){
netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, 1, 0, 0);
}
else{
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(65*1024, 1, 0, 0);
}
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
return ether;
}
static void
etherreset(void)
{
Ether *ether;
int cardno, ctlrno;
for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if((ether = etherprobe(-1, ctlrno)) == nil)
continue;
etherxx[ctlrno] = ether;
}
cardno = ctlrno = 0;
while(cards[cardno].type != nil && ctlrno < MaxEther){
if(etherxx[ctlrno] != nil){
ctlrno++;
continue;
.
404,418c
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",
ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
if(ether->mem)
i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
if(ether->size)
i += sprint(buf+i, " size 0x%luX", ether->size);
i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
.
392,402c
/*
* If ether->irq is 0, it is a hack to indicate no interrupt
* used by ethersink.
*/
if(ether->irq > 0)
intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
.
385,390c
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(ether->irq == 2)
ether->irq = 9;
snprint(name, sizeof(name), "ether%d", ctlrno);
.
376,383c
if(cardno >= MaxEther || cards[cardno].type == nil){
free(ether);
return nil;
}
if(cards[cardno].reset(ether) < 0){
free(ether);
return nil;
}
.
372,374c
}
break;
}
}
.
370c
if(parseether(ether->ea, ðer->opt[i][3]))
.
353,365c
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(cardno < 0){
if(isaconfig("ether", ctlrno, ether) == 0){
free(ether);
return nil;
}
for(cardno = 0; cards[cardno].type; cardno++){
if(cistrcmp(cards[cardno].type, ether->type))
.
350,351c
char buf[128], name[32];
.
348a
int i;
.
346,347c
static Ether*
etherprobe(int cardno, int ctlrno)
.
## diffname pc/devether.c 2002/0502
## diff -e /n/emeliedump/2002/0403/sys/src/9/pc/devether.c /n/emeliedump/2002/0502/sys/src/9/pc/devether.c
446a
if(getconf("*noetherprobe"))
return;
.
## diffname pc/devether.c 2002/0703
## diff -e /n/emeliedump/2002/0502/sys/src/9/pc/devether.c /n/emeliedump/2002/0703/sys/src/9/pc/devether.c
331c
for(i = 0; i < Eaddrlen; i++){
.
## diffname pc/devether.c 2002/0710
## diff -e /n/emeliedump/2002/0703/sys/src/9/pc/devether.c /n/emeliedump/2002/0710/sys/src/9/pc/devether.c
424c
ether->oq = qopen(128*1024, 1, 0, 0);
.
422c
netifinit(ether, name, Ntypes, 128*1024);
.
417c
netifinit(ether, name, Ntypes, 512*1024);
.
## diffname pc/devether.c 2002/0711
## diff -e /n/emeliedump/2002/0710/sys/src/9/pc/devether.c /n/emeliedump/2002/0711/sys/src/9/pc/devether.c
424c
ether->oq = qopen(128*1024, Qmsg, 0, 0);
.
419c
ether->oq = qopen(256*1024, Qmsg, 0, 0);
.
## diffname pc/devether.c 2002/0712
## diff -e /n/emeliedump/2002/0711/sys/src/9/pc/devether.c /n/emeliedump/2002/0712/sys/src/9/pc/devether.c
417c
netifinit(ether, name, Ntypes, 256*1024);
.
250c
if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
qnoblock(ether->oq, 1);
return n;
}
.
## diffname pc/devether.c 2002/1123
## diff -e /n/emeliedump/2002/0712/sys/src/9/pc/devether.c /n/emeliedump/2002/1123/sys/src/9/pc/devether.c
231c
if(ether->transmit != nil)
ether->transmit(ether);
.
## diffname pc/devether.c 2003/0301
## diff -e /n/emeliedump/2002/1123/sys/src/9/pc/devether.c /n/emeliedump/2003/0301/sys/src/9/pc/devether.c
408c
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
.
405c
if(ether->irq >= 0)
.
402c
* If ether->irq is <0, it is a hack to indicate no interrupt
.
## diffname pc/devether.c 2003/0312
## diff -e /n/emeliedump/2003/0301/sys/src/9/pc/devether.c /n/emeliedump/2003/0312/sys/src/9/pc/devether.c
254a
free(cb);
.
251,252c
cb = parsecmd(buf, n);
if(strcmp(cb->f[0], "nonblocking") == 0){
if(cb->nf <= 1)
onoff = 1;
else
onoff = atoi(cb->f[1]);
qnoblock(ether->oq, onoff);
free(cb);
.
244c
int nn, onoff;
Cmdbuf *cb;
.
|