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