|
|
|
1993/0212/sys/src/9/pc/devether.c:3,48 –
1993/1113/sys/src/9/pc/devether.c:3,44
(short | long | prev | next)
|
|
1992/0403
| |
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.h"
|
|
1993/1113
| |
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
|
|
1992/0403
| |
|
|
1992/1222
| |
#include "ether.h"
|
|
1993/1113
| |
#include "etherif.h"
|
|
1992/1222
| |
|
|
1992/0922
| |
/*
* Half-arsed attempt at a general top-level
* ethernet driver. Needs work:
* handle multiple controllers
* much tidying
* set ethernet address
|
|
1993/0212
| |
* need a ctl file passed down to card drivers
* so we can set options.
|
|
1992/0922
| |
*/
|
|
1993/0212
| |
extern Card ether8003, ether503, ether2000;
extern Card ether509;
|
|
1993/1113
| |
static Ether *ether[MaxEther];
|
|
1992/0403
| |
|
|
1992/1222
| |
/*
|
|
1993/0212
| |
* 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
|
|
1992/1222
| |
* cannot be done passively, so it must be last to
* prevent scrogging one of the others.
*/
|
|
1993/0212
| |
static Card *cards[] = {
|
|
1992/1222
| |
ðer8003,
ðer503,
ðer2000,
|
|
1993/1113
| |
void
etherinit(void)
{
}
|
|
1992/1222
| |
|
|
1992/0922
| |
ðer509,
0
|
|
1992/0404
| |
};
|
|
1993/1113
| |
Chan*
etherattach(char *spec)
{
ulong ctlrno;
char *p;
Chan *c;
|
|
1992/0404
| |
enum {
|
|
1992/1222
| |
NCtlr = 1,
|
|
1992/0424
| |
};
|
|
1993/1113
| |
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);
|
|
1992/0403
| |
|
|
1993/0212
| |
/*static */struct Ctlr *softctlr[NCtlr];
|
|
1992/1222
| |
static int nctlr;
|
|
1993/1113
| |
c = devattach('l', spec);
c->dev = ctlrno;
if(ether[ctlrno]->attach)
(*ether[ctlrno]->attach)(ether[ctlrno]);
return c;
}
|
|
1992/0922
| |
|
|
1992/0425
| |
Chan*
|
|
1992/0424
| |
etherclone(Chan *c, Chan *nc)
|
|
1993/0212/sys/src/9/pc/devether.c:53,71 –
1993/1113/sys/src/9/pc/devether.c:49,67
|
|
1992/0424
| |
int
etherwalk(Chan *c, char *name)
{
|
|
1992/1222
| |
return netwalk(c, name, &softctlr[0]->net);
|
|
1993/1113
| |
return netifwalk(ether[c->dev], c, name);
|
|
1992/0424
| |
}
void
etherstat(Chan *c, char *dp)
{
|
|
1992/1222
| |
netstat(c, dp, &softctlr[0]->net);
|
|
1993/1113
| |
netifstat(ether[c->dev], c, dp);
|
|
1992/0424
| |
}
Chan*
etheropen(Chan *c, int omode)
{
|
|
1992/1222
| |
return netopen(c, omode, &softctlr[0]->net);
|
|
1993/1113
| |
return netifopen(ether[c->dev], c, omode);
|
|
1992/0424
| |
}
void
|
|
1993/0212/sys/src/9/pc/devether.c:72,582 –
1993/1113/sys/src/9/pc/devether.c:68,212
|
|
1992/0424
| |
ethercreate(Chan *c, char *name, int omode, ulong perm)
{
|
|
1992/0711
| |
USED(c, name, omode, perm);
|
|
1992/0424
| |
error(Eperm);
}
void
etherclose(Chan *c)
{
if(c->stream)
streamclose(c);
|
|
1993/1113
| |
netifclose(ether[c->dev], c);
|
|
1992/0424
| |
}
long
etherread(Chan *c, void *a, long n, ulong offset)
|
|
1993/1113
| |
etherread(Chan *c, void *buf, long n, ulong offset)
|
|
1992/0424
| |
{
|
|
1992/1222
| |
return netread(c, a, n, offset, &softctlr[0]->net);
|
|
1993/1113
| |
return netifread(ether[c->dev], c, buf, n, offset);
|
|
1992/0411
| |
}
|
|
1992/0424
| |
long
etherwrite(Chan *c, char *a, long n, ulong offset)
{
|
|
1992/0711
| |
USED(offset);
|
|
1992/0424
| |
return streamwrite(c, a, n, 0);
}
void
etherremove(Chan *c)
{
|
|
1992/0711
| |
USED(c);
|
|
1992/0424
| |
error(Eperm);
}
void
etherwstat(Chan *c, char *dp)
{
|
|
1992/1222
| |
netwstat(c, dp, &softctlr[0]->net);
|
|
1993/1113
| |
netifwstat(ether[c->dev], c, dp);
|
|
1992/0424
| |
}
|
|
1992/0407
| |
static int
|
|
1992/0424
| |
isobuf(void *arg)
|
|
1993/1113
| |
long
etherwrite(Chan *c, void *buf, long n, ulong offset)
|
|
1992/0407
| |
{
|
|
1992/1222
| |
Ctlr *ctlr = arg;
|
|
1993/1113
| |
Ether *ctlr;
|
|
1992/0407
| |
|
|
1992/1222
| |
return ctlr->tb[ctlr->th].owner == Host;
|
|
1992/0407
| |
}
|
|
1993/1113
| |
USED(offset);
if(n > ETHERMAXTU)
error(Ebadarg);
ctlr = ether[c->dev];
|
|
1992/0407
| |
|
|
1992/0403
| |
static void
etheroput(Queue *q, Block *bp)
{
|
|
1992/1222
| |
Ctlr *ctlr;
Type *type;
Etherpkt *pkt;
RingBuf *ring;
|
|
1993/0212
| |
int len, n, s;
|
|
1992/0403
| |
Block *nbp;
|
|
1993/1113
| |
if(NETTYPE(c->qid.path) != Ndataqid)
return netifwrite(ctlr, c, buf, n);
|
|
1992/0403
| |
|
|
1992/1222
| |
type = q->ptr;
ctlr = type->ctlr;
|
|
1992/0403
| |
if(bp->type == M_CTL){
|
|
1992/1222
| |
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++;
}
|
|
1992/0403
| |
else if(streamparse("promiscuous", bp)) {
|
|
1992/1222
| |
type->prom = 1;
ctlr->prom++;
if(ctlr->prom == 1)
|
|
1993/0212
| |
(*ctlr->card.mode)(ctlr, 1);
|
|
1992/0403
| |
}
|
|
1992/1222
| |
qunlock(ctlr);
|
|
1992/0403
| |
freeb(bp);
return;
}
/*
|
|
1992/1222
| |
* Give packet a local address, return upstream if destined for
|
|
1992/0403
| |
* this machine.
*/
|
|
1992/0406
| |
if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0)
return;
|
|
1992/1222
| |
pkt = (Etherpkt*)bp->rptr;
memmove(pkt->s, ctlr->ea, sizeof(ctlr->ea));
if(memcmp(ctlr->ea, pkt->d, sizeof(ctlr->ea)) == 0){
|
|
1992/0403
| |
len = blen(bp);
|
|
1992/1222
| |
if(bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){
putq(&ctlr->lbq, bp);
wakeup(&ctlr->rr);
|
|
1992/0403
| |
}
return;
}
|
|
1992/1222
| |
if(memcmp(ctlr->ba, pkt->d, sizeof(ctlr->ba)) == 0 || ctlr->prom || ctlr->all){
|
|
1992/0403
| |
len = blen(bp);
nbp = copyb(bp, len);
|
|
1992/0406
| |
if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){
|
|
1992/0403
| |
nbp->wptr = nbp->rptr+len;
|
|
1992/1222
| |
putq(&ctlr->lbq, nbp);
wakeup(&ctlr->rr);
|
|
1992/0403
| |
}
}
/*
|
|
1992/1222
| |
* Only one transmitter at a time.
|
|
1992/0403
| |
*/
|
|
1992/1222
| |
qlock(&ctlr->tlock);
|
|
1992/0403
| |
if(waserror()){
|
|
1992/1222
| |
qunlock(&ctlr->tlock);
|
|
1993/0212
| |
freeb(bp);
|
|
1992/0403
| |
nexterror();
}
/*
|
|
1992/1222
| |
* Wait till we get an output buffer.
|
|
1992/0424
| |
* should try to restart.
|
|
1992/0403
| |
*/
|
|
1993/0212
| |
if(isobuf(ctlr) == 0){
tsleep(&ctlr->tr, isobuf, ctlr, 3*1000);
if(isobuf(ctlr) == 0){
qunlock(&ctlr->tlock);
freeb(bp);
poperror();
return;
}
}
|
|
1992/0403
| |
|
|
1992/1222
| |
ring = &ctlr->tb[ctlr->th];
|
|
1992/0424
| |
|
|
1992/0403
| |
/*
|
|
1992/1222
| |
* Copy message into buffer.
|
|
1992/0403
| |
*/
len = 0;
for(nbp = bp; nbp; nbp = nbp->next){
if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){
|
|
1992/1222
| |
memmove(ring->pkt+len, nbp->rptr, n);
|
|
1992/0403
| |
len += n;
|
|
1992/1222
| |
}
|
|
1992/0403
| |
if(bp->flags & S_DELIM)
break;
}
/*
|
|
1992/1222
| |
* Pad the packet (zero the pad).
|
|
1992/0403
| |
*/
if(len < ETHERMINTU){
|
|
1992/1222
| |
memset(ring->pkt+len, 0, ETHERMINTU-len);
|
|
1992/0403
| |
len = ETHERMINTU;
}
/*
|
|
1992/1222
| |
* Set up the transmit buffer and
* start the transmission.
|
|
1992/0403
| |
*/
|
|
1993/0212
| |
s = splhi();
|
|
1992/1222
| |
ring->len = len;
ring->owner = Interface;
ctlr->th = NEXT(ctlr->th, ctlr->ntb);
|
|
1993/0212
| |
(*ctlr->card.transmit)(ctlr);
splx(s);
|
|
1992/0403
| |
|
|
1992/1222
| |
qunlock(&ctlr->tlock);
|
|
1993/0212
| |
freeb(bp);
|
|
1993/1113
| |
n = (*ctlr->write)(ctlr, buf, n);
|
|
1992/0403
| |
poperror();
}
|
|
1993/1113
| |
qunlock(&ctlr->tlock);
|
|
1992/0403
| |
/*
|
|
1992/1222
| |
* Open an ether line discipline.
|
|
1992/0403
| |
*/
static void
etherstopen(Queue *q, Stream *s)
{
|
|
1992/1222
| |
Ctlr *ctlr = softctlr[0];
Type *type;
|
|
1992/0403
| |
|
|
1992/1222
| |
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;
|
|
1993/1113
| |
return n;
|
|
1992/0403
| |
}
/*
|
|
1992/1222
| |
* Close ether line discipline.
|
|
1992/0403
| |
*
|
|
1992/1222
| |
* The locking is to synchronize changing the ethertype with
* sending packets up the stream on interrupts.
|
|
1992/0403
| |
*/
|
|
1992/1222
| |
static int
isclosed(void *arg)
{
return ((Type*)arg)->q == 0;
}
|
|
1992/0403
| |
static void
etherstclose(Queue *q)
|
|
1993/1113
| |
etherintr(Ureg *ur)
|
|
1992/0403
| |
{
|
|
1992/1222
| |
Type *type = (Type*)(q->ptr);
Ctlr *ctlr = type->ctlr;
|
|
1993/1113
| |
int i, irq;
|
|
1992/0403
| |
|
|
1992/1222
| |
if(type->prom){
qlock(ctlr);
ctlr->prom--;
if(ctlr->prom == 0)
|
|
1993/0212
| |
(*ctlr->card.mode)(ctlr, 0);
|
|
1992/1222
| |
qunlock(ctlr);
}
if(type->type == -1){
qlock(ctlr);
ctlr->all--;
qunlock(ctlr);
}
/*
* Mark as closing and wait for kproc
* to close us.
|
|
1993/1113
| |
* 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...
|
|
1992/1222
| |
*/
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;
|
|
1992/0403
| |
}
static Qinfo info = {
nullput,
etheroput,
etherstopen,
etherstclose,
"ether"
};
static int
|
|
1992/0404
| |
clonecon(Chan *c)
|
|
1992/0403
| |
{
|
|
1992/1222
| |
Ctlr *ctlr = softctlr[0];
Type *type;
|
|
1992/0403
| |
|
|
1992/0711
| |
USED(c);
|
|
1992/1222
| |
for(type = ctlr->type; type < &ctlr->type[NType]; type++){
qlock(type);
if(type->inuse || type->q){
qunlock(type);
|
|
1992/0403
| |
continue;
}
|
|
1992/1222
| |
type->inuse = 1;
netown(type, u->p->user, 0);
qunlock(type);
return type - ctlr->type;
|
|
1993/1113
| |
irq = ur->trap-Int0vec;
for(i = 0; i < MaxEther; i++){
if(ether[i] && ether[i]->irq == irq)
(*ether[i]->interrupt)(ether[i]);
|
|
1992/0403
| |
}
exhausted("ether channels");
|
|
1992/0711
| |
return 0;
|
|
1992/0403
| |
}
static void
|
|
1992/0404
| |
statsfill(Chan *c, char *p, int n)
|
|
1992/0403
| |
{
|
|
1992/1222
| |
Ctlr *ctlr = softctlr[0];
|
|
1992/0403
| |
char buf[256];
|
|
1993/1113
| |
#define NCARD 32
static struct {
char *type;
int (*reset)(Ether*);
} cards[NCARD+1];
|
|
1992/0403
| |
|
|
1992/0711
| |
USED(c);
|
|
1992/0403
| |
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",
|
|
1992/1222
| |
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]);
|
|
1992/0403
| |
strncpy(p, buf, n);
}
static void
typefill(Chan *c, char *p, int n)
|
|
1993/1113
| |
void
addethercard(char *t, int (*r)(Ether*))
|
|
1992/0403
| |
{
char buf[16];
|
|
1992/1222
| |
Type *type;
|
|
1993/1113
| |
static int ncard;
|
|
1992/0403
| |
|
|
1992/1222
| |
type = &softctlr[0]->type[STREAMID(c->qid.path)];
sprint(buf, "%d", type->type);
|
|
1992/0403
| |
strncpy(p, buf, n);
|
|
1993/1113
| |
if(ncard == NCARD)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
|
|
1992/0403
| |
}
static void
|
|
1992/1222
| |
etherup(Ctlr *ctlr, Etherpkt *pkt, int len)
|
|
1992/0403
| |
{
|
|
1992/0404
| |
int t;
|
|
1992/1222
| |
Type *type;
|
|
1992/0501
| |
Block *bp;
|
|
1992/0404
| |
|
|
1992/1222
| |
t = (pkt->type[0]<<8)|pkt->type[1];
for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){
|
|
1992/0404
| |
/*
|
|
1992/1222
| |
* Check for open, the right type, and flow control.
|
|
1992/0404
| |
*/
|
|
1992/1222
| |
if(type->q == 0)
|
|
1992/0404
| |
continue;
|
|
1992/1222
| |
if(t != type->type && type->type != -1)
continue;
if(type->q->next->len > Streamhi)
continue;
|
|
1992/0404
| |
/*
|
|
1992/1222
| |
* Only a trace channel gets packets destined for other machines.
|
|
1992/0404
| |
*/
|
|
1992/1222
| |
if(type->type != -1 && pkt->d[0] != 0xFF
&& (*pkt->d != *ctlr->ea || memcmp(pkt->d, ctlr->ea, sizeof(pkt->d))))
|
|
1992/0404
| |
continue;
|
|
1992/1222
| |
if(waserror() == 0){
|
|
1992/0424
| |
bp = allocb(len);
|
|
1992/1222
| |
memmove(bp->rptr, pkt, len);
|
|
1992/0424
| |
bp->wptr += len;
|
|
1992/0404
| |
bp->flags |= S_DELIM;
|
|
1992/1222
| |
PUTNEXT(type->q, bp);
|
|
1992/1015
| |
poperror();
|
|
1992/0404
| |
}
}
}
|
|
1992/0403
| |
static int
isinput(void *arg)
{
|
|
1992/1222
| |
Ctlr *ctlr = arg;
|
|
1992/0403
| |
|
|
1992/1222
| |
return ctlr->lbq.first || ctlr->rb[ctlr->rh].owner == Host || ctlr->clist;
|
|
1992/0403
| |
}
static void
etherkproc(void *arg)
{
|
|
1992/1222
| |
Ctlr *ctlr = arg;
RingBuf *ring;
|
|
1992/0404
| |
Block *bp;
|
|
1992/1222
| |
Type *type;
|
|
1992/0403
| |
if(waserror()){
|
|
1992/1222
| |
print("%s noted\n", ctlr->name);
/* fix
|
|
1993/0212
| |
if(ctlr->card.reset)
(*ctlr->card.reset)(ctlr);
|
|
1992/1222
| |
*/
ctlr->kproc = 0;
|
|
1992/0403
| |
nexterror();
}
|
|
1992/1222
| |
|
|
1992/0403
| |
for(;;){
|
|
1992/1222
| |
tsleep(&ctlr->rr, isinput, ctlr, 500);
|
|
1993/0212
| |
if(ctlr->card.watch)
(*ctlr->card.watch)(ctlr);
|
|
1992/0424
| |
|
|
1992/0406
| |
/*
|
|
1992/1222
| |
* Process any internal loopback packets.
|
|
1992/0406
| |
*/
|
|
1992/1222
| |
while(bp = getq(&ctlr->lbq)){
ctlr->inpackets++;
etherup(ctlr, (Etherpkt*)bp->rptr, BLEN(bp));
|
|
1992/0404
| |
freeb(bp);
}
|
|
1992/0408
| |
|
|
1992/0406
| |
/*
|
|
1992/1222
| |
* Process any received packets.
|
|
1992/0406
| |
*/
|
|
1992/1222
| |
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);
|
|
1992/0424
| |
}
|
|
1992/1222
| |
/*
* 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);
}
|
|
1992/0424
| |
}
}
|
|
1992/0410
| |
|
|
1992/0922
| |
static void
etherintr(Ureg *ur)
{
|
|
1992/1222
| |
Ctlr *ctlr = softctlr[0];
|
|
1992/0922
| |
USED(ur);
|
|
1993/0212
| |
(*ctlr->card.intr)(ctlr);
|
|
1992/0922
| |
}
|
|
1992/0424
| |
void
etherreset(void)
{
|
|
1992/1222
| |
Ctlr *ctlr;
|
|
1993/0212
| |
Card **card;
|
|
1992/0625
| |
int i;
|
|
1993/1113
| |
Ether *ctlr;
int i, n, ctlrno;
ulong irqmask;
|
|
1992/0410
| |
|
|
1993/0212
| |
if(nctlr >= NCtlr)
return;
|
|
1992/1222
| |
if(softctlr[nctlr] == 0)
softctlr[nctlr] = xalloc(sizeof(Ctlr));
ctlr = softctlr[nctlr];
|
|
1993/0212
| |
for(card = cards; *card; card++){
memset(ctlr, 0, sizeof(Ctlr));
ctlr->card = **card;
if((*ctlr->card.reset)(ctlr) == 0){
|
|
1992/1222
| |
ctlr->present = 1;
|
|
1993/1113
| |
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;
|
|
1992/1222
| |
/*
* 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.
|
|
1993/1113
| |
* 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().
|
|
1992/1222
| |
*/
|
|
1993/0212
| |
if(ctlr->card.irq == 2)
ctlr->card.irq = 9;
setvec(Int0vec + ctlr->card.irq, etherintr);
|
|
1992/0922
| |
break;
}
|
|
1992/0917
| |
}
|
|
1992/1222
| |
if(ctlr->present == 0)
|
|
1992/0922
| |
return;
|
|
1993/1113
| |
if(ctlr->irq == 2)
ctlr->irq = 9;
if((irqmask & (1<<ctlr->irq)) == 0){
setvec(Int0vec+ctlr->irq, etherintr);
irqmask |= 1<<ctlr->irq;
}
|
|
1993/0212
| |
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");
|
|
1993/1113
| |
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");
|
|
1993/0212
| |
|
|
1992/1222
| |
nctlr++;
|
|
1993/1113
| |
netifinit(ctlr, "ether", Ntypes, 32*1024);
ctlr->alen = Eaddrlen;
memmove(ctlr->addr, ctlr->ea, sizeof(ctlr->ea));
memmove(ctlr->bcast, etherbcast, sizeof(etherbcast));
|
|
1992/0410
| |
|
|
1992/1222
| |
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);
|
|
1992/0410
| |
|
|
1992/1222
| |
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;
|
|
1992/0625
| |
for(i = 0; i < NType; i++)
|
|
1992/1222
| |
netadd(&ctlr->net, &ctlr->type[i], i);
|
|
1992/0403
| |
}
|
|
1992/0425
| |
void
etherinit(void)
|
|
1992/0403
| |
{
int ctlrno = 0;
|
|
1992/1222
| |
Ctlr *ctlr = softctlr[ctlrno];
|
|
1992/0424
| |
int i;
|
|
1992/0403
| |
|
|
1992/1222
| |
if(ctlr->present == 0)
|
|
1992/0917
| |
return;
|
|
1992/1222
| |
ctlr->rh = 0;
ctlr->ri = 0;
for(i = 0; i < ctlr->nrb; i++)
ctlr->rb[i].owner = Interface;
|
|
1992/0424
| |
|
|
1992/1222
| |
ctlr->th = 0;
ctlr->ti = 0;
for(i = 0; i < ctlr->ntb; i++)
ctlr->tb[i].owner = Host;
}
|
|
1992/0424
| |
|
|
1992/1222
| |
Chan*
etherattach(char *spec)
{
int ctlrno = 0;
Ctlr *ctlr = softctlr[ctlrno];
if(ctlr->present == 0)
error(Enodev);
|
|
1992/0403
| |
/*
|
|
1992/1222
| |
* Enable the interface
* and start the kproc.
|
|
1992/0501
| |
*/
|
|
1993/0212
| |
(*ctlr->card.attach)(ctlr);
|
|
1992/1222
| |
if(ctlr->kproc == 0){
sprint(ctlr->name, "ether%dkproc", ctlrno);
ctlr->kproc = 1;
kproc(ctlr->name, etherkproc, ctlr);
|
|
1993/1113
| |
ether[ctlrno] = ctlr;
ctlr = 0;
}
|
|
1992/0403
| |
}
|
|
1992/1222
| |
return devattach('l', spec);
|
|
1993/1113
| |
if(ctlr)
free(ctlr);
|
|
1992/0403
| |
}
|