1 /* $NetBSD: mb8795.c,v 1.66 2020/01/29 05:31:10 thorpej 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.66 2020/01/29 05:31:10 thorpej 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 if_statinc(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 if_statinc(ifp, if_oerrors); 389 } 390 if (txstat & MB8795_TXSTAT_UNDERFLOW) { 391 printf("%s: tx underflow\n", device_xname(sc->sc_dev)); 392 if_statinc(ifp, if_oerrors); 393 } 394 if (txstat & MB8795_TXSTAT_COLLERR) { 395 DPRINTF(("%s: tx collision\n", device_xname(sc->sc_dev))); 396 if_statinc(ifp, if_collisions); 397 } 398 if (txstat & MB8795_TXSTAT_COLLERR16) { 399 printf("%s: tx 16th collision\n", device_xname(sc->sc_dev)); 400 if_statinc(ifp, if_oerrors); 401 if_statadd(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 if_statinc(ifp, if_oerrors); 487 488 ifp->if_flags &= ~IFF_RUNNING; 489 mb8795_init(sc); 490 } 491 492 /* 493 * Initialization of interface; set up initialization block 494 * and transmit/receive descriptor rings. 495 */ 496 void 497 mb8795_init(struct mb8795_softc *sc) 498 { 499 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 500 int s; 501 502 DPRINTF (("%s: mb8795_init()\n", device_xname(sc->sc_dev))); 503 504 if (ifp->if_flags & IFF_UP) { 505 int rxmode; 506 507 s = spldma(); 508 if ((ifp->if_flags & IFF_RUNNING) == 0) 509 mb8795_reset(sc); 510 511 if (ifp->if_flags & IFF_PROMISC) 512 rxmode = MB8795_RXMODE_PROMISCUOUS; 513 else 514 rxmode = MB8795_RXMODE_NORMAL; 515 /* XXX add support for multicast */ 516 if (turbo) 517 rxmode |= MB8795_RXMODE_TEST; 518 519 /* switching mode probably borken now with turbo */ 520 MB_WRITE_REG(sc, MB8795_TXMODE, 521 turbo ? MB8795_TXMODE_TURBO1 : MB8795_TXMODE_LB_DISABLE); 522 MB_WRITE_REG(sc, MB8795_RXMODE, rxmode); 523 524 if ((ifp->if_flags & IFF_RUNNING) == 0) { 525 MBDMA_RX_SETUP(sc); 526 MBDMA_TX_SETUP(sc); 527 528 ifp->if_flags |= IFF_RUNNING; 529 ifp->if_flags &= ~IFF_OACTIVE; 530 ifp->if_timer = 0; 531 532 MBDMA_RX_GO(sc); 533 } 534 splx(s); 535 #if 0 536 s = spldma(); 537 if (! IF_IS_EMPTY(&sc->sc_tx_snd)) 538 mb8795_start_dma(ifp); 539 splx(s); 540 #endif 541 } else 542 mb8795_reset(sc); 543 } 544 545 void 546 mb8795_shutdown(void *arg) 547 { 548 struct mb8795_softc *sc = (struct mb8795_softc *)arg; 549 550 DPRINTF(("%s: mb8795_shutdown()\n", device_xname(sc->sc_dev))); 551 552 mb8795_reset(sc); 553 } 554 555 /****************************************************************/ 556 int 557 mb8795_ioctl(struct ifnet *ifp, u_long cmd, void *data) 558 { 559 struct mb8795_softc *sc = ifp->if_softc; 560 struct ifaddr *ifa = (struct ifaddr *)data; 561 int s, error = 0; 562 563 s = splnet(); 564 565 DPRINTF(("%s: mb8795_ioctl()\n", device_xname(sc->sc_dev))); 566 567 switch (cmd) { 568 569 case SIOCINITIFADDR: 570 DPRINTF(("%s: mb8795_ioctl() SIOCINITIFADDR\n", 571 device_xname(sc->sc_dev))); 572 ifp->if_flags |= IFF_UP; 573 574 mb8795_init(sc); 575 switch (ifa->ifa_addr->sa_family) { 576 #ifdef INET 577 case AF_INET: 578 arp_ifinit(ifp, ifa); 579 break; 580 #endif 581 default: 582 break; 583 } 584 break; 585 586 587 case SIOCSIFFLAGS: 588 DPRINTF(("%s: mb8795_ioctl() SIOCSIFFLAGS\n", 589 device_xname(sc->sc_dev))); 590 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 591 break; 592 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 593 case IFF_RUNNING: 594 /* 595 * If interface is marked down and it is running, then 596 * stop it. 597 */ 598 #if 0 599 ifp->if_flags &= ~IFF_RUNNING; 600 #endif 601 mb8795_reset(sc); 602 break; 603 case IFF_UP: 604 /* 605 * If interface is marked up and it is stopped, then 606 * start it. 607 */ 608 mb8795_init(sc); 609 break; 610 default: 611 /* 612 * Reset the interface to pick up changes in any other 613 * flags that affect hardware registers. 614 */ 615 mb8795_init(sc); 616 break; 617 } 618 #ifdef MB8795_DEBUG 619 if (ifp->if_flags & IFF_DEBUG) 620 sc->sc_debug = 1; 621 else 622 sc->sc_debug = 0; 623 #endif 624 break; 625 626 case SIOCADDMULTI: 627 case SIOCDELMULTI: 628 DPRINTF(("%s: mb8795_ioctl() SIOCADDMULTI\n", 629 device_xname(sc->sc_dev))); 630 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 631 /* 632 * Multicast list has changed; set the hardware filter 633 * accordingly. 634 */ 635 if (ifp->if_flags & IFF_RUNNING) 636 mb8795_init(sc); 637 error = 0; 638 } 639 break; 640 641 default: 642 error = ether_ioctl(ifp, cmd, data); 643 break; 644 } 645 646 splx(s); 647 648 #if 0 649 DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n", cmd, error)); 650 #endif 651 652 return error; 653 } 654 655 /* 656 * Setup output on interface. 657 * Get another datagram to send off of the interface queue, and map it to the 658 * interface before starting the output. 659 * Called only at splnet or interrupt level. 660 */ 661 void 662 mb8795_start(struct ifnet *ifp) 663 { 664 struct mb8795_softc *sc = ifp->if_softc; 665 struct mbuf *m; 666 int s; 667 668 DPRINTF(("%s: mb8795_start()\n", device_xname(sc->sc_dev))); 669 670 #ifdef DIAGNOSTIC 671 IFQ_POLL(&ifp->if_snd, m); 672 if (m == 0) 673 panic("%s: No packet to start", device_xname(sc->sc_dev)); 674 #endif 675 676 while (1) { 677 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) 678 != IFF_RUNNING) 679 return; 680 681 #if 0 682 return; /* @@@ Turn off xmit for debugging */ 683 #endif 684 685 ifp->if_flags |= IFF_OACTIVE; 686 687 IFQ_DEQUEUE(&ifp->if_snd, m); 688 if (m == 0) { 689 ifp->if_flags &= ~IFF_OACTIVE; 690 return; 691 } 692 693 /* Pass packet to bpf if there is a listener. */ 694 bpf_mtap(ifp, m, BPF_D_OUT); 695 696 s = spldma(); 697 IF_ENQUEUE(&sc->sc_tx_snd, m); 698 if (!MBDMA_TX_ISACTIVE(sc)) 699 mb8795_start_dma(sc); 700 splx(s); 701 702 ifp->if_flags &= ~IFF_OACTIVE; 703 } 704 } 705 706 void 707 mb8795_start_dma(struct mb8795_softc *sc) 708 { 709 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 710 struct mbuf *m; 711 u_char txmask; 712 713 DPRINTF(("%s: mb8795_start_dma()\n", device_xname(sc->sc_dev))); 714 715 #if (defined(DIAGNOSTIC)) 716 { 717 u_char txstat; 718 txstat = MB_READ_REG(sc, MB8795_TXSTAT); 719 if (!turbo && !(txstat & MB8795_TXSTAT_READY)) { 720 /* 721 * @@@ I used to panic here, but then it paniced once. 722 * Let's see if I can just reset instead. 723 * [ dbj 980706.1900 ] 724 */ 725 printf("%s: transmitter not ready\n", 726 device_xname(sc->sc_dev)); 727 ifp->if_flags &= ~IFF_RUNNING; 728 mb8795_init(sc); 729 return; 730 } 731 } 732 #endif 733 734 #if 0 735 return; /* @@@ Turn off xmit for debugging */ 736 #endif 737 738 IF_DEQUEUE(&sc->sc_tx_snd, m); 739 if (m == 0) { 740 #ifdef DIAGNOSTIC 741 panic("%s: No packet to start_dma", device_xname(sc->sc_dev)); 742 #endif 743 return; 744 } 745 746 MB_WRITE_REG(sc, MB8795_TXSTAT, MB8795_TXSTAT_CLEAR); 747 txmask = MB_READ_REG(sc, MB8795_TXMASK); 748 __USE(txmask); 749 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_READYIE); */ 750 /* MB_WRITE_REG(sc, MB8795_TXMASK, txmask | MB8795_TXMASK_TXRXIE); */ 751 752 ifp->if_timer = 5; 753 754 if (MBDMA_TX_MBUF(sc, m)) 755 return; 756 757 MBDMA_TX_GO(sc); 758 if (turbo) 759 MB_WRITE_REG(sc, MB8795_TXMODE, 760 MB8795_TXMODE_TURBO1 | MB8795_TXMODE_TURBOSTART); 761 762 if_statinc(ifp, if_opackets); 763 } 764 765 /****************************************************************/ 766