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