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