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