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