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