## diffname carrera/devether.c 1993/0903
## diff -e /dev/null /n/fornaxdump/1993/0903/sys/src/brazil/carrera/devether.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
/*
* ethernet address stored in prom
*/
typedef struct
{
ulong pad0;
ulong byte;
uvlong pad1;
} Etheraddr;
#define EPCENETPROM EPCSWIN(Etheraddr, 0x2000)
/*
* SEEQ/EDLC device registers
*/
typedef struct
{
struct
{
ulong pad;
ulong byte;
} addr[6]; /* address */
ulong pad;
ulong tcmd; /* transmit command */
ulong pad0;
ulong rcmd; /* receive command */
ulong pad1[5];
ulong tbaselo; /* low bits of xmit buff base */
ulong pad2;
ulong tbasehi; /* high bits of xmit buff base */
ulong pad3;
ulong tlimit; /* xmit buffer limit */
ulong pad4;
ulong tindex; /* xmit buffer limit */
ulong pad5;
ulong ttop; /* xmit buffer top */
ulong pad6;
ulong tbptr; /* xmit buffer byte pointer */
ulong pad7;
ulong tstat; /* transmit status */
ulong pad8;
ulong titimer; /* transmit interrupt timer */
ulong pad9[5];
ulong rbaselo; /* rcv buffer base addr */
ulong pad10;
ulong rbasehi; /* high bits of rcv buffer base addr */
ulong pad11;
ulong rlimit; /* rcv buffer limit */
ulong pad12;
ulong rindex; /* rcv buffer index */
ulong pad13;
ulong rtop; /* rcv buffer top */
ulong pad14;
ulong rbptr; /* rcv buffer byte pointer */
ulong pad15;
ulong rstat; /* rcv status */
ulong pad16;
ulong ritimer; /* rcv interrupt timer */
} EDLCdev;
#define EPCEDLC EPCSWIN(EDLCdev, 0xa200)
/*
* LXT901 device registers
*/
typedef struct {
ulong pad0;
ulong stat; /* some LXT901 pins + SQE ctrl (r/w) */
ulong pad1;
ulong collisions; /* total collisions -- 16 bits (r) */
uchar pad2[7];
uchar loopback; /* loopback enable -- 1 bit (w) */
ulong pad3;
ulong edlcself; /* EDLC self rcv enable -- 1 bit (w) */
} LXTdev;
#define EPCLXT EPCSWIN(LXTdev, 0x8000)
enum
{
/* transmit command bits */
Tigood= 1<<3, /* interrupt on good xmit */
Ti16tries= 1<<2, /* interrupt on 16 retries */
Ticoll= 1<<1, /* interrupt on collision */
Tiunder= 1<<0, /* interrupt on underflow */
/* receive command bits */
Rmulti= 3<<6, /* recv station/broadcast/multicast */
Rnormal= 2<<6, /* recv station/broadcast */
Rall= 1<<6, /* receive all frames */
Rigood= 1<<5, /* interrupt on good frames */
Riend= 1<<4, /* interrupt on end of frame */
Rishort= 1<<3, /* interrupt on short frame */
Ridrbl= 1<<2, /* interrupt on dribble error */
Ricrc= 1<<1, /* interrupt on CRC error */
Riover= 1<<0, /* interrupt on overflow error */
Renab= (Rigood|Riend|Rishort|Ridrbl|Ricrc),
/* receive status bits */
Rgood= 1<<5, /* good frame */
Rend= 1<<4, /* end of frame */
Rshort= 1<<3, /* short frame */
Rdrbl= 1<<2, /* dribble error */
Rcrc= 1<<1, /* CRC error */
Rover= 1<<0, /* overflow error */
/* interrupt level for ether */
ILenet= 0x60,
/* manifest constants */
logNxmt= 8,
Nxmt= 1<<logNxmt,
Tmask= Nxmt-1,
logNrcv= 8,
Nrcv= 1<<logNrcv,
Rmask= Nrcv-1,
Ntypes= 8,
/* hold off values */
ho800us= 0x100, /* 800 us hold-off */
ho1500us= 0x080, /* 1500 us hold-off */
ho2500us= 0x000, /* 2500 us hold-off */
};
#define RSUCC(i) (((i)+1)&Rmask)
#define RPREV(i) (((i)-1)&Rmask)
#define TSUCC(i) (((i)+1)&Tmask)
#define TPREV(i) (((i)-1)&Tmask)
/*
* a hardware packet buffer
*/
typedef struct
{
uchar tlen[2]; /* transmit length */
uchar d[Eaddrlen];
uchar s[Eaddrlen];
uchar type[2];
uchar data[1500];
uchar pad1[2043-ETHERMAXTU];
uchar stat;
uchar rlen[2]; /* receive length */
} Pbuf;
struct Ether
{
uchar ea[6];
int rindex; /* first rcv buffer owned by hardware */
int rtop; /* first rcv buffer owned by software */
int tindex; /* first rcv buffer owned by hardware */
int ttop; /* first rcv buffer owned by software */
Pbuf *tbuf; /* transmit buffers */
Pbuf *rbuf; /* receive buffers */
QLock tlock; /* lock for grabbing transmitter queue */
Rendez tr; /* wait here for free xmit buffer */
Netif;
} ether;
/*
* The dance in this code is very dangerous to change. Do not
* change the order of any of the labeled steps. This should run splhi.
*/
static void
etherhardreset(void)
{
EDLCdev *edlc = EPCEDLC;
LXTdev *lxt = EPCLXT;
EPCmisc *misc = EPCMISC;
ulong x, i;
/* step 1: isolate from ether */
lxt->loopback = 1;
x = lxt->loopback; USED(x);
/* step 2: shut off transmitter */
while(edlc->ttop != edlc->tindex)
edlc->ttop = edlc->tindex;
ether.tindex = ether.ttop = edlc->ttop;
/* step 3: reset edlc */
misc->set = 0x200;
x = misc->reset; USED(x);
delay(1); /* 1ms but 10micros is enough */
misc->clr = 0x200;
x = misc->reset; USED(x);
/* step 4: enable transmitter interrupts */
edlc->tcmd = Tigood | Ti16tries | Ticoll | Tiunder;
/* step 5: set address from prom, start receiver,
* and reset receive pointer
*/
for(i = 0; i < Netheraddr; i++)
edlc->addr[i].byte = EPCENETPROM[5-i].byte & 0xff;
if(ether.prom)
edlc->rcmd = Renab | Rall;
else
edlc->rcmd = Renab | Rnormal;
ether.rindex = edlc->rindex;
ether.rtop = edlc->rtop = RPREV(ether.rindex);
/* step 6: attach to ether */
lxt->loopback = 0;
}
void
etherintr(void)
{
EDLCdev *edlc = EPCEDLC;
EPCmisc *misc = EPCMISC;
Netfile *f, **fp;
Pbuf *p;
int x;
ushort t;
while(edlc->rindex != ether.rindex){
p = ðer.rbuf[ether.rindex];
/* statistics */
if(p->stat & (Rshort|Rdrbl|Rcrc|Rover)){
if(p->stat & (Rdrbl|Rcrc))
ether.crcs++;
if(p->stat & Rover)
ether.overflows++;
if(p->stat & Rshort)
ether.frames++;
}
if(p->stat & Rgood){
x = (p->rlen[0]<<8) | p->rlen[1];
t = (p->type[0]<<8) | p->type[1];
for(fp = ether.f; fp < ðer.f[Ntypes]; fp++){
f = *fp;
if(f == 0)
continue;
if(f->type == t || f->type < 0)
qproduce(f->in, p->d, x);
}
}
/*
* because of a chip bug, we have to reset if rtop
* and rindex get too close.
*/
x = edlc->rtop - edlc->rindex;
if(x < 0)
x += Nrcv;
if(x <= 64){
etherhardreset();
} else {
edlc->rtop = ether.rindex;
ether.rindex = RSUCC(ether.rindex);
}
}
/* reenable holdoff and EPC interrupts */
misc->clr = 0x10;
misc->set = 0x10;
epcenable(EIenet);
}
/*
* turn promiscuous mode on/off
*/
static void
promiscuous(void *arg, int on)
{
EDLCdev *edlc = EPCEDLC;
USED(arg);
if(on)
edlc->rcmd = Renab | Rall;
else
edlc->rcmd = Renab | Rnormal;
}
void
etherreset(void)
{
EDLCdev *edlc = EPCEDLC;
EPCmisc *misc = EPCMISC;
ulong x, i;
/* setup xmit buffers (pointers on chip assume KSEG0) */
edlc->tlimit = logNxmt - 1;
ether.tbuf = xspanalloc(Nxmt*sizeof(Pbuf), 512*1024, 0);
x = ((ulong)ether.tbuf) & ~KSEGM;
edlc->tbasehi = 0;
edlc->tbaselo = x;
/* setup rcv buffers (pointers on chip assume KSEG0) */
edlc->rlimit = logNrcv - 1;
ether.rbuf = xspanalloc(Nrcv*sizeof(Pbuf), 512*1024, 0);
x = ((ulong)ether.rbuf) & ~KSEGM;
edlc->rbasehi = 0;
edlc->rbaselo = x;
/* install interrupt handler */
sethandler(ILenet, etherintr);
setleveldest(ILenet, 0, &EPCINTR->enetdest);
epcenable(EIenet);
/* turn off receive */
edlc->rcmd = 0;
/* stop transmitter, we can't change tindex so we change ttop */
while(edlc->ttop != edlc->tindex)
edlc->ttop = edlc->tindex;
ether.tindex = ether.ttop = edlc->ttop;
/* enable transmitter interrupts */
edlc->tcmd = Tigood | Ti16tries | Ticoll | Tiunder;
/* set address from prom, start receiver, and reset receive pointer */
for(i = 0; i < Netheraddr; i++){
ether.ea[i] = EPCENETPROM[5-i].byte & 0xff;
edlc->addr[i].byte = ether.ea[i];
}
ether.rindex = edlc->rindex;
ether.rtop = edlc->rtop = RPREV(ether.rindex);
edlc->rcmd = Renab | Rnormal;
/* set hold off timer value, and enable its interrupts (pulse) */
misc->set = ho800us;
misc->clr = (~ho800us)&0x180;
misc->clr = 0x10;
misc->set = 0x10;
/* general network interface structure */
netifinit(ðer, "ether", Ntypes, 32*1024);
ether.alen = 6;
memmove(ether.addr, ether.ea, 6);
memmove(ether.bcast, etherbcast, 6);
ether.promiscuous = promiscuous;
ether.arg = ðer;
}
void
etherinit(void)
{
}
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 netifwalk(ðer, c, name);
}
Chan*
etheropen(Chan *c, int omode)
{
return netifopen(ðer, c, omode);
}
void
ethercreate(Chan *c, char *name, int omode, ulong perm)
{
USED(c, name, omode, perm);
}
void
etherclose(Chan *c)
{
netifclose(ðer, c);
}
long
etherread(Chan *c, void *buf, long n, ulong offset)
{
return netifread(ðer, c, buf, n, offset);
}
static int
isoutbuf(void *arg)
{
EDLCdev *edlc = arg;
USED(arg);
ether.tindex = edlc->tindex;
return TSUCC(ether.ttop) != ether.tindex;
}
long
etherwrite(Chan *c, void *buf, long n, ulong offset)
{
Pbuf *p;
EDLCdev *edlc = EPCEDLC;
USED(offset);
if(n > ETHERMAXTU)
error(Ebadarg);
/* etherif.c handles structure */
if(NETTYPE(c->qid.path) != Ndataqid)
return netifwrite(ðer, c, buf, n);
/* we handle data */
qlock(ðer.tlock);
tsleep(ðer.tr, isoutbuf, edlc, 10000);
if(!isoutbuf(edlc)){
print("ether transmitter jammed\n");
} else {
p = ðer.tbuf[ether.ttop];
memmove(p->d, buf, n);
if(n < 60) {
memset(p->d+n, 0, 60-n);
n = 60;
}
memmove(p->s, ether.ea, sizeof(ether.ea));
p->tlen[0] = n;
p->tlen[1] = n>>8;
ether.ttop = TSUCC(ether.ttop);
edlc->ttop = ether.ttop;
}
qunlock(ðer.tlock);
return n;
}
void
etherremove(Chan *c)
{
USED(c);
}
void
etherstat(Chan *c, char *dp)
{
netifstat(ðer, c, dp);
}
void
etherwstat(Chan *c, char *dp)
{
netifwstat(ðer, c, dp);
}
.
## diffname carrera/devether.c 1993/0904
## diff -e /n/fornaxdump/1993/0903/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0904/sys/src/brazil/carrera/devether.c
461c
netifwstat(ether[0], c, dp);
.
455c
netifstat(ether[0], c, dp);
.
442c
qunlock(&ctlr->tlock);
.
436,440c
memmove(p->s, ctlr->ea, sizeof(ctlr->ea));
txpkt = &ctlr->tda[ctlr->th];
txpkt->size = n;
txpkt->fsize = n;
txpkt->link |= Eol;
txpkt->status = Interface;
ctlr->tda[PREV(ctlr->th, Ntb)].link &= ~Eol;
ctlr->th = NEXT(ctlr->th, Ntb);
WR(cr, Txp);
.
429,430c
}
else {
p =(Etherpkt*)ctlr->tb[ctlr->th];
.
425,427c
qlock(&ctlr->tlock);
tsleep(&ctlr->tr, isoutbuf, ctlr, 10000);
if(!isoutbuf(ctlr)){
.
422c
return netifwrite(ether[0], c, buf, n);
.
412,413c
Etherpkt *p;
TXpkt *txpkt;
Ether *ctlr = ether[0];
.
404,406c
return ctlr->tda[ctlr->th].status == Host;
.
402c
Ether *ctlr = arg;
.
396c
return netifread(ether[0], c, buf, n, offset);
.
390c
netifclose(ether[0], c);
.
378c
return netifopen(ether[0], c, omode);
.
372c
return netifwalk(ether[0], c, name);
.
344,349c
netifinit(ether[0], "ether", Ntypes, 32*1024);
ether[0]->alen = 6;
memmove(ether[0]->addr, ether[0]->ea, 6);
memmove(ether[0]->bcast, ctlr->ba, 6);
ether[0]->promiscuous = promiscuous;
ether[0]->arg = ether[0];
.
337,341c
memset(ctlr->ba, 0xFF, sizeof(ctlr->ba));
.
335c
reset(ctlr);
.
332,333c
ctlr = ether[0];
.
297,330c
/*
* Map the device registers and allocate
* memory for the receive/transmit rings.
* Set the physical ethernet address and
* prime the interrupt handler.
*/
if(ether[0] == 0) {
ether[0] = xspanalloc(sizeof(Ether), BY2PG, 64*1024);
/* memmove(ether[0]->ea, eeprom.ea, sizeof(ether[0]->ea)); */
.
293,295c
Ether *ctlr;
.
287c
WR(rcr, reg&~Pro);
.
285c
WR(rcr, reg|Pro);
.
283a
reg = RD(rcr);
.
281c
ushort reg;
.
269,272d
267a
if(status & Br){
print("sonic: bus retry occurred\n");
status &= ~Br;
}
if(status & AllIntr)
print("sonic %ux\n", status);
.
259,266c
if(status & Lcd)
status &= ~Lcd;
/*
* Warnings that something is afoot.
*/
if(status & Hbl){
print("sonic: cd heartbeat lost\n");
status &= ~Hbl;
.
256,257c
* We get a 'load CAM done' interrupt
* after initialisation. Ignore it.
.
254a
noinput:
.
253a
status &= ~(Pktrx|Rde);
.
252a
else
if(rxpkt->status & Fae)
ctlr->frames++;
else
if(rxpkt->status & Crc)
ctlr->crcs++;
else
ctlr->buffs++;
/*
* Finished with this packet, it becomes the
* last free packet in the ring, so give it Eol,
* and take the Eol bit off the previous packet.
* Move the ring index on.
*/
rxpkt->link |= Eol;
rxpkt->owner = Interface;
ctlr->rda[PREV(ctlr->rh, Nrb)].link &= ~Eol;
ctlr->rh = NEXT(ctlr->rh, Nrb);
rxpkt = &ctlr->rda[ctlr->rh];
.
243,251c
if((status & (Pktrx|Rde)) == 0)
goto noinput;
/*
* A packet arrived or we ran out of descriptors.
*/
status &= ~(Pktrx|Rde);
rxpkt = &ctlr->rda[ctlr->rh];
while(rxpkt->owner == Host){
ctlr->inpackets++;
/*
* If the packet was received OK, pass it up,
* otherwise log the error.
* SONIC gives us the CRC in the packet, so
* remember to subtract it from the length.
*/
if(rxpkt->status & Prx) {
x = (rxpkt->count & 0xFFFF)-4;
p = (Etherpkt*)ctlr->rb[ctlr->rh];
t = (p->type[0]<<8) | p->type[1];
for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++){
f = *fp;
if(f == 0)
continue;
if(f->type == t || f->type < 0)
qproduce(f->in, p->d, x);
}
.
234,241c
for(;;) {
status = RD(isr) & AllIntr;
if(status == 0)
break;
WR(isr, status);
/*
* Transmission complete, for good or bad.
*/
if(status & (Txdn|Txer)){
txpkt = &ctlr->tda[ctlr->ti];
while(txpkt->status != Host){
if(txpkt->status == Interface){
WR(ctda, LS16(txpkt));
WR(cr, Txp);
break;
}
if((txpkt->status & Ptx) == 0)
ctlr->oerrs++;
txpkt->status = Host;
ctlr->ti = NEXT(ctlr->ti, Ntb);
txpkt = &ctlr->tda[ctlr->ti];
}
status &= ~(Txdn|Txer);
.
231,232c
ctlr = ether[0];
.
229a
Ether *ctlr;
ulong status;
TXpkt *txpkt;
RXpkt *rxpkt;
Etherpkt *p;
Netfile *f, **fp;
.
224,227d
217,218c
iprint("wait rra\n");
WR(cr, Rrra);
while(RD(cr) & Rrra)
;
iprint("rra done\n");
/*
* Initialise the transmit descriptor area (TDA).
* Each descriptor describes one packet, we make no use
* of having the packet in multiple fragments.
* The descriptors are linked in a ring; overlapping transmission
* with buffer queueing will cause some packets to
* go out back-to-back.
*
* Load the SONIC registers to describe the TDA.
*/
for(i = 0; i < Ntb; i++){
ctlr->tda[i].status = Host;
ctlr->tda[i].config = 0;
ctlr->tda[i].count = 1;
ctlr->tda[i].ptr0 = LS16(ctlr->tb[i]);
ctlr->tda[i].ptr1 = MS16(ctlr->tb[i]);
ctlr->tda[i].link = LS16(&ctlr->tda[NEXT(i, Ntb)]);
}
WR(ctda, LS16(&ctlr->tda[0]));
WR(utda, MS16(&ctlr->tda[0]));
/*
* Initialise the software receive and transmit
* ring indexes.
*/
ctlr->rh = 0;
ctlr->ri = 0;
ctlr->th = 0;
ctlr->ti = 0;
/*
* Initialise the CAM descriptor area (CDA).
* We only have one ethernet address to load,
* broadcast is defined by the SONIC as all 1s.
*
* Load the SONIC registers to describe the CDA.
* Tell the SONIC to load the CDA and wait for it
* to complete.
*/
ctlr->cda.cep = 0;
ctlr->cda.cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0];
ctlr->cda.cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2];
ctlr->cda.cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4];
ctlr->cda.ce = 1;
WR(cdp, LS16(&ctlr->cda));
WR(cdc, 1);
WR(cr, Lcam);
while(RD(cr) & Lcam)
;
/*
* Configure the receive control, transmit control
* and interrupt-mask registers.
* The SONIC is now initialised, but not enabled.
*/
WR(rcr, Err|Rnt|Brd);
WR(tcr, 0);
WR(imr, AllIntr);
iprint("reset done\n");
.
214,215c
/*
* Load the SONIC registers to describe the RRA.
* We set the rwp to beyond the area delimited by rsa and
* rea. This means that since we've already allocated all
* the buffers, we'll never get a 'receive buffer area
* exhausted' interrupt and the rrp will just wrap round.
* Tell the SONIC to load the RRA and wait for
* it to complete.
*/
WR(urra, MS16(&ctlr->rra[0]));
WR(rsa, LS16(&ctlr->rra[0]));
WR(rrp, LS16(&ctlr->rra[0]));
WR(rea, LS16(&ctlr->rra[Nrb]));
WR(rwp, LS16(&ctlr->rra[Nrb+1]));
.
209,212c
WR(crda, LS16(ctlr->rda));
WR(urda, MS16(ctlr->rda));
WR(eobc, sizeof(ctlr->rb[0])/2 - 2);
.
206,207c
ctlr->rda[Nrb-1].link |= Eol;
.
203,204c
/*
* Terminate the receive descriptor ring
* and load the SONIC registers to describe the RDA.
.
200,201c
ctlr->rra[i].ptr0 = ctlr->rda[i].ptr0 = LS16(ctlr->rb[i]);
ctlr->rra[i].ptr1 = ctlr->rda[i].ptr1 = MS16(ctlr->rb[i]);
}
.
193,198c
ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]);
ctlr->rda[i].owner = Interface;
.
188,191c
/*
* Initialise the receive resource area (RRA) and
* the receive descriptor area (RDA).
*
* We use a simple scheme of one packet per descriptor.
* We achieve this by setting the EOBC register to be
* 2 (16-bit words) less than the buffer size;
* thus the size of the receive buffers must be sizeof(Etherpkt)+4.
* Set up the receive descriptors as a ring.
*/
for(i = 0; i < Nrb; i++){
ctlr->rra[i].wc0 = (sizeof(ctlr->rb[0])/2) & 0xFFFF;
ctlr->rra[i].wc1 = ((sizeof(ctlr->rb[0])/2)>>16) & 0xFFFF;
.
184,186c
iprint("reset sonic dcr=#%lux mydcr=#%lux\n", RD(dcr), Sterm|Dw32|Lbr|Efm|W14tf);
/*
* Reset the SONIC, toggle the Rst bit.
* Set the data config register for synchronous termination
* and 32-bit data-path width.
* Clear the descriptor and buffer area.
*/
WR(cr, Rst);
WR(dcr, Sterm|Dw32|Lbr|Efm|W14tf);
WR(cr, 0);
.
179,182c
int i;
.
177c
reset(Ether *ctlr)
.
172,175c
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define LS16(addr) (PADDR(addr) & 0xFFFF)
#define MS16(addr) ((PADDR(addr)>>16) & 0xFFFF)
.
170a
Ether *ether[Nether];
.
169c
};
.
167a
int rh; /* first receive buffer owned by host */
int ri; /* first receive buffer owned by interface */
RXrsc rra[Nrb]; /* receive resource area */
RXpkt rda[Nrb]; /* receive descriptor area */
uchar rb[Nrb][sizeof(Etherpkt)+4]; /* receive buffer area */
TXpkt tda[Ntb]; /* transmit descriptor area */
uchar tb[Ntb][sizeof(Etherpkt)]; /* transmit buffer area */
Cam cda; /* CAM descriptor area */
.
166a
int th; /* first transmit buffer owned by host */
int ti; /* first transmit buffer owned by interface */
.
162,164d
157,160c
Sonic *sonic; /* SONIC registers */
.
155a
uchar ba[6];
.
152a
/*
* Transmit Packet Descriptor.
*/
typedef struct
{
uchar pad0[2];
ushort status; /* transmit status */
uchar pad1[2];
ushort config; /* */
uchar pad2[2];
ushort size; /* byte count of entire packet */
uchar pad3[2];
ushort count; /* fragment count */
uchar pad4[2];
ushort ptr0; /* packet pointer */
uchar pad5[2];
ushort ptr1;
uchar pad6[2];
ushort fsize; /* fragment size */
uchar pad7[2];
ushort link; /* descriptor link */
} TXpkt;
enum{
Eol = 1, /* end of list bit in descriptor link */
Host = 0, /* descriptor belongs to host */
Interface = -1, /* descriptor belongs to interface */
Nether = 1,
Ntypes= 8,
};
/*
* CAM Descriptor
*/
typedef struct {
uchar pad0[2];
ushort cep; /* CAM entry pointer */
uchar pad1[2];
ushort cap0; /* CAM address port 0 */
uchar pad2[2];
ushort cap1; /* CAM address port 1 */
uchar pad3[2];
ushort cap2; /* CAM address port 2 */
uchar pad4[2];
ushort ce; /* CAM enable */
} Cam;
typedef struct Ether Ether;
.
143,151c
uchar pad0[2];
ushort status; /* receive status */
uchar pad1[2];
ushort count; /* packet byte count */
uchar pad2[2];
ushort ptr0; /* buffer pointer */
uchar pad3[2];
ushort ptr1;
uchar pad4[2];
ushort seqno; /* */
uchar pad5[2];
ushort link; /* descriptor link and EOL */
uchar pad6[2];
ushort owner; /* in use */
} RXpkt;
.
139c
* Receive Packet Descriptor.
.
133,136c
/*
* Receive Resource Descriptor.
*/
typedef struct
{
uchar pad0[2];
ushort ptr0; /* buffer pointer in the RRA */
uchar pad1[2];
ushort ptr1;
uchar pad2[2];
ushort wc0; /* buffer word count in the RRA */
uchar pad3[2];
ushort wc1;
} RXrsc;
.
118,130c
Rfo = 0x0001, /* receive fifo overrun */
MpTally = 0x0002, /* missed packet tally counter rollover */
FaeTally= 0x0004, /* frame alignment error tally counter rollover */
CrcTally= 0x0008, /* Crc tally counter rollover */
Rbae = 0x0010, /* receive buffer area exceeded */
Rbe = 0x0020, /* receive buffer exhausted */
Rde = 0x0040, /* receive descriptors exhausted */
Txer = 0x0100, /* transmit error */
Txdn = 0x0200, /* transmission done */
Pktrx = 0x0400, /* packet received */
Pint = 0x0800, /* programmed interrupt */
Lcd = 0x1000, /* load CAM done */
Hbl = 0x2000, /* CD heartbeat lost */
Br = 0x4000, /* bus retry occurred */
AllIntr = 0x7771, /* all of the above */
.
115,116c
Ptx = 0x0001, /* packet transmitted ok */
Pintr = 0x8000, /* programmable interrupt */
.
107,113c
Prx = 0x0001, /* packet received ok */
Fae = 0x0004, /* frame alignment error */
Crc = 0x0008, /* CRC error */
Lpkt = 0x0040, /* last packet in rba */
Bc = 0x0080, /* broadcast packet received */
Pro = 0x1000, /* physical promiscuous mode */
Brd = 0x2000, /* accept broadcast packets */
Rnt = 0x4000, /* accept runt packets */
Err = 0x8000, /* accept packets with errors */
.
105c
Dw32 = 0x0020, /* data width select */
Sterm = 0x0400, /* synchronous termination */
Lbr = 0x4000, /* latched bus retry */
Efm = 0x0010, /* Empty fill mode */
W14tf = 0x0003, /* 14 Word transmit fifo */
.
94,103c
enum
{
Htx = 0x0001, /* halt transmission */
Txp = 0x0002, /* transmit packet(s) */
Rxdis = 0x0004, /* receiver disable */
Rxen = 0x0008, /* receiver enable */
Stp = 0x0010, /* stop timer */
St = 0x0020, /* start timer */
Rst = 0x0080, /* software reset */
Rrra = 0x0100, /* read RRA */
Lcam = 0x0200, /* load CAM */
.
88,92c
Nrb = 16, /* receive buffers */
Ntb = 8, /* transmit buffers */
};
.
71,84c
typedef struct
{
ulong cr; /* command */
ulong dcr; /* data configuration */
ulong rcr; /* receive control */
ulong tcr; /* transmit control */
ulong imr; /* interrupt mask */
ulong isr; /* interrupt status */
ulong utda; /* upper transmit descriptor address */
ulong ctda; /* current transmit descriptor address */
ulong pad0x08[5]; /* */
ulong urda; /* upper receive descriptor address */
ulong crda; /* current receive descriptor address */
ulong pad0x0F[4]; /* */
ulong eobc; /* end of buffer word count */
ulong urra; /* upper receive resource address */
ulong rsa; /* resource start address */
ulong rea; /* resource end address */
ulong rrp; /* resource read pointer */
ulong rwp; /* resource write pointer */
ulong pad0x19[8]; /* */
ulong cep; /* CAM entry pointer */
ulong cap2; /* CAM address port 2 */
ulong cap1; /* CAM address port 1 */
ulong cap0; /* CAM address port 0 */
ulong ce; /* CAM enable */
ulong cdp; /* CAM descriptor pointer */
ulong cdc; /* CAM descriptor count */
ulong sr; /* silicon revision */
ulong wt0; /* watchdog timer 0 */
ulong wt1; /* watchdog timer 1 */
ulong rsc; /* receive sequence counter */
ulong crct; /* CRC error tally */
ulong faet; /* FAE tally */
ulong mpt; /* missed packet tally */
ulong mdt; /* maximum deferral timer */
ulong pad0x30[15]; /* */
ulong dcr2; /* data configuration 2 */
} Sonic;
.
32,69c
#define RD(rn) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4))
#define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = v)
.
21,30c
#define SONICADDR ((Sonic*)Sonicbase)
.
13,19d
11c
* National Semiconductor DP83932
* Systems-Oriented Network Interface Controller
* (SONIC)
.
## diffname carrera/devether.c 1993/0905
## diff -e /n/fornaxdump/1993/0904/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0905/sys/src/brazil/carrera/devether.c
629a
iprint("tx done %d\n", n);
.
609d
607c
if(!isoutbuf(ctlr))
.
596a
iprint("ether tx\n");
.
540a
static int enable;
if(enable == 0) {
enable = 1;
WR(cr, Rxen);
}
.
533a
enab(void)
{
WR(cr, Rxen);
}
void
.
516c
if(PADDR(ether[0])+sizeof(Ether) > Ntranslation*BY2PG)
panic("sonic: 16M io map");
enetaddr(ether[0]->ea);
.
482c
iprint("sonic #%lux\n", status);
.
477c
iprint("sonic: bus retry occurred\n");
.
473c
iprint("sonic: cd heartbeat lost\n");
.
414a
pxp(rxpkt);
.
413d
381a
print("s %lux\n", status);
.
364a
pxp(RXpkt *rxpkt)
{
print("%lux %lux\n", rxpkt->pad0[0], rxpkt->pad0[1]);
print("status %lux\n", rxpkt->status); /* receive status */
print("%lux %lux\n", rxpkt->pad1[0], rxpkt->pad1[1]);
print("count %lux\n", rxpkt->count); /* packet byte count */
print("%lux %lux\n", rxpkt->pad2[0], rxpkt->pad2[1]);
print("ptr0 %lux\n", rxpkt->ptr0); /* buffer pointer */
print("%lux %lux\n", rxpkt->pad3[0], rxpkt->pad3[1]);
print("ptr1 %lux\n", rxpkt->ptr1);
print("%lux %lux\n", rxpkt->pad4[0], rxpkt->pad4[1]);
print("seqno %lux\n", rxpkt->seqno); /* */
print("%lux %lux\n", rxpkt->pad5[0], rxpkt->pad5[1]);
print("link %lux\n", rxpkt->link); /* descriptor link and EOL */
print("%lux %lux\n", rxpkt->pad6[0], rxpkt->pad6[1]);
print("owner %lux\n", rxpkt->owner); /* in use */
}
void
.
361d
298d
294d
277a
iprint("eobc #%lux\n", RD(eobc));
.
268a
ISquad(ctlr->rra);
ISquad(ctlr->rda);
ISquad(ctlr->rb);
.
258c
for(i = 0; i < Nrb; i++) {
.
245c
WR(dcr, 0x2423); /* 5-19 Carrera manual */
iprint("eobc #%lux\n", RD(eobc));
.
237d
186c
typedef struct
{
.
180c
Ntypes = 8,
.
19a
#define ISquad(s) if((ulong)s & 0x7) panic("sonoc: Quad alignment");
.
## diffname carrera/devether.c 1993/0906
## diff -e /n/fornaxdump/1993/0905/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0906/sys/src/brazil/carrera/devether.c
694a
}
#define swiz(s) (s<<24)|((s>>8)&0xff00)|((s<<8)&0xff0000)|(s>>24)
void
sonicswap(void *a, int n)
{
ulong *p, t0, t1;
n = ((n+8)/8)*8;
p = a;
while(n) {
t0 = p[0];
t1 = p[1];
p[0] = swiz(t1);
p[1] = swiz(t0);
p += 2;
n -= 8;
}
.
674,675d
660a
sonicswap(p, n);
.
654c
p =(Pbuf*)ctlr->tb[ctlr->th];
.
638,639d
632c
Pbuf *p;
.
581d
562,567d
541,543c
if(ether[0] == 0) {
ctlr = malloc(sizeof(Ether));
ether[0] = ctlr;
initbufs(ctlr);
.
538,539d
526a
static void
initbufs(Ether *c)
{
int i;
uchar *mem;
mem = xspanalloc(64*1024, BY2PG, 0);
mem = CACHELINE(uchar, mem);
/*
* Descriptors must be built in uncached space
*/
c->rra = UNCACHED(RXrsc, mem);
mem = QUAD(uchar, mem+Nrb*sizeof(RXrsc));
c->rda = UNCACHED(RXpkt, mem);
mem = QUAD(uchar, mem+Nrb*sizeof(RXpkt));
c->tda = UNCACHED(TXpkt, mem);
mem = QUAD(uchar, mem+Ntb*sizeof(TXpkt));
c->cda = UNCACHED(Cam, mem);
/*
* DMA buffers are cache coherent - but we must not straddle
* a cache line
*/
mem = CACHELINE(uchar, mem+sizeof(Cam));
for(i = 0; i < Nrb; i++) {
c->rb[i] = UNCACHED(uchar, mem);
mem += sizeof(Pbuf)+4;
mem = QUAD(uchar, mem);
}
for(i = 0; i < Ntb; i++) {
c->tb[i] = UNCACHED(uchar, mem);
mem += sizeof(Pbuf);
mem = QUAD(uchar, mem);
}
}
.
506c
print("sonic #%lux\n", status);
.
501c
print("sonic: bus retry occurred\n");
.
497c
print("sonic: cd heartbeat lost\n");
.
481c
rxpkt = &c->rda[c->rh];
.
478,479c
c->rda[PREV(c->rh, Nrb)].link &= ~Eol;
c->rh = NEXT(c->rh, Nrb);
.
468c
c->buffs++;
.
466c
c->crcs++;
.
463c
c->frames++;
.
448,460c
if(rxpkt->status & Prx)
sonicpkt(c, rxpkt, (Pbuf*)c->rb[c->rh]);
.
445,446d
440c
c->inpackets++;
.
437,438c
rxpkt = &c->rda[c->rh];
.
425,426c
c->ti = NEXT(c->ti, Ntb);
txpkt = &c->tda[c->ti];
.
422c
c->oerrs++;
.
413c
txpkt = &c->tda[c->ti];
.
405d
399c
c = ether[0];
.
396,397d
390,392c
Ether *c;
.
371,384c
int len;
ushort type;
Netfile *f, **fp, **ep;
/*
* Sonic delivers CRC as part of the packet count
*/
len = (r->count & 0xFFFF)-4;
sonicswap(p, len);
type = (p->type[0]<<8) | p->type[1];
ep = &ctlr->f[Ntypes];
for(fp = ctlr->f; fp < ep; fp++) {
f = *fp;
if(f && (f->type == type || f->type < 0))
qproduce(f->in, p->d, len);
}
.
369c
sonicpkt(Ether *ctlr, RXpkt *r, Pbuf *p)
.
353a
/*
* End the reset
* Load the Resource Descriptors and Cam contents
*/
WR(cr, 0);
WR(cr, Rrra);
while(RD(cr) & Rrra)
;
.
351c
WR(cdp, LS16(ctlr->cda));
.
345,349c
ctlr->cda->cep = 0;
ctlr->cda->cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0];
ctlr->cda->cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2];
ctlr->cda->cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4];
ctlr->cda->ce = 1;
.
342,343d
301,304d
292,293d
283,284c
WR(eobc, Rxbuf/2 - 2);
.
273d
270a
/*
* Check the important resources are QUAD aligned
*/
.
267,268c
loadr = LS16(ctlr->rb[i]);
wus(&ctlr->rra[i].ptr0, loadr);
wus(&ctlr->rda[i].ptr0, loadr);
hiadr = MS16(ctlr->rb[i]);
wus(&ctlr->rra[i].ptr1, hiadr);
wus(&ctlr->rda[i].ptr1, hiadr);
.
264c
ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]);
.
261,262c
wus(&ctlr->rra[i].wc0, lolen);
wus(&ctlr->rra[i].wc1, hilen);
.
259a
lolen = (Rxbuf/2) & 0xFFFF;
hilen = ((Rxbuf/2)>>16) & 0xFFFF;
.
257c
* thus the size of the receive buffers must be sizeof(Pbuf)+4.
.
247,248d
243c
* Setup the descriptor and buffer area.
.
237a
ushort lolen, hilen, loadr, hiadr;
.
234a
wus(ushort *a, ushort v)
{
a[0] = v;
a[-1] = v;
}
static void
.
233a
void sonicswap(void*, int);
.
223a
uchar *rb[Nrb]; /* receive buffer area */
uchar *tb[Ntb]; /* transmit buffer area */
.
217,222c
RXrsc *rra; /* receive resource area */
RXpkt *rda; /* receive descriptor area */
TXpkt *tda; /* transmit descriptor area */
Cam *cda; /* CAM descriptor area */
.
207,208d
189,198c
ushort pad0;
ushort cap0; /* CAM address port 0 */
ushort pad1;
ushort cep; /* CAM entry pointer */
ushort pad2;
ushort cap2; /* CAM address port 2 */
ushort pad3;
ushort cap1; /* CAM address port 1 */
ulong pad4;
ushort pad5;
ushort ce; /* CAM enable */
.
157,172c
ushort pad1;
ushort config; /* */
ushort pad0;
ushort status; /* transmit status */
ushort pad3;
ushort count; /* fragment count */
ushort pad2;
ushort size; /* byte count of entire packet */
ushort pad5;
ushort ptr1;
ushort pad4;
ushort ptr0; /* packet pointer */
ushort pad7;
ushort link; /* descriptor link */
ushort pad6;
ushort fsize; /* fragment size */
.
136,149c
ushort pad0;
ushort count; /* packet byte count */
ushort pad1;
ushort status; /* receive status */
ushort pad2;
ushort ptr1; /* buffer pointer */
ushort pad3;
ushort ptr0;
ushort pad4;
ushort link; /* descriptor link and EOL */
ushort pad5;
ushort seqno; /* */
ulong pad6;
ushort pad7;
ushort owner; /* in use */
.
121,128c
ushort pad1;
ushort ptr1; /* buffer pointer in the RRA */
ushort pad2;
ushort ptr0;
ushort pad3;
ushort wc1; /* buffer word count in the RRA */
ushort pad4;
ushort wc0;
.
113a
Rxbuf = sizeof(Pbuf)+4,
Txbuf = sizeof(Pbuf),
.
35c
ulong crba0; /* DO NOT WRITE THESE */
ulong crba1;
ulong rbwc0;
ulong rbwc1;
.
21a
typedef struct Pbuf Pbuf;
struct Pbuf
{
uchar d[6];
uchar s[6];
uchar type[2];
uchar data[1500];
uchar crc[4];
};
.
19,20c
#define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = (v))
#define ISquad(s) if((ulong)s & 0x7) panic("sonic: Quad alignment");
.
## diffname carrera/devether.c 1993/0918
## diff -e /n/fornaxdump/1993/0906/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/0918/sys/src/brazil/carrera/devether.c
725a
poperror();
.
701a
if(waserror()) {
qunlock(&ctlr->tlock);
nexterror();
}
.
464a
wakeup(&c->tr);
.
## diffname carrera/devether.c 1993/1202
## diff -e /n/fornaxdump/1993/0918/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1202/sys/src/brazil/carrera/devether.c
701a
if(etherloop(buf, n))
return n;
.
684a
static int
etherloop(Etherpkt *p, long n)
{
int s, different;
ushort t;
Netfile *f, **fp;
different = memcmp(p->d, p->s, sizeof(p->s));
if(different && memcmp(p->d, ether.bcast, sizeof(p->d)))
return 0;
s = splhi();
t = (p->type[0]<<8) | p->type[1];
for(fp = ether.f; fp < ðer.f[Ntypes]; fp++) {
f = *fp;
if(f == 0)
continue;
if(f->type == t || f->type < 0)
switch(qproduce(f->in, p->d, n)){
case -1:
print("etherloop overflow\n");
break;
case -2:
print("etherloop memory\n");
break;
}
}
splx(s);
return !different;
}
.
## diffname carrera/devether.c 1993/1208
## diff -e /n/fornaxdump/1993/1202/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1208/sys/src/brazil/carrera/devether.c
698c
for(fp = ether[0]->f; fp < ðer[0]->f[Ntypes]; fp++) {
.
693c
if(different && memcmp(p->d, ether[0]->bcast, sizeof(p->d)))
.
## diffname carrera/devether.c 1993/1211
## diff -e /n/fornaxdump/1993/1208/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1211/sys/src/brazil/carrera/devether.c
745a
reset(ctlr);
WR(cr, Rxen);
}
.
744c
if(!isoutbuf(ctlr)) {
.
742c
tsleep(&ctlr->tr, isoutbuf, ctlr, 1000);
.
## diffname carrera/devether.c 1993/1212
## diff -e /n/fornaxdump/1993/1211/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1212/sys/src/brazil/carrera/devether.c
750c
p = (Pbuf*)ctlr->tb[ctlr->th];
.
744,748c
if(!isoutbuf(ctlr))
print("ether transmitter jammed cr #%lux\n", RD(cr));
.
742c
tsleep(&ctlr->tr, isoutbuf, ctlr, 10000);
.
731a
if(n > ETHERMAXTU)
error(Ebadarg);
.
725,727d
678,685d
517c
* Warnings that something is atoe.
.
465c
if(isoutbuf(c))
wakeup(&c->tr);
.
427a
static int
isoutbuf(void *arg)
{
Ether *ctlr = arg;
return ctlr->tda[ctlr->th].status == Host;
}
.
78c
Ntb = 16, /* transmit buffers */
.
## diffname carrera/devether.c 1993/1217
## diff -e /n/fornaxdump/1993/1212/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1217/sys/src/brazil/carrera/devether.c
597a
if(mem >= base+64*1024)
panic("sonic init");
.
565a
base = mem;
.
563c
uchar *mem, *base;
.
534a
for(;;);
.
533c
WR(cr, 0);
iprint("sonic: bus retry occurred\n");
.
77,78c
Nrb = 8, /* receive buffers */
Ntb = 8, /* transmit buffers */
.
18,19c
#define RD(rn) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4))
#define WR(rn, v) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4) = (v))
.
## diffname carrera/devether.c 1993/1218
## diff -e /n/fornaxdump/1993/1217/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1218/sys/src/brazil/carrera/devether.c
536d
533,534c
print("sonic: bus retry occurred\n");
.
253a
sncdly(void)
{
int i, j, *pj;
pj = &j;
for(i = 0; i < 200; i++)
*pj++;
}
static void
.
77c
Nrb = 16, /* receive buffers */
.
18,19c
#define RD(rn) (sncdly(), *(ulong*)((ulong)&SONICADDR->rn^4))
#define WR(rn, v) (sncdly(), *(ulong*)((ulong)&SONICADDR->rn^4) = (v))
.
## diffname carrera/devether.c 1993/1219
## diff -e /n/fornaxdump/1993/1218/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1219/sys/src/brazil/carrera/devether.c
624d
466c
if(status & (Txdn|Txer)) {
.
460a
/* Clear the interrupt cause */
.
254,263d
18,19c
#define RD(rn) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4))
#define WR(rn, v) (delay(0), *(ulong*)((ulong)&SONICADDR->rn^4) = (v))
.
## diffname carrera/devether.c 1993/1231
## diff -e /n/fornaxdump/1993/1219/sys/src/brazil/carrera/devether.c /n/fornaxdump/1993/1231/sys/src/brazil/carrera/devether.c
589d
584,587d
566c
mem = xspanalloc(64*1024, 8, 64*1024);
.
## diffname carrera/devether.c 1994/0107
## diff -e /n/fornaxdump/1993/1231/sys/src/brazil/carrera/devether.c /n/fornaxdump/1994/0107/sys/src/brazil/carrera/devether.c
760c
s = &ctlr->tda[PREV(ctlr->th, Ntb)].link;
wus(s, *s & ~Eol);
.
758c
wus(&txpkt->link, txpkt->link|Eol);
.
735a
ctlr->outpackets++;
.
718a
ushort *s;
.
539a
}
.
538c
if(status & AllIntr) {
WR(isr, status);
.
533,536d
525,531d
523c
if(status & Lcd) {
WR(isr, Lcd);
.
515a
WR(isr, status & (Pktrx|Rde));
.
511c
s = &c->rda[PREV(c->rh, Nrb)].link;
wus(s, *s & ~Eol);
.
509c
wus(&rxpkt->link, rxpkt->link|Eol);
.
502a
rxpkt->status = 0;
.
472a
WR(isr, status & (Txdn|Txer));
.
451,452c
/*
* Warnings that something is atoe.
*/
if(status & Hbl){
WR(isr, Hbl);
status &= ~Hbl;
print("sonic: cd heartbeat lost\n");
}
if(status & Br){
WR(cr, Rst);
print("sonic: bus retry occurred\n");
(*(void(*)(void))0xA001C020)();
status &= ~Br;
}
.
439a
ushort *s;
.
400c
WR(rcr, Brd);
.
385,386d
382d
273a
WR(cr, 0);
.
## diffname carrera/devether.c 1994/0524
## diff -e /n/fornaxdump/1994/0107/sys/src/brazil/carrera/devether.c /n/fornaxdump/1994/0524/sys/src/brazil/carrera/devether.c
573c
/* Put the ethernet buffers in the same place
* as the bootrom
*/
mem = (void*)(KZERO|0x2000);
.
## diffname carrera/devether.c 1995/0108
## diff -e /n/fornaxdump/1994/0524/sys/src/brazil/carrera/devether.c /n/fornaxdump/1995/0108/sys/src/brazil/carrera/devether.c
781a
}
long
etherbwrite(Chan *c, Block *bp, ulong offset)
{
return devbwrite(c, bp, offset);
.
693a
Block*
etherbread(Chan *c, long n, ulong offset)
{
return devbread(c, n, offset);
}
.
## diffname carrera/devether.c 1995/0114
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/carrera/devether.c /n/fornaxdump/1995/0114/sys/src/brazil/carrera/devether.c
770d
747a
p = buf;
memmove(p->s, ctlr->ea, sizeof(ctlr->ea));
.
713c
for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++) {
.
707,708c
different = memcmp(p->d, ctlr->ea, sizeof(ctlr->ea));
if(different && memcmp(p->d, ctlr->bcast, sizeof(p->d)))
.
705a
Ether *ctlr = ether[0];
.
## diffname carrera/devether.c 1995/0520
## diff -e /n/fornaxdump/1995/0114/sys/src/brazil/carrera/devether.c /n/fornaxdump/1995/0520/sys/src/brazil/carrera/devether.c
654a
if(*spec && strcmp(spec, "0") != 0)
error(Eio);
.
## diffname carrera/devether.c 1997/0327
## diff -e /n/fornaxdump/1995/0520/sys/src/brazil/carrera/devether.c /n/emeliedump/1997/0327/sys/src/brazil/carrera/devether.c
836a
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;
}
Dev etherdevtab = {
etherreset,
devinit,
etherattach,
devclone,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
devbread,
etherwrite,
devbwrite,
etherremove,
etherwstat,
};
.
821c
static void
.
813c
static void
.
807c
static void
.
795,801c
static void
.
734c
static long
.
696,701d
684c
static void
.
678c
static void
.
672c
static Chan*
.
660,666c
static int
.
641,646c
static Chan*
.
633c
netifinit(ether[0], "ether0", Ntypes, 32*1024);
.
609c
static void
.
403c
static void
.
251c
static void sonicswap(void*, int);
.
244c
static Ether *ether[Nether];
.
## diffname carrera/devether.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/carrera/devether.c /n/emeliedump/1997/0408/sys/src/brazil/carrera/devether.c
838a
'l',
"ether",
.
## diffname carrera/devether.c 1997/1210
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/carrera/devether.c /n/emeliedump/1997/1210/sys/src/brazil/carrera/devether.c
854c
etherbwrite,
.
852c
etherbread,
.
837a
#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) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
.
816c
parseether(uchar* to, char* from)
.
812a
if(ether)
free(ether);
.
803,811c
ether->alen = Eaddrlen;
memset(ether->bcast, 0xFF, Eaddrlen);
ether->arg = ether;
ether->promiscuous = ether->dev->promiscuous;
ether->multicast = ether->dev->multicast;
etherxx[ctlrno] = ether;
ether = 0;
break;
}
.
798,801c
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);
}
if(ether->oq == 0)
panic("etherreset %s", name);
.
796c
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX",
ctlrno, ether->type, ether->mbps, ether->port);
if(ether->irq)
i += sprint(buf+i, " irq %d", 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->addr[0], ether->addr[1], ether->addr[2],
ether->addr[3], ether->addr[4], ether->addr[5]);
sprint(buf+i, "\n");
print(buf);
.
790,794c
/*
* 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;
intrenable(VectorPIC+ether->irq, ether->interrupt, ether, ether->tbdf);
.
784,788c
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)
continue;
for(n = 0; endev[n]; n++){
if(cistrcmp(endev[n]->name, ether->type))
continue;
ether->dev = endev[n];
for(i = 0; i < ether->nopt; i++){
if(strncmp(ether->opt[i], "ea=", 3))
continue;
if(parseether(ether->addr, ðer->opt[i][3]) == -1)
memset(ether->addr, 0, Eaddrlen);
}
if(endev[n]->reset(ether))
break;
.
781,782c
Ether *ether;
int i, n, ctlrno;
char name[NAMELEN], buf[128];
.
778,779c
void
etherreset(void)
.
775c
return etheroq(ether, bp);
.
772,773c
if(n < ETHERMINTU){
freeb(bp);
error(Etoosmall);
}
.
748,770c
if(n > ETHERMAXTU){
freeb(bp);
error(Ebadarg);
.
740,745d
725,738c
n = BLEN(bp);
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid){
n = netifwrite(ether, chan, bp->rp, n);
freeb(bp);
.
720,723c
Ether *ether;
long n;
.
718c
etherbwrite(Chan* chan, Block* bp, ulong)
.
673,716d
667,670c
return etheroq(ether, bp);
.
661,665c
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
memmove(bp->rp+Eaddrlen, ether->addr, Eaddrlen);
poperror();
bp->wp += n;
.
655,659c
if(n > ETHERMAXTU)
error(Etoobig);
if(n < ETHERMINTU)
error(Etoosmall);
.
646,653c
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid)
return netifwrite(ether, chan, buf, n);
.
644c
Ether *ether;
Block *bp;
.
641,642c
static long
etherwrite(Chan* chan, void* buf, long n, ulong)
.
628,638c
return len;
.
626d
609,624c
if(!loopback){
if(ether->dev && ether->dev->transmit){
qbwrite(ether->oq, bp);
ether->dev->transmit(ether);
}
else{
freeb(bp);
return 0;
}
.
600,607d
583,598c
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = (memcmp(pkt->d, ether->addr, sizeof(pkt->d)) == 0);
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
s = splhi();
etheriq(ether, bp, loopback);
splx(s);
.
581c
* 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.
.
573,578c
ether->outpackets++;
.
570,571c
int len, loopback, s;
Etherpkt *pkt;
.
567,568c
static int
etheroq(Ether* ether, Block* bp)
.
550,564c
return bp;
.
548c
if(freebp){
freeb(bp);
return 0;
}
.
533,546c
if(fx){
qpass(fx->in, bp);
return 0;
.
530,531c
}
.
507,528c
etherrtrace(f, pkt, len);
.
490,505c
/*
* 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++){
if((f = *fp) && (f->type == type || f->type < 0)){
if(f->type > -2){
if(freebp && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
qpass(f->in, xbp);
}
else
ether->soverflows++;
}
.
488a
}
.
484,487c
return bp;
.
450,482c
/* check for valid multcast addresses */
if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(freebp){
freeb(bp);
bp = 0;
.
445,448c
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = ðer->f[Ntypes];
.
443c
ether->inpackets++;
.
437,441c
Etherpkt *pkt;
ushort type;
int len;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
.
434,435c
Block*
etheriq(Ether* ether, Block* bp, int freebp)
.
431c
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(MACHP(0)->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);
.
429c
int i, n;
Block *bp;
.
426,427c
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
.
406,423c
netifwstat(etherxx[chan->dev], chan, dp);
.
404c
etherwstat(Chan* chan, char* dp)
.
263,400d
261c
etherremove(Chan*)
.
256,257c
return netifbread(etherxx[chan->dev], chan, n, offset);
.
233,254c
static Block*
etherbread(Chan* chan, long n, ulong offset)
.
230,231c
return netifread(ether, chan, buf, n, offset);
}
.
225,228c
ether = etherxx[chan->dev];
if((chan->qid.path & CHDIR) == 0 && ether->dev && ether->dev->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->dev->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->dev->ifstat(ether, buf, 0, offset);
}
.
222,223c
Ether *ether;
.
219,220c
static long
etherread(Chan* chan, void* buf, long n, ulong offset)
.
206,217c
netifclose(etherxx[chan->dev], chan);
}
.
192,204c
static void
etherclose(Chan* chan)
.
174,190c
}
.
169,172c
static void
ethercreate(Chan*, char*, int, ulong)
.
152,167c
return netifopen(etherxx[chan->dev], chan, omode);
}
.
147,150c
static Chan*
etheropen(Chan* chan, int omode)
.
137,145c
netifstat(etherxx[chan->dev], chan, dp);
}
.
93,135c
static void
etherstat(Chan* chan, char* dp)
.
83,91c
return netifwalk(etherxx[chan->dev], chan, name);
}
.
81c
static int
etherwalk(Chan* chan, char* name)
.
75,79c
chan = devattach('l', spec);
chan->dev = ctlrno;
if(etherxx[ctlrno]->dev && etherxx[ctlrno]->dev->attach)
etherxx[ctlrno]->dev->attach(etherxx[ctlrno]);
return chan;
}
.
32,73c
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
.
25,30c
ulong ctlrno;
char *p;
Chan *chan;
.
18,23c
Chan*
etherattach(char* spec)
.
16c
static Ether *etherxx[MaxEther];
.
10,14c
#include "etherif.h"
.
1,8c
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
.
## diffname carrera/devether.c 1998/0319
## diff -e /n/emeliedump/1997/1210/sys/src/brazil/carrera/devether.c /n/emeliedump/1998/0319/sys/src/brazil/carrera/devether.c
234c
etherwrite(Chan* chan, void* buf, long n, vlong)
.
70a
ulong offset = off;
.
68c
etherread(Chan* chan, void* buf, long n, vlong off)
.
## diffname carrera/devether.c 1999/0629
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/carrera/devether.c /n/emeliedump/1999/0629/sys/src/brazil/carrera/devether.c
329c
i += sprint(buf+i, " irq %ld", ether->irq);
.
## diffname carrera/devether.c 2000/0713
## diff -e /n/emeliedump/1999/0629/sys/src/brazil/carrera/devether.c /n/emeliedump/2000/0713/sys/src/9/carrera/devether.c
117,118c
bp = iallocb(64);
if(bp == nil)
.
113,114c
if(len > 58)
n = 58;
.
## diffname carrera/devether.c 2001/0527 # deleted
## diff -e /n/emeliedump/2000/0713/sys/src/9/carrera/devether.c /n/emeliedump/2001/0527/sys/src/9/carrera/devether.c
1,431d
|