mb86950.c revision 1.12 1 /* $NetBSD: mb86950.c,v 1.12 2008/11/07 00:20:02 dyoung 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.12 2008/11/07 00:20:02 dyoung 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(struct ifnet *ifp, unsigned long cmd, void *data)
448 {
449 struct mb86950_softc *sc = ifp->if_softc;
450 struct ifaddr *ifa = (struct ifaddr *)data;
451 struct ifreq *ifr = (struct ifreq *)data;
452
453 int s, error = 0;
454
455 s = splnet();
456
457 switch (cmd) {
458 case SIOCINITIFADDR:
459 /* XXX deprecated ? What should I use instead? */
460 if ((error = mb86950_enable(sc)) != 0)
461 break;
462
463 ifp->if_flags |= IFF_UP;
464
465 mb86950_init(sc);
466 switch (ifa->ifa_addr->sa_family) {
467
468 #ifdef INET
469 case AF_INET:
470 arp_ifinit(ifp, ifa);
471 break;
472 #endif
473
474
475 default:
476 break;
477 }
478 break;
479
480 case SIOCSIFFLAGS:
481 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
482 break;
483 /* XXX re-use ether_ioctl() */
484 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
485 case IFF_RUNNING:
486 /*
487 * If interface is marked down and it is running, then
488 * stop it.
489 */
490 mb86950_stop(sc);
491 ifp->if_flags &= ~IFF_RUNNING;
492 mb86950_disable(sc);
493 break;
494 case IFF_UP:
495 /*
496 * If interface is marked up and it is stopped, then
497 * start it.
498 */
499 if ((error = mb86950_enable(sc)) != 0)
500 break;
501 mb86950_init(sc);
502 break;
503 case IFF_UP|IFF_RUNNING:
504 /*
505 * Reset the interface to pick up changes in any other
506 * flags that affect hardware registers.
507 */
508 #if 0
509 /* Setmode not supported */
510 mb86950_setmode(sc);
511 #endif
512 break;
513 case 0:
514 break;
515 }
516
517 #if ESTAR_DEBUG >= 1
518 /* "ifconfig fe0 debug" to print register dump. */
519 if (ifp->if_flags & IFF_DEBUG) {
520 log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n",
521 device_xname(&sc->sc_dev));
522 mb86950_dump(LOG_DEBUG, sc);
523 }
524 #endif
525 break;
526
527 case SIOCGIFMEDIA:
528 case SIOCSIFMEDIA:
529 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
530 break;
531
532 default:
533 error = ether_ioctl(ifp, cmd, data);
534 break;
535 }
536
537 splx(s);
538 return (error);
539 }
540
541 /*
542 * Initialize device.
543 */
544 void
545 mb86950_init(sc)
546 struct mb86950_softc *sc;
547 {
548 bus_space_tag_t bst = sc->sc_bst;
549 bus_space_handle_t bsh = sc->sc_bsh;
550 struct ifnet *ifp = &sc->sc_ec.ec_if;
551
552 /* Reset transmitter flags. */
553 ifp->if_flags &= ~IFF_OACTIVE;
554 ifp->if_timer = 0;
555 sc->txb_sched = 0;
556
557 bus_space_write_1(bst, bsh, DLCR_TX_MODE, LBC);
558 bus_space_write_1(bst, bsh, DLCR_RX_MODE, NORMAL_MODE);
559
560 /* Enable interrupts. */
561 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
562 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
563
564 /* Enable transmitter and receiver. */
565 bus_space_write_1(bst, bsh, DLCR_CONFIG, ENABLE_DLC);
566 delay(200);
567
568 /* Set 'running' flag. */
569 ifp->if_flags |= IFF_RUNNING;
570
571 /* ...and attempt to start output. */
572 mb86950_start(ifp);
573
574 }
575
576 void
577 mb86950_start(ifp)
578 struct ifnet *ifp;
579 {
580 struct mb86950_softc *sc = ifp->if_softc;
581 bus_space_tag_t bst = sc->sc_bst;
582 bus_space_handle_t bsh = sc->sc_bsh;
583 struct mbuf *m;
584 int len;
585
586 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
587 return;
588
589 IF_DEQUEUE(&ifp->if_snd, m);
590 if (m == 0)
591 return;
592
593 #if NBPFILTER > 0
594 /* Tap off here if there is a BPF listener. */
595 if (ifp->if_bpf)
596 bpf_mtap(ifp->if_bpf, m);
597 #endif
598
599 /* Send the packet to the mb86950 */
600 len = mb86950_put_fifo(sc,m);
601 m_freem(m);
602
603 /* XXX bus_space_barrier here ? */
604 if (bus_space_read_1(bst, bsh, DLCR_TX_STAT) & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
605 log(LOG_ERR, "%s: tx fifo underflow/overflow\n", device_xname(&sc->sc_dev));
606 }
607
608 bus_space_write_2(bst, bsh, BMPR_TX_LENGTH, len | TRANSMIT_START);
609
610 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
611 /* XXX */
612 sc->txb_sched++;
613
614 /* We have space for 'n' transmit packets of size 'mtu. */
615 if (sc->txb_sched > sc->txb_num_pkt) {
616 ifp->if_flags |= IFF_OACTIVE;
617 ifp->if_timer = 2;
618 }
619 }
620
621 /*
622 * Send packet - copy packet from mbuf to the fifo
623 */
624 u_short
625 mb86950_put_fifo(sc, m)
626 struct mb86950_softc *sc;
627 struct mbuf *m;
628 {
629 bus_space_tag_t bst = sc->sc_bst;
630 bus_space_handle_t bsh = sc->sc_bsh;
631 u_short *data;
632 u_char savebyte[2];
633 int len, len1, wantbyte;
634 u_short totlen;
635
636 memset(savebyte, 0, sizeof(savebyte)); /* XXX gcc */
637
638 totlen = wantbyte = 0;
639
640 for (; m != NULL; m = m->m_next) {
641 data = mtod(m, u_short *);
642 len = m->m_len;
643 if (len > 0) {
644 totlen += len;
645
646 /* Finish the last word. */
647 if (wantbyte) {
648 savebyte[1] = *((u_char *)data);
649 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
650 data = (u_short *)((u_char *)data + 1);
651 len--;
652 wantbyte = 0;
653 }
654 /* Output contiguous words. */
655 if (len > 1) {
656 len1 = len/2;
657 bus_space_write_multi_stream_2(bst, bsh, BMPR_FIFO, data, len1);
658 data += len1;
659 len &= 1;
660 }
661 /* Save last byte, if necessary. */
662 if (len == 1) {
663 savebyte[0] = *((u_char *)data);
664 wantbyte = 1;
665 }
666 }
667 }
668
669 if (wantbyte) {
670 savebyte[1] = 0;
671 bus_space_write_2(bst, bsh, BMPR_FIFO, *savebyte);
672 }
673
674 if (totlen < (ETHER_MIN_LEN - ETHER_CRC_LEN)) {
675
676 /* Fill the rest of the packet with zeros. */
677 /* XXX Replace this mess with something else, eats CPU */
678 /* The zero fill and last byte ought to be combined somehow */
679 for(len = totlen + 1; len < (ETHER_MIN_LEN - ETHER_CRC_LEN); len += 2)
680 bus_space_write_2(bst, bsh, BMPR_FIFO, 0);
681 /* XXX */
682
683 totlen = (ETHER_MIN_LEN - ETHER_CRC_LEN);
684 }
685
686 return (totlen);
687 }
688
689 /*
690 * Handle interrupts.
691 * Ethernet interface interrupt processor
692 */
693 int
694 mb86950_intr(arg)
695 void *arg;
696 {
697 struct mb86950_softc *sc = arg;
698 bus_space_tag_t bst = sc->sc_bst;
699 bus_space_handle_t bsh = sc->sc_bsh;
700 struct ifnet *ifp = &sc->sc_ec.ec_if;
701 u_int8_t tstat, rstat;
702
703 /* Get interrupt status. */
704 tstat = bus_space_read_1(bst, bsh, DLCR_TX_STAT);
705 rstat = bus_space_read_1(bst, bsh, DLCR_RX_STAT);
706
707 if (tstat == 0 && rstat == 0) return (0);
708
709 /* Disable etherstar interrupts so that we won't miss anything. */
710 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, 0);
711 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, 0);
712
713 /*
714 * Handle transmitter interrupts. Handle these first because
715 * the receiver will reset the board under some conditions.
716 */
717 if (tstat != 0) {
718
719 mb86950_tint(sc, tstat);
720
721 /* acknowledge transmit interrupt status. */
722 bus_space_write_1(bst, bsh, DLCR_TX_STAT, tstat);
723
724 }
725
726 /* Handle receiver interrupts. */
727 if (rstat != 0) {
728
729 mb86950_rint(sc, rstat);
730
731 /* acknowledge receive interrupt status. */
732 bus_space_write_1(bst, bsh, DLCR_RX_STAT, rstat);
733
734 }
735
736 /* If tx still pending reset tx interrupt mask */
737 if (sc->txb_sched > 0)
738 bus_space_write_1(bst, bsh, DLCR_TX_INT_EN, TX_MASK);
739
740 /*
741 * If it looks like the transmitter can take more data,
742 * attempt to start output on the interface. This is done
743 * after handling the receiver interrupt to give the
744 * receive operation priority.
745 */
746
747 if ((ifp->if_flags & IFF_OACTIVE) == 0)
748 mb86950_start(ifp);
749
750 /* Set receive interrupts back */
751 bus_space_write_1(bst, bsh, DLCR_RX_INT_EN, RX_MASK);
752
753 return(1);
754 }
755
756 /* Transmission interrupt handler */
757 void
758 mb86950_tint(sc, tstat)
759 struct mb86950_softc *sc;
760 u_int8_t tstat;
761 {
762 bus_space_tag_t bst = sc->sc_bst;
763 bus_space_handle_t bsh = sc->sc_bsh;
764 struct ifnet *ifp = &sc->sc_ec.ec_if;
765 int col;
766
767 if (tstat & (TX_UNDERFLO | TX_BUS_WR_ERR)) {
768 /* XXX What do we need to do here? reset ? */
769 ifp->if_oerrors++;
770 }
771
772 /* excessive collision */
773 if (tstat & TX_16COL) {
774 ifp->if_collisions += 16;
775 /* 16 collisions means that the packet has been thrown away. */
776 if (sc->txb_sched > 0)
777 sc->txb_sched--;
778 }
779
780 /* transmission complete. */
781 if (tstat & TX_DONE) {
782 /* successfully transmitted packets ++. */
783 ifp->if_opackets++;
784 if (sc->txb_sched > 0)
785 sc->txb_sched--;
786
787 /* Collision count valid only when TX_DONE is set */
788 if (tstat & TX_COL) {
789 col = (bus_space_read_1(bst, bsh, DLCR_TX_MODE) & COL_MASK) >> 4;
790 ifp->if_collisions = ifp->if_collisions + col;
791 }
792 }
793
794 if (sc->txb_sched == 0) {
795 /* Reset output active flag and stop timer. */
796 ifp->if_flags &= ~IFF_OACTIVE;
797 ifp->if_timer = 0;
798 }
799 }
800
801 /* receiver interrupt. */
802 void
803 mb86950_rint(sc, rstat)
804 struct mb86950_softc *sc;
805 u_int8_t rstat;
806 {
807 bus_space_tag_t bst = sc->sc_bst;
808 bus_space_handle_t bsh = sc->sc_bsh;
809 struct ifnet *ifp = &sc->sc_ec.ec_if;
810 u_int status, len;
811 int i;
812
813 /* Update statistics if this interrupt is caused by an error. */
814 if (rstat & RX_ERR_MASK) {
815
816 /* tried to read past end of fifo, should be harmless
817 * count everything else
818 */
819 if ((rstat & RX_BUS_RD_ERR) == 0) {
820 ifp->if_ierrors++;
821 }
822 }
823
824 /*
825 * mb86950 has a flag indicating "receive buffer empty."
826 * We just loop checking the flag to pull out all received
827 * packets.
828 *
829 * We limit the number of iterrations to avoid infinite loop.
830 * It can be caused by a very slow CPU (some broken
831 * peripheral may insert incredible number of wait cycles)
832 * or, worse, by a broken mb86950 chip.
833 */
834 for (i = 0; i < sc->rxb_num_pkt; i++) {
835 /* Stop the iterration if 86950 indicates no packets. */
836 if (bus_space_read_1(bst, bsh, DLCR_RX_MODE) & RX_BUF_EMTY)
837 break;
838
839 /* receive packet status */
840 status = bus_space_read_2(bst, bsh, BMPR_FIFO);
841
842 /* bad packet? */
843 if ((status & GOOD_PKT) == 0) {
844 ifp->if_ierrors++;
845 mb86950_drain_fifo(sc);
846 continue;
847 }
848
849 /* Length valid ? */
850 len = bus_space_read_2(bst, bsh, BMPR_FIFO);
851
852 if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN) || len < ETHER_HDR_LEN) {
853 ifp->if_ierrors++;
854 mb86950_drain_fifo(sc);
855 continue;
856 }
857
858 if (mb86950_get_fifo(sc, len) != 0) {
859 /* No mbufs? Drop packet. */
860 ifp->if_ierrors++;
861 mb86950_drain_fifo(sc);
862 return;
863 }
864
865 /* Successfully received a packet. Update stat. */
866 ifp->if_ipackets++;
867 }
868 }
869
870 /*
871 * Receive packet.
872 * Retrieve packet from receive buffer and send to the next level up via
873 * ether_input(). If there is a BPF listener, give a copy to BPF, too.
874 * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
875 */
876 int
877 mb86950_get_fifo(sc, len)
878 struct mb86950_softc *sc;
879 u_int len;
880 {
881 bus_space_tag_t bst = sc->sc_bst;
882 bus_space_handle_t bsh = sc->sc_bsh;
883 struct ifnet *ifp = &sc->sc_ec.ec_if;
884 struct mbuf *m;
885
886 /* Allocate a header mbuf. */
887 MGETHDR(m, M_DONTWAIT, MT_DATA);
888 if (m == 0)
889 return (-1);
890
891 /*
892 * Round len to even value.
893 */
894 if (len & 1)
895 len++;
896
897 m->m_pkthdr.rcvif = ifp;
898 m->m_pkthdr.len = len;
899
900 /* The following silliness is to make NFS happy. */
901 #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
902 #define EOFF (EROUND - sizeof(struct ether_header))
903
904 /*
905 * Our strategy has one more problem. There is a policy on
906 * mbuf cluster allocation. It says that we must have at
907 * least MINCLSIZE (208 bytes) to allocate a cluster. For a
908 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
909 * our code violates the rule...
910 * On the other hand, the current code is short, simple,
911 * and fast, however. It does no harmful thing, just wastes
912 * some memory. Any comments? FIXME.
913 */
914
915 /* Attach a cluster if this packet doesn't fit in a normal mbuf. */
916 if (len > MHLEN - EOFF) {
917 MCLGET(m, M_DONTWAIT);
918 if ((m->m_flags & M_EXT) == 0) {
919 m_freem(m);
920 return (-1);
921 }
922 }
923
924 /*
925 * The following assumes there is room for the ether header in the
926 * header mbuf.
927 */
928 m->m_data += EOFF;
929
930 /* Set the length of this packet. */
931 m->m_len = len;
932
933 /* Get a packet. */
934 bus_space_read_multi_stream_2(bst, bsh, BMPR_FIFO, mtod(m, u_int16_t *), (len + 1) >> 1);
935
936 #if NBPFILTER > 0
937 /*
938 * Check if there's a BPF listener on this interface. If so, hand off
939 * the raw packet to bpf.
940 */
941 if (ifp->if_bpf)
942 bpf_mtap(ifp->if_bpf, m);
943 #endif
944
945 (*ifp->if_input)(ifp, m);
946 return (0);
947 }
948
949 /*
950 * Enable power on the interface.
951 */
952 int
953 mb86950_enable(sc)
954 struct mb86950_softc *sc;
955 {
956
957 if ((sc->sc_stat & ESTAR_STAT_ENABLED) == 0 && sc->sc_enable != NULL) {
958 if ((*sc->sc_enable)(sc) != 0) {
959 aprint_error_dev(&sc->sc_dev, "device enable failed\n");
960 return (EIO);
961 }
962 }
963
964 sc->sc_stat |= ESTAR_STAT_ENABLED;
965 return (0);
966 }
967
968 /*
969 * Disable power on the interface.
970 */
971 void
972 mb86950_disable(sc)
973 struct mb86950_softc *sc;
974 {
975
976 if ((sc->sc_stat & ESTAR_STAT_ENABLED) != 0 && sc->sc_disable != NULL) {
977 (*sc->sc_disable)(sc);
978 sc->sc_stat &= ~ESTAR_STAT_ENABLED;
979 }
980 }
981
982 /*
983 * mbe_activate:
984 *
985 * Handle device activation/deactivation requests.
986 */
987 int
988 mb86950_activate(self, act)
989 struct device *self;
990 enum devact act;
991 {
992 struct mb86950_softc *sc = (struct mb86950_softc *)self;
993 int rv, s;
994
995 rv = 0;
996 s = splnet();
997 switch (act) {
998 case DVACT_ACTIVATE:
999 rv = EOPNOTSUPP;
1000 break;
1001
1002 case DVACT_DEACTIVATE:
1003 if_deactivate(&sc->sc_ec.ec_if);
1004 break;
1005 }
1006 splx(s);
1007 return (rv);
1008 }
1009
1010 /*
1011 * mb86950_detach:
1012 *
1013 * Detach a mb86950 interface.
1014 */
1015 int
1016 mb86950_detach(sc)
1017 struct mb86950_softc *sc;
1018 {
1019 struct ifnet *ifp = &sc->sc_ec.ec_if;
1020
1021 /* Succeed now if there's no work to do. */
1022 if ((sc->sc_stat & ESTAR_STAT_ATTACHED) == 0)
1023 return (0);
1024
1025 /* Delete all media. */
1026 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
1027
1028 #if NRND > 0
1029 /* Unhook the entropy source. */
1030 rnd_detach_source(&sc->rnd_source);
1031 #endif
1032 ether_ifdetach(ifp);
1033 if_detach(ifp);
1034
1035 return (0);
1036 }
1037
1038 #if ESTAR_DEBUG >= 1
1039 void
1040 mb86950_dump(level, sc)
1041 int level;
1042 struct mb86950_softc *sc;
1043 {
1044 bus_space_tag_t bst = sc->sc_bst;
1045 bus_space_handle_t bsh = sc->sc_bsh;
1046
1047 log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x\n",
1048 bus_space_read_1(bst, bsh, DLCR_TX_STAT),
1049 bus_space_read_1(bst, bsh, DLCR_TX_INT_EN),
1050 bus_space_read_1(bst, bsh, DLCR_RX_STAT),
1051 bus_space_read_1(bst, bsh, DLCR_RX_INT_EN),
1052 bus_space_read_1(bst, bsh, DLCR_TX_MODE),
1053 bus_space_read_1(bst, bsh, DLCR_RX_MODE),
1054 bus_space_read_1(bst, bsh, DLCR_CONFIG));
1055
1056 /* XXX BMPR2, 4 write only ?
1057 log(level, "\tBMPR = xxxx %04x %04x\n",
1058 bus_space_read_2(bst, bsh, BMPR_TX_LENGTH),
1059 bus_space_read_2(bst, bsh, BMPR_DMA));
1060 */
1061 }
1062 #endif
1063