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