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