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