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