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