2 #include "../port/lib.h"
7 #include "../port/error.h"
9 #include "../port/netif.h"
12 extern int archether(unsigned ctlno, Ether *ether);
14 static Ether *etherxx[MaxEther];
17 etherattach(char* spec)
25 ctlrno = strtoul(spec, &p, 0);
26 if((ctlrno == 0 && p == spec) || *p != 0)
28 if(ctlrno < 0 || ctlrno >= MaxEther)
31 if(etherxx[ctlrno] == 0)
34 chan = devattach('l', spec);
40 if(etherxx[ctlrno]->attach)
41 etherxx[ctlrno]->attach(etherxx[ctlrno]);
47 etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
49 return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
53 etherstat(Chan* chan, uchar* dp, int n)
55 return netifstat(etherxx[chan->dev], chan, dp, n);
59 etheropen(Chan* chan, int omode)
61 return netifopen(etherxx[chan->dev], chan, omode);
65 ethercreate(Chan*, char*, int, ulong)
72 etherclose(Chan* chan)
74 netifclose(etherxx[chan->dev], chan);
78 etherread(Chan* chan, void* buf, long n, vlong off)
83 ether = etherxx[chan->dev];
84 if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
86 * With some controllers it is necessary to reach
87 * into the chip to extract statistics.
89 if(NETTYPE(chan->qid.path) == Nifstatqid)
90 return ether->ifstat(ether, buf, n, offset);
91 else if(NETTYPE(chan->qid.path) == Nstatqid)
92 ether->ifstat(ether, buf, 0, offset);
95 return netifread(ether, chan, buf, n, offset);
99 etherbread(Chan* chan, long n, ulong offset)
101 return netifbread(etherxx[chan->dev], chan, n, offset);
105 etherwstat(Chan* chan, uchar* dp, int n)
107 return netifwstat(etherxx[chan->dev], chan, dp, n);
111 etherrtrace(Netfile* f, Etherpkt* pkt, int len)
116 if(qwindow(f->in) <= 0)
125 memmove(bp->wp, pkt->d, n);
126 i = TK2MS(MACHP(0)->ticks);
138 etheriq(Ether* ether, Block* bp, int fromwire)
142 int len, multi, tome, fromme;
143 Netfile **ep, *f, **fp, *fx;
148 pkt = (Etherpkt*)bp->rp;
150 type = (pkt->type[0]<<8)|pkt->type[1];
152 ep = ðer->f[Ntypes];
154 multi = pkt->d[0] & 1;
155 /* check for valid multicast addresses */
156 if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
157 if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
167 tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
168 fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
171 * Multiplex the packet to all the connections which want it.
172 * If the packet is not to be used subsequently (fromwire != 0),
173 * attempt to simply pass it into one of the connections, thereby
174 * saving a copy of the data (usual case hopefully).
176 for(fp = ether->f; fp < ep; fp++){
178 if(f->type == type || f->type < 0)
179 if(tome || multi || f->prom){
180 /* Don't want to hear bridged packets */
181 if(f->bridge && !fromwire && !fromme)
184 if(fromwire && fx == 0)
186 else if(xbp = iallocb(len)){
187 memmove(xbp->wp, pkt, len);
189 if(qpass(f->in, xbp) < 0)
196 etherrtrace(f, pkt, len);
201 if(qpass(fx->in, bp) < 0)
214 etheroq(Ether* ether, Block* bp)
216 int len, loopback, s;
222 * Check if the packet has to be placed back onto the input queue,
223 * i.e. if it's a loopback or broadcast packet or the interface is
224 * in promiscuous mode.
225 * If it's a loopback packet indicate to etheriq that the data isn't
226 * needed and return, etheriq will pass-on or free the block.
227 * To enable bridging to work, only packets that were originated
228 * by this interface are fed back.
230 pkt = (Etherpkt*)bp->rp;
232 loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
233 if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
235 etheriq(ether, bp, 0);
240 qbwrite(ether->oq, bp);
241 if(ether->transmit != nil)
242 ether->transmit(ether);
250 etherwrite(Chan* chan, void* buf, long n, vlong)
257 ether = etherxx[chan->dev];
258 if(NETTYPE(chan->qid.path) != Ndataqid) {
259 nn = netifwrite(ether, chan, buf, n);
262 cb = parsecmd(buf, n);
263 if(strcmp(cb->f[0], "nonblocking") == 0){
267 onoff = atoi(cb->f[1]);
268 qnoblock(ether->oq, onoff);
274 return ether->ctl(ether,buf,n);
279 if(n > ether->maxmtu)
281 if(n < ether->minmtu)
289 memmove(bp->rp, buf, n);
290 memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
294 return etheroq(ether, bp);
298 etherbwrite(Chan* chan, Block* bp, ulong)
304 if(NETTYPE(chan->qid.path) != Ndataqid){
309 n = etherwrite(chan, bp->rp, n, 0);
314 ether = etherxx[chan->dev];
316 if(n > ether->maxmtu){
320 if(n < ether->minmtu){
325 return etheroq(ether, bp);
330 int (*reset)(Ether*);
334 addethercard(char* t, int (*r)(Ether*))
338 if(ncard == MaxEther)
339 panic("too many ether cards");
340 cards[ncard].type = t;
341 cards[ncard].reset = r;
346 parseether(uchar *to, char *from)
353 for(i = 0; i < Eaddrlen; i++){
361 to[i] = strtoul(nip, 0, 16);
373 char name[KNAMELEN], buf[128];
375 for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
377 ether = malloc(sizeof(Ether));
378 memset(ether, 0, sizeof(Ether));
379 ether->ctlrno = ctlrno;
381 ether->minmtu = ETHERMINTU;
382 ether->maxmtu = ETHERMAXTU;
384 if(archether(ctlrno, ether) <= 0)
387 for(n = 0; cards[n].type; n++){
388 if(cistrcmp(cards[n].type, ether->type))
390 for(i = 0; i < ether->nopt; i++){
391 if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
392 if(parseether(ether->ea, ðer->opt[i][3]) == -1)
393 memset(ether->ea, 0, Eaddrlen);
394 }else if(cistrcmp(ether->opt[i], "fullduplex") == 0 ||
395 cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
396 ether->fullduplex = 1;
397 else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
400 if(cards[n].reset(ether))
402 snprint(name, sizeof(name), "ether%d", ctlrno);
404 if(ether->interrupt != nil)
405 intrenable(Irqlo, ether->irq, ether->interrupt,
408 i = snprint(buf, sizeof buf,
409 "#l%d: %s: %dMbps port %#lux irq %d",
410 ctlrno, ether->type, ether->mbps, ether->port,
413 i += snprint(buf+i, sizeof buf - i,
414 " addr %#lux", PADDR(ether->mem));
416 i += snprint(buf+i, sizeof buf - i,
417 " size %#luX", ether->size);
418 i += snprint(buf+i, sizeof buf - i,
419 ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
420 ether->ea[0], ether->ea[1], ether->ea[2],
421 ether->ea[3], ether->ea[4], ether->ea[5]);
422 snprint(buf+i, sizeof buf - i, "\n");
425 if(ether->mbps >= 1000)
426 netifinit(ether, name, Ntypes, 4*1024*1024);
427 else if(ether->mbps >= 100)
428 netifinit(ether, name, Ntypes, 1024*1024);
430 netifinit(ether, name, Ntypes, 65*1024);
432 ether->oq = qopen(ether->limit, Qmsg, 0, 0);
434 panic("etherreset %s", name);
435 ether->alen = Eaddrlen;
436 memmove(ether->addr, ether->ea, Eaddrlen);
437 memset(ether->bcast, 0xFF, Eaddrlen);
439 etherxx[ctlrno] = ether;
454 for(i = 0; i < MaxEther; i++){
458 if(ether->shutdown == nil) {
459 print("#l%d: no shutdown function\n", i);
462 (*ether->shutdown)(ether);
466 #define POLY 0xedb88320
468 /* really slow 32 bit crc for ethers */
470 ethercrc(uchar *p, int len)
476 for(i = 0; i < len; i++){
478 for(j = 0; j < 8; j++){
479 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
491 else if (qisclosed(oq))
492 print("outq closed ");
496 print("outq %d ", qlen(oq));
500 dumpnetif(Netif *netif)
502 print("netif %s ", netif->name);
503 print("limit %d mbps %d link %d ",
504 netif->limit, netif->mbps, netif->link);
505 print("inpkts %lld outpkts %lld errs %d\n",
506 netif->inpackets, netif->outpackets,
507 netif->crcs + netif->oerrs + netif->frames + netif->overflows +
508 netif->buffs + netif->soverflows);