1 /* $NetBSD: if_es.c,v 1.4 1995/04/14 17:29:50 chopps Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Michael L. Hitch 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Michael L. Hitch. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * SMC 91C90 Single-Chip Ethernet Controller 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/mbuf.h> 40 #include <sys/buf.h> 41 #include <sys/protosw.h> 42 #include <sys/socket.h> 43 #include <sys/syslog.h> 44 #include <sys/ioctl.h> 45 #include <sys/errno.h> 46 #include <sys/device.h> 47 48 #include <net/if.h> 49 #include <net/netisr.h> 50 #include <net/route.h> 51 52 #ifdef INET 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/in_var.h> 56 #include <netinet/ip.h> 57 #include <netinet/if_ether.h> 58 #endif 59 60 #ifdef NS 61 #include <netns/ns.h> 62 #include <netns/ns_if.h> 63 #endif 64 65 #include <machine/cpu.h> 66 #include <machine/mtpr.h> 67 #include <amiga/amiga/device.h> 68 #include <amiga/amiga/isr.h> 69 #include <amiga/dev/zbusvar.h> 70 #include <amiga/dev/if_esreg.h> 71 72 #define SWAP(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff)) 73 74 #define ESDEBUG 75 #define USEPKTBUF 76 77 /* 78 * Ethernet software status per interface. 79 * 80 * Each interface is referenced by a network interface structure, 81 * es_if, which the routing code uses to locate the interface. 82 * This structure contains the output queue for the interface, its address, ... 83 */ 84 struct es_softc { 85 struct device sc_dev; 86 struct isr sc_isr; 87 struct arpcom sc_arpcom; /* common Ethernet structures */ 88 void *sc_base; /* base address of board */ 89 short sc_iflags; 90 unsigned short sc_intctl; 91 #ifdef ESDEBUG 92 int sc_debug; 93 #endif 94 }; 95 96 #if NBPFILTER > 0 97 #include <net/bpf.h> 98 #include <net/bpfdesc.h> 99 #endif 100 101 #ifdef ESDEBUG 102 /* console error messages */ 103 int esdebug = 0; 104 #endif 105 106 int esintr __P((struct es_softc *)); 107 void esstart __P((struct ifnet *)); 108 void eswatchdog __P((int)); 109 int esioctl __P((struct ifnet *, u_long, caddr_t)); 110 void esrint __P((struct es_softc *)); 111 void estint __P((struct es_softc *)); 112 void esinit __P((struct es_softc *)); 113 void esreset __P((struct es_softc *)); 114 115 int esmatch __P((struct device *, void *, void *)); 116 void esattach __P((struct device *, struct device *, void *)); 117 118 struct cfdriver escd = { 119 NULL, "es", esmatch, esattach, DV_IFNET, sizeof(struct es_softc) 120 }; 121 122 int 123 esmatch(parent, match, aux) 124 struct device *parent; 125 void *match, *aux; 126 { 127 struct zbus_args *zap = aux; 128 129 /* Ameristar A4066 ethernet card */ 130 if (zap->manid == 1053 && zap->prodid == 10) 131 return(1); 132 133 return (0); 134 } 135 136 /* 137 * Interface exists: make available by filling in network interface 138 * record. System will initialize the interface when it is ready 139 * to accept packets. 140 */ 141 void 142 esattach(parent, self, aux) 143 struct device *parent, *self; 144 void *aux; 145 { 146 struct es_softc *sc = (void *)self; 147 struct zbus_args *zap = aux; 148 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 149 unsigned long ser; 150 151 sc->sc_base = zap->va; 152 153 /* 154 * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID. 155 * (Currently only Ameristar.) 156 */ 157 sc->sc_arpcom.ac_enaddr[0] = 0x00; 158 sc->sc_arpcom.ac_enaddr[1] = 0x00; 159 sc->sc_arpcom.ac_enaddr[2] = 0x9f; 160 161 /* 162 * Serial number for board contains last 3 bytes. 163 */ 164 ser = (unsigned long) zap->serno; 165 166 sc->sc_arpcom.ac_enaddr[3] = (ser >> 16) & 0xff; 167 sc->sc_arpcom.ac_enaddr[4] = (ser >> 8) & 0xff; 168 sc->sc_arpcom.ac_enaddr[5] = (ser ) & 0xff; 169 170 /* Initialize ifnet structure. */ 171 ifp->if_unit = sc->sc_dev.dv_unit; 172 ifp->if_name = escd.cd_name; 173 ifp->if_ioctl = esioctl; 174 ifp->if_start = esstart; 175 ifp->if_watchdog = eswatchdog; 176 /* XXX IFF_MULTICAST */ 177 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 178 179 /* Attach the interface. */ 180 if_attach(ifp); 181 ether_ifattach(ifp); 182 183 /* Print additional info when attached. */ 184 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); 185 186 #if NBPFILTER > 0 187 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 188 #endif 189 190 sc->sc_isr.isr_intr = esintr; 191 sc->sc_isr.isr_arg = sc; 192 sc->sc_isr.isr_ipl = 2; 193 add_isr(&sc->sc_isr); 194 } 195 196 void 197 esstop(sc) 198 struct es_softc* sc; 199 { 200 } 201 202 void 203 esinit(sc) 204 struct es_softc *sc; 205 { 206 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 207 union smcregs *smc = sc->sc_base; 208 int s; 209 210 if (ifp->if_addrlist == 0) 211 return; 212 213 s = splimp(); 214 215 smc->b0.bsr = BSR_BANK0; /* Select bank 0 */ 216 smc->b0.rcr = RCR_EPH_RST; 217 smc->b0.rcr = 0; 218 smc->b3.bsr = BSR_BANK3; /* Select bank 3 */ 219 smc->b3.mt[0] = 0; /* clear Multicast table */ 220 smc->b3.mt[1] = 0; 221 smc->b3.mt[2] = 0; 222 smc->b3.mt[3] = 0; 223 /* XXX set Multicast table from Multicast list */ 224 smc->b1.bsr = BSR_BANK1; /* Select bank 1 */ 225 smc->b1.cr = CR_RAM32K | CR_NO_WAIT_ST | CR_SET_SQLCH; 226 smc->b1.ctr = CTR_AUTO_RLSE; 227 smc->b1.iar[0] = *((unsigned short *) &sc->sc_arpcom.ac_enaddr[0]); 228 smc->b1.iar[1] = *((unsigned short *) &sc->sc_arpcom.ac_enaddr[2]); 229 smc->b1.iar[2] = *((unsigned short *) &sc->sc_arpcom.ac_enaddr[4]); 230 smc->b2.bsr = BSR_BANK2; /* Select bank 2 */ 231 smc->b2.mmucr = MMUCR_RESET; 232 smc->b0.bsr = BSR_BANK0; /* Select bank 0 */ 233 smc->b0.mcr = SWAP(0x0020); /* reserve 8K for transmit buffers */ 234 smc->b0.tcr = TCR_PAD_EN | TCR_TXENA + TCR_MON_CSN; 235 smc->b0.rcr = RCR_FILT_CAR | RCR_STRIP_CRC | RCR_RXEN; 236 /* XXX add multicast/promiscuous flags */ 237 smc->b2.bsr = BSR_BANK2; /* Select bank 2 */ 238 smc->b2.msk = sc->sc_intctl = MSK_RX_OVRN | MSK_RX; 239 240 /* Interface is now 'running', with no output active. */ 241 ifp->if_flags |= IFF_RUNNING; 242 ifp->if_flags &= ~IFF_OACTIVE; 243 244 /* Attempt to start output, if any. */ 245 esstart(ifp); 246 247 splx(s); 248 } 249 250 int 251 esintr(sc) 252 struct es_softc *sc; 253 { 254 int i; 255 u_short intsts, intact; 256 int done = 0; 257 union smcregs *smc; 258 259 smc = sc->sc_base; 260 intsts = smc->b2.ist; 261 intact = smc->b2.msk & intsts; 262 if ((intact) == 0) 263 return (0); 264 #ifdef ESDEBUG 265 if (esdebug) 266 printf ("%s: esintr ist %02x msk %02x", 267 sc->sc_dev.dv_xname, intsts, smc->b2.msk); 268 #endif 269 smc->b2.msk = 0; 270 #ifdef ESDEBUG 271 if (esdebug) 272 printf ("=>%02x%02x pnr %02x arr %02x fifo %04x\n", 273 smc->b2.ist, smc->b2.ist, smc->b2.pnr, smc->b2.arr, 274 smc->b2.fifo); 275 #endif 276 if (intact & IST_ALLOC) { 277 sc->sc_intctl &= ~MSK_ALLOC; 278 #ifdef ESDEBUG 279 if (esdebug || 1) 280 printf ("%s: ist %02x\n", sc->sc_dev.dv_xname, 281 intsts); 282 #endif 283 if ((smc->b2.arr & ARR_FAILED) == 0) { 284 #ifdef ESDEBUG 285 if (esdebug || 1) 286 printf ("%s: arr %02x\n", sc->sc_dev.dv_xname, 287 smc->b2.arr); 288 #endif 289 smc->b2.pnr = smc->b2.arr; 290 smc->b2.mmucr = MMUCR_RLSPKT; 291 while (smc->b2.mmucr & MMUCR_BUSY) 292 ; 293 sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; 294 } 295 } 296 while ((smc->b2.fifo & FIFO_REMPTY) == 0) { 297 esrint(sc); 298 } 299 if (intact & IST_RX_OVRN) { 300 printf ("%s: Overrun ist %02x", sc->sc_dev.dv_xname, 301 intsts); 302 smc->b2.ist = ACK_RX_OVRN; 303 printf ("->%02x\n", smc->b2.ist); 304 sc->sc_arpcom.ac_if.if_ierrors++; 305 } 306 if (intact & IST_TX) { 307 #ifdef ESDEBUG 308 if (esdebug) 309 printf ("%s: TX INT ist %02x", 310 sc->sc_dev.dv_xname, intsts); 311 #endif 312 smc->b2.ist = ACK_TX; 313 #ifdef ESDEBUG 314 if (esdebug) 315 printf ("->%02x\n", smc->b2.ist); 316 #endif 317 smc->b0.bsr = BSR_BANK0; 318 if ((smc->b0.tcr & TCR_TXENA) == 0) { 319 printf("%s: IST %02x masked %02x EPH status %04x tcr %04x\n", 320 sc->sc_dev.dv_xname, intsts, intact, smc->b0.ephsr, 321 smc->b0.tcr); 322 if ((smc->b0.ephsr & EPHSR_TX_SUC) == 0) { 323 smc->b0.tcr |= TCR_TXENA; 324 sc->sc_arpcom.ac_if.if_oerrors++; 325 } 326 } 327 /* 328 * else - got a TX interrupt, but TCR_TXENA is still set?? 329 */ 330 #if 0 331 else if ((intact & IST_TX_EMPTY) == 0) { 332 printf("%s: unexpected TX interrupt %02x %02x\n", 333 sc->sc_dev.dv_xname, intsts, intact); 334 smc->b2.bsr = 0x0200; 335 printf (" %02x\n", smc->b2.ist); 336 } 337 #endif 338 smc->b2.bsr = BSR_BANK2; 339 } 340 if (intact & IST_TX_EMPTY) { 341 u_short ecr; 342 #ifdef ESDEBUG 343 if (esdebug) 344 printf ("%s: TX EMPTY %02x", 345 sc->sc_dev.dv_xname, intsts); 346 #endif 347 smc->b2.ist = ACK_TX_EMPTY; 348 #ifdef ESDEBUG 349 if (esdebug) 350 printf ("->%02x intcl %x pnr %02x arr %02x\n", 351 smc->b2.ist, sc->sc_intctl, smc->b2.pnr, 352 smc->b2.arr); 353 #endif 354 sc->sc_intctl &= ~(MSK_TX_EMPTY | MSK_TX); 355 smc->b0.bsr = BSR_BANK0; 356 ecr = smc->b0.ecr; /* Get error counters */ 357 if (ecr & 0xff00) 358 sc->sc_arpcom.ac_if.if_collisions += ((ecr >> 8) & 15) + 359 ((ecr >> 11) & 0x1e); 360 smc->b2.bsr = BSR_BANK2; 361 } 362 /* output packets */ 363 estint(sc); 364 smc->b2.msk = sc->sc_intctl; 365 return (1); 366 } 367 368 void 369 esrint(sc) 370 struct es_softc *sc; 371 { 372 union smcregs *smc = sc->sc_base; 373 int i; 374 u_short len; 375 short cnt; 376 u_short pktctlw, pktlen, *buf; 377 u_long *lbuf; 378 volatile u_short *data; 379 volatile u_long *ldata; 380 struct ifnet *ifp; 381 struct mbuf *top, **mp, *m; 382 struct ether_header *eh; 383 #ifdef USEPKTBUF 384 u_char *b, pktbuf[1530]; 385 #endif 386 387 #ifdef ESDEBUG 388 if (esdebug) 389 printf ("%s: esrint fifo %04x", sc->sc_dev.dv_xname, 390 smc->b2.fifo); 391 #endif 392 data = (u_short *)&smc->b2.data; 393 smc->b2.ptr = PTR_RCV | PTR_AUTOINCR | PTR_READ | SWAP(0x0002); 394 (void) smc->b2.mmucr; 395 #ifdef ESDEBUG 396 if (esdebug) 397 printf ("->%04x", smc->b2.fifo); 398 #endif 399 len = *data; 400 len = SWAP(len); /* Careful of macro side-effects */ 401 #ifdef ESDEBUG 402 if (esdebug) 403 printf (" length %d", len); 404 #endif 405 smc->b2.ptr = PTR_RCV | PTR_AUTOINCR + PTR_READ | SWAP(0x0000); 406 (void) smc->b2.mmucr; 407 pktctlw = *data; 408 pktlen = *data; 409 pktctlw = SWAP(pktctlw); 410 pktlen = SWAP(pktlen) - 6; 411 if (pktctlw & RFSW_ODDFRM) 412 pktlen++; 413 /* XXX copy directly from controller to mbuf */ 414 #ifdef USEPKTBUF 415 #if 1 416 lbuf = (u_long *) pktbuf; 417 ldata = (u_long *)data; 418 cnt = (len - 4) / 4; 419 while (cnt--) 420 *lbuf++ = *ldata; 421 if ((len - 4) & 2) { 422 buf = (u_short *) lbuf; 423 *buf = *data; 424 } 425 #else 426 buf = (u_short *)pktbuf; 427 cnt = (len - 4) / 2; 428 while (cnt--) 429 *buf++ = *data; 430 #endif 431 smc->b2.mmucr = MMUCR_REMRLS_RX; 432 while (smc->b2.mmucr & MMUCR_BUSY) 433 ; 434 #ifdef ESDEBUG 435 if (pktctlw & (RFSW_ALGNERR | RFSW_BADCRC | RFSW_TOOLNG | RFSW_TOOSHORT)) { 436 printf ("%s: Packet error %04x\n", sc->sc_dev.dv_xname, pktctlw); 437 /* count input error? */ 438 } 439 if (esdebug) { 440 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw, pktlen, 441 smc->b2.fifo); 442 for (i = 0; i < pktlen; ++i) 443 printf ("%02x%s", pktbuf[i], ((i & 31) == 31) ? "\n" : 444 ""); 445 if (i & 31) 446 printf ("\n"); 447 } 448 #endif 449 #else /* USEPKTBUF */ 450 #ifdef ESDEBUG 451 if (pktctlw & (RFSW_ALGNERR | RFSW_BADCRC | RFSW_TOOLNG | RFSW_TOOSHORT)) { 452 printf ("%s: Packet error %04x\n", sc->sc_dev.dv_xname, pktctlw); 453 /* count input error? */ 454 } 455 if (esdebug) { 456 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw, pktlen, 457 smc->b2.fifo); 458 } 459 #endif 460 #endif /* USEPKTBUF */ 461 ifp = &sc->sc_arpcom.ac_if; 462 ifp->if_ipackets++; 463 MGETHDR(m, M_DONTWAIT, MT_DATA); 464 if (m == NULL) 465 return; 466 m->m_pkthdr.rcvif = ifp; 467 m->m_pkthdr.len = pktlen; 468 len = MHLEN; 469 top = NULL; 470 mp = ⊤ 471 #ifdef USEPKTBUF 472 b = pktbuf; 473 #endif 474 while (pktlen > 0) { 475 if (top) { 476 MGET(m, M_DONTWAIT, MT_DATA); 477 if (m == 0) { 478 m_freem(top); 479 return; 480 } 481 len = MLEN; 482 } 483 if (pktlen >= MINCLSIZE) { 484 MCLGET(m, M_DONTWAIT); 485 if (m->m_flags & M_EXT) 486 len = MCLBYTES; 487 } 488 m->m_len = len = min(pktlen, len); 489 #ifdef USEPKTBUF 490 bcopy((caddr_t)b, mtod(m, caddr_t), len); 491 b += len; 492 #else /* USEPKTBUF */ 493 buf = mtod(m, u_short *); 494 cnt = len / 2; 495 while (cnt--) 496 *buf++ = *data; 497 if (len & 1) 498 *buf = *data; /* XXX should be byte store */ 499 #ifdef ESDEBUG 500 if (esdebug) { 501 buf = mtod(m, u_short *); 502 for (i = 0; i < len; ++i) 503 printf ("%02x%s", ((u_char *)buf)[i], 504 ((i & 31) == 31) ? "\n" : ""); 505 if (i & 31) 506 printf ("\n"); 507 } 508 #endif 509 #endif /* USEPKTBUF */ 510 pktlen -= len; 511 *mp = m; 512 mp = &m->m_next; 513 } 514 #ifndef USEPKTBUF 515 smc->b2.mmucr = MMUCR_REMRLS_RX; 516 while (smc->b2.mmucr & MMUCR_BUSY) 517 ; 518 #endif 519 eh = mtod(top, struct ether_header *); 520 top->m_pkthdr.len -= sizeof (*eh); 521 top->m_len -= sizeof (*eh); 522 top->m_data += sizeof (*eh); 523 524 ether_input(ifp, eh, top); 525 } 526 527 void 528 estint(sc) 529 struct es_softc *sc; 530 { 531 532 esstart(&sc->sc_arpcom.ac_if); 533 } 534 535 void 536 esstart(ifp) 537 struct ifnet *ifp; 538 { 539 struct es_softc *sc = escd.cd_devs[ifp->if_unit]; 540 union smcregs *smc = sc->sc_base; 541 struct mbuf *m0, *m; 542 #ifdef USEPKTBUF 543 u_short pktbuf[ETHERMTU + 2]; 544 #endif 545 u_short pktctlw, pktlen; 546 u_short *buf; 547 volatile u_short *data; 548 u_long *lbuf; 549 volatile u_long *ldata; 550 short cnt; 551 int i; 552 553 if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) != 554 IFF_RUNNING) 555 return; 556 557 for (;;) { 558 /* 559 * Sneak a peek at the next packet to get the length 560 * and see if the SMC 91C90 can accept it. 561 */ 562 m = sc->sc_arpcom.ac_if.if_snd.ifq_head; 563 if (!m) 564 break; 565 #ifdef ESDEBUG 566 if (esdebug && (m->m_next || m->m_len & 1)) 567 printf("%s: esstart m_next %x m_len %d\n", sc->sc_dev.dv_xname, 568 m->m_next, m->m_len); 569 #endif 570 for (m0 = m, pktlen = 0; m0; m0 = m0->m_next) 571 pktlen += m0->m_len; 572 #ifdef ESDEBUG 573 if (esdebug) 574 printf("%s: esstart r1 %x len %d", sc->sc_dev.dv_xname, smc->b2.pnr, pktlen); 575 #endif 576 pktctlw = 0; 577 pktlen += 4; 578 if (pktlen & 1) 579 ++pktlen; /* control byte after last byte */ 580 else 581 pktlen += 2; /* control byte after pad byte */ 582 smc->b2.mmucr = MMUCR_ALLOC | (pktlen & 0x0700); 583 for (i = 0; i <= 5; ++i) 584 if ((smc->b2.arr & ARR_FAILED) == 0) 585 break; 586 if (smc->b2.arr & ARR_FAILED) { 587 sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE; 588 #ifdef ESDEBUG 589 if (esdebug) 590 printf("-no xmit bufs r1 %x\n", smc->b2.pnr); 591 #endif 592 sc->sc_intctl |= MSK_ALLOC; 593 break; 594 } 595 smc->b2.pnr = smc->b2.arr; 596 597 IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m); 598 smc->b2.ptr = PTR_AUTOINCR; 599 (void) smc->b2.mmucr; 600 data = (u_short *)&smc->b2.data; 601 *data = SWAP(pktctlw); 602 *data = SWAP(pktlen); 603 #ifdef USEPKTBUF 604 i = 0; 605 for (m0 = m; m; m = m->m_next) { 606 bcopy(mtod(m, caddr_t), (char *)pktbuf + i, m->m_len); 607 i += m->m_len; 608 } 609 610 if (i & 1) /* Figure out where to put control byte */ 611 pktbuf[i/2] = (pktbuf[i/2] & 0xff00) | CTLB_ODD; 612 else 613 pktbuf[i/2] = 0; 614 #ifdef ESDEBUG 615 if (esdebug) { 616 int j; 617 printf("-sending len %d pktlen %d r1 %04x\n", i, pktlen, smc->b2.pnr); 618 for (j = 0; j < pktlen - 4; ++j) 619 printf("%02x%s", ((u_char *)pktbuf)[j], ((j & 31) == 31) ? "\n" : ""); 620 if (j & 31) 621 printf("\n"); 622 } 623 #endif 624 #if 0 /* doesn't quite work? */ 625 lbuf = (u_long *)(pktbuf); 626 ldata = (u_long *)data; 627 cnt = pktlen / 4; 628 while(cnt--) 629 *ldata = *lbuf++; 630 if (pktlen & 2) { 631 buf = (u_short *)lbuf; 632 *data = *buf; 633 } 634 #else 635 buf = pktbuf; 636 cnt = pktlen / 2; 637 while (cnt--) 638 *data = *buf++; 639 #endif 640 #else /* USEPKTBUF */ 641 #ifdef ESDEBUG 642 if (esdebug) 643 printf("-sending pktlen %d r1 %04x\n", pktlen, smc->b2.pnr); 644 #endif 645 pktctlw = 0; 646 for (m0 = m; m; m = m->m_next) { 647 buf = mtod(m, u_short *); 648 #ifdef ESDEBUG 649 if (esdebug) { 650 printf(" m->m_len %d\n", m->m_len); 651 for (i = 0; i < m->m_len; ++i) 652 printf("%02x%s", ((u_char *)buf)[i], ((i & 31) == 31) ? "\n" : ""); 653 if (i & 31) 654 printf("\n"); 655 } 656 #endif 657 cnt = m->m_len / 2; 658 while (cnt--) 659 *data = *buf++; 660 if (m->m_len & 1) 661 pktctlw = (*buf & 0xff00) | CTLB_ODD; 662 } 663 *data = pktctlw; 664 #endif /* USEPKTBUF */ 665 smc->b2.mmucr = MMUCR_ENQ_TX; 666 #ifdef ESDEBUG 667 if (esdebug) 668 printf("%s: esstart packet sent r1 %x\n", sc->sc_dev.dv_xname, smc->b2.pnr); 669 #endif 670 #if NBPFILTER > 0 671 if (sc->sc_arpcom.ac_if.if_bpf) 672 bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0); 673 #endif 674 m_freem(m0); 675 sc->sc_arpcom.ac_if.if_opackets++; /* move to interrupt? */ 676 sc->sc_intctl |= MSK_TX_EMPTY | MSK_TX; 677 } 678 smc->b2.msk = sc->sc_intctl; 679 } 680 681 int 682 esioctl(ifp, command, data) 683 register struct ifnet *ifp; 684 u_long command; 685 caddr_t data; 686 { 687 struct es_softc *sc = escd.cd_devs[ifp->if_unit]; 688 register struct ifaddr *ifa = (struct ifaddr *)data; 689 struct ifreq *ifr = (struct ifreq *)data; 690 int s, error = 0; 691 692 s = splimp(); 693 694 switch (command) { 695 696 case SIOCSIFADDR: 697 ifp->if_flags |= IFF_UP; 698 699 switch (ifa->ifa_addr->sa_family) { 700 #ifdef INET 701 case AF_INET: 702 esinit(sc); 703 arp_ifinit(&sc->sc_arpcom, ifa); 704 break; 705 #endif 706 #ifdef NS 707 case AF_NS: 708 { 709 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 710 711 if (ns_nullhost(*ina)) 712 ina->x_host = 713 *(union ns_host *)(sc->sc_arpcom.ac_enaddr); 714 else 715 bcopy(ina->x_host.c_host, 716 sc->sc_arpcom.ac_enaddr, 717 sizeof(sc->sc_arpcom.ac_enaddr)); 718 /* Set new address. */ 719 esinit(sc); 720 break; 721 #endif 722 default: 723 esinit(sc); 724 break; 725 } 726 break; 727 728 case SIOCSIFFLAGS: 729 /* 730 * If interface is marked down and it is running, then stop it 731 */ 732 if ((ifp->if_flags & IFF_UP) == 0 && 733 (ifp->if_flags & IFF_RUNNING) != 0) { 734 /* 735 * If interface is marked down and it is running, then 736 * stop it. 737 */ 738 esstop(sc); 739 ifp->if_flags &= ~IFF_RUNNING; 740 } else if ((ifp->if_flags & IFF_UP) != 0 && 741 (ifp->if_flags & IFF_RUNNING) == 0) { 742 /* 743 * If interface is marked up and it is stopped, then 744 * start it. 745 */ 746 esinit(sc); 747 } else { 748 /* 749 * Reset the interface to pick up changes in any other 750 * flags that affect hardware registers. 751 */ 752 esstop(sc); 753 esinit(sc); 754 } 755 #ifdef ESDEBUG 756 if (ifp->if_flags & IFF_DEBUG) 757 esdebug = sc->sc_debug = 1; 758 else 759 esdebug = sc->sc_debug = 0; 760 #endif 761 break; 762 763 default: 764 error = EINVAL; 765 } 766 767 splx(s); 768 return (error); 769 } 770 771 void 772 esreset(sc) 773 struct es_softc *sc; 774 { 775 int s; 776 777 s = splimp(); 778 esstop(sc); 779 esinit(sc); 780 splx(s); 781 } 782 783 void 784 eswatchdog(unit) 785 int unit; 786 { 787 struct es_softc *sc = escd.cd_devs[unit]; 788 789 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 790 ++sc->sc_arpcom.ac_if.if_oerrors; 791 792 esreset(sc); 793 } 794