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