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