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