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