FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/mb86950.c
1 /* $NetBSD: mb86950.c,v 1.35 2021/07/31 14:36:33 andvar 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.35 2021/07/31 14:36:33 andvar 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 void
240 mb86950_drain_fifo(struct mb86950_softc *sc)
241 {
242 bus_space_tag_t bst = sc->sc_bst;
243 bus_space_handle_t bsh = sc->sc_bsh;
244
245 /* Read data until bus read error (i.e. buffer empty). */
246 /* XXX There ought to be a better way, eats CPU and bothers the chip */
247 while (!(bus_space_read_1(bst, bsh, DLCR_RX_STAT) & RX_BUS_RD_ERR))
248 bus_space_read_2(bst, bsh, BMPR_FIFO);
249 /* XXX */
250
251 /* Clear Bus Rd Error */
252 bus_space_write_1(bst, bsh, DLCR_RX_STAT, RX_BUS_RD_ERR);
253 }
254
255 /*
256 * Install interface into kernel networking data structures
257 */
258 void
259 mb86950_config(struct mb86950_softc *sc, int *media, int nmedia, int defmedia)
260 {
261 struct ifnet *ifp = &sc->sc_ec.ec_if;
262 bus_space_tag_t bst = sc->sc_bst;
263 bus_space_handle_t bsh = sc->sc_bsh;
264
265 /* Initialize ifnet structure. */
266 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
267 ifp->if_softc = sc;
268 ifp->if_start = mb86950_start;
269 ifp->if_ioctl = mb86950_ioctl;
270 ifp->if_watchdog = mb86950_watchdog;
271 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
272
273 IFQ_SET_READY(&ifp->if_snd);
274
275 /* Initialize media goo. */
276 /* XXX The Tiara LANCard uses board jumpers to change media.
277 * This code may have to be changed for other cards.
278 */
279 sc->sc_ec.ec_ifmedia = &sc->sc_media;
280 ifmedia_init(&sc->sc_media, 0, mb86950_mediachange,
281 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,
291 ETHER_ADDR_LEN);
292
293 ether_ifattach(ifp, sc->sc_enaddr);
294
295 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
296 RND_TYPE_NET, RND_FLAG_DEFAULT);
297
298 /* XXX No! This doesn't work - DLCR6 of the mb86950 is different
299
300 bus_space_write_1(bst, bsh, DLCR_CONFIG, 0x0f);
301 buf_config = bus_space_read_1(bst, bsh, DLCR_CONFIG);
302
303 sc->txb_count = ((buf_config & 0x0c) ? 2 : 1);
304 sc->txb_size = 1024 * (2 << ((buf_config & 0x0c) ? (((buf_config & 0x0c) >> 2) - 1) : 0));
305 sc->txb_free = (sc->txb_size * sc->txb_count) / 1500;
306
307 sc->rxb_size = ((8 << (buf_config & 3)) * 1024) - (sc->txb_size * sc->txb_count);
308 sc->rxb_max = sc->rxb_size / 64;
309
310 printf("mb86950: Buffer Size %dKB with %d transmit buffer(s) %dKB each.\n",
311 (8 << (buf_config & 3)), sc->txb_count, (sc->txb_size / 1024));
312 printf(" Transmit Buffer Space for %d maximum sized packet(s).\n",sc->txb_free);
313 printf(" System Bus Width %d bits, Buffer Memory %d bits.\n",
314 ((buf_config & 0x20) ? 8 : 16),
315 ((buf_config & 0x10) ? 8 : 16));
316
317 */
318
319 /* Set reasonable values for number of packet flow control if not
320 * set elsewhere */
321 if (sc->txb_num_pkt == 0) sc->txb_num_pkt = 1;
322 if (sc->rxb_num_pkt == 0) sc->rxb_num_pkt = 100;
323
324 /* Print additional info when attached. */
325 printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev),
326 ether_sprintf(sc->sc_enaddr));
327
328 /* The attach is successful. */
329 sc->sc_stat |= ESTAR_STAT_ATTACHED;
330 }
331
332 /*
333 * Media change callback.
334 */
335 int
336 mb86950_mediachange(struct ifnet *ifp)
337 {
338
339 struct mb86950_softc *sc = ifp->if_softc;
340
341 if (sc->sc_mediachange)
342 return (*sc->sc_mediachange)(sc);
343
344 return 0;
345 }
346
347 /*
348 * Media status callback.
349 */
350 void
351 mb86950_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
352 {
353 struct mb86950_softc *sc = ifp->if_softc;
354
355 if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0) {
356 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
357 ifmr->ifm_status = 0;
358 return;
359 }
360
361 if (sc->sc_mediastatus)
362 (*sc->sc_mediastatus)(sc, ifmr);
363
364 }
365
366 /*
367 * Reset interface.
368 */
369 void
370 mb86950_reset(struct mb86950_softc *sc)
371 {
372 int s;
373
374 s = splnet();
375 log(LOG_ERR, "%s: device reset\n", device_xname(sc->sc_dev));
376 mb86950_stop(sc);
377 mb86950_init(sc);
378 splx(s);
379 }
380
381 /*
382 * Device timeout/watchdog routine. Entered if the device neglects to
383 * generate an interrupt after a transmit has been started on it.
384 */
385 void
386 mb86950_watchdog(struct ifnet *ifp)
387 {
388 struct mb86950_softc *sc = ifp->if_softc;
389 bus_space_tag_t bst = sc->sc_bst;
390 bus_space_handle_t bsh = sc->sc_bsh;
391 u_int8_t tstat;
392
393 /* Verbose watchdog messages for debugging timeouts */
394 if ((tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT)) != 0) {
395 if (tstat & TX_CR_LOST) {
396 if ((tstat & (TX_COL | TX_16COL)) == 0) {
397 log(LOG_ERR, "%s: carrier lost\n",
398 device_xname(sc->sc_dev));
399 } else {
400 log(LOG_ERR, "%s: excessive collisions\n",
401 device_xname(sc->sc_dev));
402 }
403 }
404 else if ((tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) != 0) {
405 log(LOG_ERR, "%s: tx fifo underflow/overflow\n",
406 device_xname(sc->sc_dev));
407 } else {
408 log(LOG_ERR, "%s: transmit error\n",
409 device_xname(sc->sc_dev));
410 }
411 } else
412 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
413
414 /*
415 * Don't know how many packets are lost by this accident.
416 * ... So just errors = errors + 1
417 */
418 if_statinc(ifp, if_oerrors);
419
420 mb86950_reset(sc);
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
433 int s, error = 0;
434
435 s = splnet();
436
437 switch (cmd) {
438 case SIOCINITIFADDR:
439 /* XXX deprecated ? What should I use instead? */
440 if ((error = mb86950_enable(sc)) != 0)
441 break;
442
443 ifp->if_flags |= IFF_UP;
444
445 mb86950_init(sc);
446 switch (ifa->ifa_addr->sa_family) {
447
448 #ifdef INET
449 case AF_INET:
450 arp_ifinit(ifp, ifa);
451 break;
452 #endif
453
454
455 default:
456 break;
457 }
458 break;
459
460 case SIOCSIFFLAGS:
461 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
462 break;
463 /* XXX re-use ether_ioctl() */
464 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
465 case IFF_RUNNING:
466 /*
467 * If interface is marked down and it is running, then
468 * stop it.
469 */
470 mb86950_stop(sc);
471 ifp->if_flags &= ~IFF_RUNNING;
472 mb86950_disable(sc);
473 break;
474 case IFF_UP:
475 /*
476 * If interface is marked up and it is stopped, then
477 * start it.
478 */
479 if ((error = mb86950_enable(sc)) != 0)
480 break;
481 mb86950_init(sc);
482 break;
483 case IFF_UP|IFF_RUNNING:
484 /*
485 * Reset the interface to pick up changes in any other
486 * flags that affect hardware registers.
487 */
488 #if 0
489 /* Setmode not supported */
490 mb86950_setmode(sc);
491 #endif
492 break;
493 case 0:
494 break;
495 }
496
497 #if ESTAR_DEBUG >= 1
498 /* "ifconfig fe0 debug" to print register dump. */
499 if (ifp->if_flags & IFF_DEBUG) {
500 log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n",
501 device_xname(sc->sc_dev));
502 mb86950_dump(LOG_DEBUG, sc);
503 }
504 #endif
505 break;
506
507 default:
508 error = ether_ioctl(ifp, cmd, data);
509 break;
510 }
511
512 splx(s);
513 return error;
514 }
515
516 /*
517 * Initialize device.
518 */
519 void
520 mb86950_init(struct mb86950_softc *sc)
521 {
522 bus_space_tag_t bst = sc->sc_bst;
523 bus_space_handle_t bsh = sc->sc_bsh;
524 struct ifnet *ifp = &sc->sc_ec.ec_if;
525
526 /* Reset transmitter flags. */
527 ifp->if_flags &= ~IFF_OACTIVE;
528 ifp->if_timer = 0;
529 sc->txb_sched = 0;
530
531 bus_space_write_1(bst, bsh, DLCR_TX_MODE, LBC);
532 bus_space_write_1(bst, bsh, DLCR_RX_MODE, NORMAL_MODE);
533
534 /* Enable interrupts. */
535 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
536 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
537
538 /* Enable transmitter and receiver. */
539 bus_space_write_1(bst, bsh, DLCR_CONFIG, ENABLE_DLC);
540 delay(200);
541
542 /* Set 'running' flag. */
543 ifp->if_flags |= IFF_RUNNING;
544
545 /* ...and attempt to start output. */
546 mb86950_start(ifp);
547 }
548
549 void
550 mb86950_start(struct ifnet *ifp)
551 {
552 struct mb86950_softc *sc = ifp->if_softc;
553 bus_space_tag_t bst = sc->sc_bst;
554 bus_space_handle_t bsh = sc->sc_bsh;
555 struct mbuf *m;
556 int len;
557
558 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
559 return;
560
561 IF_DEQUEUE(&ifp->if_snd, m);
562 if (m == 0)
563 return;
564
565 /* Tap off here if there is a BPF listener. */
566 bpf_mtap(ifp, m, BPF_D_OUT);
567
568 /* Send the packet to the mb86950 */
569 len = mb86950_put_fifo(sc,m);
570 m_freem(m);
571
572 /* XXX bus_space_barrier here ? */
573 if (bus_space_read_1(bst, bsh, DLCR_TX_STAT)
574 & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
575 log(LOG_ERR, "%s: tx fifo underflow/overflow\n",
576 device_xname(sc->sc_dev));
577 }
578
579 bus_space_write_2(bst, bsh, BMPR_TX_LENGTH, len | TRANSMIT_START);
580
581 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
582 /* XXX */
583 sc->txb_sched++;
584
585 /* We have space for 'n' transmit packets of size 'mtu. */
586 if (sc->txb_sched > sc->txb_num_pkt) {
587 ifp->if_flags |= IFF_OACTIVE;
588 ifp->if_timer = 2;
589 }
590 }
591
592 /*
593 * Send packet - copy packet from mbuf to the fifo
594 */
595 u_short
596 mb86950_put_fifo(struct mb86950_softc *sc, struct mbuf *m)
597 {
598 bus_space_tag_t bst = sc->sc_bst;
599 bus_space_handle_t bsh = sc->sc_bsh;
600 u_short *data;
601 u_char savebyte[2];
602 int len, len1, wantbyte;
603 u_short totlen;
604
605 memset(savebyte, 0, sizeof(savebyte)); /* XXX gcc */
606
607 totlen = wantbyte = 0;
608
609 for (; m != NULL; m = m->m_next) {
610 data = mtod(m, u_short *);
611 len = m->m_len;
612 if (len > 0) {
613 totlen += len;
614
615 /* Finish the last word. */
616 if (wantbyte) {
617 savebyte[1] = *((u_char *)data);
618 bus_space_write_2(bst, bsh, BMPR_FIFO,
619 *savebyte);
620 data = (u_short *)((u_char *)data + 1);
621 len--;
622 wantbyte = 0;
623 }
624 /* Output contiguous words. */
625 if (len > 1) {
626 len1 = len/2;
627 bus_space_write_multi_stream_2(bst, bsh,
628 BMPR_FIFO, data, len1);
629 data += len1;
630 len &= 1;
631 }
632 /* Save last byte, if necessary. */
633 if (len == 1) {
634 savebyte[0] = *((u_char *)data);
635 wantbyte = 1;
636 }
637 }
638 }
639
640 if (wantbyte) {
641 savebyte[1] = 0;
642 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
643 }
644
645 if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
646
647 /* Fill the rest of the packet with zeros. */
648 /* XXX Replace this mess with something else, eats CPU */
649 /* The zero fill and last byte ought to be combined somehow */
650 for (len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN);
651 len += 2)
652 bus_space_write_2(bst, bsh, BMPR_FIFO, 0);
653 /* XXX */
654
655 totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN);
656 }
657
658 return totlen;
659 }
660
661 /*
662 * Handle interrupts.
663 * Ethernet interface interrupt processor
664 */
665 int
666 mb86950_intr(void *arg)
667 {
668 struct mb86950_softc *sc = arg;
669 bus_space_tag_t bst = sc->sc_bst;
670 bus_space_handle_t bsh = sc->sc_bsh;
671 struct ifnet *ifp = &sc->sc_ec.ec_if;
672 u_int8_t tstat, rstat;
673
674 /* Get interrupt status. */
675 tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT);
676 rstat = bus_space_read_1(bst, bsh, DLCR_RX_STAT);
677
678 if (tstat == 0 && rstat == 0) return 0;
679
680 /* Disable etherstar interrupts so that we won't miss anything. */
681 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0);
682 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0);
683
684 /*
685 * Handle transmitter interrupts. Handle these first because
686 * the receiver will reset the board under some conditions.
687 */
688 if (tstat != 0) {
689
690 mb86950_tint(sc, tstat);
691
692 /* acknowledge transmit interrupt status. */
693 bus_space_write_1(bst, bsh, DLCR_TX_STAT, tstat);
694
695 }
696
697 /* Handle receiver interrupts. */
698 if (rstat != 0) {
699
700 mb86950_rint(sc, rstat);
701
702 /* acknowledge receive interrupt status. */
703 bus_space_write_1(bst, bsh, DLCR_RX_STAT, rstat);
704
705 }
706
707 /* If tx still pending reset tx interrupt mask */
708 if (sc->txb_sched > 0)
709 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
710
711 /*
712 * If it looks like the transmitter can take more data,
713 * attempt to start output on the interface. This is done
714 * after handling the receiver interrupt to give the
715 * receive operation priority.
716 */
717
718 if ((ifp->if_flags & IFF_OACTIVE) == 0)
719 if_schedule_deferred_start(ifp);
720
721 /* Set receive interrupts back */
722 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
723
724 return 1;
725 }
726
727 /* Transmission interrupt handler */
728 void
729 mb86950_tint(struct mb86950_softc *sc, u_int8_t tstat)
730 {
731 bus_space_tag_t bst = sc->sc_bst;
732 bus_space_handle_t bsh = sc->sc_bsh;
733 struct ifnet *ifp = &sc->sc_ec.ec_if;
734 int col;
735
736 if (tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
737 /* XXX What do we need to do here? reset ? */
738 if_statinc(ifp, if_oerrors);
739 }
740
741 /* Excessive collision */
742 if (tstat & TX_16COL) {
743 if_statadd(ifp, if_collisions, 16);
744 /* 16 collisions means that the packet has been thrown away. */
745 if (sc->txb_sched > 0)
746 sc->txb_sched--;
747 }
748
749 /* Transmission complete. */
750 if (tstat & TX_DONE) {
751 /* Successfully transmitted packets ++. */
752 if_statinc(ifp, if_opackets);
753 if (sc->txb_sched > 0)
754 sc->txb_sched--;
755
756 /* Collision count valid only when TX_DONE is set */
757 if (tstat & TX_COL) {
758 col = (bus_space_read_1(bst, bsh, DLCR_TX_MODE)
759 & COL_MASK) >> 4;
760 if_statadd(ifp, if_collisions, col);
761 }
762 }
763
764 if (sc->txb_sched == 0) {
765 /* Reset output active flag and stop timer. */
766 ifp->if_flags &= ~IFF_OACTIVE;
767 ifp->if_timer = 0;
768 }
769 }
770
771 /* Receiver interrupt. */
772 void
773 mb86950_rint(struct mb86950_softc *sc, u_int8_t rstat)
774 {
775 bus_space_tag_t bst = sc->sc_bst;
776 bus_space_handle_t bsh = sc->sc_bsh;
777 struct ifnet *ifp = &sc->sc_ec.ec_if;
778 u_int status, len;
779 int i;
780
781 /* Update statistics if this interrupt is caused by an error. */
782 if (rstat & RX_ERR_MASK) {
783
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 if_statinc(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 iterations 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 iteration 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 if_statinc(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)
822 || len < ETHER_HDR_LEN) {
823 if_statinc(ifp, if_ierrors);
824 mb86950_drain_fifo(sc);
825 continue;
826 }
827
828 if (mb86950_get_fifo(sc, len) != 0) {
829 /* No mbufs? Drop packet. */
830 if_statinc(ifp, if_ierrors);
831 mb86950_drain_fifo(sc);
832 return;
833 }
834 }
835 }
836
837 /*
838 * Receive packet.
839 * Retrieve packet from receive buffer and send to the next level up via
840 * ether_input().
841 * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
842 */
843 int
844 mb86950_get_fifo(struct mb86950_softc *sc, u_int len)
845 {
846 bus_space_tag_t bst = sc->sc_bst;
847 bus_space_handle_t bsh = sc->sc_bsh;
848 struct ifnet *ifp = &sc->sc_ec.ec_if;
849 struct mbuf *m;
850
851 /* Allocate a header mbuf. */
852 MGETHDR(m, M_DONTWAIT, MT_DATA);
853 if (m == 0)
854 return -1;
855
856 /* Round len to even value. */
857 if (len & 1)
858 len++;
859
860 m_set_rcvif(m, ifp);
861 m->m_pkthdr.len = len;
862
863 /* The following silliness is to make NFS happy. */
864 #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
865 #define EOFF (EROUND - sizeof(struct ether_header))
866
867 /*
868 * Our strategy has one more problem. There is a policy on
869 * mbuf cluster allocation. It says that we must have at
870 * least MINCLSIZE (208 bytes) to allocate a cluster. For a
871 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
872 * our code violates the rule...
873 * On the other hand, the current code is short, simple,
874 * and fast, however. It does no harmful thing, just wastes
875 * some memory. Any comments? FIXME.
876 */
877
878 /* Attach a cluster if this packet doesn't fit in a normal mbuf. */
879 if (len > MHLEN - EOFF) {
880 MCLGET(m, M_DONTWAIT);
881 if ((m->m_flags & M_EXT) == 0) {
882 m_freem(m);
883 return -1;
884 }
885 }
886
887 /*
888 * The following assumes there is room for the ether header in the
889 * header mbuf.
890 */
891 m->m_data += EOFF;
892
893 /* Set the length of this packet. */
894 m->m_len = len;
895
896 /* Get a packet. */
897 bus_space_read_multi_stream_2(bst, bsh, BMPR_FIFO,
898 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 /* Unhook the entropy source. */
969 rnd_detach_source(&sc->rnd_source);
970
971 ether_ifdetach(ifp);
972 if_detach(ifp);
973
974 /* Delete all media. */
975 ifmedia_fini(&sc->sc_media);
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
Cache object: 649957207369ad0679c3f62bc4aaf66f
|