1 /* if_en.c 4.81 83/06/26 */ 2 3 #include "en.h" 4 5 /* 6 * Xerox prototype (3 Mb) Ethernet interface driver. 7 */ 8 #include "../machine/pte.h" 9 10 #include "../h/param.h" 11 #include "../h/systm.h" 12 #include "../h/mbuf.h" 13 #include "../h/buf.h" 14 #include "../h/protosw.h" 15 #include "../h/socket.h" 16 #include "../h/vmmac.h" 17 #include "../h/errno.h" 18 #include "../h/ioctl.h" 19 20 #include "../net/if.h" 21 #include "../net/netisr.h" 22 #include "../net/route.h" 23 #include "../netinet/in.h" 24 #include "../netinet/in_systm.h" 25 #include "../netinet/ip.h" 26 #include "../netinet/ip_var.h" 27 #include "../netpup/pup.h" 28 29 #include "../vax/cpu.h" 30 #include "../vax/mtpr.h" 31 #include "../vaxif/if_en.h" 32 #include "../vaxif/if_enreg.h" 33 #include "../vaxif/if_uba.h" 34 #include "../vaxuba/ubareg.h" 35 #include "../vaxuba/ubavar.h" 36 37 #define ENMTU (1024+512) 38 #define ENMRU (1024+512+16) /* 16 is enough to receive trailer */ 39 40 int enprobe(), enattach(), enrint(), enxint(), encollide(); 41 struct uba_device *eninfo[NEN]; 42 u_short enstd[] = { 0 }; 43 struct uba_driver endriver = 44 { enprobe, 0, enattach, 0, enstd, "en", eninfo }; 45 #define ENUNIT(x) minor(x) 46 47 int eninit(),enoutput(),enreset(),enioctl(); 48 49 #ifdef notdef 50 /* 51 * If you need to byte swap IP's in the system, define 52 * this and do a SIOCSIFFLAGS at boot time. 53 */ 54 #define ENF_SWABIPS 0x100 55 #endif 56 57 /* 58 * Ethernet software status per interface. 59 * 60 * Each interface is referenced by a network interface structure, 61 * es_if, which the routing code uses to locate the interface. 62 * This structure contains the output queue for the interface, its address, ... 63 * We also have, for each interface, a UBA interface structure, which 64 * contains information about the UNIBUS resources held by the interface: 65 * map registers, buffered data paths, etc. Information is cached in this 66 * structure for use by the if_uba.c routines in running the interface 67 * efficiently. 68 */ 69 struct en_softc { 70 struct ifnet es_if; /* network-visible interface */ 71 struct ifuba es_ifuba; /* UNIBUS resources */ 72 short es_delay; /* current output delay */ 73 short es_mask; /* mask for current output delay */ 74 short es_lastx; /* host last transmitted to */ 75 short es_oactive; /* is output active? */ 76 short es_olen; /* length of last output */ 77 } en_softc[NEN]; 78 79 /* 80 * Do output DMA to determine interface presence and 81 * interrupt vector. DMA is too short to disturb other hosts. 82 */ 83 enprobe(reg) 84 caddr_t reg; 85 { 86 register int br, cvec; /* r11, r10 value-result */ 87 register struct endevice *addr = (struct endevice *)reg; 88 89 #ifdef lint 90 br = 0; cvec = br; br = cvec; 91 enrint(0); enxint(0); encollide(0); 92 #endif 93 addr->en_istat = 0; 94 addr->en_owc = -1; 95 addr->en_oba = 0; 96 addr->en_ostat = EN_IEN|EN_GO; 97 DELAY(100000); 98 addr->en_ostat = 0; 99 return (1); 100 } 101 102 /* 103 * Interface exists: make available by filling in network interface 104 * record. System will initialize the interface when it is ready 105 * to accept packets. 106 */ 107 enattach(ui) 108 struct uba_device *ui; 109 { 110 register struct en_softc *es = &en_softc[ui->ui_unit]; 111 112 es->es_if.if_unit = ui->ui_unit; 113 es->es_if.if_name = "en"; 114 es->es_if.if_mtu = ENMTU; 115 es->es_if.if_init = eninit; 116 es->es_if.if_output = enoutput; 117 es->es_if.if_ioctl = enioctl; 118 es->es_if.if_reset = enreset; 119 es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT; 120 #if defined(VAX750) 121 /* don't chew up 750 bdp's */ 122 if (cpu == VAX_750 && ui->ui_unit > 0) 123 es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP; 124 #endif 125 if_attach(&es->es_if); 126 } 127 128 /* 129 * Reset of interface after UNIBUS reset. 130 * If interface is on specified uba, reset its state. 131 */ 132 enreset(unit, uban) 133 int unit, uban; 134 { 135 register struct uba_device *ui; 136 137 if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 || 138 ui->ui_ubanum != uban) 139 return; 140 printf(" en%d", unit); 141 eninit(unit); 142 } 143 144 /* 145 * Initialization of interface; clear recorded pending 146 * operations, and reinitialize UNIBUS usage. 147 */ 148 eninit(unit) 149 int unit; 150 { 151 register struct en_softc *es = &en_softc[unit]; 152 register struct uba_device *ui = eninfo[unit]; 153 register struct endevice *addr; 154 struct sockaddr_in *sin = (struct sockaddr_in *)&es->es_if.if_addr; 155 int s; 156 157 if (in_netof(sin->sin_addr) == 0) 158 return; 159 if (if_ubainit(&es->es_ifuba, ui->ui_ubanum, 160 sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 161 printf("en%d: can't initialize\n", unit); 162 es->es_if.if_flags &= ~IFF_UP; 163 return; 164 } 165 addr = (struct endevice *)ui->ui_addr; 166 addr->en_istat = addr->en_ostat = 0; 167 168 /* 169 * Hang a receive and start any 170 * pending writes by faking a transmit complete. 171 */ 172 s = splimp(); 173 addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; 174 addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; 175 addr->en_istat = EN_IEN|EN_GO; 176 es->es_oactive = 1; 177 es->es_if.if_flags |= IFF_UP|IFF_RUNNING; 178 enxint(unit); 179 splx(s); 180 if_rtinit(&es->es_if, RTF_UP); 181 } 182 183 int enalldelay = 0; 184 int enlastdel = 50; 185 int enlastmask = (~0) << 5; 186 187 /* 188 * Start or restart output on interface. 189 * If interface is already active, then this is a retransmit 190 * after a collision, and just restuff registers and delay. 191 * If interface is not already active, get another datagram 192 * to send off of the interface queue, and map it to the interface 193 * before starting the output. 194 */ 195 enstart(dev) 196 dev_t dev; 197 { 198 int unit = ENUNIT(dev); 199 struct uba_device *ui = eninfo[unit]; 200 register struct en_softc *es = &en_softc[unit]; 201 register struct endevice *addr; 202 struct mbuf *m; 203 int dest; 204 205 if (es->es_oactive) 206 goto restart; 207 208 /* 209 * Not already active: dequeue another request 210 * and map it to the UNIBUS. If no more requests, 211 * just return. 212 */ 213 IF_DEQUEUE(&es->es_if.if_snd, m); 214 if (m == 0) { 215 es->es_oactive = 0; 216 return; 217 } 218 dest = mtod(m, struct en_header *)->en_dhost; 219 es->es_olen = if_wubaput(&es->es_ifuba, m); 220 #ifdef ENF_SWABIPS 221 /* 222 * The Xerox interface does word at a time DMA, so 223 * someone must do byte swapping of user data if high 224 * and low ender machines are to communicate. It doesn't 225 * belong here, but certain people depend on it, so... 226 * 227 * Should swab everybody, but this is a kludge anyway. 228 */ 229 if (es->es_if.if_flags & ENF_SWABIPS) { 230 register struct en_header *en; 231 232 en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr; 233 if (en->en_type == ENTYPE_IP) 234 enswab((caddr_t)(en + 1), (caddr_t)(en + 1), 235 es->es_olen - sizeof (struct en_header) + 1); 236 } 237 #endif 238 239 /* 240 * Ethernet cannot take back-to-back packets (no 241 * buffering in interface. To help avoid overrunning 242 * receivers, enforce a small delay (about 1ms) in interface: 243 * * between all packets when enalldelay 244 * * whenever last packet was broadcast 245 * * whenever this packet is to same host as last packet 246 */ 247 if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) { 248 es->es_delay = enlastdel; 249 es->es_mask = enlastmask; 250 } 251 es->es_lastx = dest; 252 253 restart: 254 /* 255 * Have request mapped to UNIBUS for transmission. 256 * Purge any stale data from this BDP, and start the otput. 257 */ 258 if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) 259 UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp); 260 addr = (struct endevice *)ui->ui_addr; 261 addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info; 262 addr->en_odelay = es->es_delay; 263 addr->en_owc = -((es->es_olen + 1) >> 1); 264 addr->en_ostat = EN_IEN|EN_GO; 265 es->es_oactive = 1; 266 } 267 268 /* 269 * Ethernet interface transmitter interrupt. 270 * Start another output if more data to send. 271 */ 272 enxint(unit) 273 int unit; 274 { 275 register struct uba_device *ui = eninfo[unit]; 276 register struct en_softc *es = &en_softc[unit]; 277 register struct endevice *addr = (struct endevice *)ui->ui_addr; 278 279 if (es->es_oactive == 0) 280 return; 281 if (es->es_mask && (addr->en_ostat&EN_OERROR)) { 282 es->es_if.if_oerrors++; 283 endocoll(unit); 284 return; 285 } 286 es->es_if.if_opackets++; 287 es->es_oactive = 0; 288 es->es_delay = 0; 289 es->es_mask = ~0; 290 if (es->es_ifuba.ifu_xtofree) { 291 m_freem(es->es_ifuba.ifu_xtofree); 292 es->es_ifuba.ifu_xtofree = 0; 293 } 294 if (es->es_if.if_snd.ifq_head == 0) { 295 es->es_lastx = 256; /* putatively illegal */ 296 return; 297 } 298 enstart(unit); 299 } 300 301 /* 302 * Collision on ethernet interface. Do exponential 303 * backoff, and retransmit. If have backed off all 304 * the way print warning diagnostic, and drop packet. 305 */ 306 encollide(unit) 307 int unit; 308 { 309 struct en_softc *es = &en_softc[unit]; 310 311 es->es_if.if_collisions++; 312 if (es->es_oactive == 0) 313 return; 314 endocoll(unit); 315 } 316 317 endocoll(unit) 318 int unit; 319 { 320 register struct en_softc *es = &en_softc[unit]; 321 322 /* 323 * Es_mask is a 16 bit number with n low zero bits, with 324 * n the number of backoffs. When es_mask is 0 we have 325 * backed off 16 times, and give up. 326 */ 327 if (es->es_mask == 0) { 328 printf("en%d: send error\n", unit); 329 enxint(unit); 330 return; 331 } 332 /* 333 * Another backoff. Restart with delay based on n low bits 334 * of the interval timer. 335 */ 336 es->es_mask <<= 1; 337 es->es_delay = mfpr(ICR) &~ es->es_mask; 338 enstart(unit); 339 } 340 341 struct sockaddr_pup pupsrc = { AF_PUP }; 342 struct sockaddr_pup pupdst = { AF_PUP }; 343 struct sockproto pupproto = { PF_PUP }; 344 /* 345 * Ethernet interface receiver interrupt. 346 * If input error just drop packet. 347 * Otherwise purge input buffered data path and examine 348 * packet to determine type. If can't determine length 349 * from type, then have to drop packet. Othewise decapsulate 350 * packet based on type and pass to type specific higher-level 351 * input routine. 352 */ 353 enrint(unit) 354 int unit; 355 { 356 register struct en_softc *es = &en_softc[unit]; 357 struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr; 358 register struct en_header *en; 359 struct mbuf *m; 360 int len; short resid; 361 register struct ifqueue *inq; 362 int off; 363 364 es->es_if.if_ipackets++; 365 366 /* 367 * Purge BDP; drop if input error indicated. 368 */ 369 if (es->es_ifuba.ifu_flags & UBA_NEEDBDP) 370 UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp); 371 if (addr->en_istat&EN_IERROR) { 372 es->es_if.if_ierrors++; 373 goto setup; 374 } 375 376 /* 377 * Calculate input data length. 378 * Get pointer to ethernet header (in input buffer). 379 * Deal with trailer protocol: if type is PUP trailer 380 * get true type from first 16-bit word past data. 381 * Remember that type was trailer by setting off. 382 */ 383 resid = addr->en_iwc; 384 if (resid) 385 resid |= 0176000; 386 len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1; 387 len -= sizeof (struct en_header); 388 if (len > ENMRU) 389 goto setup; /* sanity */ 390 en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr); 391 en->en_type = ntohs(en->en_type); 392 #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) 393 if (en->en_type >= ENTYPE_TRAIL && 394 en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) { 395 off = (en->en_type - ENTYPE_TRAIL) * 512; 396 if (off > ENMTU) 397 goto setup; /* sanity */ 398 en->en_type = ntohs(*endataaddr(en, off, u_short *)); 399 resid = ntohs(*(endataaddr(en, off+2, u_short *))); 400 if (off + resid > len) 401 goto setup; /* sanity */ 402 len = off + resid; 403 } else 404 off = 0; 405 if (len == 0) 406 goto setup; 407 #ifdef ENF_SWABIPS 408 if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP) 409 enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len); 410 #endif 411 /* 412 * Pull packet off interface. Off is nonzero if packet 413 * has trailing header; if_rubaget will then force this header 414 * information to be at the front, but we still have to drop 415 * the type and length which are at the front of any trailer data. 416 */ 417 m = if_rubaget(&es->es_ifuba, len, off); 418 if (m == 0) 419 goto setup; 420 if (off) { 421 m->m_off += 2 * sizeof (u_short); 422 m->m_len -= 2 * sizeof (u_short); 423 } 424 switch (en->en_type) { 425 426 #ifdef INET 427 case ENTYPE_IP: 428 schednetisr(NETISR_IP); 429 inq = &ipintrq; 430 break; 431 #endif 432 #ifdef PUP 433 case ENTYPE_PUP: { 434 struct pup_header *pup = mtod(m, struct pup_header *); 435 436 pupproto.sp_protocol = pup->pup_type; 437 bcopy((caddr_t)pup->pup_dnet, (caddr_t)pupdst.spup_net, 438 sizeof (struct pupport)); 439 bcopy((caddr_t)pup->pup_snet, (caddr_t)pupsrc.spup_net, 440 sizeof (struct pupport)); 441 raw_input(m, &pupproto, (struct sockaddr *)&pupsrc, 442 (struct sockaddr *)&pupdst); 443 goto setup; 444 } 445 #endif 446 default: 447 m_freem(m); 448 goto setup; 449 } 450 451 if (IF_QFULL(inq)) { 452 IF_DROP(inq); 453 m_freem(m); 454 } else 455 IF_ENQUEUE(inq, m); 456 457 setup: 458 /* 459 * Reset for next packet. 460 */ 461 addr->en_iba = es->es_ifuba.ifu_r.ifrw_info; 462 addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1; 463 addr->en_istat = EN_IEN|EN_GO; 464 } 465 466 /* 467 * Ethernet output routine. 468 * Encapsulate a packet of type family for the local net. 469 * Use trailer local net encapsulation if enough data in first 470 * packet leaves a multiple of 512 bytes of data in remainder. 471 */ 472 enoutput(ifp, m0, dst) 473 struct ifnet *ifp; 474 struct mbuf *m0; 475 struct sockaddr *dst; 476 { 477 int type, dest, s, error; 478 register struct mbuf *m = m0; 479 register struct en_header *en; 480 register int off; 481 482 switch (dst->sa_family) { 483 484 #ifdef INET 485 case AF_INET: 486 dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr; 487 if (in_lnaof(*((struct in_addr *)&dest)) >= 0x100) { 488 error = EPERM; /* ??? */ 489 goto bad; 490 } 491 dest = (dest >> 24) & 0xff; 492 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 493 /* need per host negotiation */ 494 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 495 if (off > 0 && (off & 0x1ff) == 0 && 496 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 497 type = ENTYPE_TRAIL + (off>>9); 498 m->m_off -= 2 * sizeof (u_short); 499 m->m_len += 2 * sizeof (u_short); 500 *mtod(m, u_short *) = htons((u_short)ENTYPE_IP); 501 *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); 502 goto gottrailertype; 503 } 504 type = ENTYPE_IP; 505 off = 0; 506 goto gottype; 507 #endif 508 #ifdef PUP 509 case AF_PUP: 510 dest = ((struct sockaddr_pup *)dst)->spup_host; 511 type = ENTYPE_PUP; 512 off = 0; 513 goto gottype; 514 #endif 515 516 default: 517 printf("en%d: can't handle af%d\n", ifp->if_unit, 518 dst->sa_family); 519 error = EAFNOSUPPORT; 520 goto bad; 521 } 522 523 gottrailertype: 524 /* 525 * Packet to be sent as trailer: move first packet 526 * (control information) to end of chain. 527 */ 528 while (m->m_next) 529 m = m->m_next; 530 m->m_next = m0; 531 m = m0->m_next; 532 m0->m_next = 0; 533 m0 = m; 534 535 gottype: 536 /* 537 * Add local net header. If no space in first mbuf, 538 * allocate another. 539 */ 540 if (m->m_off > MMAXOFF || 541 MMINOFF + sizeof (struct en_header) > m->m_off) { 542 m = m_get(M_DONTWAIT, MT_HEADER); 543 if (m == 0) { 544 error = ENOBUFS; 545 goto bad; 546 } 547 m->m_next = m0; 548 m->m_off = MMINOFF; 549 m->m_len = sizeof (struct en_header); 550 } else { 551 m->m_off -= sizeof (struct en_header); 552 m->m_len += sizeof (struct en_header); 553 } 554 en = mtod(m, struct en_header *); 555 en->en_shost = ifp->if_host[0]; 556 en->en_dhost = dest; 557 en->en_type = htons((u_short)type); 558 559 /* 560 * Queue message on interface, and start output if interface 561 * not yet active. 562 */ 563 s = splimp(); 564 if (IF_QFULL(&ifp->if_snd)) { 565 IF_DROP(&ifp->if_snd); 566 error = ENOBUFS; 567 goto qfull; 568 } 569 IF_ENQUEUE(&ifp->if_snd, m); 570 if (en_softc[ifp->if_unit].es_oactive == 0) 571 enstart(ifp->if_unit); 572 splx(s); 573 return (0); 574 qfull: 575 m0 = m; 576 splx(s); 577 bad: 578 m_freem(m0); 579 return (error); 580 } 581 582 /* 583 * Process an ioctl request. 584 */ 585 enioctl(ifp, cmd, data) 586 register struct ifnet *ifp; 587 int cmd; 588 caddr_t data; 589 { 590 struct ifreq *ifr = (struct ifreq *)data; 591 int s = splimp(), error = 0; 592 593 switch (cmd) { 594 595 case SIOCSIFADDR: 596 if (ifp->if_flags & IFF_RUNNING) 597 if_rtinit(ifp, -1); /* delete previous route */ 598 ensetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr); 599 if (ifp->if_flags & IFF_RUNNING) 600 if_rtinit(ifp, RTF_UP); 601 else 602 eninit(ifp->if_unit); 603 break; 604 605 default: 606 error = EINVAL; 607 } 608 splx(s); 609 return (error); 610 } 611 612 ensetaddr(ifp, sin) 613 register struct ifnet *ifp; 614 register struct sockaddr_in *sin; 615 { 616 struct endevice *enaddr; 617 618 ifp->if_net = in_netof(sin->sin_addr); 619 enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr; 620 ifp->if_host[0] = (~enaddr->en_addr) & 0xff; 621 sin = (struct sockaddr_in *)&ifp->if_addr; 622 sin->sin_family = AF_INET; 623 sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]); 624 sin = (struct sockaddr_in *)&ifp->if_broadaddr; 625 sin->sin_family = AF_INET; 626 sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); 627 ifp->if_flags |= IFF_BROADCAST; 628 } 629 630 #ifdef ENF_SWABIPS 631 /* 632 * Swab bytes 633 * Jeffrey Mogul, Stanford 634 */ 635 enswab(from, to, n) 636 register caddr_t *from, *to; 637 register int n; 638 { 639 register unsigned long temp; 640 641 n >>= 1; n++; 642 #define STEP temp = *from++,*to++ = *from++,*to++ = temp 643 /* round to multiple of 8 */ 644 while ((--n) & 07) 645 STEP; 646 n >>= 3; 647 while (--n >= 0) { 648 STEP; STEP; STEP; STEP; 649 STEP; STEP; STEP; STEP; 650 } 651 } 652 #endif 653