]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/dev/snc/dp83932.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / dev / snc / dp83932.c
1 /*      $FreeBSD$       */
2 /*      $NecBSD: dp83932.c,v 1.5 1999/07/29 05:08:44 kmatsuda Exp $     */
3 /*      $NetBSD: if_snc.c,v 1.18 1998/04/25 21:27:40 scottr Exp $       */
4
5 /*-
6  * Copyright (c) 1997, 1998, 1999
7  *      Kouichi Matsuda.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Kouichi Matsuda for
20  *      NetBSD/pc98.
21  * 4. The name of the author may not be used to endorse or promote products
22  *    derived from this software without specific prior written permission
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 /*
37  * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
38  */
39
40 /*
41  * Modified for NetBSD/pc98 1.2G from NetBSD/mac68k 1.2G by Kouichi Matsuda.
42  * Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and
43  * PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as
44  * Ethernet Controller and National Semiconductor NS46C46 as
45  * (64 * 16 bits) Microwire Serial EEPROM.
46  */
47
48 /*-
49  * National Semiconductor  DP8393X SONIC Driver
50  * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
51  * You may use, copy, and modify this program so long as you retain the
52  * copyright line.
53  *
54  * This driver has been substantially modified since Algorithmics donated
55  * it.
56  *
57  *   Denton Gentry <denny1@home.com>
58  * and also
59  *   Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>
60  * did the work to get this running on the Macintosh.
61  */
62
63 #include "opt_inet.h"
64
65 #include <sys/param.h>
66 #include <sys/kernel.h>
67 #include <sys/systm.h>
68 #include <sys/sockio.h>
69 #include <sys/mbuf.h>
70 #include <sys/protosw.h>
71 #include <sys/socket.h>
72 #include <sys/syslog.h>
73 #include <sys/errno.h>
74
75 #include <net/ethernet.h>
76 #include <net/if.h>
77 #include <net/if_arp.h>
78 #include <net/if_dl.h>
79 #include <net/if_media.h>
80 #include <net/if_types.h>
81
82 #include <net/bpf.h>
83
84 #include <sys/bus.h>
85 #include <machine/bus.h>
86 #include <dev/snc/dp83932reg.h>
87 #include <dev/snc/dp83932var.h>
88
89 static void     sncwatchdog(void *);
90 static void     sncinit(void *);
91 static void     sncinit_locked(struct snc_softc *);
92 static int      sncstop(struct snc_softc *sc);
93 static int      sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
94 static void     sncstart(struct ifnet *ifp);
95 static void     sncstart_locked(struct ifnet *ifp);
96 static void     sncreset(struct snc_softc *sc);
97
98 static void     caminitialise(struct snc_softc *);
99 static void     camentry(struct snc_softc *, int, u_char *ea);
100 static void     camprogram(struct snc_softc *);
101 static void     initialise_tda(struct snc_softc *);
102 static void     initialise_rda(struct snc_softc *);
103 static void     initialise_rra(struct snc_softc *);
104 #ifdef SNCDEBUG
105 static void     camdump(struct snc_softc *sc);
106 #endif
107
108 static void     sonictxint(struct snc_softc *);
109 static void     sonicrxint(struct snc_softc *);
110
111 static u_int    sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next);
112 static int      sonic_read(struct snc_softc *, u_int32_t, int);
113 static struct mbuf *sonic_get(struct snc_softc *, u_int32_t, int);
114
115 int     snc_enable(struct snc_softc *);
116 void    snc_disable(struct snc_softc *);
117
118 int     snc_mediachange(struct ifnet *);
119 void    snc_mediastatus(struct ifnet *, struct ifmediareq *);
120
121 #undef assert
122 #undef _assert
123
124 #ifdef NDEBUG
125 #define assert(e)       ((void)0)
126 #define _assert(e)      ((void)0)
127 #else
128 #define _assert(e)      assert(e)
129 #ifdef __STDC__
130 #define assert(e)       ((e) ? (void)0 : __assert("snc ", __FILE__, __LINE__, #e))
131 #else   /* PCC */
132 #define assert(e)       ((e) ? (void)0 : __assert("snc "__FILE__, __LINE__, "e"))
133 #endif
134 #endif
135
136 #ifdef  SNCDEBUG
137 #define SNC_SHOWTXHDR   0x01    /* show tx ether_header */
138 #define SNC_SHOWRXHDR   0x02    /* show rx ether_header */
139 #define SNC_SHOWCAMENT  0x04    /* show CAM entry */
140 #endif  /* SNCDEBUG */
141 int sncdebug = 0;
142
143
144 int
145 sncconfig(struct snc_softc *sc, int *media, int nmedia, int defmedia,
146     u_int8_t *myea)
147 {
148         struct ifnet *ifp;
149         int i;
150
151 #ifdef SNCDEBUG
152         if ((sncdebug & SNC_SHOWCAMENT) != 0) {
153                 camdump(sc);
154         }
155 #endif
156
157         ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
158         if (ifp == NULL) {
159                 device_printf(sc->sc_dev, "can not if_alloc()\n");
160                 return (ENOMEM);
161         }
162
163 #ifdef SNCDEBUG
164         device_printf(sc->sc_dev,
165                       "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n",
166                       sc->v_rra[0], sc->v_cda,
167                       sc->v_rda, sc->mtda[0].mtd_vtxp);
168 #endif
169
170         ifp->if_softc = sc;
171         if_initname(ifp, device_get_name(sc->sc_dev),
172             device_get_unit(sc->sc_dev));
173         ifp->if_ioctl = sncioctl;
174         ifp->if_start = sncstart;
175         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
176         ifp->if_init = sncinit;
177         ifp->if_mtu = ETHERMTU;
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         ifp->if_opackets++;             /* # 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                 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 :
939                         ((txp_status & TCR_NC) >> 12);
940
941                 if ((txp_status & TCR_PTX) == 0) {
942                         ifp->if_oerrors++;
943                         device_printf(sc->sc_dev, "Tx packet status=0x%x\n",
944                                       txp_status);
945                         
946                         /* XXX - DG This looks bogus */
947                         if (mtd_hw != sc->mtd_free) {
948                                 printf("resubmitting remaining packets\n");
949                                 mtd = &sc->mtda[mtd_hw];
950                                 NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp));
951                                 NIC_PUT(sc, SNCR_CR, CR_TXP);
952                                 wbflush();
953                                 break;
954                         }
955                 }
956         }
957
958         sc->mtd_hw = mtd_hw;
959         return;
960 }
961
962 /*
963  * Receive interrupt routine
964  */
965 static void
966 sonicrxint(struct snc_softc *sc)
967 {
968         u_int32_t rda;
969         int     orra;
970         int     len;
971         int     rramark;
972         int     rdamark;
973         u_int16_t rxpkt_ptr;
974
975         rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
976
977         while (SRO(sc, rda, RXPKT_INUSE) == 0) {
978                 u_int status = SRO(sc, rda, RXPKT_STATUS);
979
980                 orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK;
981                 rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO);
982                 /*
983                  * Do not trunc ether_header length.
984                  * Our sonic_read() and sonic_get() require it.
985                  */
986                 len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE;
987                 if (status & RCR_PRX) {
988                         /* XXX: Does PAGE_MASK require? */
989                         u_int32_t pkt =
990                             sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PAGE_MASK);
991                         if (sonic_read(sc, pkt, len))
992                                 sc->sc_ifp->if_ipackets++;
993                         else
994                                 sc->sc_ifp->if_ierrors++;
995                 } else
996                         sc->sc_ifp->if_ierrors++;
997
998                 /*
999                  * give receive buffer area back to chip.
1000                  *
1001                  * If this was the last packet in the RRA, give the RRA to
1002                  * the chip again.
1003                  * If sonic read didnt copy it out then we would have to
1004                  * wait !!
1005                  * (dont bother add it back in again straight away)
1006                  *
1007                  * Really, we're doing v_rra[rramark] = v_rra[orra] but
1008                  * we have to use the macros because SONIC might be in
1009                  * 16 or 32 bit mode.
1010                  */
1011                 if (status & RCR_LPKT) {
1012                         u_int32_t tmp1, tmp2;
1013
1014                         rramark = sc->sc_rramark;
1015                         tmp1 = sc->v_rra[rramark];
1016                         tmp2 = sc->v_rra[orra];
1017                         SWO(sc, tmp1, RXRSRC_PTRLO,
1018                                 SRO(sc, tmp2, RXRSRC_PTRLO));
1019                         SWO(sc, tmp1, RXRSRC_PTRHI,
1020                                 SRO(sc, tmp2, RXRSRC_PTRHI));
1021                         SWO(sc, tmp1, RXRSRC_WCLO,
1022                                 SRO(sc, tmp2, RXRSRC_WCLO));
1023                         SWO(sc, tmp1, RXRSRC_WCHI,
1024                                 SRO(sc, tmp2, RXRSRC_WCHI));
1025
1026                         /* zap old rra for fun */
1027                         SWO(sc, tmp2, RXRSRC_WCHI, 0);
1028                         SWO(sc, tmp2, RXRSRC_WCLO, 0);
1029
1030                         sc->sc_rramark = (++rramark) & RRAMASK;
1031                         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark]));
1032                         wbflush();
1033                 }
1034
1035                 /*
1036                  * give receive descriptor back to chip simple
1037                  * list is circular
1038                  */
1039                 rdamark = sc->sc_rdamark;
1040                 SWO(sc, rda, RXPKT_INUSE, 1);
1041                 SWO(sc, rda, RXPKT_RLINK,
1042                         SRO(sc, rda, RXPKT_RLINK) | EOL);
1043                 SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK,
1044                         SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))),
1045                         RXPKT_RLINK) & ~EOL);
1046                 sc->sc_rdamark = sc->sc_rxmark;
1047
1048                 if (++sc->sc_rxmark >= sc->sc_nrda)
1049                         sc->sc_rxmark = 0;
1050                 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
1051         }
1052 }
1053
1054 /*
1055  * sonic_read -- pull packet off interface and forward to
1056  * appropriate protocol handler
1057  */
1058 static int
1059 sonic_read(struct snc_softc *sc, u_int32_t pkt, int len)
1060 {
1061         struct ifnet *ifp = sc->sc_ifp;
1062         struct ether_header *et;
1063         struct mbuf *m;
1064
1065         if (len <= sizeof(struct ether_header) ||
1066             len > ETHERMTU + sizeof(struct ether_header)) {
1067                 device_printf(sc->sc_dev,
1068                               "invalid packet length %d bytes\n", len);
1069                 return (0);
1070         }
1071
1072         /* Pull packet off interface. */
1073         m = sonic_get(sc, pkt, len);
1074         if (m == 0) {
1075                 return (0);
1076         }
1077
1078         /* We assume that the header fit entirely in one mbuf. */
1079         et = mtod(m, struct ether_header *);
1080
1081 #ifdef SNCDEBUG
1082         if ((sncdebug & SNC_SHOWRXHDR) != 0)
1083         {
1084                 device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D",
1085                     pkt, len, htons(et->ether_type),
1086                     et->ether_shost, ":");
1087                 printf(" (to %6D)\n", et->ether_dhost, ":");
1088         }
1089 #endif /* SNCDEBUG */
1090
1091         /* Pass the packet up. */
1092         SNC_UNLOCK(sc);
1093         (*ifp->if_input)(ifp, m);
1094         SNC_LOCK(sc);
1095         return (1);
1096 }
1097
1098
1099 /*
1100  * munge the received packet into an mbuf chain
1101  */
1102 static struct mbuf *
1103 sonic_get(struct snc_softc *sc, u_int32_t pkt, int datalen)
1104 {
1105         struct  mbuf *m, *top, **mp;
1106         int     len;
1107         /*
1108          * Do not trunc ether_header length.
1109          * Our sonic_read() and sonic_get() require it.
1110          */
1111
1112         MGETHDR(m, M_NOWAIT, MT_DATA);
1113         if (m == 0)
1114                 return (0);
1115         m->m_pkthdr.rcvif = sc->sc_ifp;
1116         m->m_pkthdr.len = datalen;
1117         len = MHLEN;
1118         top = 0;
1119         mp = &top;
1120
1121         while (datalen > 0) {
1122                 if (top) {
1123                         MGET(m, M_NOWAIT, MT_DATA);
1124                         if (m == 0) {
1125                                 m_freem(top);
1126                                 return (0);
1127                         }
1128                         len = MLEN;
1129                 }
1130                 if (datalen >= MINCLSIZE) {
1131                         MCLGET(m, M_NOWAIT);
1132                         if ((m->m_flags & M_EXT) == 0) {
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