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