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