1 /* $NetBSD: mb86950.c,v 1.10 2007/10/19 11:59:55 ad Exp $ */ 2 3 /* 4 * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 5 * 6 * This software may be used, modified, copied, distributed, and sold, in 7 * both source and binary form provided that the above copyright, these 8 * terms and the following disclaimer are retained. The name of the author 9 * and/or the contributor may not be used to endorse or promote products 10 * derived from this software without specific prior written permission. 11 * 12 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND 13 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE 16 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION. 19 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 20 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 22 * SUCH DAMAGE. 23 */ 24 25 /* 26 * Portions copyright (C) 1993, David Greenman. This software may be used, 27 * modified, copied, distributed, and sold, in both source and binary form 28 * provided that the above copyright and these terms are retained. Under no 29 * circumstances is the author responsible for the proper functioning of this 30 * software, nor does the author assume any responsibility for damages 31 * incurred with its use. 32 */ 33 34 /* 35 * Portions copyright (c) 1995 Mika Kortelainen 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by Mika Kortelainen 49 * 4. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 /* 65 * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. 66 * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp> 67 */ 68 69 #include <sys/cdefs.h> 70 __KERNEL_RCSID(0, "$NetBSD: mb86950.c,v 1.10 2007/10/19 11:59:55 ad Exp $"); 71 72 /* 73 * Device driver for Fujitsu mb86950 based Ethernet cards. 74 * Adapted by Dave J. Barnes from various Internet sources including 75 * mb86960.c (NetBSD), if_qn.c (NetBSD/Amiga), DOS Packet Driver (Brian Fisher, 76 * Queens University), EtherBoot Driver (Ken Yap). 77 */ 78 79 /* XXX There are still rough edges...... 80 * 81 * (1) There is no watchdog timer for the transmitter. It's doubtful that 82 * transmit from the chip could be restarted without a hardware reset 83 * though. (Fixed - not fully tested) 84 * 85 * (2) The media interface callback goo is broke. No big deal since to change 86 * from aui to bnc on the old Tiara LANCard requires moving 8 board jumpers. 87 * Other cards (SMC ?) using the EtherStar chip may support media change 88 * via software. (Fixed - tested) 89 * 90 * (3) The maximum outstanding transmit packets is set to 4. What 91 * is a good limit of outstanding transmit packets for the EtherStar? 92 * Is there a way to tell how many bytes are remaining to be 93 * transmitted? [no] 94 --- 95 When the EtherStar was designed, CPU power was a fraction 96 of what it is now. The single EtherStar transmit buffer 97 was fine. It was unlikely that the CPU could outrun the 98 EtherStar. However, things in 2004 are quite different. 99 sc->txb_size is used to keep the CPU from overrunning the 100 EtherStar. At most allow one packet transmitting and one 101 going into the fifo. 102 103 --- 104 No, that isn't right either :( 105 106 * (4) Multicast isn't supported. Feel free to add multicast code 107 * if you know how to make the EtherStar do multicast. Otherwise 108 * you'd have to use promiscuous mode and do multicast in software. OUCH! 109 * 110 * (5) There are no bus_space_barrier calls used. Are they needed? Maybe not. 111 * 112 * (6) Access to the fifo assumes word (16 bit) mode. Cards configured for 113 * byte wide fifo access will require driver code changes. 114 * 115 * Only the minimum code necessary to make the Tiara LANCard work 116 * has been tested. Other cards may require more work, especially 117 * byte mode fifo and if DMA is used. 118 * 119 * djb / 2004 120 */ 121 122 #include "opt_inet.h" 123 #include "bpfilter.h" 124 #include "rnd.h" 125 126 #include <sys/param.h> 127 #include <sys/systm.h> 128 #include <sys/errno.h> 129 #include <sys/ioctl.h> 130 #include <sys/mbuf.h> 131 #include <sys/socket.h> 132 #include <sys/syslog.h> 133 #include <sys/device.h> 134 #if NRND > 0 135 #include <sys/rnd.h> 136 #endif 137 138 #include <net/if.h> 139 #include <net/if_dl.h> 140 #include <net/if_types.h> 141 #include <net/if_media.h> 142 #include <net/if_ether.h> 143 144 #ifdef INET 145 #include <netinet/in.h> 146 #include <netinet/in_systm.h> 147 #include <netinet/in_var.h> 148 #include <netinet/ip.h> 149 #include <netinet/if_inarp.h> 150 #endif 151 152 153 #if NBPFILTER > 0 154 #include <net/bpf.h> 155 #include <net/bpfdesc.h> 156 #endif 157 158 #include <sys/bus.h> 159 160 #include <dev/ic/mb86950reg.h> 161 #include <dev/ic/mb86950var.h> 162 163 #ifndef __BUS_SPACE_HAS_STREAM_METHODS 164 #define bus_space_write_stream_2 bus_space_write_2 165 #define bus_space_write_multi_stream_2 bus_space_write_multi_2 166 #define bus_space_read_multi_stream_2 bus_space_read_multi_2 167 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */ 168 169 /* Standard driver entry points. These can be static. */ 170 int mb86950_ioctl __P((struct ifnet *, u_long, void *)); 171 void mb86950_init __P((struct mb86950_softc *)); 172 void mb86950_start __P((struct ifnet *)); 173 void mb86950_watchdog __P((struct ifnet *)); 174 void mb86950_reset __P((struct mb86950_softc *)); 175 176 /* Local functions. */ 177 void mb86950_stop __P((struct mb86950_softc *)); 178 void mb86950_tint __P((struct mb86950_softc *, u_int8_t)); 179 void mb86950_rint __P((struct mb86950_softc *, u_int8_t)); 180 int mb86950_get_fifo __P((struct mb86950_softc *, u_int)); 181 ushort mb86950_put_fifo __P((struct mb86950_softc *, struct mbuf *)); 182 void mb86950_drain_fifo __P((struct mb86950_softc *)); 183 184 int mb86950_mediachange __P((struct ifnet *)); 185 void mb86950_mediastatus __P((struct ifnet *, struct ifmediareq *)); 186 187 188 #if ESTAR_DEBUG >= 1 189 void mb86950_dump __P((int, struct mb86950_softc *)); 190 #endif 191 192 /********************************************************************/ 193 194 void 195 mb86950_attach(sc, myea) 196 struct mb86950_softc *sc; 197 u_int8_t *myea; 198 { 199 200 #ifdef DIAGNOSTIC 201 if (myea == NULL) { 202 printf("%s: ethernet address shouldn't be NULL\n", 203 sc->sc_dev.dv_xname); 204 panic("NULL ethernet address"); 205 } 206 #endif 207 208 /* Initialize 86950. */ 209 mb86950_stop(sc); 210 211 memcpy(sc->sc_enaddr, myea, sizeof(sc->sc_enaddr)); 212 213 sc->sc_stat |= ESTAR_STAT_ENABLED; 214 } 215 216 /* 217 * Stop everything on the interface. 218 * 219 * All buffered packets, both transmitting and receiving, 220 * if any, will be lost by stopping the interface. 221 */ 222 void 223 mb86950_stop(sc) 224 struct mb86950_softc *sc; 225 { 226 bus_space_tag_t bst = sc->sc_bst; 227 bus_space_handle_t bsh = sc->sc_bsh; 228 229 /* Stop interface hardware. */ 230 bus_space_write_1(bst, bsh, DLCR_CONFIG, DISABLE_DLC); 231 delay(200); 232 233 /* Disable interrupts. */ 234 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0); 235 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0); 236 237 /* Ack / Clear all interrupt status. */ 238 bus_space_write_1(bst, bsh, DLCR_TX_STAT, 0xff); 239 bus_space_write_1(bst, bsh, DLCR_RX_STAT, 0xff); 240 241 /* Clear DMA Bit */ 242 bus_space_write_2(bst, bsh, BMPR_DMA, 0); 243 244 /* accept no packets */ 245 bus_space_write_1(bst, bsh, DLCR_TX_MODE, 0); 246 bus_space_write_1(bst, bsh, DLCR_RX_MODE, 0); 247 248 mb86950_drain_fifo(sc); 249 250 } 251 252 void 253 mb86950_drain_fifo(sc) 254 struct mb86950_softc *sc; 255 { 256 bus_space_tag_t bst = sc->sc_bst; 257 bus_space_handle_t bsh = sc->sc_bsh; 258 259 /* Read data until bus read error (i.e. buffer empty). */ 260 /* XXX There ought to be a better way, eats CPU and bothers the chip */ 261 while (!(bus_space_read_1(bst, bsh, DLCR_RX_STAT) & RX_BUS_RD_ERR)) 262 bus_space_read_2(bst, bsh, BMPR_FIFO); 263 /* XXX */ 264 265 /* Clear Bus Rd Error */ 266 bus_space_write_1(bst, bsh, DLCR_RX_STAT, RX_BUS_RD_ERR); 267 } 268 269 /* 270 * Install interface into kernel networking data structures 271 */ 272 void 273 mb86950_config(struct mb86950_softc *sc, int *media, 274 int nmedia, int defmedia) 275 { 276 struct ifnet *ifp = &sc->sc_ec.ec_if; 277 bus_space_tag_t bst = sc->sc_bst; 278 bus_space_handle_t bsh = sc->sc_bsh; 279 280 /* Initialize ifnet structure. */ 281 strcpy(ifp->if_xname, sc->sc_dev.dv_xname); 282 ifp->if_softc = sc; 283 ifp->if_start = mb86950_start; 284 ifp->if_ioctl = mb86950_ioctl; 285 ifp->if_watchdog = mb86950_watchdog; 286 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 287 288 IFQ_SET_READY(&ifp->if_snd); 289 290 /* Initialize media goo. */ 291 /* XXX The Tiara LANCard uses board jumpers to change media. 292 * This code may have to be changed for other cards. 293 */ 294 ifmedia_init(&sc->sc_media, 0, mb86950_mediachange, mb86950_mediastatus); 295 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 296 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 297 298 /* Attach the interface. */ 299 if_attach(ifp); 300 301 /* Feed the chip the station address. */ 302 bus_space_write_region_1(bst, bsh, DLCR_NODE_ID, sc->sc_enaddr, ETHER_ADDR_LEN); 303 304 ether_ifattach(ifp, sc->sc_enaddr); 305 306 #if NRND > 0 307 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 308 RND_TYPE_NET, 0); 309 #endif 310 311 /* XXX No! This doesn't work - DLCR6 of the mb86950 is different 312 313 bus_space_write_1(bst, bsh, DLCR_CONFIG, 0x0f); 314 buf_config = bus_space_read_1(bst, bsh, DLCR_CONFIG); 315 316 sc->txb_count = ((buf_config & 0x0c) ? 2 : 1); 317 sc->txb_size = 1024 * (2 << ((buf_config & 0x0c) ? (((buf_config & 0x0c) >> 2) - 1) : 0)); 318 sc->txb_free = (sc->txb_size * sc->txb_count) / 1500; 319 320 sc->rxb_size = ((8 << (buf_config & 3)) * 1024) - (sc->txb_size * sc->txb_count); 321 sc->rxb_max = sc->rxb_size / 64; 322 323 printf("mb86950: Buffer Size %dKB with %d transmit buffer(s) %dKB each.\n", 324 (8 << (buf_config & 3)), sc->txb_count, (sc->txb_size / 1024)); 325 printf(" Transmit Buffer Space for %d maximum sized packet(s).\n",sc->txb_free); 326 printf(" System Bus Width %d bits, Buffer Memory %d bits.\n", 327 ((buf_config & 0x20) ? 8 : 16), 328 ((buf_config & 0x10) ? 8 : 16)); 329 330 */ 331 332 /* Set reasonable values for number of packet flow control if not 333 * set elsewhere */ 334 if (sc->txb_num_pkt == 0) sc->txb_num_pkt = 1; 335 if (sc->rxb_num_pkt == 0) sc->rxb_num_pkt = 100; 336 337 /* Print additional info when attached. */ 338 printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname, 339 ether_sprintf(sc->sc_enaddr)); 340 341 /* The attach is successful. */ 342 sc->sc_stat |= ESTAR_STAT_ATTACHED; 343 } 344 345 /* 346 * Media change callback. 347 */ 348 int 349 mb86950_mediachange(ifp) 350 struct ifnet *ifp; 351 { 352 353 struct mb86950_softc *sc = ifp->if_softc; 354 355 if (sc->sc_mediachange) 356 return ((*sc->sc_mediachange)(sc)); 357 358 return (0); 359 } 360 361 /* 362 * Media status callback. 363 */ 364 void 365 mb86950_mediastatus(ifp, ifmr) 366 struct ifnet *ifp; 367 struct ifmediareq *ifmr; 368 { 369 struct mb86950_softc *sc = ifp->if_softc; 370 371 if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0) { 372 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 373 ifmr->ifm_status = 0; 374 return; 375 } 376 377 if (sc->sc_mediastatus) 378 (*sc->sc_mediastatus)(sc, ifmr); 379 380 } 381 382 /* 383 * Reset interface. 384 */ 385 void 386 mb86950_reset(sc) 387 struct mb86950_softc *sc; 388 { 389 int s; 390 391 s = splnet(); 392 log(LOG_ERR, "%s: device reset\n", sc->sc_dev.dv_xname); 393 mb86950_stop(sc); 394 mb86950_init(sc); 395 splx(s); 396 } 397 398 /* 399 * Device timeout/watchdog routine. Entered if the device neglects to 400 * generate an interrupt after a transmit has been started on it. 401 */ 402 void 403 mb86950_watchdog(ifp) 404 struct ifnet *ifp; 405 { 406 struct mb86950_softc *sc = ifp->if_softc; 407 bus_space_tag_t bst = sc->sc_bst; 408 bus_space_handle_t bsh = sc->sc_bsh; 409 u_int8_t tstat; 410 411 /* verbose watchdog messages for debugging timeouts */ 412 if ((tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT)) != 0) { 413 if (tstat & TX_CR_LOST) { 414 if ((tstat & (TX_COL | TX_16COL)) == 0) { 415 log(LOG_ERR, "%s: carrier lost\n", 416 sc->sc_dev.dv_xname); 417 } else { 418 log(LOG_ERR, "%s: excessive collisions\n", 419 sc->sc_dev.dv_xname); 420 } 421 } 422 else if ((tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) != 0) { 423 log(LOG_ERR, "%s: tx fifo underflow/overflow\n", 424 sc->sc_dev.dv_xname); 425 } else { 426 log(LOG_ERR, "%s: transmit error\n", 427 sc->sc_dev.dv_xname); 428 } 429 } else { 430 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 431 } 432 433 /* Don't know how many packets are lost by this accident. 434 * ... So just errors = errors + 1 435 */ 436 ifp->if_oerrors++; 437 438 mb86950_reset(sc); 439 440 } 441 442 /* 443 ******************** IOCTL 444 * Process an ioctl request. 445 */ 446 int 447 mb86950_ioctl(ifp, cmd, data) 448 struct ifnet *ifp; 449 u_long cmd; 450 void *data; 451 { 452 struct mb86950_softc *sc = ifp->if_softc; 453 struct ifaddr *ifa = (struct ifaddr *)data; 454 struct ifreq *ifr = (struct ifreq *)data; 455 456 int s, error = 0; 457 458 s = splnet(); 459 460 switch (cmd) { 461 case SIOCSIFADDR: 462 /* XXX depreciated ? What should I use instead? */ 463 if ((error = mb86950_enable(sc)) != 0) 464 break; 465 466 ifp->if_flags |= IFF_UP; 467 468 switch (ifa->ifa_addr->sa_family) { 469 470 #ifdef INET 471 case AF_INET: 472 mb86950_init(sc); 473 arp_ifinit(ifp, ifa); 474 break; 475 #endif 476 477 478 default: 479 mb86950_init(sc); 480 break; 481 } 482 break; 483 484 case SIOCSIFFLAGS: 485 if ((ifp->if_flags & IFF_UP) == 0 && 486 (ifp->if_flags & IFF_RUNNING) != 0) { 487 /* 488 * If interface is marked down and it is running, then 489 * stop it. 490 */ 491 mb86950_stop(sc); 492 ifp->if_flags &= ~IFF_RUNNING; 493 mb86950_disable(sc); 494 495 } else if ((ifp->if_flags & IFF_UP) != 0 && 496 (ifp->if_flags & IFF_RUNNING) == 0) { 497 /* 498 * If interface is marked up and it is stopped, then 499 * start it. 500 */ 501 if ((error = mb86950_enable(sc)) != 0) 502 break; 503 mb86950_init(sc); 504 505 } else if ((ifp->if_flags & IFF_UP) != 0) { 506 /* 507 * Reset the interface to pick up changes in any other 508 * flags that affect hardware registers. 509 */ 510 /* Setmode not supported 511 mb86950_setmode(sc); 512 */ 513 } 514 515 #if ESTAR_DEBUG >= 1 516 /* "ifconfig fe0 debug" to print register dump. */ 517 if (ifp->if_flags & IFF_DEBUG) { 518 log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n", 519 sc->sc_dev.dv_xname); 520 mb86950_dump(LOG_DEBUG, sc); 521 } 522 #endif 523 break; 524 525 case SIOCGIFMEDIA: 526 case SIOCSIFMEDIA: 527 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 528 break; 529 530 default: 531 error = EINVAL; 532 break; 533 } 534 535 splx(s); 536 return (error); 537 } 538 539 /* 540 * Initialize device. 541 */ 542 void 543 mb86950_init(sc) 544 struct mb86950_softc *sc; 545 { 546 bus_space_tag_t bst = sc->sc_bst; 547 bus_space_handle_t bsh = sc->sc_bsh; 548 struct ifnet *ifp = &sc->sc_ec.ec_if; 549 550 /* Reset transmitter flags. */ 551 ifp->if_flags &= ~IFF_OACTIVE; 552 ifp->if_timer = 0; 553 sc->txb_sched = 0; 554 555 bus_space_write_1(bst, bsh, DLCR_TX_MODE, LBC); 556 bus_space_write_1(bst, bsh, DLCR_RX_MODE, NORMAL_MODE); 557 558 /* Enable interrupts. */ 559 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK); 560 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK); 561 562 /* Enable transmitter and receiver. */ 563 bus_space_write_1(bst, bsh, DLCR_CONFIG, ENABLE_DLC); 564 delay(200); 565 566 /* Set 'running' flag. */ 567 ifp->if_flags |= IFF_RUNNING; 568 569 /* ...and attempt to start output. */ 570 mb86950_start(ifp); 571 572 } 573 574 void 575 mb86950_start(ifp) 576 struct ifnet *ifp; 577 { 578 struct mb86950_softc *sc = ifp->if_softc; 579 bus_space_tag_t bst = sc->sc_bst; 580 bus_space_handle_t bsh = sc->sc_bsh; 581 struct mbuf *m; 582 int len; 583 584 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 585 return; 586 587 IF_DEQUEUE(&ifp->if_snd, m); 588 if (m == 0) 589 return; 590 591 #if NBPFILTER > 0 592 /* Tap off here if there is a BPF listener. */ 593 if (ifp->if_bpf) 594 bpf_mtap(ifp->if_bpf, m); 595 #endif 596 597 /* Send the packet to the mb86950 */ 598 len = mb86950_put_fifo(sc,m); 599 m_freem(m); 600 601 /* XXX bus_space_barrier here ? */ 602 if (bus_space_read_1(bst, bsh, DLCR_TX_STAT) & (TX_UNDERFLO | TX_BUS_WR_ERR)) { 603 log(LOG_ERR, "%s: tx fifo underflow/overflow\n", sc->sc_dev.dv_xname); 604 } 605 606 bus_space_write_2(bst, bsh, BMPR_TX_LENGTH, len | TRANSMIT_START); 607 608 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK); 609 /* XXX */ 610 sc->txb_sched++; 611 612 /* We have space for 'n' transmit packets of size 'mtu. */ 613 if (sc->txb_sched > sc->txb_num_pkt) { 614 ifp->if_flags |= IFF_OACTIVE; 615 ifp->if_timer = 2; 616 } 617 } 618 619 /* 620 * Send packet - copy packet from mbuf to the fifo 621 */ 622 u_short 623 mb86950_put_fifo(sc, m) 624 struct mb86950_softc *sc; 625 struct mbuf *m; 626 { 627 bus_space_tag_t bst = sc->sc_bst; 628 bus_space_handle_t bsh = sc->sc_bsh; 629 u_short *data; 630 u_char savebyte[2]; 631 int len, len1, wantbyte; 632 u_short totlen; 633 634 memset(savebyte, 0, sizeof(savebyte)); /* XXX gcc */ 635 636 totlen = wantbyte = 0; 637 638 for (; m != NULL; m = m->m_next) { 639 data = mtod(m, u_short *); 640 len = m->m_len; 641 if (len > 0) { 642 totlen += len; 643 644 /* Finish the last word. */ 645 if (wantbyte) { 646 savebyte[1] = *((u_char *)data); 647 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte); 648 data = (u_short *)((u_char *)data + 1); 649 len--; 650 wantbyte = 0; 651 } 652 /* Output contiguous words. */ 653 if (len > 1) { 654 len1 = len/2; 655 bus_space_write_multi_stream_2(bst, bsh, BMPR_FIFO, data, len1); 656 data += len1; 657 len &= 1; 658 } 659 /* Save last byte, if necessary. */ 660 if (len == 1) { 661 savebyte[0] = *((u_char *)data); 662 wantbyte = 1; 663 } 664 } 665 } 666 667 if (wantbyte) { 668 savebyte[1] = 0; 669 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte); 670 } 671 672 if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 673 674 /* Fill the rest of the packet with zeros. */ 675 /* XXX Replace this mess with something else, eats CPU */ 676 /* The zero fill and last byte ought to be combined somehow */ 677 for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); len += 2) 678 bus_space_write_2(bst, bsh, BMPR_FIFO, 0); 679 /* XXX */ 680 681 totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN); 682 } 683 684 return (totlen); 685 } 686 687 /* 688 * Handle interrupts. 689 * Ethernet interface interrupt processor 690 */ 691 int 692 mb86950_intr(arg) 693 void *arg; 694 { 695 struct mb86950_softc *sc = arg; 696 bus_space_tag_t bst = sc->sc_bst; 697 bus_space_handle_t bsh = sc->sc_bsh; 698 struct ifnet *ifp = &sc->sc_ec.ec_if; 699 u_int8_t tstat, rstat; 700 701 /* Get interrupt status. */ 702 tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT); 703 rstat = bus_space_read_1(bst, bsh, DLCR_RX_STAT); 704 705 if (tstat == 0 && rstat == 0) return (0); 706 707 /* Disable etherstar interrupts so that we won't miss anything. */ 708 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0); 709 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0); 710 711 /* 712 * Handle transmitter interrupts. Handle these first because 713 * the receiver will reset the board under some conditions. 714 */ 715 if (tstat != 0) { 716 717 mb86950_tint(sc, tstat); 718 719 /* acknowledge transmit interrupt status. */ 720 bus_space_write_1(bst, bsh, DLCR_TX_STAT, tstat); 721 722 } 723 724 /* Handle receiver interrupts. */ 725 if (rstat != 0) { 726 727 mb86950_rint(sc, rstat); 728 729 /* acknowledge receive interrupt status. */ 730 bus_space_write_1(bst, bsh, DLCR_RX_STAT, rstat); 731 732 } 733 734 /* If tx still pending reset tx interrupt mask */ 735 if (sc->txb_sched > 0) 736 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK); 737 738 /* 739 * If it looks like the transmitter can take more data, 740 * attempt to start output on the interface. This is done 741 * after handling the receiver interrupt to give the 742 * receive operation priority. 743 */ 744 745 if ((ifp->if_flags & IFF_OACTIVE) == 0) 746 mb86950_start(ifp); 747 748 /* Set receive interrupts back */ 749 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK); 750 751 return(1); 752 } 753 754 /* Transmission interrupt handler */ 755 void 756 mb86950_tint(sc, tstat) 757 struct mb86950_softc *sc; 758 u_int8_t tstat; 759 { 760 bus_space_tag_t bst = sc->sc_bst; 761 bus_space_handle_t bsh = sc->sc_bsh; 762 struct ifnet *ifp = &sc->sc_ec.ec_if; 763 int col; 764 765 if (tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) { 766 /* XXX What do we need to do here? reset ? */ 767 ifp->if_oerrors++; 768 } 769 770 /* excessive collision */ 771 if (tstat & TX_16COL) { 772 ifp->if_collisions += 16; 773 /* 16 collisions means that the packet has been thrown away. */ 774 if (sc->txb_sched > 0) 775 sc->txb_sched--; 776 } 777 778 /* transmission complete. */ 779 if (tstat & TX_DONE) { 780 /* successfully transmitted packets ++. */ 781 ifp->if_opackets++; 782 if (sc->txb_sched > 0) 783 sc->txb_sched--; 784 785 /* Collision count valid only when TX_DONE is set */ 786 if (tstat & TX_COL) { 787 col = (bus_space_read_1(bst, bsh, DLCR_TX_MODE) & COL_MASK) >> 4; 788 ifp->if_collisions = ifp->if_collisions + col; 789 } 790 } 791 792 if (sc->txb_sched == 0) { 793 /* Reset output active flag and stop timer. */ 794 ifp->if_flags &= ~IFF_OACTIVE; 795 ifp->if_timer = 0; 796 } 797 } 798 799 /* receiver interrupt. */ 800 void 801 mb86950_rint(sc, rstat) 802 struct mb86950_softc *sc; 803 u_int8_t rstat; 804 { 805 bus_space_tag_t bst = sc->sc_bst; 806 bus_space_handle_t bsh = sc->sc_bsh; 807 struct ifnet *ifp = &sc->sc_ec.ec_if; 808 u_int status, len; 809 int i; 810 811 /* Update statistics if this interrupt is caused by an error. */ 812 if (rstat & RX_ERR_MASK) { 813 814 /* tried to read past end of fifo, should be harmless 815 * count everything else 816 */ 817 if ((rstat & RX_BUS_RD_ERR) == 0) { 818 ifp->if_ierrors++; 819 } 820 } 821 822 /* 823 * mb86950 has a flag indicating "receive buffer empty." 824 * We just loop checking the flag to pull out all received 825 * packets. 826 * 827 * We limit the number of iterrations to avoid infinite loop. 828 * It can be caused by a very slow CPU (some broken 829 * peripheral may insert incredible number of wait cycles) 830 * or, worse, by a broken mb86950 chip. 831 */ 832 for (i = 0; i < sc->rxb_num_pkt; i++) { 833 /* Stop the iterration if 86950 indicates no packets. */ 834 if (bus_space_read_1(bst, bsh, DLCR_RX_MODE) & RX_BUF_EMTY) 835 break; 836 837 /* receive packet status */ 838 status = bus_space_read_2(bst, bsh, BMPR_FIFO); 839 840 /* bad packet? */ 841 if ((status & GOOD_PKT) == 0) { 842 ifp->if_ierrors++; 843 mb86950_drain_fifo(sc); 844 continue; 845 } 846 847 /* Length valid ? */ 848 len = bus_space_read_2(bst, bsh, BMPR_FIFO); 849 850 if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || len < ETHER_HDR_LEN) { 851 ifp->if_ierrors++; 852 mb86950_drain_fifo(sc); 853 continue; 854 } 855 856 if (mb86950_get_fifo(sc, len) != 0) { 857 /* No mbufs? Drop packet. */ 858 ifp->if_ierrors++; 859 mb86950_drain_fifo(sc); 860 return; 861 } 862 863 /* Successfully received a packet. Update stat. */ 864 ifp->if_ipackets++; 865 } 866 } 867 868 /* 869 * Receive packet. 870 * Retrieve packet from receive buffer and send to the next level up via 871 * ether_input(). If there is a BPF listener, give a copy to BPF, too. 872 * Returns 0 if success, -1 if error (i.e., mbuf allocation failure). 873 */ 874 int 875 mb86950_get_fifo(sc, len) 876 struct mb86950_softc *sc; 877 u_int len; 878 { 879 bus_space_tag_t bst = sc->sc_bst; 880 bus_space_handle_t bsh = sc->sc_bsh; 881 struct ifnet *ifp = &sc->sc_ec.ec_if; 882 struct mbuf *m; 883 884 /* Allocate a header mbuf. */ 885 MGETHDR(m, M_DONTWAIT, MT_DATA); 886 if (m == 0) 887 return (-1); 888 889 /* 890 * Round len to even value. 891 */ 892 if (len & 1) 893 len++; 894 895 m->m_pkthdr.rcvif = ifp; 896 m->m_pkthdr.len = len; 897 898 /* The following silliness is to make NFS happy. */ 899 #define EROUND ((sizeof(struct ether_header) + 3) & ~3) 900 #define EOFF (EROUND - sizeof(struct ether_header)) 901 902 /* 903 * Our strategy has one more problem. There is a policy on 904 * mbuf cluster allocation. It says that we must have at 905 * least MINCLSIZE (208 bytes) to allocate a cluster. For a 906 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2), 907 * our code violates the rule... 908 * On the other hand, the current code is short, simple, 909 * and fast, however. It does no harmful thing, just wastes 910 * some memory. Any comments? FIXME. 911 */ 912 913 /* Attach a cluster if this packet doesn't fit in a normal mbuf. */ 914 if (len > MHLEN - EOFF) { 915 MCLGET(m, M_DONTWAIT); 916 if ((m->m_flags & M_EXT) == 0) { 917 m_freem(m); 918 return (-1); 919 } 920 } 921 922 /* 923 * The following assumes there is room for the ether header in the 924 * header mbuf. 925 */ 926 m->m_data += EOFF; 927 928 /* Set the length of this packet. */ 929 m->m_len = len; 930 931 /* Get a packet. */ 932 bus_space_read_multi_stream_2(bst, bsh, BMPR_FIFO, mtod(m, u_int16_t *), (len + 1) >> 1); 933 934 #if NBPFILTER > 0 935 /* 936 * Check if there's a BPF listener on this interface. If so, hand off 937 * the raw packet to bpf. 938 */ 939 if (ifp->if_bpf) 940 bpf_mtap(ifp->if_bpf, m); 941 #endif 942 943 (*ifp->if_input)(ifp, m); 944 return (0); 945 } 946 947 /* 948 * Enable power on the interface. 949 */ 950 int 951 mb86950_enable(sc) 952 struct mb86950_softc *sc; 953 { 954 955 if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0 && sc->sc_enable != NULL) { 956 if ((*sc->sc_enable)(sc) != 0) { 957 printf("%s: device enable failed\n", 958 sc->sc_dev.dv_xname); 959 return (EIO); 960 } 961 } 962 963 sc->sc_stat |= ESTAR_STAT_ENABLED; 964 return (0); 965 } 966 967 /* 968 * Disable power on the interface. 969 */ 970 void 971 mb86950_disable(sc) 972 struct mb86950_softc *sc; 973 { 974 975 if ((sc->sc_stat & ESTAR_STAT_ENABLED) != 0 && sc->sc_disable != NULL) { 976 (*sc->sc_disable)(sc); 977 sc->sc_stat &= ~ESTAR_STAT_ENABLED; 978 } 979 } 980 981 /* 982 * mbe_activate: 983 * 984 * Handle device activation/deactivation requests. 985 */ 986 int 987 mb86950_activate(self, act) 988 struct device *self; 989 enum devact act; 990 { 991 struct mb86950_softc *sc = (struct mb86950_softc *)self; 992 int rv, s; 993 994 rv = 0; 995 s = splnet(); 996 switch (act) { 997 case DVACT_ACTIVATE: 998 rv = EOPNOTSUPP; 999 break; 1000 1001 case DVACT_DEACTIVATE: 1002 if_deactivate(&sc->sc_ec.ec_if); 1003 break; 1004 } 1005 splx(s); 1006 return (rv); 1007 } 1008 1009 /* 1010 * mb86950_detach: 1011 * 1012 * Detach a mb86950 interface. 1013 */ 1014 int 1015 mb86950_detach(sc) 1016 struct mb86950_softc *sc; 1017 { 1018 struct ifnet *ifp = &sc->sc_ec.ec_if; 1019 1020 /* Succeed now if there's no work to do. */ 1021 if ((sc->sc_stat & ESTAR_STAT_ATTACHED) == 0) 1022 return (0); 1023 1024 /* Delete all media. */ 1025 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 1026 1027 #if NRND > 0 1028 /* Unhook the entropy source. */ 1029 rnd_detach_source(&sc->rnd_source); 1030 #endif 1031 ether_ifdetach(ifp); 1032 if_detach(ifp); 1033 1034 return (0); 1035 } 1036 1037 #if ESTAR_DEBUG >= 1 1038 void 1039 mb86950_dump(level, sc) 1040 int level; 1041 struct mb86950_softc *sc; 1042 { 1043 bus_space_tag_t bst = sc->sc_bst; 1044 bus_space_handle_t bsh = sc->sc_bsh; 1045 1046 log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x\n", 1047 bus_space_read_1(bst, bsh, DLCR_TX_STAT), 1048 bus_space_read_1(bst, bsh, DLCR_TX_INT_EN), 1049 bus_space_read_1(bst, bsh, DLCR_RX_STAT), 1050 bus_space_read_1(bst, bsh, DLCR_RX_INT_EN), 1051 bus_space_read_1(bst, bsh, DLCR_TX_MODE), 1052 bus_space_read_1(bst, bsh, DLCR_RX_MODE), 1053 bus_space_read_1(bst, bsh, DLCR_CONFIG)); 1054 1055 /* XXX BMPR2, 4 write only ? 1056 log(level, "\tBMPR = xxxx %04x %04x\n", 1057 bus_space_read_2(bst, bsh, BMPR_TX_LENGTH), 1058 bus_space_read_2(bst, bsh, BMPR_DMA)); 1059 */ 1060 } 1061 #endif 1062