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