1 /* $NetBSD: mb86950.c,v 1.14 2009/03/14 15:36:17 dsl 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.14 2009/03/14 15:36:17 dsl 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(struct ifnet *, u_long, void *); 171 void mb86950_init(struct mb86950_softc *); 172 void mb86950_start(struct ifnet *); 173 void mb86950_watchdog(struct ifnet *); 174 void mb86950_reset(struct mb86950_softc *); 175 176 /* Local functions. */ 177 void mb86950_stop(struct mb86950_softc *); 178 void mb86950_tint(struct mb86950_softc *, u_int8_t); 179 void mb86950_rint(struct mb86950_softc *, u_int8_t); 180 int mb86950_get_fifo(struct mb86950_softc *, u_int); 181 ushort mb86950_put_fifo(struct mb86950_softc *, struct mbuf *); 182 void mb86950_drain_fifo(struct mb86950_softc *); 183 184 int mb86950_mediachange(struct ifnet *); 185 void mb86950_mediastatus(struct ifnet *, struct ifmediareq *); 186 187 188 #if ESTAR_DEBUG >= 1 189 void mb86950_dump(int, struct mb86950_softc *); 190 #endif 191 192 /********************************************************************/ 193 194 void 195 mb86950_attach(struct mb86950_softc *sc, u_int8_t *myea) 196 { 197 198 #ifdef DIAGNOSTIC 199 if (myea == NULL) { 200 printf("%s: ethernet address shouldn't be NULL\n", 201 device_xname(&sc->sc_dev)); 202 panic("NULL ethernet address"); 203 } 204 #endif 205 206 /* Initialize 86950. */ 207 mb86950_stop(sc); 208 209 memcpy(sc->sc_enaddr, myea, sizeof(sc->sc_enaddr)); 210 211 sc->sc_stat |= ESTAR_STAT_ENABLED; 212 } 213 214 /* 215 * Stop everything on the interface. 216 * 217 * All buffered packets, both transmitting and receiving, 218 * if any, will be lost by stopping the interface. 219 */ 220 void 221 mb86950_stop(struct mb86950_softc *sc) 222 { 223 bus_space_tag_t bst = sc->sc_bst; 224 bus_space_handle_t bsh = sc->sc_bsh; 225 226 /* Stop interface hardware. */ 227 bus_space_write_1(bst, bsh, DLCR_CONFIG, DISABLE_DLC); 228 delay(200); 229 230 /* Disable interrupts. */ 231 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0); 232 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0); 233 234 /* Ack / Clear all interrupt status. */ 235 bus_space_write_1(bst, bsh, DLCR_TX_STAT, 0xff); 236 bus_space_write_1(bst, bsh, DLCR_RX_STAT, 0xff); 237 238 /* Clear DMA Bit */ 239 bus_space_write_2(bst, bsh, BMPR_DMA, 0); 240 241 /* accept no packets */ 242 bus_space_write_1(bst, bsh, DLCR_TX_MODE, 0); 243 bus_space_write_1(bst, bsh, DLCR_RX_MODE, 0); 244 245 mb86950_drain_fifo(sc); 246 247 } 248 249 void 250 mb86950_drain_fifo(struct mb86950_softc *sc) 251 { 252 bus_space_tag_t bst = sc->sc_bst; 253 bus_space_handle_t bsh = sc->sc_bsh; 254 255 /* Read data until bus read error (i.e. buffer empty). */ 256 /* XXX There ought to be a better way, eats CPU and bothers the chip */ 257 while (!(bus_space_read_1(bst, bsh, DLCR_RX_STAT) & RX_BUS_RD_ERR)) 258 bus_space_read_2(bst, bsh, BMPR_FIFO); 259 /* XXX */ 260 261 /* Clear Bus Rd Error */ 262 bus_space_write_1(bst, bsh, DLCR_RX_STAT, RX_BUS_RD_ERR); 263 } 264 265 /* 266 * Install interface into kernel networking data structures 267 */ 268 void 269 mb86950_config(struct mb86950_softc *sc, int *media, 270 int nmedia, int defmedia) 271 { 272 struct ifnet *ifp = &sc->sc_ec.ec_if; 273 bus_space_tag_t bst = sc->sc_bst; 274 bus_space_handle_t bsh = sc->sc_bsh; 275 276 /* Initialize ifnet structure. */ 277 strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ); 278 ifp->if_softc = sc; 279 ifp->if_start = mb86950_start; 280 ifp->if_ioctl = mb86950_ioctl; 281 ifp->if_watchdog = mb86950_watchdog; 282 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 283 284 IFQ_SET_READY(&ifp->if_snd); 285 286 /* Initialize media goo. */ 287 /* XXX The Tiara LANCard uses board jumpers to change media. 288 * This code may have to be changed for other cards. 289 */ 290 ifmedia_init(&sc->sc_media, 0, mb86950_mediachange, mb86950_mediastatus); 291 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 292 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 293 294 /* Attach the interface. */ 295 if_attach(ifp); 296 297 /* Feed the chip the station address. */ 298 bus_space_write_region_1(bst, bsh, DLCR_NODE_ID, sc->sc_enaddr, ETHER_ADDR_LEN); 299 300 ether_ifattach(ifp, sc->sc_enaddr); 301 302 #if NRND > 0 303 rnd_attach_source(&sc->rnd_source, device_xname(&sc->sc_dev), 304 RND_TYPE_NET, 0); 305 #endif 306 307 /* XXX No! This doesn't work - DLCR6 of the mb86950 is different 308 309 bus_space_write_1(bst, bsh, DLCR_CONFIG, 0x0f); 310 buf_config = bus_space_read_1(bst, bsh, DLCR_CONFIG); 311 312 sc->txb_count = ((buf_config & 0x0c) ? 2 : 1); 313 sc->txb_size = 1024 * (2 << ((buf_config & 0x0c) ? (((buf_config & 0x0c) >> 2) - 1) : 0)); 314 sc->txb_free = (sc->txb_size * sc->txb_count) / 1500; 315 316 sc->rxb_size = ((8 << (buf_config & 3)) * 1024) - (sc->txb_size * sc->txb_count); 317 sc->rxb_max = sc->rxb_size / 64; 318 319 printf("mb86950: Buffer Size %dKB with %d transmit buffer(s) %dKB each.\n", 320 (8 << (buf_config & 3)), sc->txb_count, (sc->txb_size / 1024)); 321 printf(" Transmit Buffer Space for %d maximum sized packet(s).\n",sc->txb_free); 322 printf(" System Bus Width %d bits, Buffer Memory %d bits.\n", 323 ((buf_config & 0x20) ? 8 : 16), 324 ((buf_config & 0x10) ? 8 : 16)); 325 326 */ 327 328 /* Set reasonable values for number of packet flow control if not 329 * set elsewhere */ 330 if (sc->txb_num_pkt == 0) sc->txb_num_pkt = 1; 331 if (sc->rxb_num_pkt == 0) sc->rxb_num_pkt = 100; 332 333 /* Print additional info when attached. */ 334 printf("%s: Ethernet address %s\n", device_xname(&sc->sc_dev), 335 ether_sprintf(sc->sc_enaddr)); 336 337 /* The attach is successful. */ 338 sc->sc_stat |= ESTAR_STAT_ATTACHED; 339 } 340 341 /* 342 * Media change callback. 343 */ 344 int 345 mb86950_mediachange(struct ifnet *ifp) 346 { 347 348 struct mb86950_softc *sc = ifp->if_softc; 349 350 if (sc->sc_mediachange) 351 return ((*sc->sc_mediachange)(sc)); 352 353 return (0); 354 } 355 356 /* 357 * Media status callback. 358 */ 359 void 360 mb86950_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 361 { 362 struct mb86950_softc *sc = ifp->if_softc; 363 364 if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0) { 365 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 366 ifmr->ifm_status = 0; 367 return; 368 } 369 370 if (sc->sc_mediastatus) 371 (*sc->sc_mediastatus)(sc, ifmr); 372 373 } 374 375 /* 376 * Reset interface. 377 */ 378 void 379 mb86950_reset(struct mb86950_softc *sc) 380 { 381 int s; 382 383 s = splnet(); 384 log(LOG_ERR, "%s: device reset\n", device_xname(&sc->sc_dev)); 385 mb86950_stop(sc); 386 mb86950_init(sc); 387 splx(s); 388 } 389 390 /* 391 * Device timeout/watchdog routine. Entered if the device neglects to 392 * generate an interrupt after a transmit has been started on it. 393 */ 394 void 395 mb86950_watchdog(struct ifnet *ifp) 396 { 397 struct mb86950_softc *sc = ifp->if_softc; 398 bus_space_tag_t bst = sc->sc_bst; 399 bus_space_handle_t bsh = sc->sc_bsh; 400 u_int8_t tstat; 401 402 /* verbose watchdog messages for debugging timeouts */ 403 if ((tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT)) != 0) { 404 if (tstat & TX_CR_LOST) { 405 if ((tstat & (TX_COL | TX_16COL)) == 0) { 406 log(LOG_ERR, "%s: carrier lost\n", 407 device_xname(&sc->sc_dev)); 408 } else { 409 log(LOG_ERR, "%s: excessive collisions\n", 410 device_xname(&sc->sc_dev)); 411 } 412 } 413 else if ((tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) != 0) { 414 log(LOG_ERR, "%s: tx fifo underflow/overflow\n", 415 device_xname(&sc->sc_dev)); 416 } else { 417 log(LOG_ERR, "%s: transmit error\n", 418 device_xname(&sc->sc_dev)); 419 } 420 } else { 421 log(LOG_ERR, "%s: device timeout\n", device_xname(&sc->sc_dev)); 422 } 423 424 /* Don't know how many packets are lost by this accident. 425 * ... So just errors = errors + 1 426 */ 427 ifp->if_oerrors++; 428 429 mb86950_reset(sc); 430 431 } 432 433 /* 434 ******************** IOCTL 435 * Process an ioctl request. 436 */ 437 int 438 mb86950_ioctl(struct ifnet *ifp, unsigned long cmd, void *data) 439 { 440 struct mb86950_softc *sc = ifp->if_softc; 441 struct ifaddr *ifa = (struct ifaddr *)data; 442 struct ifreq *ifr = (struct ifreq *)data; 443 444 int s, error = 0; 445 446 s = splnet(); 447 448 switch (cmd) { 449 case SIOCINITIFADDR: 450 /* XXX deprecated ? What should I use instead? */ 451 if ((error = mb86950_enable(sc)) != 0) 452 break; 453 454 ifp->if_flags |= IFF_UP; 455 456 mb86950_init(sc); 457 switch (ifa->ifa_addr->sa_family) { 458 459 #ifdef INET 460 case AF_INET: 461 arp_ifinit(ifp, ifa); 462 break; 463 #endif 464 465 466 default: 467 break; 468 } 469 break; 470 471 case SIOCSIFFLAGS: 472 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 473 break; 474 /* XXX re-use ether_ioctl() */ 475 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 476 case IFF_RUNNING: 477 /* 478 * If interface is marked down and it is running, then 479 * stop it. 480 */ 481 mb86950_stop(sc); 482 ifp->if_flags &= ~IFF_RUNNING; 483 mb86950_disable(sc); 484 break; 485 case IFF_UP: 486 /* 487 * If interface is marked up and it is stopped, then 488 * start it. 489 */ 490 if ((error = mb86950_enable(sc)) != 0) 491 break; 492 mb86950_init(sc); 493 break; 494 case IFF_UP|IFF_RUNNING: 495 /* 496 * Reset the interface to pick up changes in any other 497 * flags that affect hardware registers. 498 */ 499 #if 0 500 /* Setmode not supported */ 501 mb86950_setmode(sc); 502 #endif 503 break; 504 case 0: 505 break; 506 } 507 508 #if ESTAR_DEBUG >= 1 509 /* "ifconfig fe0 debug" to print register dump. */ 510 if (ifp->if_flags & IFF_DEBUG) { 511 log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n", 512 device_xname(&sc->sc_dev)); 513 mb86950_dump(LOG_DEBUG, sc); 514 } 515 #endif 516 break; 517 518 case SIOCGIFMEDIA: 519 case SIOCSIFMEDIA: 520 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 521 break; 522 523 default: 524 error = ether_ioctl(ifp, cmd, data); 525 break; 526 } 527 528 splx(s); 529 return (error); 530 } 531 532 /* 533 * Initialize device. 534 */ 535 void 536 mb86950_init(struct mb86950_softc *sc) 537 { 538 bus_space_tag_t bst = sc->sc_bst; 539 bus_space_handle_t bsh = sc->sc_bsh; 540 struct ifnet *ifp = &sc->sc_ec.ec_if; 541 542 /* Reset transmitter flags. */ 543 ifp->if_flags &= ~IFF_OACTIVE; 544 ifp->if_timer = 0; 545 sc->txb_sched = 0; 546 547 bus_space_write_1(bst, bsh, DLCR_TX_MODE, LBC); 548 bus_space_write_1(bst, bsh, DLCR_RX_MODE, NORMAL_MODE); 549 550 /* Enable interrupts. */ 551 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK); 552 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK); 553 554 /* Enable transmitter and receiver. */ 555 bus_space_write_1(bst, bsh, DLCR_CONFIG, ENABLE_DLC); 556 delay(200); 557 558 /* Set 'running' flag. */ 559 ifp->if_flags |= IFF_RUNNING; 560 561 /* ...and attempt to start output. */ 562 mb86950_start(ifp); 563 564 } 565 566 void 567 mb86950_start(struct ifnet *ifp) 568 { 569 struct mb86950_softc *sc = ifp->if_softc; 570 bus_space_tag_t bst = sc->sc_bst; 571 bus_space_handle_t bsh = sc->sc_bsh; 572 struct mbuf *m; 573 int len; 574 575 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 576 return; 577 578 IF_DEQUEUE(&ifp->if_snd, m); 579 if (m == 0) 580 return; 581 582 #if NBPFILTER > 0 583 /* Tap off here if there is a BPF listener. */ 584 if (ifp->if_bpf) 585 bpf_mtap(ifp->if_bpf, m); 586 #endif 587 588 /* Send the packet to the mb86950 */ 589 len = mb86950_put_fifo(sc,m); 590 m_freem(m); 591 592 /* XXX bus_space_barrier here ? */ 593 if (bus_space_read_1(bst, bsh, DLCR_TX_STAT) & (TX_UNDERFLO | TX_BUS_WR_ERR)) { 594 log(LOG_ERR, "%s: tx fifo underflow/overflow\n", device_xname(&sc->sc_dev)); 595 } 596 597 bus_space_write_2(bst, bsh, BMPR_TX_LENGTH, len | TRANSMIT_START); 598 599 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK); 600 /* XXX */ 601 sc->txb_sched++; 602 603 /* We have space for 'n' transmit packets of size 'mtu. */ 604 if (sc->txb_sched > sc->txb_num_pkt) { 605 ifp->if_flags |= IFF_OACTIVE; 606 ifp->if_timer = 2; 607 } 608 } 609 610 /* 611 * Send packet - copy packet from mbuf to the fifo 612 */ 613 u_short 614 mb86950_put_fifo(struct mb86950_softc *sc, struct mbuf *m) 615 { 616 bus_space_tag_t bst = sc->sc_bst; 617 bus_space_handle_t bsh = sc->sc_bsh; 618 u_short *data; 619 u_char savebyte[2]; 620 int len, len1, wantbyte; 621 u_short totlen; 622 623 memset(savebyte, 0, sizeof(savebyte)); /* XXX gcc */ 624 625 totlen = wantbyte = 0; 626 627 for (; m != NULL; m = m->m_next) { 628 data = mtod(m, u_short *); 629 len = m->m_len; 630 if (len > 0) { 631 totlen += len; 632 633 /* Finish the last word. */ 634 if (wantbyte) { 635 savebyte[1] = *((u_char *)data); 636 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte); 637 data = (u_short *)((u_char *)data + 1); 638 len--; 639 wantbyte = 0; 640 } 641 /* Output contiguous words. */ 642 if (len > 1) { 643 len1 = len/2; 644 bus_space_write_multi_stream_2(bst, bsh, BMPR_FIFO, data, len1); 645 data += len1; 646 len &= 1; 647 } 648 /* Save last byte, if necessary. */ 649 if (len == 1) { 650 savebyte[0] = *((u_char *)data); 651 wantbyte = 1; 652 } 653 } 654 } 655 656 if (wantbyte) { 657 savebyte[1] = 0; 658 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte); 659 } 660 661 if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) { 662 663 /* Fill the rest of the packet with zeros. */ 664 /* XXX Replace this mess with something else, eats CPU */ 665 /* The zero fill and last byte ought to be combined somehow */ 666 for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); len += 2) 667 bus_space_write_2(bst, bsh, BMPR_FIFO, 0); 668 /* XXX */ 669 670 totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN); 671 } 672 673 return (totlen); 674 } 675 676 /* 677 * Handle interrupts. 678 * Ethernet interface interrupt processor 679 */ 680 int 681 mb86950_intr(void *arg) 682 { 683 struct mb86950_softc *sc = arg; 684 bus_space_tag_t bst = sc->sc_bst; 685 bus_space_handle_t bsh = sc->sc_bsh; 686 struct ifnet *ifp = &sc->sc_ec.ec_if; 687 u_int8_t tstat, rstat; 688 689 /* Get interrupt status. */ 690 tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT); 691 rstat = bus_space_read_1(bst, bsh, DLCR_RX_STAT); 692 693 if (tstat == 0 && rstat == 0) return (0); 694 695 /* Disable etherstar interrupts so that we won't miss anything. */ 696 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0); 697 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0); 698 699 /* 700 * Handle transmitter interrupts. Handle these first because 701 * the receiver will reset the board under some conditions. 702 */ 703 if (tstat != 0) { 704 705 mb86950_tint(sc, tstat); 706 707 /* acknowledge transmit interrupt status. */ 708 bus_space_write_1(bst, bsh, DLCR_TX_STAT, tstat); 709 710 } 711 712 /* Handle receiver interrupts. */ 713 if (rstat != 0) { 714 715 mb86950_rint(sc, rstat); 716 717 /* acknowledge receive interrupt status. */ 718 bus_space_write_1(bst, bsh, DLCR_RX_STAT, rstat); 719 720 } 721 722 /* If tx still pending reset tx interrupt mask */ 723 if (sc->txb_sched > 0) 724 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK); 725 726 /* 727 * If it looks like the transmitter can take more data, 728 * attempt to start output on the interface. This is done 729 * after handling the receiver interrupt to give the 730 * receive operation priority. 731 */ 732 733 if ((ifp->if_flags & IFF_OACTIVE) == 0) 734 mb86950_start(ifp); 735 736 /* Set receive interrupts back */ 737 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK); 738 739 return(1); 740 } 741 742 /* Transmission interrupt handler */ 743 void 744 mb86950_tint(struct mb86950_softc *sc, u_int8_t tstat) 745 { 746 bus_space_tag_t bst = sc->sc_bst; 747 bus_space_handle_t bsh = sc->sc_bsh; 748 struct ifnet *ifp = &sc->sc_ec.ec_if; 749 int col; 750 751 if (tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) { 752 /* XXX What do we need to do here? reset ? */ 753 ifp->if_oerrors++; 754 } 755 756 /* excessive collision */ 757 if (tstat & TX_16COL) { 758 ifp->if_collisions += 16; 759 /* 16 collisions means that the packet has been thrown away. */ 760 if (sc->txb_sched > 0) 761 sc->txb_sched--; 762 } 763 764 /* transmission complete. */ 765 if (tstat & TX_DONE) { 766 /* successfully transmitted packets ++. */ 767 ifp->if_opackets++; 768 if (sc->txb_sched > 0) 769 sc->txb_sched--; 770 771 /* Collision count valid only when TX_DONE is set */ 772 if (tstat & TX_COL) { 773 col = (bus_space_read_1(bst, bsh, DLCR_TX_MODE) & COL_MASK) >> 4; 774 ifp->if_collisions = ifp->if_collisions + col; 775 } 776 } 777 778 if (sc->txb_sched == 0) { 779 /* Reset output active flag and stop timer. */ 780 ifp->if_flags &= ~IFF_OACTIVE; 781 ifp->if_timer = 0; 782 } 783 } 784 785 /* receiver interrupt. */ 786 void 787 mb86950_rint(struct mb86950_softc *sc, u_int8_t rstat) 788 { 789 bus_space_tag_t bst = sc->sc_bst; 790 bus_space_handle_t bsh = sc->sc_bsh; 791 struct ifnet *ifp = &sc->sc_ec.ec_if; 792 u_int status, len; 793 int i; 794 795 /* Update statistics if this interrupt is caused by an error. */ 796 if (rstat & RX_ERR_MASK) { 797 798 /* tried to read past end of fifo, should be harmless 799 * count everything else 800 */ 801 if ((rstat & RX_BUS_RD_ERR) == 0) { 802 ifp->if_ierrors++; 803 } 804 } 805 806 /* 807 * mb86950 has a flag indicating "receive buffer empty." 808 * We just loop checking the flag to pull out all received 809 * packets. 810 * 811 * We limit the number of iterrations to avoid infinite loop. 812 * It can be caused by a very slow CPU (some broken 813 * peripheral may insert incredible number of wait cycles) 814 * or, worse, by a broken mb86950 chip. 815 */ 816 for (i = 0; i < sc->rxb_num_pkt; i++) { 817 /* Stop the iterration if 86950 indicates no packets. */ 818 if (bus_space_read_1(bst, bsh, DLCR_RX_MODE) & RX_BUF_EMTY) 819 break; 820 821 /* receive packet status */ 822 status = bus_space_read_2(bst, bsh, BMPR_FIFO); 823 824 /* bad packet? */ 825 if ((status & GOOD_PKT) == 0) { 826 ifp->if_ierrors++; 827 mb86950_drain_fifo(sc); 828 continue; 829 } 830 831 /* Length valid ? */ 832 len = bus_space_read_2(bst, bsh, BMPR_FIFO); 833 834 if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || len < ETHER_HDR_LEN) { 835 ifp->if_ierrors++; 836 mb86950_drain_fifo(sc); 837 continue; 838 } 839 840 if (mb86950_get_fifo(sc, len) != 0) { 841 /* No mbufs? Drop packet. */ 842 ifp->if_ierrors++; 843 mb86950_drain_fifo(sc); 844 return; 845 } 846 847 /* Successfully received a packet. Update stat. */ 848 ifp->if_ipackets++; 849 } 850 } 851 852 /* 853 * Receive packet. 854 * Retrieve packet from receive buffer and send to the next level up via 855 * ether_input(). If there is a BPF listener, give a copy to BPF, too. 856 * Returns 0 if success, -1 if error (i.e., mbuf allocation failure). 857 */ 858 int 859 mb86950_get_fifo(struct mb86950_softc *sc, u_int len) 860 { 861 bus_space_tag_t bst = sc->sc_bst; 862 bus_space_handle_t bsh = sc->sc_bsh; 863 struct ifnet *ifp = &sc->sc_ec.ec_if; 864 struct mbuf *m; 865 866 /* Allocate a header mbuf. */ 867 MGETHDR(m, M_DONTWAIT, MT_DATA); 868 if (m == 0) 869 return (-1); 870 871 /* 872 * Round len to even value. 873 */ 874 if (len & 1) 875 len++; 876 877 m->m_pkthdr.rcvif = ifp; 878 m->m_pkthdr.len = len; 879 880 /* The following silliness is to make NFS happy. */ 881 #define EROUND ((sizeof(struct ether_header) + 3) & ~3) 882 #define EOFF (EROUND - sizeof(struct ether_header)) 883 884 /* 885 * Our strategy has one more problem. There is a policy on 886 * mbuf cluster allocation. It says that we must have at 887 * least MINCLSIZE (208 bytes) to allocate a cluster. For a 888 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2), 889 * our code violates the rule... 890 * On the other hand, the current code is short, simple, 891 * and fast, however. It does no harmful thing, just wastes 892 * some memory. Any comments? FIXME. 893 */ 894 895 /* Attach a cluster if this packet doesn't fit in a normal mbuf. */ 896 if (len > MHLEN - EOFF) { 897 MCLGET(m, M_DONTWAIT); 898 if ((m->m_flags & M_EXT) == 0) { 899 m_freem(m); 900 return (-1); 901 } 902 } 903 904 /* 905 * The following assumes there is room for the ether header in the 906 * header mbuf. 907 */ 908 m->m_data += EOFF; 909 910 /* Set the length of this packet. */ 911 m->m_len = len; 912 913 /* Get a packet. */ 914 bus_space_read_multi_stream_2(bst, bsh, BMPR_FIFO, mtod(m, u_int16_t *), (len + 1) >> 1); 915 916 #if NBPFILTER > 0 917 /* 918 * Check if there's a BPF listener on this interface. If so, hand off 919 * the raw packet to bpf. 920 */ 921 if (ifp->if_bpf) 922 bpf_mtap(ifp->if_bpf, m); 923 #endif 924 925 (*ifp->if_input)(ifp, m); 926 return (0); 927 } 928 929 /* 930 * Enable power on the interface. 931 */ 932 int 933 mb86950_enable(struct mb86950_softc *sc) 934 { 935 936 if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0 && sc->sc_enable != NULL) { 937 if ((*sc->sc_enable)(sc) != 0) { 938 aprint_error_dev(&sc->sc_dev, "device enable failed\n"); 939 return (EIO); 940 } 941 } 942 943 sc->sc_stat |= ESTAR_STAT_ENABLED; 944 return (0); 945 } 946 947 /* 948 * Disable power on the interface. 949 */ 950 void 951 mb86950_disable(struct mb86950_softc *sc) 952 { 953 954 if ((sc->sc_stat & ESTAR_STAT_ENABLED) != 0 && sc->sc_disable != NULL) { 955 (*sc->sc_disable)(sc); 956 sc->sc_stat &= ~ESTAR_STAT_ENABLED; 957 } 958 } 959 960 /* 961 * mbe_activate: 962 * 963 * Handle device activation/deactivation requests. 964 */ 965 int 966 mb86950_activate(struct device *self, enum devact act) 967 { 968 struct mb86950_softc *sc = (struct mb86950_softc *)self; 969 int rv, s; 970 971 rv = 0; 972 s = splnet(); 973 switch (act) { 974 case DVACT_ACTIVATE: 975 rv = EOPNOTSUPP; 976 break; 977 978 case DVACT_DEACTIVATE: 979 if_deactivate(&sc->sc_ec.ec_if); 980 break; 981 } 982 splx(s); 983 return (rv); 984 } 985 986 /* 987 * mb86950_detach: 988 * 989 * Detach a mb86950 interface. 990 */ 991 int 992 mb86950_detach(struct mb86950_softc *sc) 993 { 994 struct ifnet *ifp = &sc->sc_ec.ec_if; 995 996 /* Succeed now if there's no work to do. */ 997 if ((sc->sc_stat & ESTAR_STAT_ATTACHED) == 0) 998 return (0); 999 1000 /* Delete all media. */ 1001 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 1002 1003 #if NRND > 0 1004 /* Unhook the entropy source. */ 1005 rnd_detach_source(&sc->rnd_source); 1006 #endif 1007 ether_ifdetach(ifp); 1008 if_detach(ifp); 1009 1010 return (0); 1011 } 1012 1013 #if ESTAR_DEBUG >= 1 1014 void 1015 mb86950_dump(int level, struct mb86950_softc *sc) 1016 { 1017 bus_space_tag_t bst = sc->sc_bst; 1018 bus_space_handle_t bsh = sc->sc_bsh; 1019 1020 log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x\n", 1021 bus_space_read_1(bst, bsh, DLCR_TX_STAT), 1022 bus_space_read_1(bst, bsh, DLCR_TX_INT_EN), 1023 bus_space_read_1(bst, bsh, DLCR_RX_STAT), 1024 bus_space_read_1(bst, bsh, DLCR_RX_INT_EN), 1025 bus_space_read_1(bst, bsh, DLCR_TX_MODE), 1026 bus_space_read_1(bst, bsh, DLCR_RX_MODE), 1027 bus_space_read_1(bst, bsh, DLCR_CONFIG)); 1028 1029 /* XXX BMPR2, 4 write only ? 1030 log(level, "\tBMPR = xxxx %04x %04x\n", 1031 bus_space_read_2(bst, bsh, BMPR_TX_LENGTH), 1032 bus_space_read_2(bst, bsh, BMPR_DMA)); 1033 */ 1034 } 1035 #endif 1036