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