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