1 /* $NetBSD: mb8795.c,v 1.34 2004/10/30 18:08:34 thorpej Exp $ */ 2 /* 3 * Copyright (c) 1998 Darrin B. Jewell 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Darrin B. Jewell 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: mb8795.c,v 1.34 2004/10/30 18:08:34 thorpej Exp $"); 34 35 #include "opt_inet.h" 36 #include "opt_ccitt.h" 37 #include "opt_llc.h" 38 #include "opt_ns.h" 39 #include "bpfilter.h" 40 #include "rnd.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/mbuf.h> 45 #include <sys/syslog.h> 46 #include <sys/socket.h> 47 #include <sys/device.h> 48 #include <sys/malloc.h> 49 #include <sys/ioctl.h> 50 #include <sys/errno.h> 51 #if NRND > 0 52 #include <sys/rnd.h> 53 #endif 54 55 #include <net/if.h> 56 #include <net/if_dl.h> 57 #include <net/if_ether.h> 58 59 #include <net/if_media.h> 60 61 #ifdef INET 62 #include <netinet/in.h> 63 #include <netinet/if_inarp.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/in_var.h> 66 #include <netinet/ip.h> 67 #endif 68 69 #ifdef NS 70 #include <netns/ns.h> 71 #include <netns/ns_if.h> 72 #endif 73 74 #if defined(CCITT) && defined(LLC) 75 #include <sys/socketvar.h> 76 #include <netccitt/x25.h> 77 #include <netccitt/pk.h> 78 #include <netccitt/pk_var.h> 79 #include <netccitt/pk_extern.h> 80 #endif 81 82 #if NBPFILTER > 0 83 #include <net/bpf.h> 84 #include <net/bpfdesc.h> 85 #endif 86 87 #include <machine/cpu.h> 88 #include <machine/bus.h> 89 #include <machine/intr.h> 90 91 /* @@@ this is here for the REALIGN_DMABUF hack below */ 92 #include "nextdmareg.h" 93 #include "nextdmavar.h" 94 95 #include "mb8795reg.h" 96 #include "mb8795var.h" 97 98 #include "bmapreg.h" 99 100 #ifdef DEBUG 101 #define MB8795_DEBUG 102 #endif 103 104 #define PRINTF(x) printf x; 105 #ifdef MB8795_DEBUG 106 int mb8795_debug = 0; 107 #define DPRINTF(x) if (mb8795_debug) printf x; 108 #else 109 #define DPRINTF(x) 110 #endif 111 112 extern int turbo; 113 114 /* 115 * Support for 116 * Fujitsu Ethernet Data Link Controller (MB8795) 117 * and the Fujitsu Manchester Encoder/Decoder (MB502). 118 */ 119 120 void mb8795_shutdown __P((void *)); 121 122 bus_dmamap_t mb8795_txdma_restart __P((bus_dmamap_t,void *)); 123 void mb8795_start_dma __P((struct mb8795_softc *)); 124 125 int mb8795_mediachange __P((struct ifnet *)); 126 void mb8795_mediastatus __P((struct ifnet *, struct ifmediareq *)); 127 128 void 129 mb8795_config(sc, media, nmedia, defmedia) 130 struct mb8795_softc *sc; 131 int *media, nmedia, defmedia; 132 { 133 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 134 135 DPRINTF(("%s: mb8795_config()\n",sc->sc_dev.dv_xname)); 136 137 /* Initialize ifnet structure. */ 138 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 139 ifp->if_softc = sc; 140 ifp->if_start = mb8795_start; 141 ifp->if_ioctl = mb8795_ioctl; 142 ifp->if_watchdog = mb8795_watchdog; 143 ifp->if_flags = 144 IFF_BROADCAST | IFF_NOTRAILERS; 145 146 /* Initialize media goo. */ 147 ifmedia_init(&sc->sc_media, 0, mb8795_mediachange, 148 mb8795_mediastatus); 149 if (media != NULL) { 150 int i; 151 for (i = 0; i < nmedia; i++) 152 ifmedia_add(&sc->sc_media, media[i], 0, NULL); 153 ifmedia_set(&sc->sc_media, defmedia); 154 } else { 155 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); 156 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); 157 } 158 159 /* Attach the interface. */ 160 if_attach(ifp); 161 ether_ifattach(ifp, sc->sc_enaddr); 162 163 sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc); 164 if (sc->sc_sh == NULL) 165 panic("mb8795_config: can't establish shutdownhook"); 166 167 #if NRND > 0 168 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 169 RND_TYPE_NET, 0); 170 #endif 171 172 DPRINTF(("%s: leaving mb8795_config()\n",sc->sc_dev.dv_xname)); 173 } 174 175 /* 176 * Media change callback. 177 */ 178 int 179 mb8795_mediachange(ifp) 180 struct ifnet *ifp; 181 { 182 struct mb8795_softc *sc = ifp->if_softc; 183 int data; 184 185 if (turbo) 186 return (0); 187 188 switch IFM_SUBTYPE(sc->sc_media.ifm_media) { 189 case IFM_AUTO: 190 if ((bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) & 191 BMAP_DATA_UTPENABLED_MASK) || 192 !(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) & 193 BMAP_DATA_UTPCARRIER_MASK)) { 194 data = BMAP_DATA_UTPENABLE; 195 sc->sc_media.ifm_cur->ifm_data = IFM_ETHER|IFM_10_T; 196 } else { 197 data = BMAP_DATA_BNCENABLE; 198 sc->sc_media.ifm_cur->ifm_data = IFM_ETHER|IFM_10_2; 199 } 200 break; 201 case IFM_10_T: 202 data = BMAP_DATA_UTPENABLE; 203 break; 204 case IFM_10_2: 205 data = BMAP_DATA_BNCENABLE; 206 break; 207 default: 208 return (1); 209 break; 210 } 211 212 bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, 213 BMAP_DDIR, BMAP_DDIR_UTPENABLE_MASK); 214 bus_space_write_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, 215 BMAP_DATA, data); 216 217 return (0); 218 } 219 220 /* 221 * Media status callback. 222 */ 223 void 224 mb8795_mediastatus(ifp, ifmr) 225 struct ifnet *ifp; 226 struct ifmediareq *ifmr; 227 { 228 struct mb8795_softc *sc = ifp->if_softc; 229 230 if (turbo) 231 return; 232 233 if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_AUTO) { 234 ifmr->ifm_active = sc->sc_media.ifm_cur->ifm_data; 235 } 236 if (IFM_SUBTYPE(ifmr->ifm_active) == IFM_10_T) { 237 ifmr->ifm_status = IFM_AVALID; 238 if (!(bus_space_read_1(sc->sc_bmap_bst, sc->sc_bmap_bsh, BMAP_DATA) & 239 BMAP_DATA_UTPCARRIER_MASK)) 240 ifmr->ifm_status |= IFM_ACTIVE; 241 } else { 242 ifmr->ifm_status &= ~IFM_AVALID; /* don't know for 10_2 */ 243 } 244 return; 245 } 246 247 /****************************************************************/ 248 #ifdef MB8795_DEBUG 249 #define XCHR(x) "0123456789abcdef"[(x) & 0xf] 250 static void 251 mb8795_hex_dump(unsigned char *pkt, size_t len) 252 { 253 size_t i, j; 254 255 printf("00000000 "); 256 for(i=0; i<len; i++) { 257 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i])); 258 if ((i+1) % 16 == 8) { 259 printf(" "); 260 } 261 if ((i+1) % 16 == 0) { 262 printf(" %c", '|'); 263 for(j=0; j<16; j++) { 264 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.'); 265 } 266 printf("%c\n%c%c%c%c%c%c%c%c ", '|', 267 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16), 268 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1)); 269 } 270 } 271 printf("\n"); 272 } 273 #undef XCHR 274 #endif 275 276 /* 277 * Controller receive interrupt. 278 */ 279 void 280 mb8795_rint(sc) 281 struct mb8795_softc *sc; 282 { 283 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 284 int error = 0; 285 u_char rxstat; 286 u_char rxmask; 287 288 rxstat = MB_READ_REG(sc, MB8795_RXSTAT); 289 rxmask = MB_READ_REG(sc, MB8795_RXMASK); 290 291 MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR); 292 293 if (rxstat & MB8795_RXSTAT_RESET) { 294 DPRINTF(("%s: rx reset packet\n", 295 sc->sc_dev.dv_xname)); 296 error++; 297 } 298 if (rxstat & MB8795_RXSTAT_SHORT) { 299 DPRINTF(("%s: rx short packet\n", 300 sc->sc_dev.dv_xname)); 301 error++; 302 } 303 if (rxstat & MB8795_RXSTAT_ALIGNERR) { 304 DPRINTF(("%s: rx alignment error\n", 305 sc->sc_dev.dv_xname)); 306 #if 0 307 error++; 308 #endif 309 } 310 if (rxstat & MB8795_RXSTAT_CRCERR) { 311 DPRINTF(("%s: rx CRC error\n", 312 sc->sc_dev.dv_xname)); 313 #if 0 314 error++; 315 #endif 316 } 317 if (rxstat & MB8795_RXSTAT_OVERFLOW) { 318 DPRINTF(("%s: rx overflow error\n", 319 sc->sc_dev.dv_xname)); 320 #if 0 321 error++; 322 #endif 323 } 324 325 if (error) { 326 ifp->if_ierrors++; 327 /* @@@ handle more gracefully, free memory, etc. */ 328 } 329 330 if (rxstat & MB8795_RXSTAT_OK) { 331 struct mbuf *m; 332 int s; 333 s = spldma(); 334 335 while ((m = MBDMA_RX_MBUF (sc))) { 336 m->m_pkthdr.len = m->m_len; 337 m->m_flags |= M_HASFCS; 338 m->m_pkthdr.rcvif = ifp; 339 340 /* Find receive length, keep crc */ 341 /* enable DMA interrupts while we process the packet */ 342 splx(s); 343 344 #if defined(MB8795_DEBUG) 345 /* Peek at the packet */ 346 DPRINTF(("%s: received packet, at VA %p-%p,len %d\n", 347 sc->sc_dev.dv_xname,mtod(m,u_char *),mtod(m,u_char *)+m->m_len,m->m_len)); 348 if (mb8795_debug > 3) { 349 mb8795_hex_dump(mtod(m,u_char *), m->m_pkthdr.len); 350 } else if (mb8795_debug > 2) { 351 mb8795_hex_dump(mtod(m,u_char *), m->m_pkthdr.len < 255 ? m->m_pkthdr.len : 128 ); 352 } 353 #endif 354 355 #if NBPFILTER > 0 356 /* 357 * Pass packet to bpf if there is a listener. 358 */ 359 if (ifp->if_bpf) 360 bpf_mtap(ifp->if_bpf, m); 361 #endif 362 363 { 364 ifp->if_ipackets++; 365 366 /* Pass the packet up. */ 367 (*ifp->if_input)(ifp, m); 368 } 369 370 s = spldma(); 371 372 } 373 374 splx(s); 375 376 } 377 378 #ifdef MB8795_DEBUG 379 if (mb8795_debug) { 380 char sbuf[256]; 381 382 bitmask_snprintf(rxstat, MB8795_RXSTAT_BITS, sbuf, sizeof(sbuf)); 383 printf("%s: rx interrupt, rxstat = %s\n", 384 sc->sc_dev.dv_xname, sbuf); 385 386 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXSTAT), 387 MB8795_RXSTAT_BITS, sbuf, sizeof(sbuf)); 388 printf("rxstat = 0x%s\n", sbuf); 389 390 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXMASK), 391 MB8795_RXMASK_BITS, sbuf, sizeof(sbuf)); 392 printf("rxmask = 0x%s\n", sbuf); 393 394 bitmask_snprintf(MB_READ_REG(sc, MB8795_RXMODE), 395 MB8795_RXMODE_BITS, sbuf, sizeof(sbuf)); 396 printf("rxmode = 0x%s\n", sbuf); 397 } 398 #endif 399 400 return; 401 } 402 403 /* 404 * Controller transmit interrupt. 405 */ 406 void 407 mb8795_tint(sc) 408 struct mb8795_softc *sc; 409 { 410 u_char txstat; 411 u_char txmask; 412 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 413 414 panic ("tint"); 415 txstat = MB_READ_REG(sc, MB8795_TXSTAT); 416 txmask = MB_READ_REG(sc, MB8795_TXMASK); 417 418 if ((txstat & MB8795_TXSTAT_READY) || 419 (txstat & MB8795_TXSTAT_TXRECV)) { 420 /* printf("X"); */ 421 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); 422 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE); */ 423 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_TXRXIE); */ 424 MB_WRITE_REG(sc, MB8795_TXMASK, 0); 425 if ((ifp->if_flags & IFF_RUNNING) && !IF_IS_EMPTY(&sc->sc_tx_snd)) { 426 void mb8795_start_dma __P((struct mb8795_softc *)); /* XXXX */ 427 /* printf ("Z"); */ 428 mb8795_start_dma(sc); 429 } 430 return; 431 } 432 433 if (txstat & MB8795_TXSTAT_SHORTED) { 434 printf("%s: tx cable shorted\n", sc->sc_dev.dv_xname); 435 ifp->if_oerrors++; 436 } 437 if (txstat & MB8795_TXSTAT_UNDERFLOW) { 438 printf("%s: tx underflow\n", sc->sc_dev.dv_xname); 439 ifp->if_oerrors++; 440 } 441 if (txstat & MB8795_TXSTAT_COLLERR) { 442 DPRINTF(("%s: tx collision\n", sc->sc_dev.dv_xname)); 443 ifp->if_collisions++; 444 } 445 if (txstat & MB8795_TXSTAT_COLLERR16) { 446 printf("%s: tx 16th collision\n", sc->sc_dev.dv_xname); 447 ifp->if_oerrors++; 448 ifp->if_collisions += 16; 449 } 450 451 #if 0 452 if (txstat & MB8795_TXSTAT_READY) { 453 char sbuf[256]; 454 455 bitmask_snprintf(txstat, MB8795_TXSTAT_BITS, sbuf, sizeof(sbuf)); 456 panic("%s: unexpected tx interrupt %s", 457 sc->sc_dev.dv_xname, sbuf); 458 459 /* turn interrupt off */ 460 MB_WRITE_REG(sc, MB8795_TXMASK, txmask & ~MB8795_TXMASK_READYIE); 461 } 462 #endif 463 464 return; 465 } 466 467 /****************************************************************/ 468 469 void 470 mb8795_reset(sc) 471 struct mb8795_softc *sc; 472 { 473 int s; 474 int i; 475 476 s = splnet(); 477 478 DPRINTF (("%s: mb8795_reset()\n",sc->sc_dev.dv_xname)); 479 480 sc->sc_ethercom.ec_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 481 sc->sc_ethercom.ec_if.if_timer = 0; 482 483 MBDMA_RESET(sc); 484 485 MB_WRITE_REG(sc, MB8795_RESET, MB8795_RESET_MODE); 486 487 mb8795_mediachange(&sc->sc_ethercom.ec_if); 488 489 #if 0 /* This interrupt was sometimes failing to ack correctly 490 * causing a loop @@@ 491 */ 492 MB_WRITE_REG(sc, MB8795_TXMASK, 493 MB8795_TXMASK_UNDERFLOWIE | MB8795_TXMASK_COLLIE | MB8795_TXMASK_COLL16IE 494 | MB8795_TXMASK_PARERRIE); 495 #else 496 MB_WRITE_REG(sc, MB8795_TXMASK, 0); 497 #endif 498 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); 499 500 #if 0 501 MB_WRITE_REG(sc, MB8795_RXMASK, 502 MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE | 503 MB8795_RXMASK_ALIGNERRIE | MB8795_RXMASK_CRCERRIE | MB8795_RXMASK_OVERFLOWIE); 504 #else 505 MB_WRITE_REG(sc, MB8795_RXMASK, 506 MB8795_RXMASK_OKIE | MB8795_RXMASK_RESETIE | MB8795_RXMASK_SHORTIE); 507 #endif 508 509 MB_WRITE_REG(sc, MB8795_RXSTAT, MB8795_RXSTAT_CLEAR); 510 511 for(i=0;i<sizeof(sc->sc_enaddr);i++) { 512 MB_WRITE_REG(sc, MB8795_ENADDR+i, sc->sc_enaddr[i]); 513 } 514 515 DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, size=%d\n", 516 sc->sc_dev.dv_xname, 517 sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2], 518 sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5], 519 sizeof(sc->sc_enaddr))); 520 521 MB_WRITE_REG(sc, MB8795_RESET, 0); 522 523 splx(s); 524 } 525 526 void 527 mb8795_watchdog(ifp) 528 struct ifnet *ifp; 529 { 530 struct mb8795_softc *sc = ifp->if_softc; 531 532 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 533 ++ifp->if_oerrors; 534 535 DPRINTF(("%s: %lld input errors, %lld input packets\n", 536 sc->sc_dev.dv_xname, ifp->if_ierrors, ifp->if_ipackets)); 537 538 ifp->if_flags &= ~IFF_RUNNING; 539 mb8795_init(sc); 540 } 541 542 /* 543 * Initialization of interface; set up initialization block 544 * and transmit/receive descriptor rings. 545 */ 546 void 547 mb8795_init(sc) 548 struct mb8795_softc *sc; 549 { 550 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 551 int s; 552 553 DPRINTF (("%s: mb8795_init()\n",sc->sc_dev.dv_xname)); 554 555 if (ifp->if_flags & IFF_UP) { 556 int rxmode; 557 558 s = spldma(); 559 if ((ifp->if_flags & IFF_RUNNING) == 0) 560 mb8795_reset(sc); 561 562 if (ifp->if_flags & IFF_PROMISC) 563 rxmode = MB8795_RXMODE_PROMISCUOUS; 564 else 565 rxmode = MB8795_RXMODE_NORMAL; 566 /* XXX add support for multicast */ 567 if (turbo) 568 rxmode |= MB8795_RXMODE_TEST; 569 570 /* switching mode probably borken now with turbo */ 571 MB_WRITE_REG(sc, MB8795_TXMODE, 572 turbo ? MB8795_TXMODE_TURBO1 : MB8795_TXMODE_LB_DISABLE); 573 MB_WRITE_REG(sc, MB8795_RXMODE, rxmode); 574 575 if ((ifp->if_flags & IFF_RUNNING) == 0) { 576 MBDMA_RX_SETUP(sc); 577 MBDMA_TX_SETUP(sc); 578 579 ifp->if_flags |= IFF_RUNNING; 580 ifp->if_flags &= ~IFF_OACTIVE; 581 ifp->if_timer = 0; 582 583 MBDMA_RX_GO(sc); 584 } 585 splx(s); 586 #if 0 587 s = spldma(); 588 if (! IF_IS_EMPTY(&sc->sc_tx_snd)) { 589 mb8795_start_dma(ifp); 590 } 591 splx(s); 592 #endif 593 } else { 594 mb8795_reset(sc); 595 } 596 } 597 598 void 599 mb8795_shutdown(arg) 600 void *arg; 601 { 602 struct mb8795_softc *sc = (struct mb8795_softc *)arg; 603 604 DPRINTF(("%s: mb8795_shutdown()\n",sc->sc_dev.dv_xname)); 605 606 mb8795_reset(sc); 607 } 608 609 /****************************************************************/ 610 int 611 mb8795_ioctl(ifp, cmd, data) 612 register struct ifnet *ifp; 613 u_long cmd; 614 caddr_t data; 615 { 616 register struct mb8795_softc *sc = ifp->if_softc; 617 struct ifaddr *ifa = (struct ifaddr *)data; 618 struct ifreq *ifr = (struct ifreq *)data; 619 int s, error = 0; 620 621 s = splnet(); 622 623 DPRINTF(("%s: mb8795_ioctl()\n",sc->sc_dev.dv_xname)); 624 625 switch (cmd) { 626 627 case SIOCSIFADDR: 628 DPRINTF(("%s: mb8795_ioctl() SIOCSIFADDR\n",sc->sc_dev.dv_xname)); 629 ifp->if_flags |= IFF_UP; 630 631 switch (ifa->ifa_addr->sa_family) { 632 #ifdef INET 633 case AF_INET: 634 mb8795_init(sc); 635 arp_ifinit(ifp, ifa); 636 break; 637 #endif 638 #ifdef NS 639 case AF_NS: 640 { 641 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 642 643 if (ns_nullhost(*ina)) 644 ina->x_host = 645 *(union ns_host *)LLADDR(ifp->if_sadl); 646 else { 647 bcopy(ina->x_host.c_host, 648 LLADDR(ifp->if_sadl), 649 sizeof(sc->sc_enaddr)); 650 } 651 /* Set new address. */ 652 mb8795_init(sc); 653 break; 654 } 655 #endif 656 default: 657 mb8795_init(sc); 658 break; 659 } 660 break; 661 662 #if defined(CCITT) && defined(LLC) 663 case SIOCSIFCONF_X25: 664 ifp->if_flags |= IFF_UP; 665 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ 666 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); 667 if (error == 0) 668 mb8795_init(sc); 669 break; 670 #endif /* CCITT && LLC */ 671 672 case SIOCSIFFLAGS: 673 DPRINTF(("%s: mb8795_ioctl() SIOCSIFFLAGS\n",sc->sc_dev.dv_xname)); 674 if ((ifp->if_flags & IFF_UP) == 0 && 675 (ifp->if_flags & IFF_RUNNING) != 0) { 676 /* 677 * If interface is marked down and it is running, then 678 * stop it. 679 */ 680 /* ifp->if_flags &= ~IFF_RUNNING; */ 681 mb8795_reset(sc); 682 } else if ((ifp->if_flags & IFF_UP) != 0 && 683 (ifp->if_flags & IFF_RUNNING) == 0) { 684 /* 685 * If interface is marked up and it is stopped, then 686 * start it. 687 */ 688 mb8795_init(sc); 689 } else { 690 /* 691 * Reset the interface to pick up changes in any other 692 * flags that affect hardware registers. 693 */ 694 mb8795_init(sc); 695 } 696 #ifdef MB8795_DEBUG 697 if (ifp->if_flags & IFF_DEBUG) 698 sc->sc_debug = 1; 699 else 700 sc->sc_debug = 0; 701 #endif 702 break; 703 704 case SIOCADDMULTI: 705 case SIOCDELMULTI: 706 DPRINTF(("%s: mb8795_ioctl() SIOCADDMULTI\n",sc->sc_dev.dv_xname)); 707 error = (cmd == SIOCADDMULTI) ? 708 ether_addmulti(ifr, &sc->sc_ethercom) : 709 ether_delmulti(ifr, &sc->sc_ethercom); 710 711 if (error == ENETRESET) { 712 /* 713 * Multicast list has changed; set the hardware filter 714 * accordingly. 715 */ 716 if (ifp->if_flags & IFF_RUNNING) 717 mb8795_init(sc); 718 error = 0; 719 } 720 break; 721 722 case SIOCGIFMEDIA: 723 case SIOCSIFMEDIA: 724 DPRINTF(("%s: mb8795_ioctl() SIOCSIFMEDIA\n",sc->sc_dev.dv_xname)); 725 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 726 break; 727 728 default: 729 error = EINVAL; 730 break; 731 } 732 733 splx(s); 734 735 #if 0 736 DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n", 737 cmd,error)); 738 #endif 739 740 return (error); 741 } 742 743 /* 744 * Setup output on interface. 745 * Get another datagram to send off of the interface queue, and map it to the 746 * interface before starting the output. 747 * Called only at splnet or interrupt level. 748 */ 749 void 750 mb8795_start(ifp) 751 struct ifnet *ifp; 752 { 753 struct mb8795_softc *sc = ifp->if_softc; 754 struct mbuf *m; 755 int s; 756 757 DPRINTF(("%s: mb8795_start()\n",sc->sc_dev.dv_xname)); 758 759 #ifdef DIAGNOSTIC 760 IFQ_POLL(&ifp->if_snd, m); 761 if (m == 0) { 762 panic("%s: No packet to start", 763 sc->sc_dev.dv_xname); 764 } 765 #endif 766 767 while (1) { 768 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 769 return; 770 771 #if 0 772 return; /* @@@ Turn off xmit for debugging */ 773 #endif 774 775 ifp->if_flags |= IFF_OACTIVE; 776 777 IFQ_DEQUEUE(&ifp->if_snd, m); 778 if (m == 0) { 779 ifp->if_flags &= ~IFF_OACTIVE; 780 return; 781 } 782 783 #if NBPFILTER > 0 784 /* 785 * Pass packet to bpf if there is a listener. 786 */ 787 if (ifp->if_bpf) 788 bpf_mtap(ifp->if_bpf, m); 789 #endif 790 791 s = spldma(); 792 IF_ENQUEUE(&sc->sc_tx_snd, m); 793 if (!MBDMA_TX_ISACTIVE(sc)) 794 mb8795_start_dma(sc); 795 splx(s); 796 797 ifp->if_flags &= ~IFF_OACTIVE; 798 } 799 800 } 801 802 void 803 mb8795_start_dma(sc) 804 struct mb8795_softc *sc; 805 { 806 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 807 struct mbuf *m; 808 u_char txmask; 809 810 DPRINTF(("%s: mb8795_start_dma()\n",sc->sc_dev.dv_xname)); 811 812 #if (defined(DIAGNOSTIC)) 813 { 814 u_char txstat; 815 txstat = MB_READ_REG(sc, MB8795_TXSTAT); 816 if (!turbo && !(txstat & MB8795_TXSTAT_READY)) { 817 /* @@@ I used to panic here, but then it paniced once. 818 * Let's see if I can just reset instead. [ dbj 980706.1900 ] 819 */ 820 printf("%s: transmitter not ready\n", 821 sc->sc_dev.dv_xname); 822 ifp->if_flags &= ~IFF_RUNNING; 823 mb8795_init(sc); 824 return; 825 } 826 } 827 #endif 828 829 #if 0 830 return; /* @@@ Turn off xmit for debugging */ 831 #endif 832 833 IF_DEQUEUE(&sc->sc_tx_snd, m); 834 if (m == 0) { 835 #ifdef DIAGNOSTIC 836 panic("%s: No packet to start_dma", 837 sc->sc_dev.dv_xname); 838 #endif 839 return; 840 } 841 842 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); 843 txmask = MB_READ_REG(sc, MB8795_TXMASK); 844 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_READYIE); */ 845 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_TXRXIE); */ 846 847 ifp->if_timer = 5; 848 849 if (MBDMA_TX_MBUF(sc, m)) 850 return; 851 852 MBDMA_TX_GO(sc); 853 if (turbo) 854 MB_WRITE_REG(sc, MB8795_TXMODE, MB8795_TXMODE_TURBO1 | MB8795_TXMODE_TURBOSTART); 855 856 ifp->if_opackets++; 857 } 858 859 /****************************************************************/ 860