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