1 /* $NetBSD: mb8795.c,v 1.24 2001/06/16 09:18:46 dbj 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 "opt_inet.h" 33 #include "opt_ccitt.h" 34 #include "opt_llc.h" 35 #include "opt_ns.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 #if 0 57 #include <net/if_media.h> 58 #endif 59 60 #ifdef INET 61 #include <netinet/in.h> 62 #include <netinet/if_inarp.h> 63 #include <netinet/in_systm.h> 64 #include <netinet/in_var.h> 65 #include <netinet/ip.h> 66 #endif 67 68 #ifdef NS 69 #include <netns/ns.h> 70 #include <netns/ns_if.h> 71 #endif 72 73 #if defined(CCITT) && defined(LLC) 74 #include <sys/socketvar.h> 75 #include <netccitt/x25.h> 76 #include <netccitt/pk.h> 77 #include <netccitt/pk_var.h> 78 #include <netccitt/pk_extern.h> 79 #endif 80 81 #if NBPFILTER > 0 82 #include <net/bpf.h> 83 #include <net/bpfdesc.h> 84 #endif 85 86 #include <machine/cpu.h> 87 #include <machine/bus.h> 88 #include <machine/intr.h> 89 90 /* @@@ this is here for the REALIGN_DMABUF hack below */ 91 #include "nextdmareg.h" 92 #include "nextdmavar.h" 93 94 #include "mb8795reg.h" 95 #include "mb8795var.h" 96 97 #if 1 98 #define XE_DEBUG 99 #endif 100 101 #ifdef XE_DEBUG 102 int xe_debug = 0; 103 #define DPRINTF(x) if (xe_debug) printf x; 104 #else 105 #define DPRINTF(x) 106 #endif 107 108 109 /* 110 * Support for 111 * Fujitsu Ethernet Data Link Controller (MB8795) 112 * and the Fujitsu Manchester Encoder/Decoder (MB502). 113 */ 114 115 void mb8795_shutdown __P((void *)); 116 117 struct mbuf * mb8795_rxdmamap_load __P((struct mb8795_softc *, 118 bus_dmamap_t map)); 119 120 bus_dmamap_t mb8795_rxdma_continue __P((void *)); 121 void mb8795_rxdma_completed __P((bus_dmamap_t,void *)); 122 bus_dmamap_t mb8795_txdma_continue __P((void *)); 123 void mb8795_txdma_completed __P((bus_dmamap_t,void *)); 124 void mb8795_rxdma_shutdown __P((void *)); 125 void mb8795_txdma_shutdown __P((void *)); 126 bus_dmamap_t mb8795_txdma_restart __P((bus_dmamap_t,void *)); 127 128 void 129 mb8795_config(sc) 130 struct mb8795_softc *sc; 131 { 132 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 133 134 DPRINTF(("%s: mb8795_config()\n",sc->sc_dev.dv_xname)); 135 136 /* Initialize ifnet structure. */ 137 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 138 ifp->if_softc = sc; 139 ifp->if_start = mb8795_start; 140 ifp->if_ioctl = mb8795_ioctl; 141 ifp->if_watchdog = mb8795_watchdog; 142 ifp->if_flags = 143 IFF_BROADCAST | IFF_NOTRAILERS; 144 145 /* Attach the interface. */ 146 if_attach(ifp); 147 ether_ifattach(ifp, sc->sc_enaddr); 148 149 sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc); 150 if (sc->sc_sh == NULL) 151 panic("mb8795_config: can't establish shutdownhook"); 152 153 #if NRND > 0 154 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 155 RND_TYPE_NET, 0); 156 #endif 157 158 /* Initialize the dma maps */ 159 { 160 int error; 161 if ((error = bus_dmamap_create(sc->sc_tx_dmat, MCLBYTES, 162 (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW, 163 &sc->sc_tx_dmamap)) != 0) { 164 panic("%s: can't create tx DMA map, error = %d\n", 165 sc->sc_dev.dv_xname, error); 166 } 167 { 168 int i; 169 for(i=0;i<MB8795_NRXBUFS;i++) { 170 if ((error = bus_dmamap_create(sc->sc_rx_dmat, MCLBYTES, 171 (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW, 172 &sc->sc_rx_dmamap[i])) != 0) { 173 panic("%s: can't create rx DMA map, error = %d\n", 174 sc->sc_dev.dv_xname, error); 175 } 176 sc->sc_rx_mb_head[i] = NULL; 177 } 178 sc->sc_rx_loaded_idx = 0; 179 sc->sc_rx_completed_idx = 0; 180 sc->sc_rx_handled_idx = 0; 181 } 182 } 183 184 /* @@@ more next hacks 185 * the 2000 covers at least a 1500 mtu + headers 186 * + DMA_BEGINALIGNMENT+ DMA_ENDALIGNMENT 187 */ 188 sc->sc_txbuf = malloc(2000, M_DEVBUF, M_NOWAIT); 189 if (!sc->sc_txbuf) panic("%s: can't malloc tx DMA buffer", 190 sc->sc_dev.dv_xname); 191 192 sc->sc_tx_mb_head = NULL; 193 sc->sc_tx_loaded = 0; 194 195 sc->sc_tx_nd->nd_shutdown_cb = mb8795_txdma_shutdown; 196 sc->sc_tx_nd->nd_continue_cb = mb8795_txdma_continue; 197 sc->sc_tx_nd->nd_completed_cb = mb8795_txdma_completed; 198 sc->sc_tx_nd->nd_cb_arg = sc; 199 200 sc->sc_rx_nd->nd_shutdown_cb = mb8795_rxdma_shutdown; 201 sc->sc_rx_nd->nd_continue_cb = mb8795_rxdma_continue; 202 sc->sc_rx_nd->nd_completed_cb = mb8795_rxdma_completed; 203 sc->sc_rx_nd->nd_cb_arg = sc; 204 205 DPRINTF(("%s: leaving mb8795_config()\n",sc->sc_dev.dv_xname)); 206 } 207 208 209 /****************************************************************/ 210 #ifdef XE_DEBUG 211 #define XCHR(x) "0123456789abcdef"[(x) & 0xf] 212 static void 213 xe_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", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.'); 227 } 228 printf("%c\n%c%c%c%c%c%c%c%c ", '|', 229 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16), 230 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1)); 231 } 232 } 233 printf("\n"); 234 } 235 #undef XCHR 236 #endif 237 238 /* 239 * Controller receive interrupt. 240 */ 241 void 242 mb8795_rint(sc) 243 struct mb8795_softc *sc; 244 { 245 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 246 int error = 0; 247 u_char rxstat; 248 u_char rxmask; 249 250 rxstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT); 251 rxmask = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK); 252 253 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT, XE_RXSTAT_CLEAR); 254 255 if (rxstat & XE_RXSTAT_RESET) { 256 DPRINTF(("%s: rx reset packet\n", 257 sc->sc_dev.dv_xname)); 258 error++; 259 } 260 if (rxstat & XE_RXSTAT_SHORT) { 261 DPRINTF(("%s: rx short packet\n", 262 sc->sc_dev.dv_xname)); 263 error++; 264 } 265 if (rxstat & XE_RXSTAT_ALIGNERR) { 266 DPRINTF(("%s: rx alignment error\n", 267 sc->sc_dev.dv_xname)); 268 #if 0 269 error++; 270 #endif 271 } 272 if (rxstat & XE_RXSTAT_CRCERR) { 273 DPRINTF(("%s: rx CRC error\n", 274 sc->sc_dev.dv_xname)); 275 #if 0 276 error++; 277 #endif 278 } 279 if (rxstat & XE_RXSTAT_OVERFLOW) { 280 DPRINTF(("%s: rx overflow error\n", 281 sc->sc_dev.dv_xname)); 282 #if 0 283 error++; 284 #endif 285 } 286 287 if (error) { 288 ifp->if_ierrors++; 289 /* @@@ handle more gracefully, free memory, etc. */ 290 } 291 292 if (rxstat & XE_RXSTAT_OK) { 293 int s; 294 s = spldma(); 295 296 while(sc->sc_rx_handled_idx != sc->sc_rx_completed_idx) { 297 struct mbuf *m; 298 bus_dmamap_t map; 299 300 sc->sc_rx_handled_idx++; 301 sc->sc_rx_handled_idx %= MB8795_NRXBUFS; 302 303 /* Should probably not do this much while interrupts 304 * are disabled, but for now we will. 305 */ 306 307 map = sc->sc_rx_dmamap[sc->sc_rx_handled_idx]; 308 m = sc->sc_rx_mb_head[sc->sc_rx_handled_idx]; 309 310 m->m_pkthdr.len = m->m_len = map->dm_xfer_len; 311 m->m_flags |= M_HASFCS; 312 m->m_pkthdr.rcvif = ifp; 313 314 bus_dmamap_sync(sc->sc_rx_dmat, map, 315 0, map->dm_mapsize, BUS_DMASYNC_POSTREAD); 316 317 bus_dmamap_unload(sc->sc_rx_dmat, map); 318 319 /* Install a fresh mbuf for next packet */ 320 321 sc->sc_rx_mb_head[sc->sc_rx_handled_idx] = 322 mb8795_rxdmamap_load(sc,map); 323 324 /* Punt runt packets 325 * dma restarts create 0 length packets for example 326 */ 327 if (m->m_len < ETHER_MIN_LEN) { 328 m_freem(m); 329 continue; 330 } 331 332 /* Find receive length, keep crc */ 333 /* enable dma interrupts while we process the packet */ 334 splx(s); 335 336 #if defined(XE_DEBUG) 337 /* Peek at the packet */ 338 DPRINTF(("%s: received packet, at VA %p-%p,len %d\n", 339 sc->sc_dev.dv_xname,mtod(m,u_char *),mtod(m,u_char *)+m->m_len,m->m_len)); 340 if (xe_debug > 3) { 341 xe_hex_dump(mtod(m,u_char *), m->m_pkthdr.len); 342 } else if (xe_debug > 2) { 343 xe_hex_dump(mtod(m,u_char *), m->m_pkthdr.len < 255 ? m->m_pkthdr.len : 128 ); 344 } 345 #endif 346 347 #if NBPFILTER > 0 348 /* 349 * Pass packet to bpf if there is a listener. 350 */ 351 if (ifp->if_bpf) 352 bpf_mtap(ifp->if_bpf, m); 353 #endif 354 355 { 356 ifp->if_ipackets++; 357 358 /* Pass the packet up. */ 359 (*ifp->if_input)(ifp, m); 360 } 361 362 s = spldma(); 363 364 } 365 366 splx(s); 367 368 } 369 370 #ifdef XE_DEBUG 371 if (xe_debug) { 372 char sbuf[256]; 373 374 bitmask_snprintf(rxstat, XE_RXSTAT_BITS, sbuf, sizeof(sbuf)); 375 printf("%s: rx interrupt, rxstat = %s\n", 376 sc->sc_dev.dv_xname, sbuf); 377 378 bitmask_snprintf(bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT), 379 XE_RXSTAT_BITS, sbuf, sizeof(sbuf)); 380 printf("rxstat = 0x%s\n", sbuf); 381 382 bitmask_snprintf(bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK), 383 XE_RXMASK_BITS, sbuf, sizeof(sbuf)); 384 printf("rxmask = 0x%s\n", sbuf); 385 386 bitmask_snprintf(bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMODE), 387 XE_RXMODE_BITS, sbuf, sizeof(sbuf)); 388 printf("rxmode = 0x%s\n", sbuf); 389 } 390 #endif 391 392 return; 393 } 394 395 /* 396 * Controller transmit interrupt. 397 */ 398 void 399 mb8795_tint(sc) 400 struct mb8795_softc *sc; 401 402 { 403 u_char txstat; 404 u_char txmask; 405 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 406 407 txstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT); 408 txmask = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK); 409 410 if (txstat & XE_TXSTAT_SHORTED) { 411 printf("%s: tx cable shorted\n", sc->sc_dev.dv_xname); 412 ifp->if_oerrors++; 413 } 414 if (txstat & XE_TXSTAT_UNDERFLOW) { 415 printf("%s: tx underflow\n", sc->sc_dev.dv_xname); 416 ifp->if_oerrors++; 417 } 418 if (txstat & XE_TXSTAT_COLLERR) { 419 DPRINTF(("%s: tx collision\n", sc->sc_dev.dv_xname)); 420 ifp->if_collisions++; 421 } 422 if (txstat & XE_TXSTAT_COLLERR16) { 423 printf("%s: tx 16th collision\n", sc->sc_dev.dv_xname); 424 ifp->if_oerrors++; 425 ifp->if_collisions += 16; 426 } 427 428 #if 0 429 if (txstat & XE_TXSTAT_READY) { 430 char sbuf[256]; 431 432 bitmask_snprintf(txstat, XE_TXSTAT_BITS, sbuf, sizeof(sbuf)); 433 panic("%s: unexpected tx interrupt %s", 434 sc->sc_dev.dv_xname, sbuf); 435 436 /* turn interrupt off */ 437 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK, 438 txmask & ~XE_TXMASK_READYIE); 439 } 440 #endif 441 442 return; 443 } 444 445 /****************************************************************/ 446 447 void 448 mb8795_reset(sc) 449 struct mb8795_softc *sc; 450 { 451 int s; 452 453 s = splnet(); 454 mb8795_init(sc); 455 splx(s); 456 } 457 458 void 459 mb8795_watchdog(ifp) 460 struct ifnet *ifp; 461 { 462 struct mb8795_softc *sc = ifp->if_softc; 463 464 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 465 ++ifp->if_oerrors; 466 467 DPRINTF(("%s: %lld input errors, %lld input packets\n", 468 sc->sc_dev.dv_xname, ifp->if_ierrors, ifp->if_ipackets)); 469 470 mb8795_reset(sc); 471 } 472 473 /* 474 * Initialization of interface; set up initialization block 475 * and transmit/receive descriptor rings. 476 * @@@ error handling is bogus in here. memory leaks 477 */ 478 void 479 mb8795_init(sc) 480 struct mb8795_softc *sc; 481 { 482 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 483 484 m_freem(sc->sc_tx_mb_head); 485 sc->sc_tx_mb_head = NULL; 486 sc->sc_tx_loaded = 0; 487 488 { 489 int i; 490 for(i=0;i<MB8795_NRXBUFS;i++) { 491 if (sc->sc_rx_mb_head[i]) { 492 bus_dmamap_unload(sc->sc_rx_dmat, sc->sc_rx_dmamap[i]); 493 m_freem(sc->sc_rx_mb_head[i]); 494 } 495 sc->sc_rx_mb_head[i] = 496 mb8795_rxdmamap_load(sc, sc->sc_rx_dmamap[i]); 497 } 498 sc->sc_rx_loaded_idx = 0; 499 sc->sc_rx_completed_idx = 0; 500 sc->sc_rx_handled_idx = 0; 501 } 502 503 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RESET, XE_RESET_MODE); 504 505 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMODE, XE_TXMODE_LB_DISABLE); 506 #if 0 /* This interrupt was sometimes failing to ack correctly 507 * causing a loop @@@ 508 */ 509 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK, 510 XE_TXMASK_UNDERFLOWIE | XE_TXMASK_COLLIE | XE_TXMASK_COLL16IE 511 | XE_TXMASK_PARERRIE); 512 #else 513 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK, 0); 514 #endif 515 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT, XE_TXSTAT_CLEAR); 516 517 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXMODE, XE_RXMODE_NORMAL); 518 519 #if 0 520 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK, 521 XE_RXMASK_OKIE | XE_RXMASK_RESETIE | XE_RXMASK_SHORTIE | 522 XE_RXMASK_ALIGNERRIE | XE_RXMASK_CRCERRIE | XE_RXMASK_OVERFLOWIE); 523 #else 524 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK, 525 XE_RXMASK_OKIE | XE_RXMASK_RESETIE | XE_RXMASK_SHORTIE); 526 #endif 527 528 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT, XE_RXSTAT_CLEAR); 529 530 { 531 int i; 532 for(i=0;i<sizeof(sc->sc_enaddr);i++) { 533 bus_space_write_1(sc->sc_bst,sc->sc_bsh,XE_ENADDR+i,sc->sc_enaddr[i]); 534 } 535 } 536 537 DPRINTF(("%s: initializing ethernet %02x:%02x:%02x:%02x:%02x:%02x, size=%d\n", 538 sc->sc_dev.dv_xname, 539 sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2], 540 sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5], 541 sizeof(sc->sc_enaddr))); 542 543 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RESET, 0); 544 545 ifp->if_flags |= IFF_RUNNING; 546 ifp->if_flags &= ~IFF_OACTIVE; 547 ifp->if_timer = 0; 548 549 nextdma_init(sc->sc_tx_nd); 550 nextdma_init(sc->sc_rx_nd); 551 552 nextdma_start(sc->sc_rx_nd, DMACSR_SETREAD); 553 554 if (ifp->if_snd.ifq_head != NULL) { 555 mb8795_start(ifp); 556 } 557 } 558 559 void 560 mb8795_stop(sc) 561 struct mb8795_softc *sc; 562 { 563 printf("%s: stop not implemented\n", sc->sc_dev.dv_xname); 564 } 565 566 567 void 568 mb8795_shutdown(arg) 569 void *arg; 570 { 571 struct mb8795_softc *sc = (struct mb8795_softc *)arg; 572 mb8795_stop(sc); 573 } 574 575 /****************************************************************/ 576 int 577 mb8795_ioctl(ifp, cmd, data) 578 register struct ifnet *ifp; 579 u_long cmd; 580 caddr_t data; 581 { 582 register struct mb8795_softc *sc = ifp->if_softc; 583 struct ifaddr *ifa = (struct ifaddr *)data; 584 struct ifreq *ifr = (struct ifreq *)data; 585 int s, error = 0; 586 587 s = splnet(); 588 589 switch (cmd) { 590 591 case SIOCSIFADDR: 592 ifp->if_flags |= IFF_UP; 593 594 switch (ifa->ifa_addr->sa_family) { 595 #ifdef INET 596 case AF_INET: 597 mb8795_init(sc); 598 arp_ifinit(ifp, ifa); 599 break; 600 #endif 601 #ifdef NS 602 case AF_NS: 603 { 604 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 605 606 if (ns_nullhost(*ina)) 607 ina->x_host = 608 *(union ns_host *)LLADDR(ifp->if_sadl); 609 else { 610 bcopy(ina->x_host.c_host, 611 LLADDR(ifp->if_sadl), 612 sizeof(sc->sc_enaddr)); 613 } 614 /* Set new address. */ 615 mb8795_init(sc); 616 break; 617 } 618 #endif 619 default: 620 mb8795_init(sc); 621 break; 622 } 623 break; 624 625 #if defined(CCITT) && defined(LLC) 626 case SIOCSIFCONF_X25: 627 ifp->if_flags |= IFF_UP; 628 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ 629 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); 630 if (error == 0) 631 mb8795_init(sc); 632 break; 633 #endif /* CCITT && LLC */ 634 635 case SIOCSIFFLAGS: 636 if ((ifp->if_flags & IFF_UP) == 0 && 637 (ifp->if_flags & IFF_RUNNING) != 0) { 638 /* 639 * If interface is marked down and it is running, then 640 * stop it. 641 */ 642 mb8795_stop(sc); 643 ifp->if_flags &= ~IFF_RUNNING; 644 } else if ((ifp->if_flags & IFF_UP) != 0 && 645 (ifp->if_flags & IFF_RUNNING) == 0) { 646 /* 647 * If interface is marked up and it is stopped, then 648 * start it. 649 */ 650 mb8795_init(sc); 651 } else { 652 /* 653 * Reset the interface to pick up changes in any other 654 * flags that affect hardware registers. 655 */ 656 /*mb8795_stop(sc);*/ 657 mb8795_init(sc); 658 } 659 #ifdef XE_DEBUG 660 if (ifp->if_flags & IFF_DEBUG) 661 sc->sc_debug = 1; 662 else 663 sc->sc_debug = 0; 664 #endif 665 break; 666 667 case SIOCADDMULTI: 668 case SIOCDELMULTI: 669 error = (cmd == SIOCADDMULTI) ? 670 ether_addmulti(ifr, &sc->sc_ethercom) : 671 ether_delmulti(ifr, &sc->sc_ethercom); 672 673 if (error == ENETRESET) { 674 /* 675 * Multicast list has changed; set the hardware filter 676 * accordingly. 677 */ 678 mb8795_reset(sc); 679 error = 0; 680 } 681 break; 682 683 #if 0 684 case SIOCGIFMEDIA: 685 case SIOCSIFMEDIA: 686 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 687 break; 688 #endif 689 690 default: 691 error = EINVAL; 692 break; 693 } 694 695 splx(s); 696 697 #if 0 698 DPRINTF(("DEBUG: mb8795_ioctl(0x%lx) returning %d\n", 699 cmd,error)); 700 #endif 701 702 return (error); 703 } 704 705 /* 706 * Setup output on interface. 707 * Get another datagram to send off of the interface queue, and map it to the 708 * interface before starting the output. 709 * Called only at splnet or interrupt level. 710 */ 711 void 712 mb8795_start(ifp) 713 struct ifnet *ifp; 714 { 715 int error; 716 struct mb8795_softc *sc = ifp->if_softc; 717 718 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 719 return; 720 721 DPRINTF(("%s: mb8795_start()\n",sc->sc_dev.dv_xname)); 722 723 #if (defined(DIAGNOSTIC)) 724 { 725 u_char txstat; 726 txstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT); 727 if (!(txstat & XE_TXSTAT_READY)) { 728 /* @@@ I used to panic here, but then it paniced once. 729 * Let's see if I can just reset instead. [ dbj 980706.1900 ] 730 */ 731 printf("%s: transmitter not ready\n", sc->sc_dev.dv_xname); 732 mb8795_reset(sc); 733 return; 734 } 735 } 736 #endif 737 738 #if 0 739 return; /* @@@ Turn off xmit for debugging */ 740 #endif 741 742 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT, XE_TXSTAT_CLEAR); 743 744 IF_DEQUEUE(&ifp->if_snd, sc->sc_tx_mb_head); 745 if (sc->sc_tx_mb_head == 0) { 746 printf("%s: No packet to start\n", 747 sc->sc_dev.dv_xname); 748 return; 749 } 750 751 ifp->if_timer = 5; 752 753 /* The following is a next specific hack that should 754 * probably be moved out of MI code. 755 * This macro assumes it can move forward as needed 756 * in the buffer. Perhaps it should zero the extra buffer. 757 */ 758 #define REALIGN_DMABUF(s,l) \ 759 { (s) = ((u_char *)(((unsigned)(s)+DMA_BEGINALIGNMENT-1) \ 760 &~(DMA_BEGINALIGNMENT-1))); \ 761 (l) = ((u_char *)(((unsigned)((s)+(l))+DMA_ENDALIGNMENT-1) \ 762 &~(DMA_ENDALIGNMENT-1)))-(s);} 763 764 #if 0 765 error = bus_dmamap_load_mbuf(sc->sc_tx_dmat, 766 sc->sc_tx_dmamap, 767 sc->sc_tx_mb_head, 768 BUS_DMA_NOWAIT); 769 #else 770 { 771 u_char *buf = sc->sc_txbuf; 772 int buflen = 0; 773 struct mbuf *m = sc->sc_tx_mb_head; 774 buflen = m->m_pkthdr.len; 775 776 /* Fix runt packets, @@@ memory overrun */ 777 if (buflen < ETHERMIN+sizeof(struct ether_header)) { 778 buflen = ETHERMIN+sizeof(struct ether_header); 779 } 780 781 { 782 u_char *p = buf; 783 for (m=sc->sc_tx_mb_head; m; m = m->m_next) { 784 if (m->m_len == 0) continue; 785 bcopy(mtod(m, u_char *), p, m->m_len); 786 p += m->m_len; 787 } 788 } 789 790 error = bus_dmamap_load(sc->sc_tx_dmat, sc->sc_tx_dmamap, 791 buf,buflen,NULL,BUS_DMA_NOWAIT); 792 } 793 #endif 794 if (error) { 795 printf("%s: can't load mbuf chain, error = %d\n", 796 sc->sc_dev.dv_xname, error); 797 m_freem(sc->sc_tx_mb_head); 798 sc->sc_tx_mb_head = NULL; 799 return; 800 } 801 802 #ifdef DIAGNOSTIC 803 if (sc->sc_tx_loaded != 0) { 804 panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname, 805 sc->sc_tx_loaded); 806 } 807 #endif 808 809 ifp->if_flags |= IFF_OACTIVE; 810 811 bus_dmamap_sync(sc->sc_tx_dmat, sc->sc_tx_dmamap, 0, 812 sc->sc_tx_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); 813 814 nextdma_start(sc->sc_tx_nd, DMACSR_SETWRITE); 815 816 #if NBPFILTER > 0 817 /* 818 * Pass packet to bpf if there is a listener. 819 */ 820 if (ifp->if_bpf) 821 bpf_mtap(ifp->if_bpf, sc->sc_tx_mb_head); 822 #endif 823 824 } 825 826 /****************************************************************/ 827 828 void 829 mb8795_txdma_completed(map, arg) 830 bus_dmamap_t map; 831 void *arg; 832 { 833 struct mb8795_softc *sc = arg; 834 835 DPRINTF(("%s: mb8795_txdma_completed()\n",sc->sc_dev.dv_xname)); 836 837 #ifdef DIAGNOSTIC 838 if (!sc->sc_tx_loaded) { 839 panic("%s: tx completed never loaded ",sc->sc_dev.dv_xname); 840 } 841 if (map != sc->sc_tx_dmamap) { 842 panic("%s: unexpected tx completed map",sc->sc_dev.dv_xname); 843 } 844 845 #endif 846 } 847 848 void 849 mb8795_txdma_shutdown(arg) 850 void *arg; 851 { 852 struct mb8795_softc *sc = arg; 853 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 854 855 DPRINTF(("%s: mb8795_txdma_shutdown()\n",sc->sc_dev.dv_xname)); 856 857 #ifdef DIAGNOSTIC 858 if (!sc->sc_tx_loaded) { 859 panic("%s: tx shutdown never loaded ",sc->sc_dev.dv_xname); 860 } 861 #endif 862 863 { 864 865 if (sc->sc_tx_loaded) { 866 bus_dmamap_sync(sc->sc_tx_dmat, sc->sc_tx_dmamap, 867 0, sc->sc_tx_dmamap->dm_mapsize, 868 BUS_DMASYNC_POSTWRITE); 869 bus_dmamap_unload(sc->sc_tx_dmat, sc->sc_tx_dmamap); 870 m_freem(sc->sc_tx_mb_head); 871 sc->sc_tx_mb_head = NULL; 872 873 sc->sc_tx_loaded--; 874 } 875 876 #ifdef DIAGNOSTIC 877 if (sc->sc_tx_loaded != 0) { 878 panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname, 879 sc->sc_tx_loaded); 880 } 881 #endif 882 883 ifp->if_flags &= ~IFF_OACTIVE; 884 885 ifp->if_timer = 0; 886 887 if (ifp->if_snd.ifq_head != NULL) { 888 mb8795_start(ifp); 889 } 890 891 } 892 893 #if 0 894 /* Enable ready interrupt */ 895 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK, 896 bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK) 897 | XE_TXMASK_READYIE); 898 #endif 899 } 900 901 902 void 903 mb8795_rxdma_completed(map, arg) 904 bus_dmamap_t map; 905 void *arg; 906 { 907 struct mb8795_softc *sc = arg; 908 909 sc->sc_rx_completed_idx++; 910 sc->sc_rx_completed_idx %= MB8795_NRXBUFS; 911 912 DPRINTF(("%s: mb8795_rxdma_completed(), sc->sc_rx_completed_idx = %d\n", 913 sc->sc_dev.dv_xname, sc->sc_rx_completed_idx)); 914 915 #if (defined(DIAGNOSTIC)) 916 if (map != sc->sc_rx_dmamap[sc->sc_rx_completed_idx]) { 917 panic("%s: Unexpected rx dmamap completed\n", 918 sc->sc_dev.dv_xname); 919 } 920 #endif 921 } 922 923 void 924 mb8795_rxdma_shutdown(arg) 925 void *arg; 926 { 927 struct mb8795_softc *sc = arg; 928 929 DPRINTF(("%s: mb8795_rxdma_shutdown(), restarting.\n",sc->sc_dev.dv_xname)); 930 931 nextdma_start(sc->sc_rx_nd, DMACSR_SETREAD); 932 } 933 934 935 /* 936 * load a dmamap with a freshly allocated mbuf 937 */ 938 struct mbuf * 939 mb8795_rxdmamap_load(sc,map) 940 struct mb8795_softc *sc; 941 bus_dmamap_t map; 942 { 943 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 944 struct mbuf *m; 945 int error; 946 947 MGETHDR(m, M_DONTWAIT, MT_DATA); 948 if (m) { 949 MCLGET(m, M_DONTWAIT); 950 if ((m->m_flags & M_EXT) == 0) { 951 m_freem(m); 952 m = NULL; 953 } else { 954 m->m_len = MCLBYTES; 955 } 956 } 957 if (!m) { 958 /* @@@ Handle this gracefully by reusing a scratch buffer 959 * or something. 960 */ 961 panic("Unable to get memory for incoming ethernet\n"); 962 } 963 964 /* Align buffer, @@@ next specific. 965 * perhaps should be using M_ALIGN here instead? 966 * First we give us a little room to align with. 967 */ 968 { 969 u_char *buf = m->m_data; 970 int buflen = m->m_len; 971 buflen -= DMA_ENDALIGNMENT+DMA_BEGINALIGNMENT; 972 REALIGN_DMABUF(buf, buflen); 973 m->m_data = buf; 974 m->m_len = buflen; 975 } 976 977 m->m_pkthdr.rcvif = ifp; 978 m->m_pkthdr.len = m->m_len; 979 980 error = bus_dmamap_load_mbuf(sc->sc_rx_dmat, 981 map, m, BUS_DMA_NOWAIT); 982 983 bus_dmamap_sync(sc->sc_rx_dmat, map, 0, 984 map->dm_mapsize, BUS_DMASYNC_PREREAD); 985 986 if (error) { 987 DPRINTF(("DEBUG: m->m_data = %p, m->m_len = %d\n", 988 m->m_data, m->m_len)); 989 DPRINTF(("DEBUG: MCLBYTES = %d, map->_dm_size = %ld\n", 990 MCLBYTES, map->_dm_size)); 991 992 panic("%s: can't load rx mbuf chain, error = %d\n", 993 sc->sc_dev.dv_xname, error); 994 m_freem(m); 995 m = NULL; 996 } 997 998 return(m); 999 } 1000 1001 bus_dmamap_t 1002 mb8795_rxdma_continue(arg) 1003 void *arg; 1004 { 1005 struct mb8795_softc *sc = arg; 1006 bus_dmamap_t map = NULL; 1007 1008 /* 1009 * Currently, starts dumping new packets if the buffers 1010 * fill up. This should probably reclaim unhandled 1011 * buffers instead so we drop older packets instead 1012 * of newer ones. 1013 */ 1014 if (((sc->sc_rx_loaded_idx+1)%MB8795_NRXBUFS) != sc->sc_rx_handled_idx) { 1015 sc->sc_rx_loaded_idx++; 1016 sc->sc_rx_loaded_idx %= MB8795_NRXBUFS; 1017 map = sc->sc_rx_dmamap[sc->sc_rx_loaded_idx]; 1018 1019 DPRINTF(("%s: mb8795_rxdma_continue() sc->sc_rx_loaded_idx = %d\nn", 1020 sc->sc_dev.dv_xname,sc->sc_rx_loaded_idx)); 1021 } 1022 #if (defined(DIAGNOSTIC)) 1023 else { 1024 panic("%s: out of receive DMA buffers\n",sc->sc_dev.dv_xname); 1025 } 1026 #endif 1027 1028 return(map); 1029 } 1030 1031 bus_dmamap_t 1032 mb8795_txdma_continue(arg) 1033 void *arg; 1034 { 1035 struct mb8795_softc *sc = arg; 1036 bus_dmamap_t map; 1037 1038 DPRINTF(("%s: mb8795_txdma_continue()\n",sc->sc_dev.dv_xname)); 1039 1040 if (sc->sc_tx_loaded) { 1041 map = NULL; 1042 } else { 1043 map = sc->sc_tx_dmamap; 1044 sc->sc_tx_loaded++; 1045 } 1046 1047 #ifdef DIAGNOSTIC 1048 if (sc->sc_tx_loaded != 1) { 1049 panic("%s: sc->sc_tx_loaded is %d",sc->sc_dev.dv_xname, 1050 sc->sc_tx_loaded); 1051 } 1052 #endif 1053 1054 return(map); 1055 } 1056 1057 /****************************************************************/ 1058