1 /* $NetBSD: mb8795.c,v 1.17 1999/08/29 05:51:45 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 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 #if NBPFILTER > 0 178 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 179 #endif 180 181 sc->sc_sh = shutdownhook_establish(mb8795_shutdown, sc); 182 if (sc->sc_sh == NULL) 183 panic("mb8795_config: can't establish shutdownhook"); 184 185 #if NRND > 0 186 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 187 RND_TYPE_NET, 0); 188 #endif 189 190 /* Initialize the dma maps */ 191 { 192 int error; 193 if ((error = bus_dmamap_create(sc->sc_tx_dmat, MCLBYTES, 194 (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW, 195 &sc->sc_tx_dmamap)) != 0) { 196 panic("%s: can't create tx DMA map, error = %d\n", 197 sc->sc_dev.dv_xname, error); 198 } 199 { 200 int i; 201 for(i=0;i<MB8795_NRXBUFS;i++) { 202 if ((error = bus_dmamap_create(sc->sc_rx_dmat, MCLBYTES, 203 (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW, 204 &sc->sc_rx_dmamap[i])) != 0) { 205 panic("%s: can't create rx DMA map, error = %d\n", 206 sc->sc_dev.dv_xname, error); 207 } 208 sc->sc_rx_mb_head[i] = NULL; 209 } 210 sc->sc_rx_loaded_idx = 0; 211 sc->sc_rx_completed_idx = 0; 212 sc->sc_rx_handled_idx = 0; 213 } 214 } 215 216 /* @@@ more next hacks 217 * the 2000 covers at least a 1500 mtu + headers 218 * + DMA_BEGINALIGNMENT+ DMA_ENDALIGNMENT 219 */ 220 sc->sc_txbuf = malloc(2000, M_DEVBUF, M_NOWAIT); 221 if (!sc->sc_txbuf) panic("%s: can't malloc tx DMA buffer", 222 sc->sc_dev.dv_xname); 223 224 sc->sc_tx_mb_head = NULL; 225 sc->sc_tx_loaded = 0; 226 227 sc->sc_tx_nd->nd_shutdown_cb = mb8795_txdma_shutdown; 228 sc->sc_tx_nd->nd_continue_cb = mb8795_txdma_continue; 229 sc->sc_tx_nd->nd_completed_cb = mb8795_txdma_completed; 230 sc->sc_tx_nd->nd_cb_arg = sc; 231 232 sc->sc_rx_nd->nd_shutdown_cb = mb8795_rxdma_shutdown; 233 sc->sc_rx_nd->nd_continue_cb = mb8795_rxdma_continue; 234 sc->sc_rx_nd->nd_completed_cb = mb8795_rxdma_completed; 235 sc->sc_rx_nd->nd_cb_arg = sc; 236 237 DPRINTF(("%s: leaving mb8795_config()\n",sc->sc_dev.dv_xname)); 238 } 239 240 241 /****************************************************************/ 242 #if 0 243 #define XCHR(x) "0123456789abcdef"[(x) & 0xf] 244 static void 245 hex_dump(unsigned char *pkt, size_t len) 246 { 247 size_t i, j; 248 249 printf("0000: "); 250 for(i=0; i<len; i++) { 251 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i])); 252 if ((i+1) % 16 == 0) { 253 printf(" %c", '"'); 254 for(j=0; j<16; j++) 255 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.'); 256 printf("%c\n%c%c%c%c: ", '"', XCHR((i+1)>>12), 257 XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1)); 258 } 259 } 260 printf("\n"); 261 } 262 #endif 263 264 /* 265 * Controller receive interrupt. 266 */ 267 void 268 mb8795_rint(sc) 269 struct mb8795_softc *sc; 270 { 271 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 272 int error = 0; 273 u_char rxstat; 274 u_char rxmask; 275 276 rxstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT); 277 rxmask = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK); 278 279 bus_space_write_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT, XE_RXSTAT_CLEAR); 280 281 #if 0 282 printf("%s: rx interrupt, rxstat = %b\n", 283 sc->sc_dev.dv_xname, rxstat, XE_RXSTAT_BITS); 284 #endif 285 286 if (rxstat & XE_RXSTAT_RESET) { 287 DPRINTF(("%s: rx reset packet\n", 288 sc->sc_dev.dv_xname)); 289 error++; 290 } 291 if (rxstat & XE_RXSTAT_SHORT) { 292 DPRINTF(("%s: rx short packet\n", 293 sc->sc_dev.dv_xname)); 294 error++; 295 } 296 if (rxstat & XE_RXSTAT_ALIGNERR) { 297 DPRINTF(("%s: rx alignment error\n", 298 sc->sc_dev.dv_xname)); 299 error++; 300 } 301 if (rxstat & XE_RXSTAT_CRCERR) { 302 DPRINTF(("%s: rx CRC error\n", 303 sc->sc_dev.dv_xname)); 304 error++; 305 } 306 if (rxstat & XE_RXSTAT_OVERFLOW) { 307 DPRINTF(("%s: rx overflow error\n", 308 sc->sc_dev.dv_xname)); 309 error++; 310 } 311 312 if (error) { 313 ifp->if_ierrors++; 314 /* @@@ handle more gracefully, free memory, etc. */ 315 } 316 317 if (rxstat & XE_RXSTAT_OK) { 318 int s; 319 s = spldma(); 320 321 while(sc->sc_rx_handled_idx != sc->sc_rx_completed_idx) { 322 struct mbuf *m; 323 bus_dmamap_t map; 324 325 sc->sc_rx_handled_idx++; 326 sc->sc_rx_handled_idx %= MB8795_NRXBUFS; 327 328 /* Should probably not do this much while interrupts 329 * are disabled, but for now we will. 330 */ 331 332 map = sc->sc_rx_dmamap[sc->sc_rx_handled_idx]; 333 m = sc->sc_rx_mb_head[sc->sc_rx_handled_idx]; 334 335 bus_dmamap_sync(sc->sc_rx_dmat, map, 336 0, map->dm_mapsize, BUS_DMASYNC_POSTREAD); 337 338 339 /* Find receive length and chop off CRC */ 340 /* @@@ assumes packet is all in first segment 341 */ 342 m->m_pkthdr.len = map->dm_segs[0].ds_xfer_len-4; 343 m->m_len = map->dm_segs[0].ds_xfer_len-4; 344 m->m_pkthdr.rcvif = ifp; 345 346 bus_dmamap_unload(sc->sc_rx_dmat, map); 347 348 /* Install a fresh mbuf for next packet */ 349 350 sc->sc_rx_mb_head[sc->sc_rx_handled_idx] = 351 mb8795_rxdmamap_load(sc,map); 352 353 /* enable interrupts while we process the packet */ 354 splx(s); 355 356 #if defined(XE_DEBUG) 357 /* Peek at the packet */ 358 DPRINTF(("%s: received packet, at VA 0x%08x-0x%08x,len %d\n", 359 sc->sc_dev.dv_xname,mtod(m,u_char *),mtod(m,u_char *)+m->m_len,m->m_len)); 360 #if 0 361 hex_dump(mtod(m,u_char *), m->m_pkthdr.len < 255 ? m->m_pkthdr.len : 128 ); 362 #endif 363 #endif 364 365 { 366 ifp->if_ipackets++; 367 debugipkt++; 368 369 /* Pass the packet up. */ 370 (*ifp->if_input)(ifp, m); 371 } 372 373 s = spldma(); 374 375 } 376 377 splx(s); 378 379 } 380 381 DPRINTF(("%s: rx interrupt, rxstat = %b\n", 382 sc->sc_dev.dv_xname, rxstat, XE_RXSTAT_BITS)); 383 384 DPRINTF(("rxstat = 0x%b\n", 385 bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXSTAT), XE_RXSTAT_BITS)); 386 DPRINTF(("rxmask = 0x%b\n", 387 bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMASK), XE_RXMASK_BITS)); 388 DPRINTF(("rxmode = 0x%b\n", 389 bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_RXMODE), XE_RXMODE_BITS)); 390 391 return; 392 } 393 394 /* 395 * Controller transmit interrupt. 396 */ 397 void 398 mb8795_tint(sc) 399 struct mb8795_softc *sc; 400 401 { 402 u_char txstat; 403 u_char txmask; 404 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 405 406 txstat = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXSTAT); 407 txmask = bus_space_read_1(sc->sc_bst,sc->sc_bsh, XE_TXMASK); 408 409 #if 0 410 DPRINTF(("%s: tx interrupt, txstat = %b\n", 411 sc->sc_dev.dv_xname, txstat, XE_TXSTAT_BITS)); 412 #endif 413 414 if (txstat & XE_TXSTAT_SHORTED) { 415 printf("%s: tx cable shorted\n", sc->sc_dev.dv_xname); 416 ifp->if_oerrors++; 417 } 418 if (txstat & XE_TXSTAT_UNDERFLOW) { 419 printf("%s: tx underflow\n", sc->sc_dev.dv_xname); 420 ifp->if_oerrors++; 421 } 422 if (txstat & XE_TXSTAT_COLLERR) { 423 DPRINTF(("%s: tx collision\n", sc->sc_dev.dv_xname)); 424 ifp->if_collisions++; 425 } 426 if (txstat & XE_TXSTAT_COLLERR16) { 427 printf("%s: tx 16th collision\n", sc->sc_dev.dv_xname); 428 ifp->if_oerrors++; 429 ifp->if_collisions += 16; 430 } 431 432 #if 0 433 if (txstat & XE_TXSTAT_READY) { 434 435 panic("%s: unexpected tx interrupt %b", 436 sc->sc_dev.dv_xname,txstat,XE_TXSTAT_BITS); 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