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