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