1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * from: $Hdr: if_en.c,v 4.300 91/06/09 06:25:54 root Rel41 $ SONY 11 * 12 * @(#)if_en.c 7.1 (Berkeley) 06/04/92 13 */ 14 15 #include "en.h" 16 #include "rawether.h" 17 #include "bpfilter.h" 18 19 #if NEN > 0 20 21 /* 22 * Interlan Ethernet Communications Controller interface 23 */ 24 #include "types.h" 25 #include "../include/fix_machine_type.h" 26 #include "../include/pte.h" 27 28 #include "param.h" 29 #include "systm.h" 30 #include "mbuf.h" 31 #include "buf.h" 32 #include "protosw.h" 33 #include "socket.h" 34 #include "ioctl.h" 35 #include "errno.h" 36 #include "time.h" 37 #include "cdefs.h" 38 39 #include "net/if.h" 40 #include "net/netisr.h" 41 #include "net/route.h" 42 43 #ifdef INET 44 #include "netinet/in.h" 45 #include "netinet/in_systm.h" 46 #include "netinet/in_var.h" 47 #include "netinet/ip.h" 48 #include "netinet/if_ether.h" 49 #endif 50 51 #include "../if/if_news.h" 52 #include "../if/if_en.h" 53 54 #ifdef CPU_SINGLE 55 #include "../hbdev/hbvar.h" 56 #define iop_device hb_device 57 #define iop_driver hb_driver 58 #define ii_unit hi_unit 59 #define ii_intr hi_intr 60 #define ii_alive hi_alive 61 #else 62 #include "../iop/iopvar.h" 63 #endif 64 65 int enprobe(), enattach(), enrint(), enxint(); 66 struct mbuf *m_devget(); 67 68 #ifdef CPU_SINGLE 69 struct hb_device *eninfo[NEN]; 70 struct hb_driver endriver = { enprobe, 0, enattach, 0, 0, "en", eninfo }; 71 #else 72 struct iop_device *eninfo[NEN]; 73 struct iop_driver endriver = { enprobe, 0, enattach, 0, "en", eninfo }; 74 #endif 75 76 #define ENUNIT(x) minor(x) 77 78 int eninit(),enoutput(),enioctl(),enreset(),enwatch(),enstart(); 79 int endebug = 0; 80 81 struct ether_addr { 82 u_char addr[6]; 83 }; 84 85 extern struct ifnet loif; 86 87 struct en_softc en_softc[NEN]; 88 struct ether_addr myether[NEN]; 89 90 #if NBPFILTER > 0 91 #include "../net/bpf.h" 92 caddr_t en_bpf[NEN]; 93 #endif 94 95 enprobe(ii) 96 struct iop_device *ii; 97 { 98 99 return (en_probe(ii)); 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. A STATUS command is done to get the ethernet 106 * address and other interesting data. 107 */ 108 enattach(ii) 109 register struct iop_device *ii; 110 { 111 register struct en_softc *es = &en_softc[ii->ii_unit]; 112 register struct ifnet *ifp = &es->es_if; 113 extern char *ether_sprintf(); 114 115 en_attach(ii->ii_unit); 116 bcopy((caddr_t)es->es_addr, &myether[ii->ii_unit], 117 sizeof(struct ether_addr)); 118 printf("en%d: hardware address %s\n", 119 ii->ii_unit, ether_sprintf((u_char *)es->es_addr)); 120 ifp->if_unit = ii->ii_unit; 121 ifp->if_name = "en"; 122 ifp->if_mtu = ETHERMTU; 123 ifp->if_init = eninit; 124 ifp->if_ioctl = enioctl; 125 ifp->if_output = ether_output; 126 #ifdef NOTDEF /* KU:XXX if_reset is obsolete */ 127 ifp->if_reset = enreset; 128 #endif 129 ifp->if_start = enstart; 130 ifp->if_flags = IFF_BROADCAST; 131 #if NBPFILTER > 0 132 { 133 static struct bpf_devp dev = 134 { DLT_EN10MB, sizeof(struct ether_header) }; 135 136 bpfattach(&en_bpf[ii->ii_unit], ifp, &dev); 137 } 138 #endif 139 if_attach(ifp); 140 } 141 142 /* 143 * Reset of interface after IOP reset. 144 */ 145 enreset(unit) 146 int unit; 147 { 148 register struct iop_device *ii; 149 150 if (unit >= NEN || (ii = eninfo[unit]) == 0 || ii->ii_alive == 0) 151 return; 152 printf(" en%d", unit); 153 en_softc[unit].es_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 154 en_softc[unit].es_flags &= ~ENF_RUNNING; 155 eninit(unit); 156 } 157 158 /* 159 * Initialization of interface; clear recorded pending 160 * operations, and reinitialize IOP usage. 161 */ 162 eninit(unit) 163 int unit; 164 { 165 register struct en_softc *es = &en_softc[unit]; 166 register struct ifnet *ifp = &es->es_if; 167 int s; 168 169 /* not yet, if address still unknown */ 170 if (ifp->if_addrlist == (struct ifaddr *)0) 171 return; 172 if (es->es_flags & ENF_RUNNING) 173 return; 174 if ((ifp->if_flags & IFF_RUNNING) == 0) { 175 if (if_newsinit(&es->es_ifnews, 176 sizeof (struct en_rheader), (int)btoc(ETHERMTU)) == 0) { 177 printf("en%d: can't initialize\n", unit); 178 es->es_if.if_flags &= ~IFF_UP; 179 return; 180 } 181 ifp->if_watchdog = enwatch; 182 es->es_interval = ENWATCHINTERVAL; 183 ifp->if_timer = es->es_interval; 184 s = splimp(); 185 en_init(unit); 186 splx(s); 187 } 188 es->es_if.if_flags |= IFF_RUNNING|IFF_NOTRAILERS; 189 es->es_flags |= ENF_RUNNING; 190 } 191 192 /* 193 * Start output on interface. 194 * Get another datagram to send off of the interface queue, 195 * and map it to the interface before starting the output. 196 */ 197 enstart(ifp) 198 register struct ifnet *ifp; 199 { 200 int unit = ifp->if_unit, len; 201 register struct en_softc *es = &en_softc[unit]; 202 register struct mbuf *m; 203 204 IF_DEQUEUE(&es->es_if.if_snd, m); 205 if (m == 0) 206 return(0); 207 #ifdef CPU_SINGLE 208 es->es_ifnews.ifn_waddr = (caddr_t)get_xmit_buffer(unit); 209 #endif 210 len = if_wnewsput(&es->es_ifnews, m); 211 /* 212 * Ensure minimum packet length. 213 * This makes the safe assumtion that there are no virtual holes 214 * after the data. 215 * For security, it might be wise to zero out the added bytes, 216 * but we're mainly interested in speed at the moment. 217 */ 218 if (len - sizeof(struct ether_header) < ETHERMIN) 219 len = ETHERMIN + sizeof(struct ether_header); 220 en_start(unit, len); 221 #if NBPFILTER > 0 222 /* 223 * If bpf is listening on this interface, let it 224 * see the packet before we commit it to the wire. 225 */ 226 if (en_bpf[unit]) { 227 #ifdef CPU_SINGLE 228 bpf_tap(en_bpf[unit], es->es_ifnews.ifn_waddr, len); 229 #else 230 bpf_mtap(en_bpf[unit], m); 231 #endif 232 } 233 #endif /* NBPFILTER > 0 */ 234 es->es_if.if_flags |= IFF_OACTIVE; 235 return(0); 236 } 237 238 /* 239 * Transmit done interrupt. 240 */ 241 _enxint(unit, error, collision) 242 int unit; 243 int error, collision; 244 { 245 register struct en_softc *es = &en_softc[unit]; 246 247 #ifdef notyet /* KU:XXX */ 248 intrcnt[INTR_ETHER0 + unit]++; 249 #endif 250 if ((es->es_if.if_flags & IFF_OACTIVE) == 0) { 251 printf("en%d: stray xmit interrupt\n", unit); 252 /* 253 return; 254 */ 255 } else { 256 es->es_if.if_flags &= ~IFF_OACTIVE; 257 es->es_if.if_opackets++; 258 } 259 if (error) 260 es->es_if.if_oerrors++; 261 if (collision) 262 es->es_if.if_collisions++; 263 enstart(&es->es_if); 264 } 265 266 /* 267 * Ethernet interface receiver interrupt. 268 * If input error just drop packet. 269 * Otherwise purge input buffered data path and examine 270 * packet to determine type. If can't determine length 271 * from type, then have to drop packet. Othewise decapsulate 272 * packet based on type and pass to type specific higher-level 273 * input routine. 274 */ 275 _enrint(unit, len) 276 int unit; 277 register int len; 278 { 279 register struct en_softc *es = &en_softc[unit]; 280 register struct en_rheader *en; 281 struct mbuf *m; 282 int off, resid, s; 283 int type; 284 register struct ensw *esp; 285 extern struct mbuf *if_rnewsget(); 286 287 #ifdef notyet /* KU:XXX */ 288 intrcnt[INTR_ETHER0 + unit]++; 289 #endif 290 es->es_if.if_ipackets++; 291 if ((es->es_flags & ENF_RUNNING) == 0) 292 return; 293 en = (struct en_rheader *)(es->es_ifnews.ifn_raddr); 294 if (len < ETHERMIN || len > ETHERMTU) { 295 es->es_if.if_ierrors++; 296 return; 297 } 298 #if NBPFILTER > 0 299 #if NRAWETHER > 0 300 etherinput(unit, en, len + sizeof(struct en_rheader)); 301 #endif 302 /* 303 * Check if there's a bpf filter listening on this interface. 304 * If so, hand off the raw packet to enet. 305 */ 306 if (en_bpf[unit]) { 307 bpf_tap(en_bpf[unit], es->es_ifnews.ifn_raddr, 308 len + sizeof(struct en_rheader)); 309 /* 310 * Note that the interface cannot be in promiscuous mode if 311 * there are no bpf listeners. And if we are in promiscuous 312 * mode, we have to check if this packet is really ours. 313 * 314 * XXX This test does not support multicasts. 315 */ 316 if ((es->es_if.if_flags & IFF_PROMISC) 317 && bcmp(en->enr_dhost, es->es_addr, 318 sizeof(en->enr_dhost)) != 0 319 && bcmp(en->enr_dhost, etherbroadcastaddr, 320 sizeof(en->enr_dhost)) != 0) 321 return; 322 } 323 #else /* NBPFILTER > 0 */ 324 #if NRAWETHER > 0 325 if (etherinput(unit, en, len + sizeof(struct en_rheader))) 326 return; 327 #endif 328 #endif /* NBPFILTER > 0 */ 329 /* 330 * Deal with trailer protocol: if type is trailer type 331 * get true type from first 16-bit word past data. 332 * Remember that type was trailer by setting off. 333 */ 334 en->enr_type = ntohs((u_short)en->enr_type); 335 #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) 336 if (en->enr_type >= ETHERTYPE_TRAIL && 337 en->enr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 338 off = (en->enr_type - ETHERTYPE_TRAIL) * 512; 339 if (off >= ETHERMTU) 340 return; 341 en->enr_type = ntohs(*endataaddr(en, off, u_short *)); 342 resid = ntohs(*(endataaddr(en, off+2, u_short *))); 343 if (off + resid > len) 344 return; 345 len = off + resid; 346 } else 347 off = 0; 348 /* 349 * Pull packet off interface. Off is nonzero if packet 350 * has trailing header; m_devget will then force this header 351 * information to be at the front, but we still have to drop 352 * the type and length which are at the front of any trailer data. 353 * KU:XXX really? 354 */ 355 type = en->enr_type; 356 m = m_devget((char *)(en + 1), len, off, &es->es_if, 0); 357 if (m == 0) 358 return; 359 ether_input(&es->es_if, (struct ether_header *) en->enr_dhost, m); 360 } 361 362 /* 363 * Watchdog routine, request statistics from board. 364 */ 365 enwatch(unit) 366 int unit; 367 { 368 register struct en_softc *es = &en_softc[unit]; 369 register struct ifnet *ifp = &es->es_if; 370 371 ifp->if_timer = es->es_interval; 372 } 373 374 /* 375 * Process an ioctl request. 376 */ 377 enioctl(ifp, cmd, data) 378 register struct ifnet *ifp; 379 int cmd; 380 caddr_t data; 381 { 382 register struct ifaddr *ifa = (struct ifaddr *)data; 383 register struct en_softc *es = &en_softc[ifp->if_unit]; 384 register struct ensw *esp; 385 register int family; 386 int s = splimp(), error = 0; 387 388 switch (cmd) { 389 390 case SIOCSIFADDR: 391 ifp->if_flags |= IFF_UP; 392 eninit(ifp->if_unit); 393 switch (ifa->ifa_addr->sa_family) { 394 #ifdef INET 395 case AF_INET: 396 ((struct arpcom *)ifp)->ac_ipaddr = 397 IA_SIN(ifa)->sin_addr; 398 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 399 break; 400 #endif 401 } 402 break; 403 404 case SIOCSIFFLAGS: 405 if ((ifp->if_flags & IFF_UP) == 0 && 406 es->es_flags & ENF_RUNNING) { 407 es->es_flags &= ~ENF_RUNNING; 408 } else if (ifp->if_flags & IFF_UP && 409 (es->es_flags & ENF_RUNNING) == 0) 410 eninit(ifp->if_unit); 411 #if NBPFILTER > 0 412 else if (ifp->if_flags & IFF_UP && 413 (ifp->if_flags & IFF_RUNNING) == 0) { 414 en_prom_mode(ifp->if_unit, 415 ifp->if_flags & IFF_PROMISC); 416 ifp->if_flags |= IFF_RUNNING; 417 } 418 #endif 419 break; 420 421 default: 422 error = EINVAL; 423 } 424 splx(s); 425 return (error); 426 } 427 428 /* 429 * set ethernet address for unit 430 */ 431 ensetaddr(physaddr, unit) 432 u_char *physaddr; 433 int unit; 434 { 435 register struct en_softc *es = &en_softc[unit]; 436 437 if (!(es->es_flags & ENF_RUNNING)) 438 return; 439 440 bcopy((caddr_t)physaddr, (caddr_t)es->es_addr, sizeof es->es_addr); 441 es->es_flags &= ~ENF_RUNNING; 442 es->es_flags |= ENF_SETADDR; 443 eninit(unit); 444 } 445 446 /* 447 * Machine dependent functions 448 * 449 * en_probe(); 450 * en_attach(); 451 * en_init(); 452 * enxint(); 453 * enrint(); 454 * en_prom_mode() 455 */ 456 #ifdef CPU_SINGLE 457 #include "../include/cpu.h" 458 459 en_probe(hi) 460 struct hb_device *hi; 461 { 462 463 return (lance_probe(hi->hi_unit)); 464 } 465 466 en_attach(unit) 467 int unit; 468 { 469 register struct en_softc *es = &en_softc[unit]; 470 register u_char *p; 471 register int i; 472 extern lance_intr(); 473 474 #if !defined(news700) && !defined(mips) 475 register_hb_intr4(lance_intr, unit, eninfo[unit]->ii_intr); 476 #endif 477 if (lance_open(unit) < 0) 478 printf("lance initialize error\n"); 479 lance_get_addr(unit, (caddr_t)es->es_addr); 480 } 481 482 en_init(unit) 483 int unit; 484 { 485 486 } 487 488 en_start(unit, len) 489 int unit; 490 int len; 491 { 492 493 lance_transmit(unit, len); 494 } 495 496 enxint(unit) 497 register int unit; 498 { 499 500 _enxint(unit, lance_xmit_error(unit), lance_collision(unit)); 501 } 502 503 enrint(unit) 504 register int unit; 505 { 506 register struct en_softc *es = &en_softc[unit]; 507 caddr_t get_recv_buffer(); 508 509 while (es->es_ifnews.ifn_raddr = get_recv_buffer(unit)) { 510 _enrint(unit, 511 get_recv_length(unit) - sizeof(struct en_rheader)); 512 free_recv_buffer(unit); 513 } 514 } 515 516 en_prom_mode(unit, mode) 517 int unit, mode; 518 { 519 520 lance_prom_mode(unit, mode); 521 } 522 #endif /* CPU_SINGLE */ 523 524 #ifdef IPC_MRX 525 #include "../ipc/newsipc.h" 526 #include "../mrx/h/lancereg.h" 527 #include "../mrx/h/lance.h" 528 529 int port_enxmit[NEN]; 530 int port_enrecv[NEN]; 531 int port_enctrl[NEN]; 532 int port_enxmit_iop[NEN]; 533 int port_enrecv_iop[NEN]; 534 int port_enctrl_iop[NEN]; 535 536 en_probe(ii) 537 register struct iop_device *ii; 538 { 539 int unit = ii->ii_unit; 540 int lance_func, *reply; 541 char name[32]; 542 extern char *make_name(); 543 544 if (port_enrecv[unit] == 0) { 545 546 #define PT_CREATE(buf, name, unit, func) \ 547 port_create(make_name(buf, name, unit), func, unit) 548 #define OB_QUERY(buf, name, unit) \ 549 object_query(make_name(buf, name, unit)) 550 551 make_name(name, "@enrecvX", unit); 552 port_enrecv[unit] = PT_CREATE(name, "@enrecvX", unit, enrint); 553 port_enxmit[unit] = PT_CREATE(name, "@enxmitX", unit, enxint); 554 port_enctrl[unit] = PT_CREATE(name, "@enctrlX", unit, NULL); 555 /* use NULL action port */ 556 port_enrecv_iop[unit] = OB_QUERY(name, "lance_inputX", unit); 557 port_enxmit_iop[unit] = OB_QUERY(name, "lance_outputX", unit); 558 port_enctrl_iop[unit] = OB_QUERY(name, "lance_ctrlX", unit); 559 } 560 if (port_enctrl_iop[unit] < 0) 561 goto bad; 562 lance_func = EN_START; 563 msg_send(port_enctrl_iop[unit], port_enctrl[unit], &lance_func, 564 sizeof(lance_func), 0); 565 msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0); 566 if (*reply < 0) 567 goto bad; 568 lance_func = EN_STOP; 569 msg_send(port_enctrl_iop[unit], port_enctrl[unit], &lance_func, 570 sizeof(lance_func), 0); 571 msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0); 572 return (1); 573 bad: 574 return (0); 575 } 576 577 en_attach(unit) 578 int unit; 579 { 580 register struct en_softc *es = &en_softc[unit]; 581 int lance_func; 582 struct ether_addr *ether_addr; 583 584 lance_func = EN_GETADDR; 585 msg_send(port_enctrl_iop[unit], port_enctrl[unit], &lance_func, 586 sizeof(lance_func), 0); 587 msg_recv(port_enctrl[unit], NULL, ðer_addr, NULL, 0); 588 bcopy(ether_addr, es->es_addr, sizeof(struct ether_addr)); 589 msg_free(port_enctrl[unit]); 590 } 591 592 en_init(unit) 593 int unit; 594 { 595 register struct en_softc *es = &en_softc[unit]; 596 register int port; 597 struct lance_ctrl_req req; 598 int *reply; 599 600 req.lance_func = EN_SETXMITBUF; 601 mapsetup(&req.lance_map, es->es_ifnews.ifn_waddr, 602 ETHERMTU + sizeof(struct en_rheader)); 603 msg_send(port_enctrl_iop[unit], port_enctrl[unit], 604 &req, sizeof(req), 0); 605 msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0); 606 607 req.lance_func = EN_START; 608 msg_send(port_enctrl_iop[unit], port_enctrl[unit], 609 &req, sizeof(req), 0); 610 msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0); 611 msg_free(port_enctrl[unit]); 612 613 msg_send(port_enrecv_iop[unit], port_enrecv[unit], 614 es->es_ifnews.ifn_raddr, 615 ETHERMTU + sizeof(struct en_rheader), MSG_INDIRECT); 616 } 617 618 en_start(unit, len) 619 int unit; 620 int len; 621 { 622 623 msg_send(port_enxmit_iop[unit], port_enxmit[unit], &len, sizeof(len), 0); 624 } 625 626 enxint(unit) 627 register int unit; 628 { 629 int *len; 630 struct en_softc *es = &en_softc[unit]; 631 632 if (msg_recv(port_enxmit[unit], NULL, &len, NULL, 0) < 0) { 633 printf("stray enxint\n"); 634 return; 635 } 636 if (es->es_ifnews.ifn_mbuf) 637 m_freem(es->es_ifnews.ifn_mbuf); 638 _enxint(unit, *len < 0, *len & 0x10000); 639 } 640 641 enrint(unit) 642 int unit; 643 { 644 int len; 645 int *reply; 646 647 if (msg_recv(port_enrecv[unit], NULL, &reply, NULL, 0) < 0) { 648 printf("stray enrint\n"); 649 return; 650 } 651 len = *reply - sizeof(struct en_rheader); 652 msg_free(port_enrecv[unit]); 653 #ifdef mips 654 /* 655 * cache flush address must aligned long word boundary. 656 * so, add 3 for sanity. 657 */ 658 clean_k2dcache((int)en_softc[unit].es_ifnews.ifn_raddr & ~03, 659 len + sizeof (struct en_rheader) + 3); 660 #endif 661 _enrint(unit, len); 662 msg_send(port_enrecv_iop[unit], port_enrecv[unit], 663 en_softc[unit].es_ifnews.ifn_raddr, 664 ETHERMTU + sizeof(struct en_rheader), MSG_INDIRECT); 665 } 666 667 en_prom_mode(unit, mode) 668 int unit, mode; 669 { 670 static int port; 671 struct lance_ctrl_req req; 672 extern int port_enctrl_iop[]; 673 674 req.lance_func = EN_PROMMODE; 675 req.lance_mode = mode; 676 msg_send(port_enctrl_iop[unit], 0, &req, sizeof(req), 0); 677 } 678 #endif /* IPC_MRX */ 679 #endif /* NEN > 0 */ 680