]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/snc/dp83932.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / snc / dp83932.c
1 /*      $FreeBSD$       */
2 /*      $NecBSD: dp83932.c,v 1.5 1999/07/29 05:08:44 kmatsuda Exp $     */
3 /*      $NetBSD: if_snc.c,v 1.18 1998/04/25 21:27:40 scottr Exp $       */
4
5 /*-
6  * Copyright (c) 1997, 1998, 1999
7  *      Kouichi Matsuda.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Kouichi Matsuda for
20  *      NetBSD/pc98.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 /*
37  * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
38  */
39
40 /*
41  * Modified for NetBSD/pc98 1.2G from NetBSD/mac68k 1.2G by Kouichi Matsuda.
42  * Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and
43  * PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as
44  * Ethernet Controller and National Semiconductor NS46C46 as
45  * (64 * 16 bits) Microwire Serial EEPROM.
46  */
47
48 /*-
49  * National Semiconductor  DP8393X SONIC Driver
50  * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
51  * You may use, copy, and modify this program so long as you retain the
52  * copyright line.
53  *
54  * This driver has been substantially modified since Algorithmics donated
55  * it.
56  *
57  *   Denton Gentry <denny1@home.com>
58  * and also
59  *   Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>
60  * did the work to get this running on the Macintosh.
61  */
62
63 #include "opt_inet.h"
64
65 #include <sys/param.h>
66 #include <sys/kernel.h>
67 #include <sys/systm.h>
68 #include <sys/sockio.h>
69 #include <sys/mbuf.h>
70 #include <sys/protosw.h>
71 #include <sys/socket.h>
72 #include <sys/syslog.h>
73 #include <sys/errno.h>
74
75 #include <net/ethernet.h>
76 #include <net/if.h>
77 #include <net/if_arp.h>
78 #include <net/if_dl.h>
79 #include <net/if_media.h>
80 #include <net/if_types.h>
81
82 #include <net/bpf.h>
83
84 #include <sys/bus.h>
85 #include <machine/bus.h>
86 #include <dev/snc/dp83932reg.h>
87 #include <dev/snc/dp83932var.h>
88
89 static void     sncwatchdog(void *);
90 static void     sncinit(void *);
91 static void     sncinit_locked(struct snc_softc *);
92 static int      sncstop(struct snc_softc *sc);
93 static int      sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
94 static void     sncstart(struct ifnet *ifp);
95 static void     sncstart_locked(struct ifnet *ifp);
96 static void     sncreset(struct snc_softc *sc);
97
98 static void     caminitialise(struct snc_softc *);
99 static void     camentry(struct snc_softc *, int, u_char *ea);
100 static void     camprogram(struct snc_softc *);
101 static void     initialise_tda(struct snc_softc *);
102 static void     initialise_rda(struct snc_softc *);
103 static void     initialise_rra(struct snc_softc *);
104 #ifdef SNCDEBUG
105 static void     camdump(struct snc_softc *sc);
106 #endif
107
108 static void     sonictxint(struct snc_softc *);
109 static void     sonicrxint(struct snc_softc *);
110
111 static u_int    sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next);
112 static int      sonic_read(struct snc_softc *, u_int32_t, int);
113 static struct mbuf *sonic_get(struct snc_softc *, u_int32_t, int);
114
115 int     snc_enable(struct snc_softc *);
116 void    snc_disable(struct snc_softc *);
117
118 int     snc_mediachange(struct ifnet *);
119 void    snc_mediastatus(struct ifnet *, struct ifmediareq *);
120
121 #undef assert
122 #undef _assert
123
124 #ifdef NDEBUG
125 #define assert(e)       ((void)0)
126 #define _assert(e)      ((void)0)
127 #else
128 #define _assert(e)      assert(e)
129 #ifdef __STDC__
130 #define assert(e)       ((e) ? (void)0 : __assert("snc ", __FILE__, __LINE__, #e))
131 #else   /* PCC */
132 #define assert(e)       ((e) ? (void)0 : __assert("snc "__FILE__, __LINE__, "e"))
133 #endif
134 #endif
135
136 #ifdef  SNCDEBUG
137 #define SNC_SHOWTXHDR   0x01    /* show tx ether_header */
138 #define SNC_SHOWRXHDR   0x02    /* show rx ether_header */
139 #define SNC_SHOWCAMENT  0x04    /* show CAM entry */
140 #endif  /* SNCDEBUG */
141 int sncdebug = 0;
142
143
144 int
145 sncconfig(struct snc_softc *sc, int *media, int nmedia, int defmedia,
146     u_int8_t *myea)
147 {
148         struct ifnet *ifp;
149         int i;
150
151 #ifdef SNCDEBUG
152         if ((sncdebug & SNC_SHOWCAMENT) != 0) {
153                 camdump(sc);
154         }
155 #endif
156
157         ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
158         if (ifp == NULL) {
159                 device_printf(sc->sc_dev, "can not if_alloc()\n");
160                 return (ENOMEM);
161         }
162
163 #ifdef SNCDEBUG
164         device_printf(sc->sc_dev,
165                       "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n",
166                       sc->v_rra[0], sc->v_cda,
167                       sc->v_rda, sc->mtda[0].mtd_vtxp);
168 #endif
169
170         ifp->if_softc = sc;
171         if_initname(ifp, device_get_name(sc->sc_dev),
172             device_get_unit(sc->sc_dev));
173         ifp->if_ioctl = sncioctl;
174         ifp->if_start = sncstart;
175         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
176         ifp->if_init = sncinit;
177         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
178
179         /* Initialize media goo. */
180         ifmedia_init(&sc->sc_media, 0, snc_mediachange,
181             snc_mediastatus);
182         if (media != NULL) {
183                 for (i = 0; i < nmedia; i++)
184                         ifmedia_add(&sc->sc_media, media[i], 0, NULL);
185                 ifmedia_set(&sc->sc_media, defmedia);
186         } else {
187                 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
188                 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
189         }
190
191         ether_ifattach(ifp, myea);
192         return (0);
193 }
194
195 void
196 sncshutdown(void *arg)
197 {
198         struct snc_softc *sc = arg;
199
200         SNC_ASSERT_LOCKED(sc);
201         sncstop(sc);
202 }
203
204 /*
205  * Media change callback.
206  */
207 int
208 snc_mediachange(struct ifnet *ifp)
209 {
210         struct snc_softc *sc = ifp->if_softc;
211         int error;
212
213         SNC_LOCK(sc);
214         if (sc->sc_mediachange)
215                 error = (*sc->sc_mediachange)(sc);
216         else
217                 error = EINVAL;
218         SNC_UNLOCK(sc);
219         return (error);
220 }
221
222 /*
223  * Media status callback.
224  */
225 void
226 snc_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
227 {
228         struct snc_softc *sc = ifp->if_softc;
229
230         SNC_LOCK(sc);
231         if (sc->sc_enabled == 0) {
232                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
233                 ifmr->ifm_status = 0;
234                 SNC_UNLOCK(sc);
235                 return;
236         }
237
238         if (sc->sc_mediastatus)
239                 (*sc->sc_mediastatus)(sc, ifmr);
240         SNC_UNLOCK(sc);
241 }
242
243
244 static int
245 sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
246 {
247         struct ifreq *ifr;
248         struct snc_softc *sc = ifp->if_softc;
249         int     err = 0;
250
251         switch (cmd) {
252
253         case SIOCSIFFLAGS:
254                 SNC_LOCK(sc);
255                 if ((ifp->if_flags & IFF_UP) == 0 &&
256                     (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
257                         /*
258                          * If interface is marked down and it is running,
259                          * then stop it.
260                          */
261                         sncstop(sc);
262                         snc_disable(sc);
263                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
264                     (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
265                         /*
266                          * If interface is marked up and it is stopped,
267                          * then start it.
268                          */
269                         if ((err = snc_enable(sc)) != 0)
270                                 break;
271                         sncinit_locked(sc);
272                 } else if (sc->sc_enabled) {
273                         /*
274                          * reset the interface to pick up any other changes
275                          * in flags
276                          */
277                         sncreset(sc);
278                         sncstart_locked(ifp);
279                 }
280                 SNC_UNLOCK(sc);
281                 break;
282
283         case SIOCADDMULTI:
284         case SIOCDELMULTI:
285                 SNC_LOCK(sc);
286                 if (sc->sc_enabled == 0) {
287                         err = EIO;
288                         SNC_UNLOCK(sc);
289                         break;
290                 }
291                 sncreset(sc);
292                 SNC_UNLOCK(sc);
293                 err = 0;
294                 break;
295         case SIOCGIFMEDIA:
296         case SIOCSIFMEDIA:
297                 ifr = (struct ifreq *) data;
298                 err = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
299                 break;
300         default:
301                 err = ether_ioctl(ifp, cmd, data);
302                 break;
303         }
304         return (err);
305 }
306
307 /*
308  * Encapsulate a packet of type family for the local net.
309  */
310 static void
311 sncstart(struct ifnet *ifp)
312 {
313         struct snc_softc        *sc = ifp->if_softc;
314
315         SNC_LOCK(sc);
316         sncstart_locked(ifp);
317         SNC_UNLOCK(sc);
318 }
319
320 static void
321 sncstart_locked(struct ifnet *ifp)
322 {
323         struct snc_softc        *sc = ifp->if_softc;
324         struct mbuf     *m;
325         int             mtd_next;
326
327         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
328             IFF_DRV_RUNNING)
329                 return;
330
331 outloop:
332         /* Check for room in the xmit buffer. */
333         if ((mtd_next = (sc->mtd_free + 1)) == NTDA)
334                 mtd_next = 0;
335
336         if (mtd_next == sc->mtd_hw) {
337                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
338                 return;
339         }
340
341         IF_DEQUEUE(&ifp->if_snd, m);
342         if (m == 0)
343                 return;
344
345         /* We need the header for m_pkthdr.len. */
346         M_ASSERTPKTHDR(m);
347
348         /*
349          * If there is nothing in the o/p queue, and there is room in
350          * the Tx ring, then send the packet directly.  Otherwise append
351          * it to the o/p queue.
352          */
353         if ((sonicput(sc, m, mtd_next)) == 0) {
354                 IF_PREPEND(&ifp->if_snd, m);
355                 return;
356         }
357
358         /*
359          * If bpf is listening on this interface, let it see the packet
360          * before we commit it to the wire, but only if we are really
361          * committed to send it.
362          *
363          * XXX: Locking must protect m against premature m_freem() in
364          * sonictxint().
365          */
366         BPF_MTAP(ifp, m);
367
368         sc->mtd_prev = sc->mtd_free;
369         sc->mtd_free = mtd_next;
370
371         ifp->if_opackets++;             /* # of pkts */
372
373         /* Jump back for possibly more punishment. */
374         goto outloop;
375 }
376
377 /*
378  * reset and restart the SONIC.  Called in case of fatal
379  * hardware/software errors.
380  */
381 static void
382 sncreset(struct snc_softc *sc)
383 {
384         sncstop(sc);
385         sncinit_locked(sc);
386 }
387
388 static void
389 sncinit(void *xsc)
390 {
391         struct snc_softc *sc = xsc;
392
393         SNC_LOCK(sc);
394         sncinit_locked(sc);
395         SNC_UNLOCK(sc);
396 }
397
398 static void
399 sncinit_locked(struct snc_softc *sc)
400 {
401         u_long  s_rcr;
402
403         if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
404                 /* already running */
405                 return;
406
407         NIC_PUT(sc, SNCR_CR, CR_RST);   /* DCR only accessable in reset mode! */
408
409         /* config it */
410         NIC_PUT(sc, SNCR_DCR, (sc->sncr_dcr |
411                 (sc->bitmode ? DCR_DW32 : DCR_DW16)));
412         NIC_PUT(sc, SNCR_DCR2, sc->sncr_dcr2);
413
414         s_rcr = RCR_BRD | RCR_LBNONE;
415         if (sc->sc_ifp->if_flags & IFF_PROMISC)
416                 s_rcr |= RCR_PRO;
417         if (sc->sc_ifp->if_flags & IFF_ALLMULTI)
418                 s_rcr |= RCR_AMC;
419         NIC_PUT(sc, SNCR_RCR, s_rcr);
420
421         NIC_PUT(sc, SNCR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN));
422
423         /* clear pending interrupts */
424         NIC_PUT(sc, SNCR_ISR, ISR_ALL);
425
426         /* clear tally counters */
427         NIC_PUT(sc, SNCR_CRCT, -1);
428         NIC_PUT(sc, SNCR_FAET, -1);
429         NIC_PUT(sc, SNCR_MPT, -1);
430
431         initialise_tda(sc);
432         initialise_rda(sc);
433         initialise_rra(sc);
434
435         /* enable the chip */
436         NIC_PUT(sc, SNCR_CR, 0);
437         wbflush();
438
439         /* program the CAM */
440         camprogram(sc);
441
442         /* get it to read resource descriptors */
443         NIC_PUT(sc, SNCR_CR, CR_RRRA);
444         wbflush();
445         while ((NIC_GET(sc, SNCR_CR)) & CR_RRRA)
446                 continue;
447
448         /* enable rx */
449         NIC_PUT(sc, SNCR_CR, CR_RXEN);
450         wbflush();
451
452         /* flag interface as "running" */
453         sc->sc_ifp->if_drv_flags |= IFF_DRV_RUNNING;
454         sc->sc_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
455         callout_reset(&sc->sc_timer, hz, sncwatchdog, sc);
456
457         return;
458 }
459
460 /*
461  * close down an interface and free its buffers
462  * Called on final close of device, or if sncinit() fails
463  * part way through.
464  */
465 static int
466 sncstop(struct snc_softc *sc)
467 {
468         struct mtd *mtd;
469
470         SNC_ASSERT_LOCKED(sc);
471
472         /* stick chip in reset */
473         NIC_PUT(sc, SNCR_CR, CR_RST);
474         wbflush();
475
476         /* free all receive buffers (currently static so nothing to do) */
477
478         /* free all pending transmit mbufs */
479         while (sc->mtd_hw != sc->mtd_free) {
480                 mtd = &sc->mtda[sc->mtd_hw];
481                 if (mtd->mtd_mbuf)
482                         m_freem(mtd->mtd_mbuf);
483                 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
484         }
485
486         callout_stop(&sc->sc_timer);
487         sc->sc_tx_timeout = 0;
488         sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
489
490         return (0);
491 }
492
493 /*
494  * Called if any Tx packets remain unsent after 5 seconds,
495  * In all cases we just reset the chip, and any retransmission
496  * will be handled by higher level protocol timeouts.
497  */
498 static void
499 sncwatchdog(void *arg)
500 {
501         struct snc_softc *sc = arg;
502         struct mtd *mtd;
503
504         SNC_ASSERT_LOCKED(sc);
505         if (sc->sc_tx_timeout && --sc->sc_tx_timeout == 0) {
506                 if (sc->mtd_hw != sc->mtd_free) {
507                         /* something still pending for transmit */
508                         mtd = &sc->mtda[sc->mtd_hw];
509                         if (SRO(sc, mtd->mtd_vtxp, TXP_STATUS) == 0)
510                                 log(LOG_ERR, "%s: Tx - timeout\n",
511                                     device_get_nameunit(sc->sc_dev));
512                         else
513                                 log(LOG_ERR, "%s: Tx - lost interrupt\n",
514                                     device_get_nameunit(sc->sc_dev));
515                         sncreset(sc);
516                 }
517         }
518         callout_reset(&sc->sc_timer, hz, sncwatchdog, sc);
519 }
520
521 /*
522  * stuff packet into sonic
523  */
524 static u_int
525 sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next)
526 {
527         struct mtd *mtdp;
528         struct mbuf *m;
529         u_int32_t buff;
530         u_int32_t txp;
531         u_int   len = 0;
532         u_int   totlen = 0;
533
534 #ifdef whyonearthwouldyoudothis
535         if (NIC_GET(sc, SNCR_CR) & CR_TXP)
536                 return (0);
537 #endif
538
539         /* grab the replacement mtd */
540         mtdp = &sc->mtda[sc->mtd_free];
541
542         buff = mtdp->mtd_vbuf;
543         
544         /* this packet goes to mtdnext fill in the TDA */
545         mtdp->mtd_mbuf = m0;
546         txp = mtdp->mtd_vtxp;
547
548         /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */
549         if (sc->mtd_pint == 0) {
550                 sc->mtd_pint = NTDA/2;
551                 SWO(sc, txp, TXP_CONFIG, TCR_PINT);
552         } else {
553                 sc->mtd_pint--;
554                 SWO(sc, txp, TXP_CONFIG, 0);
555         }
556
557         for (m = m0; m; m = m->m_next) {
558                 len = m->m_len;
559                 totlen += len;
560                 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), buff, len);
561                 buff += len;
562         }
563         if (totlen >= TXBSIZE) {
564                 panic("%s: sonicput: packet overflow",
565                       device_get_nameunit(sc->sc_dev));
566         }
567
568         SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO,
569             LOWER(mtdp->mtd_vbuf));
570         SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI,
571             UPPER(mtdp->mtd_vbuf));
572
573         if (totlen < ETHERMIN + sizeof(struct ether_header)) {
574                 int pad = ETHERMIN + sizeof(struct ether_header) - totlen;
575                 (*sc->sc_zerobuf)(sc, mtdp->mtd_vbuf + totlen, pad);
576                 totlen = ETHERMIN + sizeof(struct ether_header);
577         }
578
579         SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE,
580             totlen);
581         SWO(sc, txp, TXP_FRAGCNT, 1);
582         SWO(sc, txp, TXP_PKTSIZE, totlen);
583
584         /* link onto the next mtd that will be used */
585         SWO(sc, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO,
586             LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);
587
588         /*
589          * The previous txp.tlink currently contains a pointer to
590          * our txp | EOL. Want to clear the EOL, so write our
591          * pointer to the previous txp.
592          */
593         SWO(sc, sc->mtda[sc->mtd_prev].mtd_vtxp, sc->mtd_tlinko,
594             LOWER(mtdp->mtd_vtxp));
595
596         /* make sure chip is running */
597         wbflush();
598         NIC_PUT(sc, SNCR_CR, CR_TXP);
599         wbflush();
600
601         /* 5 seconds to watch for failing to transmit */
602         sc->sc_tx_timeout = 5;
603
604         return (totlen);
605 }
606
607 /*
608  * These are called from sonicioctl() when /etc/ifconfig is run to set
609  * the address or switch the i/f on.
610  */
611 /*
612  * CAM support
613  */
614 static void
615 caminitialise(struct snc_softc *sc)
616 {
617         u_int32_t v_cda = sc->v_cda;
618         int     i;
619         int     camoffset;
620
621         for (i = 0; i < MAXCAM; i++) {
622                 camoffset = i * CDA_CAMDESC;
623                 SWO(sc, v_cda, (camoffset + CDA_CAMEP), i);
624                 SWO(sc, v_cda, (camoffset + CDA_CAMAP2), 0);
625                 SWO(sc, v_cda, (camoffset + CDA_CAMAP1), 0);
626                 SWO(sc, v_cda, (camoffset + CDA_CAMAP0), 0);
627         }
628         SWO(sc, v_cda, CDA_ENABLE, 0);
629
630 #ifdef SNCDEBUG
631         if ((sncdebug & SNC_SHOWCAMENT) != 0) {
632                 camdump(sc);
633         }
634 #endif
635 }
636
637 static void
638 camentry(struct snc_softc *sc, int entry, u_char *ea)
639 {
640         u_int32_t v_cda = sc->v_cda;
641         int     camoffset = entry * CDA_CAMDESC;
642
643         SWO(sc, v_cda, camoffset + CDA_CAMEP, entry);
644         SWO(sc, v_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]);
645         SWO(sc, v_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]);
646         SWO(sc, v_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]);
647         SWO(sc, v_cda, CDA_ENABLE, 
648             (SRO(sc, v_cda, CDA_ENABLE) | (1 << entry)));
649 }
650
651 static void
652 camprogram(struct snc_softc *sc)
653 {
654         struct ifmultiaddr      *ifma;
655         struct ifnet *ifp;
656         int     timeout;
657         int     mcount = 0;
658
659         caminitialise(sc);
660
661         ifp = sc->sc_ifp;
662
663         /* Always load our own address first. */
664         camentry (sc, mcount, IF_LLADDR(sc->sc_ifp));
665         mcount++;
666
667         /* Assume we won't need allmulti bit. */
668         ifp->if_flags &= ~IFF_ALLMULTI;
669
670         /* Loop through multicast addresses */
671         if_maddr_rlock(ifp);
672         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
673                 if (ifma->ifma_addr->sa_family != AF_LINK)
674                         continue;
675                 if (mcount == MAXCAM) {
676                          ifp->if_flags |= IFF_ALLMULTI;
677                          break;
678                 }
679
680                 /* program the CAM with the specified entry */
681                 camentry(sc, mcount,
682                          LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
683                 mcount++;
684         }
685         if_maddr_runlock(ifp);
686
687         NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda));
688         NIC_PUT(sc, SNCR_CDC, MAXCAM);
689         NIC_PUT(sc, SNCR_CR, CR_LCAM);
690         wbflush();
691
692         timeout = 10000;
693         while ((NIC_GET(sc, SNCR_CR) & CR_LCAM) && timeout--)
694                 continue;
695         if (timeout == 0) {
696                 /* XXX */
697                 panic("%s: CAM initialisation failed\n",
698                       device_get_nameunit(sc->sc_dev));
699         }
700         timeout = 10000;
701         while (((NIC_GET(sc, SNCR_ISR) & ISR_LCD) == 0) && timeout--)
702                 continue;
703
704         if (NIC_GET(sc, SNCR_ISR) & ISR_LCD)
705                 NIC_PUT(sc, SNCR_ISR, ISR_LCD);
706         else
707                 device_printf(sc->sc_dev,
708                               "CAM initialisation without interrupt\n");
709 }
710
711 #ifdef SNCDEBUG
712 static void
713 camdump(struct snc_softc *sc)
714 {
715         int     i;
716
717         printf("CAM entries:\n");
718         NIC_PUT(sc, SNCR_CR, CR_RST);
719         wbflush();
720
721         for (i = 0; i < 16; i++) {
722                 u_short  ap2, ap1, ap0;
723                 NIC_PUT(sc, SNCR_CEP, i);
724                 wbflush();
725                 ap2 = NIC_GET(sc, SNCR_CAP2);
726                 ap1 = NIC_GET(sc, SNCR_CAP1);
727                 ap0 = NIC_GET(sc, SNCR_CAP0);
728                 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
729         }
730         printf("CAM enable 0x%x\n", NIC_GET(sc, SNCR_CEP));
731
732         NIC_PUT(sc, SNCR_CR, 0);
733         wbflush();
734 }
735 #endif
736
737 static void
738 initialise_tda(struct snc_softc *sc)
739 {
740         struct mtd *mtd;
741         int     i;
742
743         for (i = 0; i < NTDA; i++) {
744                 mtd = &sc->mtda[i];
745                 mtd->mtd_mbuf = 0;
746         }
747
748         sc->mtd_hw = 0;
749         sc->mtd_prev = NTDA - 1;
750         sc->mtd_free = 0;
751         sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
752         sc->mtd_pint = NTDA/2;
753
754         NIC_PUT(sc, SNCR_UTDA, UPPER(sc->mtda[0].mtd_vtxp));
755         NIC_PUT(sc, SNCR_CTDA, LOWER(sc->mtda[0].mtd_vtxp));
756 }
757
758 static void
759 initialise_rda(struct snc_softc *sc)
760 {
761         int             i;
762         u_int32_t       vv_rda = 0;
763         u_int32_t       v_rda = 0;
764
765         /* link the RDA's together into a circular list */
766         for (i = 0; i < (sc->sc_nrda - 1); i++) {
767                 v_rda = sc->v_rda + (i * RXPKT_SIZE(sc));
768                 vv_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc));
769                 SWO(sc, v_rda, RXPKT_RLINK, LOWER(vv_rda));
770                 SWO(sc, v_rda, RXPKT_INUSE, 1);
771         }
772         v_rda = sc->v_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc));
773         SWO(sc, v_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL);
774         SWO(sc, v_rda, RXPKT_INUSE, 1);
775
776         /* mark end of receive descriptor list */
777         sc->sc_rdamark = sc->sc_nrda - 1;
778
779         sc->sc_rxmark = 0;
780
781         NIC_PUT(sc, SNCR_URDA, UPPER(sc->v_rda));
782         NIC_PUT(sc, SNCR_CRDA, LOWER(sc->v_rda));
783         wbflush();
784 }
785
786 static void
787 initialise_rra(struct snc_softc *sc)
788 {
789         int     i;
790         u_int   v;
791         int     bitmode = sc->bitmode;
792
793         if (bitmode)
794                 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 2);
795         else
796                 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 1);
797
798         NIC_PUT(sc, SNCR_URRA, UPPER(sc->v_rra[0]));
799         NIC_PUT(sc, SNCR_RSA, LOWER(sc->v_rra[0]));
800         /* rea must point just past the end of the rra space */
801         NIC_PUT(sc, SNCR_REA, LOWER(sc->v_rea));
802         NIC_PUT(sc, SNCR_RRP, LOWER(sc->v_rra[0]));
803         NIC_PUT(sc, SNCR_RSC, 0);
804
805         /* fill up SOME of the rra with buffers */
806         for (i = 0; i < NRBA; i++) {
807                 v = SONIC_GETDMA(sc->rbuf[i]);
808                 SWO(sc, sc->v_rra[i], RXRSRC_PTRHI, UPPER(v));
809                 SWO(sc, sc->v_rra[i], RXRSRC_PTRLO, LOWER(v));
810                 SWO(sc, sc->v_rra[i], RXRSRC_WCHI, UPPER(PAGE_SIZE/2));
811                 SWO(sc, sc->v_rra[i], RXRSRC_WCLO, LOWER(PAGE_SIZE/2));
812         }
813         sc->sc_rramark = NRBA;
814         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[sc->sc_rramark]));
815         wbflush();
816 }
817
818 void
819 sncintr(void *arg)
820 {
821         struct snc_softc *sc = (struct snc_softc *)arg;
822         int     isr;
823
824         if (sc->sc_enabled == 0)
825                 return;
826
827         SNC_LOCK(sc);
828         while ((isr = (NIC_GET(sc, SNCR_ISR) & ISR_ALL)) != 0) {
829                 /* scrub the interrupts that we are going to service */
830                 NIC_PUT(sc, SNCR_ISR, isr);
831                 wbflush();
832
833                 if (isr & (ISR_BR | ISR_LCD | ISR_TC))
834                         device_printf(sc->sc_dev,
835                                       "unexpected interrupt status 0x%x\n",
836                                       isr);
837
838                 if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT))
839                         sonictxint(sc);
840
841                 if (isr & ISR_PKTRX)
842                         sonicrxint(sc);
843
844                 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
845                         if (isr & ISR_HBL)
846                                 /*
847                                  * The repeater is not providing a heartbeat.
848                                  * In itself this isn't harmful, lots of the
849                                  * cheap repeater hubs don't supply a heartbeat.
850                                  * So ignore the lack of heartbeat. Its only
851                                  * if we can't detect a carrier that we have a
852                                  * problem.
853                                  */
854                                 ;
855                         if (isr & ISR_RDE)
856                                 device_printf(sc->sc_dev, 
857                                         "receive descriptors exhausted\n");
858                         if (isr & ISR_RBE)
859                                 device_printf(sc->sc_dev, 
860                                         "receive buffers exhausted\n");
861                         if (isr & ISR_RBAE)
862                                 device_printf(sc->sc_dev, 
863                                         "receive buffer area exhausted\n");
864                         if (isr & ISR_RFO)
865                                 device_printf(sc->sc_dev, 
866                                         "receive FIFO overrun\n");
867                 }
868                 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
869 #ifdef notdef
870                         if (isr & ISR_CRC)
871                                 sc->sc_crctally++;
872                         if (isr & ISR_FAE)
873                                 sc->sc_faetally++;
874                         if (isr & ISR_MP)
875                                 sc->sc_mptally++;
876 #endif
877                 }
878                 sncstart_locked(sc->sc_ifp);
879         }
880         SNC_UNLOCK(sc);
881         return;
882 }
883
884 /*
885  * Transmit interrupt routine
886  */
887 static void
888 sonictxint(struct snc_softc *sc)
889 {
890         struct mtd      *mtd;
891         u_int32_t       txp;
892         unsigned short  txp_status;
893         int             mtd_hw;
894         struct ifnet    *ifp = sc->sc_ifp;
895
896         mtd_hw = sc->mtd_hw;
897
898         if (mtd_hw == sc->mtd_free)
899                 return;
900
901         while (mtd_hw != sc->mtd_free) {
902                 mtd = &sc->mtda[mtd_hw];
903
904                 txp = mtd->mtd_vtxp;
905
906                 if (SRO(sc, txp, TXP_STATUS) == 0) {
907                         break; /* it hasn't really gone yet */
908                 }
909
910 #ifdef SNCDEBUG
911                 if ((sncdebug & SNC_SHOWTXHDR) != 0)
912                 {
913                         struct ether_header eh;
914
915                         (*sc->sc_copyfrombuf)(sc, &eh, mtd->mtd_vbuf, sizeof(eh));
916                         device_printf(sc->sc_dev,
917                             "xmit status=0x%x len=%d type=0x%x from %6D",
918                             SRO(sc, txp, TXP_STATUS),
919                             SRO(sc, txp, TXP_PKTSIZE),
920                             htons(eh.ether_type),
921                             eh.ether_shost, ":");
922                         printf(" (to %6D)\n", eh.ether_dhost, ":");
923                 }
924 #endif /* SNCDEBUG */
925
926                 sc->sc_tx_timeout = 0;
927                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
928
929                 if (mtd->mtd_mbuf != 0) {
930                         m_freem(mtd->mtd_mbuf);
931                         mtd->mtd_mbuf = 0;
932                 }
933                 if (++mtd_hw == NTDA) mtd_hw = 0;
934
935                 txp_status = SRO(sc, txp, TXP_STATUS);
936
937                 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 :
938                         ((txp_status & TCR_NC) >> 12);
939
940                 if ((txp_status & TCR_PTX) == 0) {
941                         ifp->if_oerrors++;
942                         device_printf(sc->sc_dev, "Tx packet status=0x%x\n",
943                                       txp_status);
944                         
945                         /* XXX - DG This looks bogus */
946                         if (mtd_hw != sc->mtd_free) {
947                                 printf("resubmitting remaining packets\n");
948                                 mtd = &sc->mtda[mtd_hw];
949                                 NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp));
950                                 NIC_PUT(sc, SNCR_CR, CR_TXP);
951                                 wbflush();
952                                 break;
953                         }
954                 }
955         }
956
957         sc->mtd_hw = mtd_hw;
958         return;
959 }
960
961 /*
962  * Receive interrupt routine
963  */
964 static void
965 sonicrxint(struct snc_softc *sc)
966 {
967         u_int32_t rda;
968         int     orra;
969         int     len;
970         int     rramark;
971         int     rdamark;
972         u_int16_t rxpkt_ptr;
973
974         rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
975
976         while (SRO(sc, rda, RXPKT_INUSE) == 0) {
977                 u_int status = SRO(sc, rda, RXPKT_STATUS);
978
979                 orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK;
980                 rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO);
981                 /*
982                  * Do not trunc ether_header length.
983                  * Our sonic_read() and sonic_get() require it.
984                  */
985                 len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE;
986                 if (status & RCR_PRX) {
987                         /* XXX: Does PAGE_MASK require? */
988                         u_int32_t pkt =
989                             sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PAGE_MASK);
990                         if (sonic_read(sc, pkt, len))
991                                 sc->sc_ifp->if_ipackets++;
992                         else
993                                 sc->sc_ifp->if_ierrors++;
994                 } else
995                         sc->sc_ifp->if_ierrors++;
996
997                 /*
998                  * give receive buffer area back to chip.
999                  *
1000                  * If this was the last packet in the RRA, give the RRA to
1001                  * the chip again.
1002                  * If sonic read didnt copy it out then we would have to
1003                  * wait !!
1004                  * (dont bother add it back in again straight away)
1005                  *
1006                  * Really, we're doing v_rra[rramark] = v_rra[orra] but
1007                  * we have to use the macros because SONIC might be in
1008                  * 16 or 32 bit mode.
1009                  */
1010                 if (status & RCR_LPKT) {
1011                         u_int32_t tmp1, tmp2;
1012
1013                         rramark = sc->sc_rramark;
1014                         tmp1 = sc->v_rra[rramark];
1015                         tmp2 = sc->v_rra[orra];
1016                         SWO(sc, tmp1, RXRSRC_PTRLO,
1017                                 SRO(sc, tmp2, RXRSRC_PTRLO));
1018                         SWO(sc, tmp1, RXRSRC_PTRHI,
1019                                 SRO(sc, tmp2, RXRSRC_PTRHI));
1020                         SWO(sc, tmp1, RXRSRC_WCLO,
1021                                 SRO(sc, tmp2, RXRSRC_WCLO));
1022                         SWO(sc, tmp1, RXRSRC_WCHI,
1023                                 SRO(sc, tmp2, RXRSRC_WCHI));
1024
1025                         /* zap old rra for fun */
1026                         SWO(sc, tmp2, RXRSRC_WCHI, 0);
1027                         SWO(sc, tmp2, RXRSRC_WCLO, 0);
1028
1029                         sc->sc_rramark = (++rramark) & RRAMASK;
1030                         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark]));
1031                         wbflush();
1032                 }
1033
1034                 /*
1035                  * give receive descriptor back to chip simple
1036                  * list is circular
1037                  */
1038                 rdamark = sc->sc_rdamark;
1039                 SWO(sc, rda, RXPKT_INUSE, 1);
1040                 SWO(sc, rda, RXPKT_RLINK,
1041                         SRO(sc, rda, RXPKT_RLINK) | EOL);
1042                 SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK,
1043                         SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))),
1044                         RXPKT_RLINK) & ~EOL);
1045                 sc->sc_rdamark = sc->sc_rxmark;
1046
1047                 if (++sc->sc_rxmark >= sc->sc_nrda)
1048                         sc->sc_rxmark = 0;
1049                 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
1050         }
1051 }
1052
1053 /*
1054  * sonic_read -- pull packet off interface and forward to
1055  * appropriate protocol handler
1056  */
1057 static int
1058 sonic_read(struct snc_softc *sc, u_int32_t pkt, int len)
1059 {
1060         struct ifnet *ifp = sc->sc_ifp;
1061         struct ether_header *et;
1062         struct mbuf *m;
1063
1064         if (len <= sizeof(struct ether_header) ||
1065             len > ETHERMTU + sizeof(struct ether_header)) {
1066                 device_printf(sc->sc_dev,
1067                               "invalid packet length %d bytes\n", len);
1068                 return (0);
1069         }
1070
1071         /* Pull packet off interface. */
1072         m = sonic_get(sc, pkt, len);
1073         if (m == 0) {
1074                 return (0);
1075         }
1076
1077         /* We assume that the header fit entirely in one mbuf. */
1078         et = mtod(m, struct ether_header *);
1079
1080 #ifdef SNCDEBUG
1081         if ((sncdebug & SNC_SHOWRXHDR) != 0)
1082         {
1083                 device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D",
1084                     pkt, len, htons(et->ether_type),
1085                     et->ether_shost, ":");
1086                 printf(" (to %6D)\n", et->ether_dhost, ":");
1087         }
1088 #endif /* SNCDEBUG */
1089
1090         /* Pass the packet up. */
1091         SNC_UNLOCK(sc);
1092         (*ifp->if_input)(ifp, m);
1093         SNC_LOCK(sc);
1094         return (1);
1095 }
1096
1097
1098 /*
1099  * munge the received packet into an mbuf chain
1100  */
1101 static struct mbuf *
1102 sonic_get(struct snc_softc *sc, u_int32_t pkt, int datalen)
1103 {
1104         struct  mbuf *m, *top, **mp;
1105         int     len;
1106         /*
1107          * Do not trunc ether_header length.
1108          * Our sonic_read() and sonic_get() require it.
1109          */
1110
1111         MGETHDR(m, M_NOWAIT, MT_DATA);
1112         if (m == 0)
1113                 return (0);
1114         m->m_pkthdr.rcvif = sc->sc_ifp;
1115         m->m_pkthdr.len = datalen;
1116         len = MHLEN;
1117         top = 0;
1118         mp = &top;
1119
1120         while (datalen > 0) {
1121                 if (top) {
1122                         MGET(m, M_NOWAIT, MT_DATA);
1123                         if (m == 0) {
1124                                 m_freem(top);
1125                                 return (0);
1126                         }
1127                         len = MLEN;
1128                 }
1129                 if (datalen >= MINCLSIZE) {
1130                         MCLGET(m, M_NOWAIT);
1131                         if ((m->m_flags & M_EXT) == 0) {
1132                                 if (top) m_freem(top);
1133                                 return (0);
1134                         }
1135                         len = MCLBYTES;
1136                 }
1137 #if 0
1138                 /* XXX: Require? */
1139                 if (!top) {
1140                         register int pad =
1141                             ALIGN(sizeof(struct ether_header)) -
1142                                 sizeof(struct ether_header);
1143                         m->m_data += pad;
1144                         len -= pad;
1145                 }
1146 #endif
1147                 m->m_len = len = min(datalen, len);
1148
1149                 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), pkt, len);
1150                 pkt += len;
1151                 datalen -= len;
1152                 *mp = m;
1153                 mp = &m->m_next;
1154         }
1155
1156         return (top);
1157 }
1158 /*
1159  * Enable power on the interface.
1160  */
1161 int
1162 snc_enable(struct snc_softc *sc)
1163 {
1164
1165 #ifdef  SNCDEBUG
1166         device_printf(sc->sc_dev, "snc_enable()\n");
1167 #endif  /* SNCDEBUG */
1168
1169         if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
1170                 if ((*sc->sc_enable)(sc) != 0) {
1171                         device_printf(sc->sc_dev, "device enable failed\n");
1172                         return (EIO);
1173                 }
1174         }
1175
1176         sc->sc_enabled = 1;
1177         return (0);
1178 }
1179
1180 /*
1181  * Disable power on the interface.
1182  */
1183 void
1184 snc_disable(struct snc_softc *sc)
1185 {
1186
1187 #ifdef  SNCDEBUG
1188         device_printf(sc->sc_dev, "snc_disable()\n");
1189 #endif  /* SNCDEBUG */
1190
1191         if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
1192                 (*sc->sc_disable)(sc);
1193                 sc->sc_enabled = 0;
1194         }
1195 }
1196
1197