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