2 #include "../port/lib.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
14 static Ether *etherxx[MaxEther];
17 etherattach(char* spec)
25 ctlrno = strtoul(spec, &p, 0);
26 if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
29 if(etherxx[ctlrno] == 0)
32 chan = devattach('l', spec);
38 if(etherxx[ctlrno]->attach)
39 etherxx[ctlrno]->attach(etherxx[ctlrno]);
45 etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
47 return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
51 etherstat(Chan* chan, uchar* dp, int n)
53 return netifstat(etherxx[chan->dev], chan, dp, n);
57 etheropen(Chan* chan, int omode)
59 return netifopen(etherxx[chan->dev], chan, omode);
63 ethercreate(Chan*, char*, int, ulong)
70 etherclose(Chan* chan)
72 netifclose(etherxx[chan->dev], chan);
76 etherread(Chan* chan, void* buf, long n, vlong off)
81 ether = etherxx[chan->dev];
82 if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
84 * With some controllers it is necessary to reach
85 * into the chip to extract statistics.
87 if(NETTYPE(chan->qid.path) == Nifstatqid)
88 return ether->ifstat(ether, buf, n, offset);
89 else if(NETTYPE(chan->qid.path) == Nstatqid)
90 ether->ifstat(ether, buf, 0, offset);
93 return netifread(ether, chan, buf, n, offset);
97 etherbread(Chan* chan, long n, ulong offset)
99 return netifbread(etherxx[chan->dev], chan, n, offset);
103 etherwstat(Chan* chan, uchar* dp, int n)
105 return netifwstat(etherxx[chan->dev], chan, dp, n);
109 etherrtrace(Netfile* f, Etherpkt* pkt, int len)
114 if(qwindow(f->in) <= 0)
123 memmove(bp->wp, pkt->d, n);
124 i = TK2MS(MACHP(0)->ticks);
136 etheriq(Ether* ether, Block* bp, int fromwire)
140 int len, multi, tome, fromme;
141 Netfile **ep, *f, **fp, *fx;
146 pkt = (Etherpkt*)bp->rp;
148 type = (pkt->type[0]<<8)|pkt->type[1];
150 ep = ðer->f[Ntypes];
152 multi = pkt->d[0] & 1;
153 /* check for valid multicast addresses */
154 if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
155 if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
165 tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
166 fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
169 * Multiplex the packet to all the connections which want it.
170 * If the packet is not to be used subsequently (fromwire != 0),
171 * attempt to simply pass it into one of the connections, thereby
172 * saving a copy of the data (usual case hopefully).
174 for(fp = ether->f; fp < ep; fp++){
176 if(f->type == type || f->type < 0)
177 if(tome || multi || f->prom){
178 /* Don't want to hear bridged packets */
179 if(f->bridge && !fromwire && !fromme)
182 if(fromwire && fx == 0)
184 else if(xbp = iallocb(len)){
185 memmove(xbp->wp, pkt, len);
187 if(qpass(f->in, xbp) < 0) {
188 // print("soverflow for f->in\n");
193 // print("soverflow iallocb\n");
198 etherrtrace(f, pkt, len);
203 if(qpass(fx->in, bp) < 0) {
204 // print("soverflow for fx->in\n");
218 etheroq(Ether* ether, Block* bp)
220 int len, loopback, s;
226 * Check if the packet has to be placed back onto the input queue,
227 * i.e. if it's a loopback or broadcast packet or the interface is
228 * in promiscuous mode.
229 * If it's a loopback packet indicate to etheriq that the data isn't
230 * needed and return, etheriq will pass-on or free the block.
231 * To enable bridging to work, only packets that were originated
232 * by this interface are fed back.
234 pkt = (Etherpkt*)bp->rp;
236 loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
237 if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
239 etheriq(ether, bp, 0);
245 print("etheroq: WARNING: ether->oq full!\n");
246 qbwrite(ether->oq, bp);
247 if(ether->transmit != nil)
248 ether->transmit(ether);
256 etherwrite(Chan* chan, void* buf, long n, vlong)
263 ether = etherxx[chan->dev];
264 if(NETTYPE(chan->qid.path) != Ndataqid) {
265 nn = netifwrite(ether, chan, buf, n);
268 cb = parsecmd(buf, n);
269 if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
273 onoff = atoi(cb->f[1]);
274 qnoblock(ether->oq, onoff);
280 return ether->ctl(ether,buf,n);
285 if(n > ether->maxmtu)
287 if(n < ether->minmtu)
295 memmove(bp->rp, buf, n);
296 memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
300 return etheroq(ether, bp);
304 etherbwrite(Chan* chan, Block* bp, ulong)
310 if(NETTYPE(chan->qid.path) != Ndataqid){
315 n = etherwrite(chan, bp->rp, n, 0);
320 ether = etherxx[chan->dev];
322 if(n > ether->maxmtu){
326 if(n < ether->minmtu){
331 return etheroq(ether, bp);
336 int (*reset)(Ether*);
340 addethercard(char* t, int (*r)(Ether*))
344 if(ncard == MaxEther)
345 panic("too many ether cards");
346 cards[ncard].type = t;
347 cards[ncard].reset = r;
352 parseether(uchar *to, char *from)
359 for(i = 0; i < Eaddrlen; i++){
367 to[i] = strtoul(nip, 0, 16);
375 etherprobe(int cardno, int ctlrno)
380 char buf[128], name[32];
382 ether = malloc(sizeof(Ether));
383 memset(ether, 0, sizeof(Ether));
384 ether->ctlrno = ctlrno;
385 ether->tbdf = BUSUNKNOWN;
387 ether->minmtu = ETHERMINTU;
388 ether->maxmtu = ETHERMAXTU;
391 if(isaconfig("ether", ctlrno, ether) == 0){
395 for(cardno = 0; cards[cardno].type; cardno++){
396 if(cistrcmp(cards[cardno].type, ether->type))
398 for(i = 0; i < ether->nopt; i++){
399 if(strncmp(ether->opt[i], "ea=", 3))
401 if(parseether(ether->ea, ðer->opt[i][3]))
402 memset(ether->ea, 0, Eaddrlen);
408 if(cardno >= MaxEther || cards[cardno].type == nil){
412 if(cards[cardno].reset(ether) < 0){
418 * IRQ2 doesn't really exist, it's used to gang the interrupt
419 * controllers together. A device set to IRQ2 will appear on
420 * the second interrupt controller as IRQ9.
424 snprint(name, sizeof(name), "ether%d", ctlrno);
427 * If ether->irq is <0, it is a hack to indicate no interrupt
431 intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
433 i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
434 ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
436 i += sprint(buf+i, " addr 0x%luX", ether->mem);
438 i += sprint(buf+i, " size 0x%luX", ether->size);
439 i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
440 ether->ea[0], ether->ea[1], ether->ea[2],
441 ether->ea[3], ether->ea[4], ether->ea[5]);
445 /* compute log10(ether->mbps) into lg */
446 for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
450 if (lg > 14) /* 2^(14+17) = 2³¹ */
452 /* allocate larger output queues for higher-speed interfaces */
453 bsz = 1UL << (lg + 17); /* 2¹⁷ = 128K, bsz = 2ⁿ × 128K */
454 while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
457 netifinit(ether, name, Ntypes, bsz);
458 if(ether->oq == nil) {
459 ether->oq = qopen(bsz, Qmsg, 0, 0);
463 panic("etherreset %s: can't allocate output queue of %ld bytes",
465 ether->alen = Eaddrlen;
466 memmove(ether->addr, ether->ea, Eaddrlen);
467 memset(ether->bcast, 0xFF, Eaddrlen);
478 for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
479 if((ether = etherprobe(-1, ctlrno)) == nil)
481 etherxx[ctlrno] = ether;
484 if(getconf("*noetherprobe"))
488 while(cards[cardno].type != nil && ctlrno < MaxEther){
489 if(etherxx[ctlrno] != nil){
493 if((ether = etherprobe(cardno, ctlrno)) == nil){
497 etherxx[ctlrno] = ether;
508 for(i = 0; i < MaxEther; i++){
512 if(ether->shutdown == nil) {
513 print("#l%d: no shutdown fuction\n", i);
516 (*ether->shutdown)(ether);
521 #define POLY 0xedb88320
523 /* really slow 32 bit crc for ethers */
525 ethercrc(uchar *p, int len)
531 for(i = 0; i < len; i++){
533 for(j = 0; j < 8; j++){
534 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);