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