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