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