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