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