devether.c (10561B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "io.h" 7 #include "ureg.h" 8 #include "error.h" 9 #include "netif.h" 10 11 #include "etherif.h" 12 13 extern int memsize; 14 static Ether *etherxx[MaxEther]; 15 16 Chan* 17 etherattach(char* spec) 18 { 19 ulong ctlrno; 20 char *p; 21 Chan *chan; 22 23 ctlrno = 0; 24 if(spec && *spec){ 25 ctlrno = strtoul(spec, &p, 0); 26 if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) 27 error(Ebadarg); 28 } 29 if(etherxx[ctlrno] == 0) 30 error(Enodev); 31 32 chan = devattach('l', spec); 33 if(waserror()){ 34 chanfree(chan); 35 nexterror(); 36 } 37 chan->dev = ctlrno; 38 if(etherxx[ctlrno]->attach) 39 etherxx[ctlrno]->attach(etherxx[ctlrno]); 40 poperror(); 41 return chan; 42 } 43 44 static Walkqid* 45 etherwalk(Chan* chan, Chan* nchan, char** name, int nname) 46 { 47 return netifwalk(ðerxx[chan->dev]->ni, chan, nchan, name, nname); 48 } 49 50 static int 51 etherstat(Chan* chan, uchar* dp, int n) 52 { 53 return netifstat(ðerxx[chan->dev]->ni, chan, dp, n); 54 } 55 56 static Chan* 57 etheropen(Chan* chan, int omode) 58 { 59 return netifopen(ðerxx[chan->dev]->ni, chan, omode); 60 } 61 62 static void 63 ethercreate(Chan* ch, char* c, int i, ulong ul) 64 { 65 } 66 67 static void 68 etherclose(Chan* chan) 69 { 70 netifclose(ðerxx[chan->dev]->ni, chan); 71 } 72 73 static long 74 etherread(Chan* chan, void* buf, long n, vlong off) 75 { 76 Ether *ether; 77 ulong offset = off; 78 79 ether = etherxx[chan->dev]; 80 if((chan->qid.type & QTDIR) == 0 && ether->ifstat){ 81 /* 82 * With some controllers it is necessary to reach 83 * into the chip to extract statistics. 84 */ 85 if(NETTYPE(chan->qid.path) == Nifstatqid) 86 return ether->ifstat(ether, buf, n, offset); 87 else if(NETTYPE(chan->qid.path) == Nstatqid) 88 ether->ifstat(ether, buf, 0, offset); 89 } 90 91 return netifread(ðer->ni, chan, buf, n, offset); 92 } 93 94 static Block* 95 etherbread(Chan* chan, long n, ulong offset) 96 { 97 return netifbread(ðerxx[chan->dev]->ni, chan, n, offset); 98 } 99 100 static int 101 etherwstat(Chan* chan, uchar* dp, int n) 102 { 103 return netifwstat(ðerxx[chan->dev]->ni, chan, dp, n); 104 } 105 106 static void 107 etherrtrace(Netfile* f, Etherpkt* pkt, int len) 108 { 109 int i, n; 110 Block *bp; 111 112 if(qwindow(f->in) <= 0) 113 return; 114 if(len > 58) 115 n = 58; 116 else 117 n = len; 118 bp = iallocb(64); 119 if(bp == nil) 120 return; 121 memmove(bp->wp, pkt->d, n); 122 i = TK2MS(MACHP(0)->tscticks); 123 bp->wp[58] = len>>8; 124 bp->wp[59] = len; 125 bp->wp[60] = i>>24; 126 bp->wp[61] = i>>16; 127 bp->wp[62] = i>>8; 128 bp->wp[63] = i; 129 bp->wp += 64; 130 qpass(f->in, bp); 131 } 132 133 Block* 134 etheriq(Ether* ether, Block* bp, int fromwire) 135 { 136 Etherpkt *pkt; 137 ushort type; 138 int len, multi, tome, fromme; 139 Netfile **ep, *f, **fp, *fx; 140 Block *xbp; 141 142 ether->ni.inpackets++; 143 144 pkt = (Etherpkt*)bp->rp; 145 len = BLEN(bp); 146 type = (pkt->type[0]<<8)|pkt->type[1]; 147 fx = 0; 148 ep = ðer->ni.f[Ntypes]; 149 150 multi = pkt->d[0] & 1; 151 /* check for valid multicast addresses */ 152 if(multi && memcmp(pkt->d, ether->ni.bcast, sizeof(pkt->d)) != 0 && ether->ni.prom == 0){ 153 if(!activemulti(ðer->ni, pkt->d, sizeof(pkt->d))){ 154 if(fromwire){ 155 freeb(bp); 156 bp = 0; 157 } 158 return bp; 159 } 160 } 161 162 /* is it for me? */ 163 tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; 164 fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0; 165 166 /* 167 * Multiplex the packet to all the connections which want it. 168 * If the packet is not to be used subsequently (fromwire != 0), 169 * attempt to simply pass it into one of the connections, thereby 170 * saving a copy of the data (usual case hopefully). 171 */ 172 for(fp = ether->ni.f; fp < ep; fp++){ 173 if(f = *fp) 174 if(f->type == type || f->type < 0) 175 if(tome || multi || f->prom){ 176 /* Don't want to hear bridged packets */ 177 if(f->bridge && !fromwire && !fromme) 178 continue; 179 if(!f->headersonly){ 180 if(fromwire && fx == 0) 181 fx = f; 182 else if(xbp = iallocb(len)){ 183 memmove(xbp->wp, pkt, len); 184 xbp->wp += len; 185 if(qpass(f->in, xbp) < 0) { 186 print("soverflow for f->in\n"); 187 ether->ni.soverflows++; 188 } 189 } 190 else { 191 print("soverflow iallocb\n"); 192 ether->ni.soverflows++; 193 } 194 } 195 else 196 etherrtrace(f, pkt, len); 197 } 198 } 199 200 if(fx){ 201 if(qpass(fx->in, bp) < 0) { 202 print("soverflow for fx->in\n"); 203 ether->ni.soverflows++; 204 } 205 return 0; 206 } 207 if(fromwire){ 208 freeb(bp); 209 return 0; 210 } 211 212 return bp; 213 } 214 215 static int 216 etheroq(Ether* ether, Block* bp) 217 { 218 int len, loopback, s; 219 Etherpkt *pkt; 220 221 ether->ni.outpackets++; 222 223 /* 224 * Check if the packet has to be placed back onto the input queue, 225 * i.e. if it's a loopback or broadcast packet or the interface is 226 * in promiscuous mode. 227 * If it's a loopback packet indicate to etheriq that the data isn't 228 * needed and return, etheriq will pass-on or free the block. 229 * To enable bridging to work, only packets that were originated 230 * by this interface are fed back. 231 */ 232 pkt = (Etherpkt*)bp->rp; 233 len = BLEN(bp); 234 loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; 235 if(loopback || memcmp(pkt->d, ether->ni.bcast, sizeof(pkt->d)) == 0 || ether->ni.prom){ 236 s = splhi(); 237 etheriq(ether, bp, 0); 238 splx(s); 239 } 240 241 if(!loopback){ 242 if(qfull(ether->oq)) 243 print("etheroq: WARNING: ether->oq full!\n"); 244 qbwrite(ether->oq, bp); 245 if(ether->transmit != nil) 246 ether->transmit(ether); 247 } else 248 freeb(bp); 249 250 return len; 251 } 252 253 static long 254 etherwrite(Chan* chan, void* buf, long n, vlong v) 255 { 256 Ether *ether; 257 Block *bp; 258 int nn, onoff; 259 Cmdbuf *cb; 260 261 ether = etherxx[chan->dev]; 262 if(NETTYPE(chan->qid.path) != Ndataqid) { 263 nn = netifwrite(ðer->ni, chan, buf, n); 264 if(nn >= 0) 265 return nn; 266 cb = parsecmd(buf, n); 267 if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){ 268 if(cb->nf <= 1) 269 onoff = 1; 270 else 271 onoff = atoi(cb->f[1]); 272 qnoblock(ether->oq, onoff); 273 free(cb); 274 return n; 275 } 276 free(cb); 277 if(ether->ctl!=nil) 278 return ether->ctl(ether,buf,n); 279 280 error(Ebadctl); 281 } 282 283 if(n > ether->maxmtu) 284 error(Etoobig); 285 if(n < ether->minmtu) 286 error(Etoosmall); 287 288 bp = allocb(n); 289 if(waserror()){ 290 freeb(bp); 291 nexterror(); 292 } 293 memmove(bp->rp, buf, n); 294 memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen); 295 poperror(); 296 bp->wp += n; 297 298 return etheroq(ether, bp); 299 } 300 301 static long 302 etherbwrite(Chan* chan, Block* bp, ulong u) 303 { 304 Ether *ether; 305 long n; 306 307 n = BLEN(bp); 308 if(NETTYPE(chan->qid.path) != Ndataqid){ 309 if(waserror()) { 310 freeb(bp); 311 nexterror(); 312 } 313 n = etherwrite(chan, bp->rp, n, 0); 314 poperror(); 315 freeb(bp); 316 return n; 317 } 318 ether = etherxx[chan->dev]; 319 320 if(n > ether->maxmtu){ 321 freeb(bp); 322 error(Etoobig); 323 } 324 if(n < ether->minmtu){ 325 freeb(bp); 326 error(Etoosmall); 327 } 328 329 return etheroq(ether, bp); 330 } 331 332 static struct { 333 char* type; 334 int (*reset)(Ether*); 335 } cards[MaxEther+1]; 336 337 void 338 addethercard(char* t, int (*r)(Ether*)) 339 { 340 static int ncard; 341 342 if(ncard == MaxEther) 343 panic("too many ether cards"); 344 cards[ncard].type = t; 345 cards[ncard].reset = r; 346 ncard++; 347 } 348 349 int 350 parseether(uchar *to, char *from) 351 { 352 char nip[4]; 353 char *p; 354 int i; 355 356 p = from; 357 for(i = 0; i < Eaddrlen; i++){ 358 if(*p == 0) 359 return -1; 360 nip[0] = *p++; 361 if(*p == 0) 362 return -1; 363 nip[1] = *p++; 364 nip[2] = 0; 365 to[i] = strtoul(nip, 0, 16); 366 if(*p == ':') 367 p++; 368 } 369 return 0; 370 } 371 372 static Ether* 373 etherprobe(int cardno, int ctlrno) 374 { 375 int i, lg; 376 ulong mb, bsz; 377 Ether *ether; 378 char buf[128], name[32]; 379 380 ether = malloc(sizeof(Ether)); 381 memset(ether, 0, sizeof(Ether)); 382 ether->ctlrno = ctlrno; 383 ether->tbdf = BUSUNKNOWN; 384 ether->ni.mbps = 10; 385 ether->minmtu = ETHERMINTU; 386 ether->maxmtu = ETHERMAXTU; 387 388 if(cardno < 0){ 389 for(cardno = 0; cards[cardno].type; cardno++){ 390 for(i = 0; i < ether->isac.nopt; i++){ 391 if(strncmp(ether->isac.opt[i], "ea=", 3)) 392 continue; 393 if(parseether(ether->ea, ðer->isac.opt[i][3])) 394 memset(ether->ea, 0, Eaddrlen); 395 } 396 break; 397 } 398 } 399 400 if(cardno >= MaxEther || cards[cardno].type == nil){ 401 free(ether); 402 return nil; 403 } 404 if(cards[cardno].reset(ether) < 0){ 405 free(ether); 406 return nil; 407 } 408 409 /* 410 * IRQ2 doesn't really exist, it's used to gang the interrupt 411 * controllers together. A device set to IRQ2 will appear on 412 * the second interrupt controller as IRQ9. 413 */ 414 if(ether->isac.irq == 2) 415 ether->isac.irq = 9; 416 snprint(name, sizeof(name), "ether%d", ctlrno); 417 418 i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d", 419 ctlrno, cards[cardno].type, ether->ni.mbps, ether->isac.port, ether->isac.irq); 420 if(ether->isac.mem) 421 i += sprint(buf+i, " addr 0x%luX", ether->isac.mem); 422 if(ether->isac.size) 423 i += sprint(buf+i, " size 0x%luX", ether->isac.size); 424 i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 425 ether->ea[0], ether->ea[1], ether->ea[2], 426 ether->ea[3], ether->ea[4], ether->ea[5]); 427 sprint(buf+i, "\n"); 428 print(buf); 429 430 /* compute log10(ether->ni.mbps) into lg */ 431 for(lg = 0, mb = ether->ni.mbps; mb >= 10; lg++) 432 mb /= 10; 433 if (lg > 0) 434 lg--; 435 if (lg > 14) /* 2^(14+17) = 2ⁱ */ 436 lg = 14; 437 /* allocate larger output queues for higher-speed interfaces */ 438 bsz = 1UL << (lg + 17); /* 2ⁱ⁷ = 128K, bsz = 2ⁿ × 128K */ 439 while (bsz > memsize && bsz > 128*1024) 440 bsz /= 2; 441 442 netifinit(ðer->ni, name, Ntypes, bsz); 443 if(ether->oq == nil) { 444 ether->oq = qopen(bsz, Qmsg, 0, 0); 445 ether->ni.limit = bsz; 446 } 447 if(ether->oq == nil) 448 panic("etherreset %s: can't allocate output queue of %ld bytes", 449 name, bsz); 450 ether->ni.alen = Eaddrlen; 451 memmove(ether->ni.addr, ether->ea, Eaddrlen); 452 memset(ether->ni.bcast, 0xFF, Eaddrlen); 453 454 return ether; 455 } 456 457 static void 458 etherreset(void) 459 { 460 Ether *ether; 461 int cardno, ctlrno; 462 463 for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ 464 if((ether = etherprobe(-1, ctlrno)) == nil) 465 continue; 466 etherxx[ctlrno] = ether; 467 } 468 469 cardno = ctlrno = 0; 470 while(cards[cardno].type != nil && ctlrno < MaxEther){ 471 if(etherxx[ctlrno] != nil){ 472 ctlrno++; 473 continue; 474 } 475 if((ether = etherprobe(cardno, ctlrno)) == nil){ 476 cardno++; 477 continue; 478 } 479 etherxx[ctlrno] = ether; 480 ctlrno++; 481 } 482 } 483 484 static void 485 ethershutdown(void) 486 { 487 Ether *ether; 488 int i; 489 490 for(i = 0; i < MaxEther; i++){ 491 ether = etherxx[i]; 492 if(ether == nil) 493 continue; 494 if(ether->shutdown == nil) { 495 print("#l%d: no shutdown fuction\n", i); 496 continue; 497 } 498 (*ether->shutdown)(ether); 499 } 500 } 501 502 503 #define POLY 0xedb88320 504 505 /* really slow 32 bit crc for ethers */ 506 ulong 507 ethercrc(uchar *p, int len) 508 { 509 int i, j; 510 ulong crc, b; 511 512 crc = 0xffffffff; 513 for(i = 0; i < len; i++){ 514 b = *p++; 515 for(j = 0; j < 8; j++){ 516 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); 517 b >>= 1; 518 } 519 } 520 return crc; 521 } 522 523 Dev etherdevtab = { 524 'l', 525 "ether", 526 527 etherreset, 528 devinit, 529 ethershutdown, 530 etherattach, 531 etherwalk, 532 etherstat, 533 etheropen, 534 ethercreate, 535 etherclose, 536 etherread, 537 etherbread, 538 etherwrite, 539 etherbwrite, 540 devremove, 541 etherwstat, 542 };