xref: /netbsd-src/sys/dev/ic/mb86950.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /*	$NetBSD: mb86950.c,v 1.14 2009/03/14 15:36:17 dsl Exp $	*/
2 
3 /*
4  * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
5  *
6  * This software may be used, modified, copied, distributed, and sold, in
7  * both source and binary form provided that the above copyright, these
8  * terms and the following disclaimer are retained.  The name of the author
9  * and/or the contributor may not be used to endorse or promote products
10  * derived from this software without specific prior written permission.
11  *
12  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
13  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
16  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
19  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22  * SUCH DAMAGE.
23  */
24 
25 /*
26  * Portions copyright (C) 1993, David Greenman.  This software may be used,
27  * modified, copied, distributed, and sold, in both source and binary form
28  * provided that the above copyright and these terms are retained.  Under no
29  * circumstances is the author responsible for the proper functioning of this
30  * software, nor does the author assume any responsibility for damages
31  * incurred with its use.
32  */
33 
34  /*
35   * Portions copyright (c) 1995 Mika Kortelainen
36   * All rights reserved.
37   *
38   * Redistribution and use in source and binary forms, with or without
39   * modification, are permitted provided that the following conditions
40   * are met:
41   * 1. Redistributions of source code must retain the above copyright
42   *    notice, this list of conditions and the following disclaimer.
43   * 2. Redistributions in binary form must reproduce the above copyright
44   *    notice, this list of conditions and the following disclaimer in the
45   *    documentation and/or other materials provided with the distribution.
46   * 3. All advertising materials mentioning features or use of this software
47   *    must display the following acknowledgement:
48   *      This product includes software developed by  Mika Kortelainen
49   * 4. The name of the author may not be used to endorse or promote products
50   *    derived from this software without specific prior written permission
51   *
52   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62   */
63 
64  /*
65   * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards.
66   * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp>
67   */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: mb86950.c,v 1.14 2009/03/14 15:36:17 dsl Exp $");
71 
72 /*
73  * Device driver for Fujitsu mb86950 based Ethernet cards.
74  * Adapted by Dave J. Barnes from various Internet sources including
75  * mb86960.c (NetBSD), if_qn.c (NetBSD/Amiga), DOS Packet Driver (Brian Fisher,
76  * Queens University), EtherBoot Driver (Ken Yap).
77  */
78 
79 /* XXX There are still rough edges......
80  *
81  * (1) There is no watchdog timer for the transmitter. It's doubtful that
82  *     transmit from the chip could be restarted without a hardware reset
83  *     though. (Fixed - not fully tested)
84  *
85  * (2) The media interface callback goo is broke.  No big deal since to change
86  *     from aui to bnc on the old Tiara LANCard requires moving 8 board jumpers.
87  *     Other cards (SMC ?) using the EtherStar chip may support media change
88  *     via software. (Fixed - tested)
89  *
90  * (3) The maximum outstanding transmit packets is set to 4.  What
91  *     is a good limit of outstanding transmit packets for the EtherStar?
92  *     Is there a way to tell how many bytes are remaining to be
93  *     transmitted? [no]
94 ---
95 	When the EtherStar was designed, CPU power was a fraction
96 	of what it is now.  The single EtherStar transmit buffer
97 	was fine.  It was unlikely that the CPU could outrun the
98 	EtherStar. However, things in 2004 are quite different.
99 	sc->txb_size is used to keep the CPU from overrunning the
100 	EtherStar.  At most allow one packet transmitting and one
101 	going into the fifo.
102 
103 ---
104     No, that isn't right either :(
105 
106  * (4) Multicast isn't supported.  Feel free to add multicast code
107  *     if you know how to make the EtherStar do multicast.  Otherwise
108  *     you'd have to use promiscuous mode and do multicast in software. OUCH!
109  *
110  * (5) There are no bus_space_barrier calls used. Are they needed? Maybe not.
111  *
112  * (6) Access to the fifo assumes word (16 bit) mode.  Cards configured for
113  *     byte wide fifo access will require driver code changes.
114  *
115  * Only the minimum code necessary to make the Tiara LANCard work
116  * has been tested. Other cards may require more work, especially
117  * byte mode fifo and if DMA is used.
118  *
119  * djb / 2004
120  */
121 
122 #include "opt_inet.h"
123 #include "bpfilter.h"
124 #include "rnd.h"
125 
126 #include <sys/param.h>
127 #include <sys/systm.h>
128 #include <sys/errno.h>
129 #include <sys/ioctl.h>
130 #include <sys/mbuf.h>
131 #include <sys/socket.h>
132 #include <sys/syslog.h>
133 #include <sys/device.h>
134 #if NRND > 0
135 #include <sys/rnd.h>
136 #endif
137 
138 #include <net/if.h>
139 #include <net/if_dl.h>
140 #include <net/if_types.h>
141 #include <net/if_media.h>
142 #include <net/if_ether.h>
143 
144 #ifdef INET
145 #include <netinet/in.h>
146 #include <netinet/in_systm.h>
147 #include <netinet/in_var.h>
148 #include <netinet/ip.h>
149 #include <netinet/if_inarp.h>
150 #endif
151 
152 
153 #if NBPFILTER > 0
154 #include <net/bpf.h>
155 #include <net/bpfdesc.h>
156 #endif
157 
158 #include <sys/bus.h>
159 
160 #include <dev/ic/mb86950reg.h>
161 #include <dev/ic/mb86950var.h>
162 
163 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
164 #define bus_space_write_stream_2	bus_space_write_2
165 #define bus_space_write_multi_stream_2	bus_space_write_multi_2
166 #define bus_space_read_multi_stream_2	bus_space_read_multi_2
167 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
168 
169 /* Standard driver entry points.  These can be static. */
170 int		mb86950_ioctl(struct ifnet *, u_long, void *);
171 void	mb86950_init(struct mb86950_softc *);
172 void	mb86950_start(struct ifnet *);
173 void	mb86950_watchdog(struct ifnet *);
174 void	mb86950_reset(struct mb86950_softc *);
175 
176 /* Local functions. */
177 void	mb86950_stop(struct mb86950_softc *);
178 void	mb86950_tint(struct mb86950_softc *, u_int8_t);
179 void	mb86950_rint(struct mb86950_softc *, u_int8_t);
180 int		mb86950_get_fifo(struct mb86950_softc *, u_int);
181 ushort	mb86950_put_fifo(struct mb86950_softc *, struct mbuf *);
182 void	mb86950_drain_fifo(struct mb86950_softc *);
183 
184 int		mb86950_mediachange(struct ifnet *);
185 void	mb86950_mediastatus(struct ifnet *, struct ifmediareq *);
186 
187 
188 #if ESTAR_DEBUG >= 1
189 void	mb86950_dump(int, struct mb86950_softc *);
190 #endif
191 
192 /********************************************************************/
193 
194 void
195 mb86950_attach(struct mb86950_softc *sc, u_int8_t *myea)
196 {
197 
198 #ifdef DIAGNOSTIC
199 	if (myea == NULL) {
200 		printf("%s: ethernet address shouldn't be NULL\n",
201 		    device_xname(&sc->sc_dev));
202 		panic("NULL ethernet address");
203 	}
204 #endif
205 
206 	/* Initialize 86950. */
207 	mb86950_stop(sc);
208 
209 	memcpy(sc->sc_enaddr, myea, sizeof(sc->sc_enaddr));
210 
211 	sc->sc_stat |= ESTAR_STAT_ENABLED;
212 }
213 
214 /*
215  * Stop everything on the interface.
216  *
217  * All buffered packets, both transmitting and receiving,
218  * if any, will be lost by stopping the interface.
219  */
220 void
221 mb86950_stop(struct mb86950_softc *sc)
222 {
223 	bus_space_tag_t bst = sc->sc_bst;
224 	bus_space_handle_t bsh = sc->sc_bsh;
225 
226 	/* Stop interface hardware. */
227 	bus_space_write_1(bst, bsh, DLCR_CONFIG, DISABLE_DLC);
228 	delay(200);
229 
230 	/* Disable interrupts. */
231 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0);
232 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0);
233 
234 	/* Ack / Clear all interrupt status. */
235 	bus_space_write_1(bst, bsh, DLCR_TX_STAT, 0xff);
236 	bus_space_write_1(bst, bsh, DLCR_RX_STAT, 0xff);
237 
238 	/* Clear DMA Bit */
239     bus_space_write_2(bst, bsh, BMPR_DMA, 0);
240 
241     /* accept no packets */
242 	bus_space_write_1(bst, bsh, DLCR_TX_MODE, 0);
243 	bus_space_write_1(bst, bsh, DLCR_RX_MODE, 0);
244 
245     mb86950_drain_fifo(sc);
246 
247 }
248 
249 void
250 mb86950_drain_fifo(struct mb86950_softc *sc)
251 {
252 	bus_space_tag_t bst = sc->sc_bst;
253 	bus_space_handle_t bsh = sc->sc_bsh;
254 
255 	/* Read data until bus read error (i.e. buffer empty). */
256 	/* XXX There ought to be a better way, eats CPU and bothers the chip */
257 	while (!(bus_space_read_1(bst, bsh, DLCR_RX_STAT) & RX_BUS_RD_ERR))
258 		bus_space_read_2(bst, bsh, BMPR_FIFO);
259 	/* XXX */
260 
261 	/* Clear Bus Rd Error */
262 	bus_space_write_1(bst, bsh, DLCR_RX_STAT, RX_BUS_RD_ERR);
263 }
264 
265 /*
266  * Install interface into kernel networking data structures
267  */
268 void
269 mb86950_config(struct mb86950_softc *sc, int *media,
270     int nmedia, int defmedia)
271 {
272 	struct ifnet *ifp = &sc->sc_ec.ec_if;
273 	bus_space_tag_t bst = sc->sc_bst;
274 	bus_space_handle_t bsh = sc->sc_bsh;
275 
276 	/* Initialize ifnet structure. */
277 	strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ);
278 	ifp->if_softc = sc;
279 	ifp->if_start = mb86950_start;
280 	ifp->if_ioctl = mb86950_ioctl;
281 	ifp->if_watchdog = mb86950_watchdog;
282 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
283 
284 	IFQ_SET_READY(&ifp->if_snd);
285 
286 	/* Initialize media goo. */
287 	/* XXX The Tiara LANCard uses board jumpers to change media.
288 	 *       This code may have to be changed for other cards.
289 	 */
290 	ifmedia_init(&sc->sc_media, 0, mb86950_mediachange, mb86950_mediastatus);
291 	ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
292 	ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL);
293 
294 	/* Attach the interface. */
295 	if_attach(ifp);
296 
297 	/* Feed the chip the station address. */
298 	bus_space_write_region_1(bst, bsh, DLCR_NODE_ID, sc->sc_enaddr, ETHER_ADDR_LEN);
299 
300 	ether_ifattach(ifp, sc->sc_enaddr);
301 
302 #if NRND > 0
303 	rnd_attach_source(&sc->rnd_source, device_xname(&sc->sc_dev),
304 	    RND_TYPE_NET, 0);
305 #endif
306 
307 /* XXX No! This doesn't work - DLCR6 of the mb86950 is different
308 
309 	bus_space_write_1(bst, bsh, DLCR_CONFIG, 0x0f);
310 	buf_config = bus_space_read_1(bst, bsh, DLCR_CONFIG);
311 
312 	sc->txb_count = ((buf_config & 0x0c) ? 2 : 1);
313 	sc->txb_size = 1024 * (2 << ((buf_config & 0x0c) ? (((buf_config & 0x0c) >> 2) - 1) : 0));
314 	sc->txb_free = (sc->txb_size * sc->txb_count) / 1500;
315 
316   	sc->rxb_size = ((8 << (buf_config & 3)) * 1024) - (sc->txb_size * sc->txb_count);
317 	sc->rxb_max = sc->rxb_size / 64;
318 
319 	printf("mb86950: Buffer Size %dKB with %d transmit buffer(s) %dKB each.\n",
320 		(8 << (buf_config & 3)), sc->txb_count,	(sc->txb_size / 1024));
321 	printf("         Transmit Buffer Space for %d maximum sized packet(s).\n",sc->txb_free);
322 	printf("         System Bus Width %d bits, Buffer Memory %d bits.\n",
323 		((buf_config & 0x20) ? 8 : 16),
324 		((buf_config & 0x10) ? 8 : 16));
325 
326 */
327 
328 	/* Set reasonable values for number of packet flow control if not
329 	 * set elsewhere */
330 	if (sc->txb_num_pkt == 0) sc->txb_num_pkt = 1;
331 	if (sc->rxb_num_pkt == 0) sc->rxb_num_pkt = 100;
332 
333 	/* Print additional info when attached. */
334 	printf("%s: Ethernet address %s\n", device_xname(&sc->sc_dev),
335 	    ether_sprintf(sc->sc_enaddr));
336 
337 	/* The attach is successful. */
338 	sc->sc_stat |= ESTAR_STAT_ATTACHED;
339 }
340 
341 /*
342  * Media change callback.
343  */
344 int
345 mb86950_mediachange(struct ifnet *ifp)
346 {
347 
348 	struct mb86950_softc *sc = ifp->if_softc;
349 
350 	if (sc->sc_mediachange)
351 		return ((*sc->sc_mediachange)(sc));
352 
353 	return (0);
354 }
355 
356 /*
357  * Media status callback.
358  */
359 void
360 mb86950_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
361 {
362 	struct mb86950_softc *sc = ifp->if_softc;
363 
364 	if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0) {
365 		ifmr->ifm_active = IFM_ETHER | IFM_NONE;
366 		ifmr->ifm_status = 0;
367 		return;
368 	}
369 
370 	if (sc->sc_mediastatus)
371 		(*sc->sc_mediastatus)(sc, ifmr);
372 
373 }
374 
375 /*
376  * Reset interface.
377  */
378 void
379 mb86950_reset(struct mb86950_softc *sc)
380 {
381 	int s;
382 
383 	s = splnet();
384 	log(LOG_ERR, "%s: device reset\n", device_xname(&sc->sc_dev));
385 	mb86950_stop(sc);
386 	mb86950_init(sc);
387 	splx(s);
388 }
389 
390 /*
391  * Device timeout/watchdog routine. Entered if the device neglects to
392  * generate an interrupt after a transmit has been started on it.
393  */
394 void
395 mb86950_watchdog(struct ifnet *ifp)
396 {
397 	struct mb86950_softc *sc = ifp->if_softc;
398 	bus_space_tag_t bst = sc->sc_bst;
399 	bus_space_handle_t bsh = sc->sc_bsh;
400 	u_int8_t tstat;
401 
402 	/* verbose watchdog messages for debugging timeouts */
403     if ((tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT)) != 0) {
404 		if (tstat & TX_CR_LOST) {
405 			if ((tstat & (TX_COL | TX_16COL)) == 0) {
406 				 log(LOG_ERR, "%s: carrier lost\n",
407 				    device_xname(&sc->sc_dev));
408 			} else {
409 				log(LOG_ERR, "%s: excessive collisions\n",
410 				    device_xname(&sc->sc_dev));
411 			}
412 		}
413 		else if ((tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) != 0) {
414 			log(LOG_ERR, "%s: tx fifo underflow/overflow\n",
415 			    device_xname(&sc->sc_dev));
416 		} else {
417 			log(LOG_ERR, "%s: transmit error\n",
418 			    device_xname(&sc->sc_dev));
419 		}
420 	} else {
421 		log(LOG_ERR, "%s: device timeout\n", device_xname(&sc->sc_dev));
422 	}
423 
424 	/* Don't know how many packets are lost by this accident.
425 	 *  ... So just errors = errors + 1
426 	 */
427 	ifp->if_oerrors++;
428 
429 	mb86950_reset(sc);
430 
431 }
432 
433 /*
434  ******************** IOCTL
435  * Process an ioctl request.
436  */
437 int
438 mb86950_ioctl(struct ifnet *ifp, unsigned long cmd, void *data)
439 {
440 	struct mb86950_softc *sc = ifp->if_softc;
441 	struct ifaddr *ifa = (struct ifaddr *)data;
442 	struct ifreq *ifr = (struct ifreq *)data;
443 
444 	int s, error = 0;
445 
446 	s = splnet();
447 
448 	switch (cmd) {
449 	case SIOCINITIFADDR:
450 		/* XXX deprecated ? What should I use instead? */
451 		if ((error = mb86950_enable(sc)) != 0)
452 			break;
453 
454 		ifp->if_flags |= IFF_UP;
455 
456 		mb86950_init(sc);
457 		switch (ifa->ifa_addr->sa_family) {
458 
459 #ifdef INET
460 		case AF_INET:
461 			arp_ifinit(ifp, ifa);
462 			break;
463 #endif
464 
465 
466 		default:
467 			break;
468 		}
469 		break;
470 
471 	case SIOCSIFFLAGS:
472 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
473 			break;
474 		/* XXX re-use ether_ioctl() */
475 		switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
476 		case IFF_RUNNING:
477 			/*
478 			 * If interface is marked down and it is running, then
479 			 * stop it.
480 			 */
481 			mb86950_stop(sc);
482 			ifp->if_flags &= ~IFF_RUNNING;
483 			mb86950_disable(sc);
484 			break;
485 		case IFF_UP:
486 			/*
487 			 * If interface is marked up and it is stopped, then
488 			 * start it.
489 			 */
490 			if ((error = mb86950_enable(sc)) != 0)
491 				break;
492 			mb86950_init(sc);
493 			break;
494 		case IFF_UP|IFF_RUNNING:
495 			/*
496 			 * Reset the interface to pick up changes in any other
497 			 * flags that affect hardware registers.
498 			 */
499 #if 0
500 			/* Setmode not supported */
501 			mb86950_setmode(sc);
502 #endif
503 			break;
504 		case 0:
505 			break;
506 		}
507 
508 #if ESTAR_DEBUG >= 1
509 		/* "ifconfig fe0 debug" to print register dump. */
510 		if (ifp->if_flags & IFF_DEBUG) {
511 			log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n",
512 			    device_xname(&sc->sc_dev));
513 			mb86950_dump(LOG_DEBUG, sc);
514 		}
515 #endif
516 		break;
517 
518 	case SIOCGIFMEDIA:
519 	case SIOCSIFMEDIA:
520 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
521 		break;
522 
523 	default:
524 		error = ether_ioctl(ifp, cmd, data);
525 		break;
526 	}
527 
528 	splx(s);
529 	return (error);
530 }
531 
532 /*
533  * Initialize device.
534  */
535 void
536 mb86950_init(struct mb86950_softc *sc)
537 {
538 	bus_space_tag_t bst = sc->sc_bst;
539 	bus_space_handle_t bsh = sc->sc_bsh;
540 	struct ifnet *ifp = &sc->sc_ec.ec_if;
541 
542 	/* Reset transmitter flags. */
543 	ifp->if_flags &= ~IFF_OACTIVE;
544 	ifp->if_timer = 0;
545 	sc->txb_sched = 0;
546 
547 	bus_space_write_1(bst, bsh, DLCR_TX_MODE, LBC);
548 	bus_space_write_1(bst, bsh, DLCR_RX_MODE, NORMAL_MODE);
549 
550 	/* Enable interrupts. */
551 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
552 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
553 
554 	/* Enable transmitter and receiver. */
555 	bus_space_write_1(bst, bsh, DLCR_CONFIG, ENABLE_DLC);
556 	delay(200);
557 
558 	/* Set 'running' flag. */
559 	ifp->if_flags |= IFF_RUNNING;
560 
561 	/* ...and attempt to start output. */
562 	mb86950_start(ifp);
563 
564 }
565 
566 void
567 mb86950_start(struct ifnet *ifp)
568 {
569 	struct mb86950_softc *sc = ifp->if_softc;
570     bus_space_tag_t bst = sc->sc_bst;
571     bus_space_handle_t bsh = sc->sc_bsh;
572 	struct mbuf *m;
573 	int len;
574 
575 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
576 		return;
577 
578 	IF_DEQUEUE(&ifp->if_snd, m);
579 	if (m == 0)
580 		return;
581 
582 #if NBPFILTER > 0
583 	/* Tap off here if there is a BPF listener. */
584 	if (ifp->if_bpf)
585 		bpf_mtap(ifp->if_bpf, m);
586 #endif
587 
588 	/* Send the packet to the mb86950 */
589 	len = mb86950_put_fifo(sc,m);
590 	m_freem(m);
591 
592 	/* XXX bus_space_barrier here ? */
593 	if (bus_space_read_1(bst, bsh, DLCR_TX_STAT) & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
594 		log(LOG_ERR, "%s: tx fifo underflow/overflow\n", device_xname(&sc->sc_dev));
595 	}
596 
597 	bus_space_write_2(bst, bsh, BMPR_TX_LENGTH, len | TRANSMIT_START);
598 
599 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
600 	/* XXX                          */
601 	sc->txb_sched++;
602 
603 	/* We have space for 'n' transmit packets of size 'mtu. */
604 	if (sc->txb_sched > sc->txb_num_pkt) {
605 		ifp->if_flags |= IFF_OACTIVE;
606 		ifp->if_timer = 2;
607 	}
608 }
609 
610 /*
611  * Send packet - copy packet from mbuf to the fifo
612  */
613 u_short
614 mb86950_put_fifo(struct mb86950_softc *sc, struct mbuf *m)
615 {
616 	bus_space_tag_t bst = sc->sc_bst;
617 	bus_space_handle_t bsh = sc->sc_bsh;
618 	u_short *data;
619 	u_char savebyte[2];
620 	int len, len1, wantbyte;
621 	u_short totlen;
622 
623 	memset(savebyte, 0, sizeof(savebyte));	/* XXX gcc */
624 
625 	totlen = wantbyte = 0;
626 
627 	for (; m != NULL; m = m->m_next) {
628 		data = mtod(m, u_short *);
629 		len = m->m_len;
630 		if (len > 0) {
631 			totlen += len;
632 
633 			/* Finish the last word. */
634 			if (wantbyte) {
635 				savebyte[1] = *((u_char *)data);
636 				bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
637 				data = (u_short *)((u_char *)data + 1);
638 				len--;
639 				wantbyte = 0;
640 			}
641 			/* Output contiguous words. */
642 			if (len > 1) {
643 				len1 = len/2;
644 				bus_space_write_multi_stream_2(bst, bsh, BMPR_FIFO, data, len1);
645 				data += len1;
646 				len &= 1;
647 			}
648 			/* Save last byte, if necessary. */
649 			if (len == 1) {
650 				savebyte[0] = *((u_char *)data);
651 				wantbyte = 1;
652 			}
653 		}
654 	}
655 
656 	if (wantbyte) {
657 		savebyte[1] = 0;
658 		bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
659 	}
660 
661 	if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
662 
663 		/* Fill the rest of the packet with zeros. */
664 		/* XXX Replace this mess with something else, eats CPU */
665 		/* The zero fill and last byte ought to be combined somehow */
666 		for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); len += 2)
667 	  		bus_space_write_2(bst, bsh, BMPR_FIFO, 0);
668 		/* XXX                                       */
669 
670 		totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN);
671 	}
672 
673 	return (totlen);
674 }
675 
676 /*
677  * Handle interrupts.
678  * Ethernet interface interrupt processor
679  */
680 int
681 mb86950_intr(void *arg)
682 {
683 	struct mb86950_softc *sc = arg;
684 	bus_space_tag_t bst = sc->sc_bst;
685 	bus_space_handle_t bsh = sc->sc_bsh;
686 	struct ifnet *ifp = &sc->sc_ec.ec_if;
687 	u_int8_t tstat, rstat;
688 
689 	/* Get interrupt status. */
690 	tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT);
691 	rstat = bus_space_read_1(bst, bsh, DLCR_RX_STAT);
692 
693 	if (tstat == 0 && rstat == 0) return (0);
694 
695 	/* Disable etherstar interrupts so that we won't miss anything. */
696 	bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0);
697 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0);
698 
699 	/*
700 	 * Handle transmitter interrupts. Handle these first because
701 	 * the receiver will reset the board under some conditions.
702 	 */
703 	if (tstat != 0) {
704 
705 		mb86950_tint(sc, tstat);
706 
707 		/* acknowledge transmit interrupt status. */
708 		bus_space_write_1(bst, bsh, DLCR_TX_STAT, tstat);
709 
710 	}
711 
712 	/* Handle receiver interrupts. */
713 	if (rstat != 0) {
714 
715 		mb86950_rint(sc, rstat);
716 
717 		/* acknowledge receive interrupt status. */
718 		bus_space_write_1(bst, bsh, DLCR_RX_STAT, rstat);
719 
720 	}
721 
722 	/* If tx still pending reset tx interrupt mask */
723 	if (sc->txb_sched > 0)
724 		bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
725 
726 	/*
727 	 * If it looks like the transmitter can take more data,
728 	 * attempt to start output on the interface. This is done
729 	 * after handling the receiver interrupt to give the
730 	 * receive operation priority.
731 	 */
732 
733 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
734 		mb86950_start(ifp);
735 
736 	/* Set receive interrupts back */
737 	bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
738 
739 	return(1);
740 }
741 
742 /* Transmission interrupt handler */
743 void
744 mb86950_tint(struct mb86950_softc *sc, u_int8_t tstat)
745 {
746 	bus_space_tag_t bst = sc->sc_bst;
747 	bus_space_handle_t bsh = sc->sc_bsh;
748 	struct ifnet *ifp = &sc->sc_ec.ec_if;
749 	int col;
750 
751 	if (tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
752 		/* XXX What do we need to do here? reset ? */
753 		ifp->if_oerrors++;
754 	}
755 
756 	/* excessive collision */
757 	if (tstat & TX_16COL) {
758 		ifp->if_collisions += 16;
759 		/* 16 collisions means that the packet has been thrown away. */
760 		if (sc->txb_sched > 0)
761 			sc->txb_sched--;
762 	}
763 
764 	/* transmission complete. */
765 	if (tstat & TX_DONE) {
766 		/* successfully transmitted packets ++. */
767 		ifp->if_opackets++;
768 		if (sc->txb_sched > 0)
769 			sc->txb_sched--;
770 
771 		/* Collision count valid only when TX_DONE is set */
772 		if (tstat & TX_COL) {
773 			col = (bus_space_read_1(bst, bsh, DLCR_TX_MODE) & COL_MASK) >> 4;
774 			ifp->if_collisions = ifp->if_collisions + col;
775 		}
776 	}
777 
778 	if (sc->txb_sched == 0) {
779 		 /* Reset output active flag and stop timer. */
780 		 ifp->if_flags &= ~IFF_OACTIVE;
781 		 ifp->if_timer = 0;
782 	}
783 }
784 
785 /* receiver interrupt. */
786 void
787 mb86950_rint(struct mb86950_softc *sc, u_int8_t rstat)
788 {
789 	bus_space_tag_t bst = sc->sc_bst;
790 	bus_space_handle_t bsh = sc->sc_bsh;
791 	struct ifnet *ifp = &sc->sc_ec.ec_if;
792 	u_int status, len;
793 	int i;
794 
795 	 /* Update statistics if this interrupt is caused by an error. */
796 	 if (rstat & RX_ERR_MASK) {
797 
798 		/* tried to read past end of fifo, should be harmless
799 		 * count everything else
800 		 */
801 		if ((rstat & RX_BUS_RD_ERR) == 0) {
802 			ifp->if_ierrors++;
803 		}
804 	}
805 
806 	/*
807 	 * mb86950 has a flag indicating "receive buffer empty."
808 	 * We just loop checking the flag to pull out all received
809 	 * packets.
810 	 *
811 	 * We limit the number of iterrations to avoid infinite loop.
812 	 * It can be caused by a very slow CPU (some broken
813 	 * peripheral may insert incredible number of wait cycles)
814 	 * or, worse, by a broken mb86950 chip.
815 	 */
816 	for (i = 0; i < sc->rxb_num_pkt; i++) {
817 		/* Stop the iterration if 86950 indicates no packets. */
818 		if (bus_space_read_1(bst, bsh, DLCR_RX_MODE) & RX_BUF_EMTY)
819 			break;
820 
821 		/* receive packet status */
822 		status = bus_space_read_2(bst, bsh, BMPR_FIFO);
823 
824 		/* bad packet? */
825 		if ((status & GOOD_PKT) == 0) {
826 			ifp->if_ierrors++;
827 			mb86950_drain_fifo(sc);
828 			continue;
829 		}
830 
831 		/* Length valid ? */
832 		len = bus_space_read_2(bst, bsh, BMPR_FIFO);
833 
834 		if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || len < ETHER_HDR_LEN) {
835 			ifp->if_ierrors++;
836 			mb86950_drain_fifo(sc);
837 			continue;
838 		}
839 
840 		if (mb86950_get_fifo(sc, len) != 0) {
841 			/* No mbufs? Drop packet. */
842 			ifp->if_ierrors++;
843 			mb86950_drain_fifo(sc);
844 			return;
845 		}
846 
847 		/* Successfully received a packet.  Update stat. */
848 		ifp->if_ipackets++;
849 	}
850 }
851 
852 /*
853  * Receive packet.
854  * Retrieve packet from receive buffer and send to the next level up via
855  * ether_input(). If there is a BPF listener, give a copy to BPF, too.
856  * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
857  */
858 int
859 mb86950_get_fifo(struct mb86950_softc *sc, u_int len)
860 {
861 	bus_space_tag_t bst = sc->sc_bst;
862 	bus_space_handle_t bsh = sc->sc_bsh;
863 	struct ifnet *ifp = &sc->sc_ec.ec_if;
864 	struct mbuf *m;
865 
866 	/* Allocate a header mbuf. */
867 	MGETHDR(m, M_DONTWAIT, MT_DATA);
868 	if (m == 0)
869 		return (-1);
870 
871 	/*
872 	 * Round len to even value.
873 	 */
874 	if (len & 1)
875 		len++;
876 
877 	m->m_pkthdr.rcvif = ifp;
878 	m->m_pkthdr.len = len;
879 
880 	/* The following silliness is to make NFS happy. */
881 #define	EROUND	((sizeof(struct ether_header) + 3) & ~3)
882 #define	EOFF	(EROUND - sizeof(struct ether_header))
883 
884 	/*
885 	 * Our strategy has one more problem.  There is a policy on
886 	 * mbuf cluster allocation.  It says that we must have at
887 	 * least MINCLSIZE (208 bytes) to allocate a cluster.  For a
888 	 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
889 	 * our code violates the rule...
890 	 * On the other hand, the current code is short, simple,
891 	 * and fast, however.  It does no harmful thing, just wastes
892 	 * some memory.  Any comments?  FIXME.
893 	 */
894 
895 	/* Attach a cluster if this packet doesn't fit in a normal mbuf. */
896 	if (len > MHLEN - EOFF) {
897 		MCLGET(m, M_DONTWAIT);
898 		if ((m->m_flags & M_EXT) == 0) {
899 			m_freem(m);
900 			return (-1);
901 		}
902 	}
903 
904 	/*
905 	 * The following assumes there is room for the ether header in the
906 	 * header mbuf.
907 	 */
908 	m->m_data += EOFF;
909 
910 	/* Set the length of this packet. */
911 	m->m_len = len;
912 
913 	/* Get a packet. */
914 	bus_space_read_multi_stream_2(bst, bsh, BMPR_FIFO, mtod(m, u_int16_t *), (len + 1) >> 1);
915 
916 #if NBPFILTER > 0
917 	/*
918 	 * Check if there's a BPF listener on this interface.  If so, hand off
919 	 * the raw packet to bpf.
920 	 */
921 	if (ifp->if_bpf)
922 		bpf_mtap(ifp->if_bpf, m);
923 #endif
924 
925 	(*ifp->if_input)(ifp, m);
926 	return (0);
927 }
928 
929 /*
930  * Enable power on the interface.
931  */
932 int
933 mb86950_enable(struct mb86950_softc *sc)
934 {
935 
936 	if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0 && sc->sc_enable != NULL) {
937 		if ((*sc->sc_enable)(sc) != 0) {
938 			aprint_error_dev(&sc->sc_dev, "device enable failed\n");
939 			return (EIO);
940 		}
941 	}
942 
943 	sc->sc_stat |= ESTAR_STAT_ENABLED;
944 	return (0);
945 }
946 
947 /*
948  * Disable power on the interface.
949  */
950 void
951 mb86950_disable(struct mb86950_softc *sc)
952 {
953 
954 	if ((sc->sc_stat & ESTAR_STAT_ENABLED) != 0 && sc->sc_disable != NULL) {
955 		(*sc->sc_disable)(sc);
956 		sc->sc_stat &= ~ESTAR_STAT_ENABLED;
957 	}
958 }
959 
960 /*
961  * mbe_activate:
962  *
963  *	Handle device activation/deactivation requests.
964  */
965 int
966 mb86950_activate(struct device *self, enum devact act)
967 {
968 	struct mb86950_softc *sc = (struct mb86950_softc *)self;
969 	int rv, s;
970 
971 	rv = 0;
972 	s = splnet();
973 	switch (act) {
974 	case DVACT_ACTIVATE:
975 		rv = EOPNOTSUPP;
976 		break;
977 
978 	case DVACT_DEACTIVATE:
979 		if_deactivate(&sc->sc_ec.ec_if);
980 		break;
981 	}
982 	splx(s);
983 	return (rv);
984 }
985 
986 /*
987  * mb86950_detach:
988  *
989  *	Detach a mb86950 interface.
990  */
991 int
992 mb86950_detach(struct mb86950_softc *sc)
993 {
994 	struct ifnet *ifp = &sc->sc_ec.ec_if;
995 
996 	/* Succeed now if there's no work to do. */
997 	if ((sc->sc_stat & ESTAR_STAT_ATTACHED) == 0)
998 		return (0);
999 
1000 	/* Delete all media. */
1001 	ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
1002 
1003 #if NRND > 0
1004 	/* Unhook the entropy source. */
1005 	rnd_detach_source(&sc->rnd_source);
1006 #endif
1007 	ether_ifdetach(ifp);
1008 	if_detach(ifp);
1009 
1010 	return (0);
1011 }
1012 
1013 #if ESTAR_DEBUG >= 1
1014 void
1015 mb86950_dump(int level, struct mb86950_softc *sc)
1016 {
1017 	bus_space_tag_t bst = sc->sc_bst;
1018 	bus_space_handle_t bsh = sc->sc_bsh;
1019 
1020 	log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x\n",
1021 	    bus_space_read_1(bst, bsh, DLCR_TX_STAT),
1022 	    bus_space_read_1(bst, bsh, DLCR_TX_INT_EN),
1023 	    bus_space_read_1(bst, bsh, DLCR_RX_STAT),
1024 	    bus_space_read_1(bst, bsh, DLCR_RX_INT_EN),
1025 	    bus_space_read_1(bst, bsh, DLCR_TX_MODE),
1026 	    bus_space_read_1(bst, bsh, DLCR_RX_MODE),
1027 	    bus_space_read_1(bst, bsh, DLCR_CONFIG));
1028 
1029 	/* XXX BMPR2, 4 write only ?
1030 	log(level, "\tBMPR = xxxx %04x %04x\n",
1031 		bus_space_read_2(bst, bsh, BMPR_TX_LENGTH),
1032 		bus_space_read_2(bst, bsh, BMPR_DMA));
1033 	*/
1034 }
1035 #endif
1036