1 /* $NetBSD: mb86950.c,v 1.15 2009/05/12 14:25:17 cegger Exp $ */
4 * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
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.
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
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.
35 * Portions copyright (c) 1995 Mika Kortelainen
36 * All rights reserved.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
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
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.
65 * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards.
66 * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp>
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: mb86950.c,v 1.15 2009/05/12 14:25:17 cegger Exp $");
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).
79 /* XXX There are still rough edges......
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)
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)
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
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
104 No, that isn't right either :(
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!
110 * (5) There are no bus_space_barrier calls used. Are they needed? Maybe not.
112 * (6) Access to the fifo assumes word (16 bit) mode. Cards configured for
113 * byte wide fifo access will require driver code changes.
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.
122 #include "opt_inet.h"
123 #include "bpfilter.h"
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>
139 #include <net/if_dl.h>
140 #include <net/if_types.h>
141 #include <net/if_media.h>
142 #include <net/if_ether.h>
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>
155 #include <net/bpfdesc.h>
160 #include <dev/ic/mb86950reg.h>
161 #include <dev/ic/mb86950var.h>
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 */
169 /* Standard driver entry points. These can be static. */
170 int mb86950_ioctl(struct ifnet
*, u_long
, void *);
171 void mb86950_init(struct mb86950_softc
*);
172 void mb86950_start(struct ifnet
*);
173 void mb86950_watchdog(struct ifnet
*);
174 void mb86950_reset(struct mb86950_softc
*);
176 /* Local functions. */
177 void mb86950_stop(struct mb86950_softc
*);
178 void mb86950_tint(struct mb86950_softc
*, u_int8_t
);
179 void mb86950_rint(struct mb86950_softc
*, u_int8_t
);
180 int mb86950_get_fifo(struct mb86950_softc
*, u_int
);
181 ushort
mb86950_put_fifo(struct mb86950_softc
*, struct mbuf
*);
182 void mb86950_drain_fifo(struct mb86950_softc
*);
184 int mb86950_mediachange(struct ifnet
*);
185 void mb86950_mediastatus(struct ifnet
*, struct ifmediareq
*);
189 void mb86950_dump(int, struct mb86950_softc
*);
192 /********************************************************************/
195 mb86950_attach(struct mb86950_softc
*sc
, u_int8_t
*myea
)
200 printf("%s: ethernet address shouldn't be NULL\n",
201 device_xname(&sc
->sc_dev
));
202 panic("NULL ethernet address");
206 /* Initialize 86950. */
209 memcpy(sc
->sc_enaddr
, myea
, sizeof(sc
->sc_enaddr
));
211 sc
->sc_stat
|= ESTAR_STAT_ENABLED
;
215 * Stop everything on the interface.
217 * All buffered packets, both transmitting and receiving,
218 * if any, will be lost by stopping the interface.
221 mb86950_stop(struct mb86950_softc
*sc
)
223 bus_space_tag_t bst
= sc
->sc_bst
;
224 bus_space_handle_t bsh
= sc
->sc_bsh
;
226 /* Stop interface hardware. */
227 bus_space_write_1(bst
, bsh
, DLCR_CONFIG
, DISABLE_DLC
);
230 /* Disable interrupts. */
231 bus_space_write_1(bst
, bsh
, DLCR_TX_INT_EN
, 0);
232 bus_space_write_1(bst
, bsh
, DLCR_RX_INT_EN
, 0);
234 /* Ack / Clear all interrupt status. */
235 bus_space_write_1(bst
, bsh
, DLCR_TX_STAT
, 0xff);
236 bus_space_write_1(bst
, bsh
, DLCR_RX_STAT
, 0xff);
239 bus_space_write_2(bst
, bsh
, BMPR_DMA
, 0);
241 /* accept no packets */
242 bus_space_write_1(bst
, bsh
, DLCR_TX_MODE
, 0);
243 bus_space_write_1(bst
, bsh
, DLCR_RX_MODE
, 0);
245 mb86950_drain_fifo(sc
);
250 mb86950_drain_fifo(struct mb86950_softc
*sc
)
252 bus_space_tag_t bst
= sc
->sc_bst
;
253 bus_space_handle_t bsh
= sc
->sc_bsh
;
255 /* Read data until bus read error (i.e. buffer empty). */
256 /* XXX There ought to be a better way, eats CPU and bothers the chip */
257 while (!(bus_space_read_1(bst
, bsh
, DLCR_RX_STAT
) & RX_BUS_RD_ERR
))
258 bus_space_read_2(bst
, bsh
, BMPR_FIFO
);
261 /* Clear Bus Rd Error */
262 bus_space_write_1(bst
, bsh
, DLCR_RX_STAT
, RX_BUS_RD_ERR
);
266 * Install interface into kernel networking data structures
269 mb86950_config(struct mb86950_softc
*sc
, int *media
,
270 int nmedia
, int defmedia
)
272 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
273 bus_space_tag_t bst
= sc
->sc_bst
;
274 bus_space_handle_t bsh
= sc
->sc_bsh
;
276 /* Initialize ifnet structure. */
277 strlcpy(ifp
->if_xname
, device_xname(&sc
->sc_dev
), IFNAMSIZ
);
279 ifp
->if_start
= mb86950_start
;
280 ifp
->if_ioctl
= mb86950_ioctl
;
281 ifp
->if_watchdog
= mb86950_watchdog
;
282 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
;
284 IFQ_SET_READY(&ifp
->if_snd
);
286 /* Initialize media goo. */
287 /* XXX The Tiara LANCard uses board jumpers to change media.
288 * This code may have to be changed for other cards.
290 ifmedia_init(&sc
->sc_media
, 0, mb86950_mediachange
, mb86950_mediastatus
);
291 ifmedia_add(&sc
->sc_media
, IFM_ETHER
| IFM_MANUAL
, 0, NULL
);
292 ifmedia_set(&sc
->sc_media
, IFM_ETHER
| IFM_MANUAL
);
294 /* Attach the interface. */
297 /* Feed the chip the station address. */
298 bus_space_write_region_1(bst
, bsh
, DLCR_NODE_ID
, sc
->sc_enaddr
, ETHER_ADDR_LEN
);
300 ether_ifattach(ifp
, sc
->sc_enaddr
);
303 rnd_attach_source(&sc
->rnd_source
, device_xname(&sc
->sc_dev
),
307 /* XXX No! This doesn't work - DLCR6 of the mb86950 is different
309 bus_space_write_1(bst, bsh, DLCR_CONFIG, 0x0f);
310 buf_config = bus_space_read_1(bst, bsh, DLCR_CONFIG);
312 sc->txb_count = ((buf_config & 0x0c) ? 2 : 1);
313 sc->txb_size = 1024 * (2 << ((buf_config & 0x0c) ? (((buf_config & 0x0c) >> 2) - 1) : 0));
314 sc->txb_free = (sc->txb_size * sc->txb_count) / 1500;
316 sc->rxb_size = ((8 << (buf_config & 3)) * 1024) - (sc->txb_size * sc->txb_count);
317 sc->rxb_max = sc->rxb_size / 64;
319 printf("mb86950: Buffer Size %dKB with %d transmit buffer(s) %dKB each.\n",
320 (8 << (buf_config & 3)), sc->txb_count, (sc->txb_size / 1024));
321 printf(" Transmit Buffer Space for %d maximum sized packet(s).\n",sc->txb_free);
322 printf(" System Bus Width %d bits, Buffer Memory %d bits.\n",
323 ((buf_config & 0x20) ? 8 : 16),
324 ((buf_config & 0x10) ? 8 : 16));
328 /* Set reasonable values for number of packet flow control if not
330 if (sc
->txb_num_pkt
== 0) sc
->txb_num_pkt
= 1;
331 if (sc
->rxb_num_pkt
== 0) sc
->rxb_num_pkt
= 100;
333 /* Print additional info when attached. */
334 printf("%s: Ethernet address %s\n", device_xname(&sc
->sc_dev
),
335 ether_sprintf(sc
->sc_enaddr
));
337 /* The attach is successful. */
338 sc
->sc_stat
|= ESTAR_STAT_ATTACHED
;
342 * Media change callback.
345 mb86950_mediachange(struct ifnet
*ifp
)
348 struct mb86950_softc
*sc
= ifp
->if_softc
;
350 if (sc
->sc_mediachange
)
351 return ((*sc
->sc_mediachange
)(sc
));
357 * Media status callback.
360 mb86950_mediastatus(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
362 struct mb86950_softc
*sc
= ifp
->if_softc
;
364 if ((sc
->sc_stat
& ESTAR_STAT_ENABLED
) == 0) {
365 ifmr
->ifm_active
= IFM_ETHER
| IFM_NONE
;
366 ifmr
->ifm_status
= 0;
370 if (sc
->sc_mediastatus
)
371 (*sc
->sc_mediastatus
)(sc
, ifmr
);
379 mb86950_reset(struct mb86950_softc
*sc
)
384 log(LOG_ERR
, "%s: device reset\n", device_xname(&sc
->sc_dev
));
391 * Device timeout/watchdog routine. Entered if the device neglects to
392 * generate an interrupt after a transmit has been started on it.
395 mb86950_watchdog(struct ifnet
*ifp
)
397 struct mb86950_softc
*sc
= ifp
->if_softc
;
398 bus_space_tag_t bst
= sc
->sc_bst
;
399 bus_space_handle_t bsh
= sc
->sc_bsh
;
402 /* verbose watchdog messages for debugging timeouts */
403 if ((tstat
= bus_space_read_1(bst
, bsh
, DLCR_TX_STAT
)) != 0) {
404 if (tstat
& TX_CR_LOST
) {
405 if ((tstat
& (TX_COL
| TX_16COL
)) == 0) {
406 log(LOG_ERR
, "%s: carrier lost\n",
407 device_xname(&sc
->sc_dev
));
409 log(LOG_ERR
, "%s: excessive collisions\n",
410 device_xname(&sc
->sc_dev
));
413 else if ((tstat
& (TX_UNDERFLO
| TX_BUS_WR_ERR
)) != 0) {
414 log(LOG_ERR
, "%s: tx fifo underflow/overflow\n",
415 device_xname(&sc
->sc_dev
));
417 log(LOG_ERR
, "%s: transmit error\n",
418 device_xname(&sc
->sc_dev
));
421 log(LOG_ERR
, "%s: device timeout\n", device_xname(&sc
->sc_dev
));
424 /* Don't know how many packets are lost by this accident.
425 * ... So just errors = errors + 1
434 ******************** IOCTL
435 * Process an ioctl request.
438 mb86950_ioctl(struct ifnet
*ifp
, unsigned long cmd
, void *data
)
440 struct mb86950_softc
*sc
= ifp
->if_softc
;
441 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
442 struct ifreq
*ifr
= (struct ifreq
*)data
;
450 /* XXX deprecated ? What should I use instead? */
451 if ((error
= mb86950_enable(sc
)) != 0)
454 ifp
->if_flags
|= IFF_UP
;
457 switch (ifa
->ifa_addr
->sa_family
) {
461 arp_ifinit(ifp
, ifa
);
472 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
474 /* XXX re-use ether_ioctl() */
475 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
478 * If interface is marked down and it is running, then
482 ifp
->if_flags
&= ~IFF_RUNNING
;
487 * If interface is marked up and it is stopped, then
490 if ((error
= mb86950_enable(sc
)) != 0)
494 case IFF_UP
|IFF_RUNNING
:
496 * Reset the interface to pick up changes in any other
497 * flags that affect hardware registers.
500 /* Setmode not supported */
509 /* "ifconfig fe0 debug" to print register dump. */
510 if (ifp
->if_flags
& IFF_DEBUG
) {
511 log(LOG_INFO
, "%s: SIOCSIFFLAGS(DEBUG)\n",
512 device_xname(&sc
->sc_dev
));
513 mb86950_dump(LOG_DEBUG
, sc
);
520 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->sc_media
, cmd
);
524 error
= ether_ioctl(ifp
, cmd
, data
);
536 mb86950_init(struct mb86950_softc
*sc
)
538 bus_space_tag_t bst
= sc
->sc_bst
;
539 bus_space_handle_t bsh
= sc
->sc_bsh
;
540 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
542 /* Reset transmitter flags. */
543 ifp
->if_flags
&= ~IFF_OACTIVE
;
547 bus_space_write_1(bst
, bsh
, DLCR_TX_MODE
, LBC
);
548 bus_space_write_1(bst
, bsh
, DLCR_RX_MODE
, NORMAL_MODE
);
550 /* Enable interrupts. */
551 bus_space_write_1(bst
, bsh
, DLCR_TX_INT_EN
, TX_MASK
);
552 bus_space_write_1(bst
, bsh
, DLCR_RX_INT_EN
, RX_MASK
);
554 /* Enable transmitter and receiver. */
555 bus_space_write_1(bst
, bsh
, DLCR_CONFIG
, ENABLE_DLC
);
558 /* Set 'running' flag. */
559 ifp
->if_flags
|= IFF_RUNNING
;
561 /* ...and attempt to start output. */
567 mb86950_start(struct ifnet
*ifp
)
569 struct mb86950_softc
*sc
= ifp
->if_softc
;
570 bus_space_tag_t bst
= sc
->sc_bst
;
571 bus_space_handle_t bsh
= sc
->sc_bsh
;
575 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
578 IF_DEQUEUE(&ifp
->if_snd
, m
);
583 /* Tap off here if there is a BPF listener. */
585 bpf_mtap(ifp
->if_bpf
, m
);
588 /* Send the packet to the mb86950 */
589 len
= mb86950_put_fifo(sc
,m
);
592 /* XXX bus_space_barrier here ? */
593 if (bus_space_read_1(bst
, bsh
, DLCR_TX_STAT
) & (TX_UNDERFLO
| TX_BUS_WR_ERR
)) {
594 log(LOG_ERR
, "%s: tx fifo underflow/overflow\n", device_xname(&sc
->sc_dev
));
597 bus_space_write_2(bst
, bsh
, BMPR_TX_LENGTH
, len
| TRANSMIT_START
);
599 bus_space_write_1(bst
, bsh
, DLCR_TX_INT_EN
, TX_MASK
);
603 /* We have space for 'n' transmit packets of size 'mtu. */
604 if (sc
->txb_sched
> sc
->txb_num_pkt
) {
605 ifp
->if_flags
|= IFF_OACTIVE
;
611 * Send packet - copy packet from mbuf to the fifo
614 mb86950_put_fifo(struct mb86950_softc
*sc
, struct mbuf
*m
)
616 bus_space_tag_t bst
= sc
->sc_bst
;
617 bus_space_handle_t bsh
= sc
->sc_bsh
;
620 int len
, len1
, wantbyte
;
623 memset(savebyte
, 0, sizeof(savebyte
)); /* XXX gcc */
625 totlen
= wantbyte
= 0;
627 for (; m
!= NULL
; m
= m
->m_next
) {
628 data
= mtod(m
, u_short
*);
633 /* Finish the last word. */
635 savebyte
[1] = *((u_char
*)data
);
636 bus_space_write_2(bst
, bsh
, BMPR_FIFO
, *savebyte
);
637 data
= (u_short
*)((u_char
*)data
+ 1);
641 /* Output contiguous words. */
644 bus_space_write_multi_stream_2(bst
, bsh
, BMPR_FIFO
, data
, len1
);
648 /* Save last byte, if necessary. */
650 savebyte
[0] = *((u_char
*)data
);
658 bus_space_write_2(bst
, bsh
, BMPR_FIFO
, *savebyte
);
661 if (totlen
< (ETHER_MIN_LEN
- ETHER_CRC_LEN
)) {
663 /* Fill the rest of the packet with zeros. */
664 /* XXX Replace this mess with something else, eats CPU */
665 /* The zero fill and last byte ought to be combined somehow */
666 for(len
= totlen
+ 1; len
< (ETHER_MIN_LEN
- ETHER_CRC_LEN
); len
+= 2)
667 bus_space_write_2(bst
, bsh
, BMPR_FIFO
, 0);
670 totlen
= (ETHER_MIN_LEN
- ETHER_CRC_LEN
);
678 * Ethernet interface interrupt processor
681 mb86950_intr(void *arg
)
683 struct mb86950_softc
*sc
= arg
;
684 bus_space_tag_t bst
= sc
->sc_bst
;
685 bus_space_handle_t bsh
= sc
->sc_bsh
;
686 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
687 u_int8_t tstat
, rstat
;
689 /* Get interrupt status. */
690 tstat
= bus_space_read_1(bst
, bsh
, DLCR_TX_STAT
);
691 rstat
= bus_space_read_1(bst
, bsh
, DLCR_RX_STAT
);
693 if (tstat
== 0 && rstat
== 0) return (0);
695 /* Disable etherstar interrupts so that we won't miss anything. */
696 bus_space_write_1(bst
, bsh
, DLCR_TX_INT_EN
, 0);
697 bus_space_write_1(bst
, bsh
, DLCR_RX_INT_EN
, 0);
700 * Handle transmitter interrupts. Handle these first because
701 * the receiver will reset the board under some conditions.
705 mb86950_tint(sc
, tstat
);
707 /* acknowledge transmit interrupt status. */
708 bus_space_write_1(bst
, bsh
, DLCR_TX_STAT
, tstat
);
712 /* Handle receiver interrupts. */
715 mb86950_rint(sc
, rstat
);
717 /* acknowledge receive interrupt status. */
718 bus_space_write_1(bst
, bsh
, DLCR_RX_STAT
, rstat
);
722 /* If tx still pending reset tx interrupt mask */
723 if (sc
->txb_sched
> 0)
724 bus_space_write_1(bst
, bsh
, DLCR_TX_INT_EN
, TX_MASK
);
727 * If it looks like the transmitter can take more data,
728 * attempt to start output on the interface. This is done
729 * after handling the receiver interrupt to give the
730 * receive operation priority.
733 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0)
736 /* Set receive interrupts back */
737 bus_space_write_1(bst
, bsh
, DLCR_RX_INT_EN
, RX_MASK
);
742 /* Transmission interrupt handler */
744 mb86950_tint(struct mb86950_softc
*sc
, u_int8_t tstat
)
746 bus_space_tag_t bst
= sc
->sc_bst
;
747 bus_space_handle_t bsh
= sc
->sc_bsh
;
748 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
751 if (tstat
& (TX_UNDERFLO
| TX_BUS_WR_ERR
)) {
752 /* XXX What do we need to do here? reset ? */
756 /* excessive collision */
757 if (tstat
& TX_16COL
) {
758 ifp
->if_collisions
+= 16;
759 /* 16 collisions means that the packet has been thrown away. */
760 if (sc
->txb_sched
> 0)
764 /* transmission complete. */
765 if (tstat
& TX_DONE
) {
766 /* successfully transmitted packets ++. */
768 if (sc
->txb_sched
> 0)
771 /* Collision count valid only when TX_DONE is set */
772 if (tstat
& TX_COL
) {
773 col
= (bus_space_read_1(bst
, bsh
, DLCR_TX_MODE
) & COL_MASK
) >> 4;
774 ifp
->if_collisions
= ifp
->if_collisions
+ col
;
778 if (sc
->txb_sched
== 0) {
779 /* Reset output active flag and stop timer. */
780 ifp
->if_flags
&= ~IFF_OACTIVE
;
785 /* receiver interrupt. */
787 mb86950_rint(struct mb86950_softc
*sc
, u_int8_t rstat
)
789 bus_space_tag_t bst
= sc
->sc_bst
;
790 bus_space_handle_t bsh
= sc
->sc_bsh
;
791 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
795 /* Update statistics if this interrupt is caused by an error. */
796 if (rstat
& RX_ERR_MASK
) {
798 /* tried to read past end of fifo, should be harmless
799 * count everything else
801 if ((rstat
& RX_BUS_RD_ERR
) == 0) {
807 * mb86950 has a flag indicating "receive buffer empty."
808 * We just loop checking the flag to pull out all received
811 * We limit the number of iterrations to avoid infinite loop.
812 * It can be caused by a very slow CPU (some broken
813 * peripheral may insert incredible number of wait cycles)
814 * or, worse, by a broken mb86950 chip.
816 for (i
= 0; i
< sc
->rxb_num_pkt
; i
++) {
817 /* Stop the iterration if 86950 indicates no packets. */
818 if (bus_space_read_1(bst
, bsh
, DLCR_RX_MODE
) & RX_BUF_EMTY
)
821 /* receive packet status */
822 status
= bus_space_read_2(bst
, bsh
, BMPR_FIFO
);
825 if ((status
& GOOD_PKT
) == 0) {
827 mb86950_drain_fifo(sc
);
832 len
= bus_space_read_2(bst
, bsh
, BMPR_FIFO
);
834 if (len
> (ETHER_MAX_LEN
- ETHER_CRC_LEN
) || len
< ETHER_HDR_LEN
) {
836 mb86950_drain_fifo(sc
);
840 if (mb86950_get_fifo(sc
, len
) != 0) {
841 /* No mbufs? Drop packet. */
843 mb86950_drain_fifo(sc
);
847 /* Successfully received a packet. Update stat. */
854 * Retrieve packet from receive buffer and send to the next level up via
855 * ether_input(). If there is a BPF listener, give a copy to BPF, too.
856 * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
859 mb86950_get_fifo(struct mb86950_softc
*sc
, u_int len
)
861 bus_space_tag_t bst
= sc
->sc_bst
;
862 bus_space_handle_t bsh
= sc
->sc_bsh
;
863 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
866 /* Allocate a header mbuf. */
867 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
872 * Round len to even value.
877 m
->m_pkthdr
.rcvif
= ifp
;
878 m
->m_pkthdr
.len
= len
;
880 /* The following silliness is to make NFS happy. */
881 #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
882 #define EOFF (EROUND - sizeof(struct ether_header))
885 * Our strategy has one more problem. There is a policy on
886 * mbuf cluster allocation. It says that we must have at
887 * least MINCLSIZE (208 bytes) to allocate a cluster. For a
888 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
889 * our code violates the rule...
890 * On the other hand, the current code is short, simple,
891 * and fast, however. It does no harmful thing, just wastes
892 * some memory. Any comments? FIXME.
895 /* Attach a cluster if this packet doesn't fit in a normal mbuf. */
896 if (len
> MHLEN
- EOFF
) {
897 MCLGET(m
, M_DONTWAIT
);
898 if ((m
->m_flags
& M_EXT
) == 0) {
905 * The following assumes there is room for the ether header in the
910 /* Set the length of this packet. */
914 bus_space_read_multi_stream_2(bst
, bsh
, BMPR_FIFO
, mtod(m
, u_int16_t
*), (len
+ 1) >> 1);
918 * Check if there's a BPF listener on this interface. If so, hand off
919 * the raw packet to bpf.
922 bpf_mtap(ifp
->if_bpf
, m
);
925 (*ifp
->if_input
)(ifp
, m
);
930 * Enable power on the interface.
933 mb86950_enable(struct mb86950_softc
*sc
)
936 if ((sc
->sc_stat
& ESTAR_STAT_ENABLED
) == 0 && sc
->sc_enable
!= NULL
) {
937 if ((*sc
->sc_enable
)(sc
) != 0) {
938 aprint_error_dev(&sc
->sc_dev
, "device enable failed\n");
943 sc
->sc_stat
|= ESTAR_STAT_ENABLED
;
948 * Disable power on the interface.
951 mb86950_disable(struct mb86950_softc
*sc
)
954 if ((sc
->sc_stat
& ESTAR_STAT_ENABLED
) != 0 && sc
->sc_disable
!= NULL
) {
955 (*sc
->sc_disable
)(sc
);
956 sc
->sc_stat
&= ~ESTAR_STAT_ENABLED
;
963 * Handle device activation/deactivation requests.
966 mb86950_activate(device_t self
, enum devact act
)
968 struct mb86950_softc
*sc
= device_private(self
);
971 case DVACT_DEACTIVATE
:
972 if_deactivate(&sc
->sc_ec
.ec_if
);
982 * Detach a mb86950 interface.
985 mb86950_detach(struct mb86950_softc
*sc
)
987 struct ifnet
*ifp
= &sc
->sc_ec
.ec_if
;
989 /* Succeed now if there's no work to do. */
990 if ((sc
->sc_stat
& ESTAR_STAT_ATTACHED
) == 0)
993 /* Delete all media. */
994 ifmedia_delete_instance(&sc
->sc_media
, IFM_INST_ANY
);
997 /* Unhook the entropy source. */
998 rnd_detach_source(&sc
->rnd_source
);
1000 ether_ifdetach(ifp
);
1006 #if ESTAR_DEBUG >= 1
1008 mb86950_dump(int level
, struct mb86950_softc
*sc
)
1010 bus_space_tag_t bst
= sc
->sc_bst
;
1011 bus_space_handle_t bsh
= sc
->sc_bsh
;
1013 log(level
, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x\n",
1014 bus_space_read_1(bst
, bsh
, DLCR_TX_STAT
),
1015 bus_space_read_1(bst
, bsh
, DLCR_TX_INT_EN
),
1016 bus_space_read_1(bst
, bsh
, DLCR_RX_STAT
),
1017 bus_space_read_1(bst
, bsh
, DLCR_RX_INT_EN
),
1018 bus_space_read_1(bst
, bsh
, DLCR_TX_MODE
),
1019 bus_space_read_1(bst
, bsh
, DLCR_RX_MODE
),
1020 bus_space_read_1(bst
, bsh
, DLCR_CONFIG
));
1022 /* XXX BMPR2, 4 write only ?
1023 log(level, "\tBMPR = xxxx %04x %04x\n",
1024 bus_space_read_2(bst, bsh, BMPR_TX_LENGTH),
1025 bus_space_read_2(bst, bsh, BMPR_DMA));