Home | History | Annotate | Line # | Download | only in ic
mb86950.c revision 1.29
      1 /*	$NetBSD: mb86950.c,v 1.29 2019/02/05 06:17:02 msaitoh 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.29 2019/02/05 06:17:02 msaitoh 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 
    240 void
    241 mb86950_drain_fifo(struct mb86950_softc *sc)
    242 {
    243 	bus_space_tag_t bst = sc->sc_bst;
    244 	bus_space_handle_t bsh = sc->sc_bsh;
    245 
    246 	/* Read data until bus read error (i.e. buffer empty). */
    247 	/* XXX There ought to be a better way, eats CPU and bothers the chip */
    248 	while (!(bus_space_read_1(bst, bsh, DLCR_RX_STAT) & RX_BUS_RD_ERR))
    249 		bus_space_read_2(bst, bsh, BMPR_FIFO);
    250 	/* XXX */
    251 
    252 	/* Clear Bus Rd Error */
    253 	bus_space_write_1(bst, bsh, DLCR_RX_STAT, RX_BUS_RD_ERR);
    254 }
    255 
    256 /*
    257  * Install interface into kernel networking data structures
    258  */
    259 void
    260 mb86950_config(struct mb86950_softc *sc, int *media,
    261     int nmedia, int defmedia)
    262 {
    263 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    264 	bus_space_tag_t bst = sc->sc_bst;
    265 	bus_space_handle_t bsh = sc->sc_bsh;
    266 
    267 	/* Initialize ifnet structure. */
    268 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
    269 	ifp->if_softc = sc;
    270 	ifp->if_start = mb86950_start;
    271 	ifp->if_ioctl = mb86950_ioctl;
    272 	ifp->if_watchdog = mb86950_watchdog;
    273 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
    274 
    275 	IFQ_SET_READY(&ifp->if_snd);
    276 
    277 	/* Initialize media goo. */
    278 	/* XXX The Tiara LANCard uses board jumpers to change media.
    279 	 *       This code may have to be changed for other cards.
    280 	 */
    281 	ifmedia_init(&sc->sc_media, 0, mb86950_mediachange, 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, ETHER_ADDR_LEN);
    291 
    292 	ether_ifattach(ifp, sc->sc_enaddr);
    293 
    294 	rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
    295 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
    296 
    297 /* XXX No! This doesn't work - DLCR6 of the mb86950 is different
    298 
    299 	bus_space_write_1(bst, bsh, DLCR_CONFIG, 0x0f);
    300 	buf_config = bus_space_read_1(bst, bsh, DLCR_CONFIG);
    301 
    302 	sc->txb_count = ((buf_config & 0x0c) ? 2 : 1);
    303 	sc->txb_size = 1024 * (2 << ((buf_config & 0x0c) ? (((buf_config & 0x0c) >> 2) - 1) : 0));
    304 	sc->txb_free = (sc->txb_size * sc->txb_count) / 1500;
    305 
    306   	sc->rxb_size = ((8 << (buf_config & 3)) * 1024) - (sc->txb_size * sc->txb_count);
    307 	sc->rxb_max = sc->rxb_size / 64;
    308 
    309 	printf("mb86950: Buffer Size %dKB with %d transmit buffer(s) %dKB each.\n",
    310 		(8 << (buf_config & 3)), sc->txb_count,	(sc->txb_size / 1024));
    311 	printf("         Transmit Buffer Space for %d maximum sized packet(s).\n",sc->txb_free);
    312 	printf("         System Bus Width %d bits, Buffer Memory %d bits.\n",
    313 		((buf_config & 0x20) ? 8 : 16),
    314 		((buf_config & 0x10) ? 8 : 16));
    315 
    316 */
    317 
    318 	/* Set reasonable values for number of packet flow control if not
    319 	 * set elsewhere */
    320 	if (sc->txb_num_pkt == 0) sc->txb_num_pkt = 1;
    321 	if (sc->rxb_num_pkt == 0) sc->rxb_num_pkt = 100;
    322 
    323 	/* Print additional info when attached. */
    324 	printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev),
    325 	    ether_sprintf(sc->sc_enaddr));
    326 
    327 	/* The attach is successful. */
    328 	sc->sc_stat |= ESTAR_STAT_ATTACHED;
    329 }
    330 
    331 /*
    332  * Media change callback.
    333  */
    334 int
    335 mb86950_mediachange(struct ifnet *ifp)
    336 {
    337 
    338 	struct mb86950_softc *sc = ifp->if_softc;
    339 
    340 	if (sc->sc_mediachange)
    341 		return ((*sc->sc_mediachange)(sc));
    342 
    343 	return (0);
    344 }
    345 
    346 /*
    347  * Media status callback.
    348  */
    349 void
    350 mb86950_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
    351 {
    352 	struct mb86950_softc *sc = ifp->if_softc;
    353 
    354 	if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0) {
    355 		ifmr->ifm_active = IFM_ETHER | IFM_NONE;
    356 		ifmr->ifm_status = 0;
    357 		return;
    358 	}
    359 
    360 	if (sc->sc_mediastatus)
    361 		(*sc->sc_mediastatus)(sc, ifmr);
    362 
    363 }
    364 
    365 /*
    366  * Reset interface.
    367  */
    368 void
    369 mb86950_reset(struct mb86950_softc *sc)
    370 {
    371 	int s;
    372 
    373 	s = splnet();
    374 	log(LOG_ERR, "%s: device reset\n", device_xname(sc->sc_dev));
    375 	mb86950_stop(sc);
    376 	mb86950_init(sc);
    377 	splx(s);
    378 }
    379 
    380 /*
    381  * Device timeout/watchdog routine. Entered if the device neglects to
    382  * generate an interrupt after a transmit has been started on it.
    383  */
    384 void
    385 mb86950_watchdog(struct ifnet *ifp)
    386 {
    387 	struct mb86950_softc *sc = ifp->if_softc;
    388 	bus_space_tag_t bst = sc->sc_bst;
    389 	bus_space_handle_t bsh = sc->sc_bsh;
    390 	u_int8_t tstat;
    391 
    392 	/* verbose watchdog messages for debugging timeouts */
    393     if ((tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT)) != 0) {
    394 		if (tstat & TX_CR_LOST) {
    395 			if ((tstat & (TX_COL | TX_16COL)) == 0) {
    396 				 log(LOG_ERR, "%s: carrier lost\n",
    397 				    device_xname(sc->sc_dev));
    398 			} else {
    399 				log(LOG_ERR, "%s: excessive collisions\n",
    400 				    device_xname(sc->sc_dev));
    401 			}
    402 		}
    403 		else if ((tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) != 0) {
    404 			log(LOG_ERR, "%s: tx fifo underflow/overflow\n",
    405 			    device_xname(sc->sc_dev));
    406 		} else {
    407 			log(LOG_ERR, "%s: transmit error\n",
    408 			    device_xname(sc->sc_dev));
    409 		}
    410 	} else {
    411 		log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
    412 	}
    413 
    414 	/* Don't know how many packets are lost by this accident.
    415 	 *  ... So just errors = errors + 1
    416 	 */
    417 	ifp->if_oerrors++;
    418 
    419 	mb86950_reset(sc);
    420 
    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 	struct ifreq *ifr = (struct ifreq *)data;
    433 
    434 	int s, error = 0;
    435 
    436 	s = splnet();
    437 
    438 	switch (cmd) {
    439 	case SIOCINITIFADDR:
    440 		/* XXX deprecated ? What should I use instead? */
    441 		if ((error = mb86950_enable(sc)) != 0)
    442 			break;
    443 
    444 		ifp->if_flags |= IFF_UP;
    445 
    446 		mb86950_init(sc);
    447 		switch (ifa->ifa_addr->sa_family) {
    448 
    449 #ifdef INET
    450 		case AF_INET:
    451 			arp_ifinit(ifp, ifa);
    452 			break;
    453 #endif
    454 
    455 
    456 		default:
    457 			break;
    458 		}
    459 		break;
    460 
    461 	case SIOCSIFFLAGS:
    462 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
    463 			break;
    464 		/* XXX re-use ether_ioctl() */
    465 		switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
    466 		case IFF_RUNNING:
    467 			/*
    468 			 * If interface is marked down and it is running, then
    469 			 * stop it.
    470 			 */
    471 			mb86950_stop(sc);
    472 			ifp->if_flags &= ~IFF_RUNNING;
    473 			mb86950_disable(sc);
    474 			break;
    475 		case IFF_UP:
    476 			/*
    477 			 * If interface is marked up and it is stopped, then
    478 			 * start it.
    479 			 */
    480 			if ((error = mb86950_enable(sc)) != 0)
    481 				break;
    482 			mb86950_init(sc);
    483 			break;
    484 		case IFF_UP|IFF_RUNNING:
    485 			/*
    486 			 * Reset the interface to pick up changes in any other
    487 			 * flags that affect hardware registers.
    488 			 */
    489 #if 0
    490 			/* Setmode not supported */
    491 			mb86950_setmode(sc);
    492 #endif
    493 			break;
    494 		case 0:
    495 			break;
    496 		}
    497 
    498 #if ESTAR_DEBUG >= 1
    499 		/* "ifconfig fe0 debug" to print register dump. */
    500 		if (ifp->if_flags & IFF_DEBUG) {
    501 			log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n",
    502 			    device_xname(sc->sc_dev));
    503 			mb86950_dump(LOG_DEBUG, sc);
    504 		}
    505 #endif
    506 		break;
    507 
    508 	case SIOCGIFMEDIA:
    509 	case SIOCSIFMEDIA:
    510 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
    511 		break;
    512 
    513 	default:
    514 		error = ether_ioctl(ifp, cmd, data);
    515 		break;
    516 	}
    517 
    518 	splx(s);
    519 	return (error);
    520 }
    521 
    522 /*
    523  * Initialize device.
    524  */
    525 void
    526 mb86950_init(struct mb86950_softc *sc)
    527 {
    528 	bus_space_tag_t bst = sc->sc_bst;
    529 	bus_space_handle_t bsh = sc->sc_bsh;
    530 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    531 
    532 	/* Reset transmitter flags. */
    533 	ifp->if_flags &= ~IFF_OACTIVE;
    534 	ifp->if_timer = 0;
    535 	sc->txb_sched = 0;
    536 
    537 	bus_space_write_1(bst, bsh, DLCR_TX_MODE, LBC);
    538 	bus_space_write_1(bst, bsh, DLCR_RX_MODE, NORMAL_MODE);
    539 
    540 	/* Enable interrupts. */
    541 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
    542 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
    543 
    544 	/* Enable transmitter and receiver. */
    545 	bus_space_write_1(bst, bsh, DLCR_CONFIG, ENABLE_DLC);
    546 	delay(200);
    547 
    548 	/* Set 'running' flag. */
    549 	ifp->if_flags |= IFF_RUNNING;
    550 
    551 	/* ...and attempt to start output. */
    552 	mb86950_start(ifp);
    553 
    554 }
    555 
    556 void
    557 mb86950_start(struct ifnet *ifp)
    558 {
    559 	struct mb86950_softc *sc = ifp->if_softc;
    560     bus_space_tag_t bst = sc->sc_bst;
    561     bus_space_handle_t bsh = sc->sc_bsh;
    562 	struct mbuf *m;
    563 	int len;
    564 
    565 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    566 		return;
    567 
    568 	IF_DEQUEUE(&ifp->if_snd, m);
    569 	if (m == 0)
    570 		return;
    571 
    572 	/* Tap off here if there is a BPF listener. */
    573 	bpf_mtap(ifp, m, BPF_D_OUT);
    574 
    575 	/* Send the packet to the mb86950 */
    576 	len = mb86950_put_fifo(sc,m);
    577 	m_freem(m);
    578 
    579 	/* XXX bus_space_barrier here ? */
    580 	if (bus_space_read_1(bst, bsh, DLCR_TX_STAT) & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
    581 		log(LOG_ERR, "%s: tx fifo underflow/overflow\n", device_xname(sc->sc_dev));
    582 	}
    583 
    584 	bus_space_write_2(bst, bsh, BMPR_TX_LENGTH, len | TRANSMIT_START);
    585 
    586 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
    587 	/* XXX                          */
    588 	sc->txb_sched++;
    589 
    590 	/* We have space for 'n' transmit packets of size 'mtu. */
    591 	if (sc->txb_sched > sc->txb_num_pkt) {
    592 		ifp->if_flags |= IFF_OACTIVE;
    593 		ifp->if_timer = 2;
    594 	}
    595 }
    596 
    597 /*
    598  * Send packet - copy packet from mbuf to the fifo
    599  */
    600 u_short
    601 mb86950_put_fifo(struct mb86950_softc *sc, struct mbuf *m)
    602 {
    603 	bus_space_tag_t bst = sc->sc_bst;
    604 	bus_space_handle_t bsh = sc->sc_bsh;
    605 	u_short *data;
    606 	u_char savebyte[2];
    607 	int len, len1, wantbyte;
    608 	u_short totlen;
    609 
    610 	memset(savebyte, 0, sizeof(savebyte));	/* XXX gcc */
    611 
    612 	totlen = wantbyte = 0;
    613 
    614 	for (; m != NULL; m = m->m_next) {
    615 		data = mtod(m, u_short *);
    616 		len = m->m_len;
    617 		if (len > 0) {
    618 			totlen += len;
    619 
    620 			/* Finish the last word. */
    621 			if (wantbyte) {
    622 				savebyte[1] = *((u_char *)data);
    623 				bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
    624 				data = (u_short *)((u_char *)data + 1);
    625 				len--;
    626 				wantbyte = 0;
    627 			}
    628 			/* Output contiguous words. */
    629 			if (len > 1) {
    630 				len1 = len/2;
    631 				bus_space_write_multi_stream_2(bst, bsh, BMPR_FIFO, data, len1);
    632 				data += len1;
    633 				len &= 1;
    634 			}
    635 			/* Save last byte, if necessary. */
    636 			if (len == 1) {
    637 				savebyte[0] = *((u_char *)data);
    638 				wantbyte = 1;
    639 			}
    640 		}
    641 	}
    642 
    643 	if (wantbyte) {
    644 		savebyte[1] = 0;
    645 		bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
    646 	}
    647 
    648 	if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
    649 
    650 		/* Fill the rest of the packet with zeros. */
    651 		/* XXX Replace this mess with something else, eats CPU */
    652 		/* The zero fill and last byte ought to be combined somehow */
    653 		for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); len += 2)
    654 	  		bus_space_write_2(bst, bsh, BMPR_FIFO, 0);
    655 		/* XXX                                       */
    656 
    657 		totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN);
    658 	}
    659 
    660 	return (totlen);
    661 }
    662 
    663 /*
    664  * Handle interrupts.
    665  * Ethernet interface interrupt processor
    666  */
    667 int
    668 mb86950_intr(void *arg)
    669 {
    670 	struct mb86950_softc *sc = arg;
    671 	bus_space_tag_t bst = sc->sc_bst;
    672 	bus_space_handle_t bsh = sc->sc_bsh;
    673 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    674 	u_int8_t tstat, rstat;
    675 
    676 	/* Get interrupt status. */
    677 	tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT);
    678 	rstat = bus_space_read_1(bst, bsh, DLCR_RX_STAT);
    679 
    680 	if (tstat == 0 && rstat == 0) return (0);
    681 
    682 	/* Disable etherstar interrupts so that we won't miss anything. */
    683 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0);
    684 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0);
    685 
    686 	/*
    687 	 * Handle transmitter interrupts. Handle these first because
    688 	 * the receiver will reset the board under some conditions.
    689 	 */
    690 	if (tstat != 0) {
    691 
    692 		mb86950_tint(sc, tstat);
    693 
    694 		/* acknowledge transmit interrupt status. */
    695 		bus_space_write_1(bst, bsh, DLCR_TX_STAT, tstat);
    696 
    697 	}
    698 
    699 	/* Handle receiver interrupts. */
    700 	if (rstat != 0) {
    701 
    702 		mb86950_rint(sc, rstat);
    703 
    704 		/* acknowledge receive interrupt status. */
    705 		bus_space_write_1(bst, bsh, DLCR_RX_STAT, rstat);
    706 
    707 	}
    708 
    709 	/* If tx still pending reset tx interrupt mask */
    710 	if (sc->txb_sched > 0)
    711 		bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
    712 
    713 	/*
    714 	 * If it looks like the transmitter can take more data,
    715 	 * attempt to start output on the interface. This is done
    716 	 * after handling the receiver interrupt to give the
    717 	 * receive operation priority.
    718 	 */
    719 
    720 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
    721 		if_schedule_deferred_start(ifp);
    722 
    723 	/* Set receive interrupts back */
    724 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
    725 
    726 	return(1);
    727 }
    728 
    729 /* Transmission interrupt handler */
    730 void
    731 mb86950_tint(struct mb86950_softc *sc, u_int8_t tstat)
    732 {
    733 	bus_space_tag_t bst = sc->sc_bst;
    734 	bus_space_handle_t bsh = sc->sc_bsh;
    735 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    736 	int col;
    737 
    738 	if (tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
    739 		/* XXX What do we need to do here? reset ? */
    740 		ifp->if_oerrors++;
    741 	}
    742 
    743 	/* excessive collision */
    744 	if (tstat & TX_16COL) {
    745 		ifp->if_collisions += 16;
    746 		/* 16 collisions means that the packet has been thrown away. */
    747 		if (sc->txb_sched > 0)
    748 			sc->txb_sched--;
    749 	}
    750 
    751 	/* transmission complete. */
    752 	if (tstat & TX_DONE) {
    753 		/* successfully transmitted packets ++. */
    754 		ifp->if_opackets++;
    755 		if (sc->txb_sched > 0)
    756 			sc->txb_sched--;
    757 
    758 		/* Collision count valid only when TX_DONE is set */
    759 		if (tstat & TX_COL) {
    760 			col = (bus_space_read_1(bst, bsh, DLCR_TX_MODE) & COL_MASK) >> 4;
    761 			ifp->if_collisions = ifp->if_collisions + col;
    762 		}
    763 	}
    764 
    765 	if (sc->txb_sched == 0) {
    766 		 /* Reset output active flag and stop timer. */
    767 		 ifp->if_flags &= ~IFF_OACTIVE;
    768 		 ifp->if_timer = 0;
    769 	}
    770 }
    771 
    772 /* receiver interrupt. */
    773 void
    774 mb86950_rint(struct mb86950_softc *sc, u_int8_t rstat)
    775 {
    776 	bus_space_tag_t bst = sc->sc_bst;
    777 	bus_space_handle_t bsh = sc->sc_bsh;
    778 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    779 	u_int status, len;
    780 	int i;
    781 
    782 	 /* Update statistics if this interrupt is caused by an error. */
    783 	 if (rstat & RX_ERR_MASK) {
    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 			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 iterrations 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 iterration 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 			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) || len < ETHER_HDR_LEN) {
    822 			ifp->if_ierrors++;
    823 			mb86950_drain_fifo(sc);
    824 			continue;
    825 		}
    826 
    827 		if (mb86950_get_fifo(sc, len) != 0) {
    828 			/* No mbufs? Drop packet. */
    829 			ifp->if_ierrors++;
    830 			mb86950_drain_fifo(sc);
    831 			return;
    832 		}
    833 	}
    834 }
    835 
    836 /*
    837  * Receive packet.
    838  * Retrieve packet from receive buffer and send to the next level up via
    839  * ether_input().
    840  * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
    841  */
    842 int
    843 mb86950_get_fifo(struct mb86950_softc *sc, u_int len)
    844 {
    845 	bus_space_tag_t bst = sc->sc_bst;
    846 	bus_space_handle_t bsh = sc->sc_bsh;
    847 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    848 	struct mbuf *m;
    849 
    850 	/* Allocate a header mbuf. */
    851 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    852 	if (m == 0)
    853 		return (-1);
    854 
    855 	/*
    856 	 * Round len to even value.
    857 	 */
    858 	if (len & 1)
    859 		len++;
    860 
    861 	m_set_rcvif(m, ifp);
    862 	m->m_pkthdr.len = len;
    863 
    864 	/* The following silliness is to make NFS happy. */
    865 #define	EROUND	((sizeof(struct ether_header) + 3) & ~3)
    866 #define	EOFF	(EROUND - sizeof(struct ether_header))
    867 
    868 	/*
    869 	 * Our strategy has one more problem.  There is a policy on
    870 	 * mbuf cluster allocation.  It says that we must have at
    871 	 * least MINCLSIZE (208 bytes) to allocate a cluster.  For a
    872 	 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
    873 	 * our code violates the rule...
    874 	 * On the other hand, the current code is short, simple,
    875 	 * and fast, however.  It does no harmful thing, just wastes
    876 	 * some memory.  Any comments?  FIXME.
    877 	 */
    878 
    879 	/* Attach a cluster if this packet doesn't fit in a normal mbuf. */
    880 	if (len > MHLEN - EOFF) {
    881 		MCLGET(m, M_DONTWAIT);
    882 		if ((m->m_flags & M_EXT) == 0) {
    883 			m_freem(m);
    884 			return (-1);
    885 		}
    886 	}
    887 
    888 	/*
    889 	 * The following assumes there is room for the ether header in the
    890 	 * header mbuf.
    891 	 */
    892 	m->m_data += EOFF;
    893 
    894 	/* Set the length of this packet. */
    895 	m->m_len = len;
    896 
    897 	/* Get a packet. */
    898 	bus_space_read_multi_stream_2(bst, bsh, BMPR_FIFO, 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 	/* Delete all media. */
    969 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
    970 
    971 	/* Unhook the entropy source. */
    972 	rnd_detach_source(&sc->rnd_source);
    973 
    974 	ether_ifdetach(ifp);
    975 	if_detach(ifp);
    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