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