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