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