1/*	$FreeBSD$	*/
2/*	$NecBSD: dp83932.c,v 1.5 1999/07/29 05:08:44 kmatsuda Exp $	*/
3/*	$NetBSD: if_snc.c,v 1.18 1998/04/25 21:27:40 scottr Exp $	*/
4
5/*-
6 * Copyright (c) 1997, 1998, 1999
7 *	Kouichi Matsuda.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by Kouichi Matsuda for
20 *      NetBSD/pc98.
21 * 4. The name of the author may not be used to endorse or promote products
22 *    derived from this software without specific prior written permission
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/*
37 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
38 */
39
40/*
41 * Modified for NetBSD/pc98 1.2G from NetBSD/mac68k 1.2G by Kouichi Matsuda.
42 * Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and
43 * PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as
44 * Ethernet Controller and National Semiconductor NS46C46 as
45 * (64 * 16 bits) Microwire Serial EEPROM.
46 */
47
48/*-
49 * National Semiconductor  DP8393X SONIC Driver
50 * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
51 * You may use, copy, and modify this program so long as you retain the
52 * copyright line.
53 *
54 * This driver has been substantially modified since Algorithmics donated
55 * it.
56 *
57 *   Denton Gentry <denny1@home.com>
58 * and also
59 *   Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>
60 * did the work to get this running on the Macintosh.
61 */
62
63#include "opt_inet.h"
64
65#include <sys/param.h>
66#include <sys/kernel.h>
67#include <sys/systm.h>
68#include <sys/sockio.h>
69#include <sys/mbuf.h>
70#include <sys/protosw.h>
71#include <sys/socket.h>
72#include <sys/syslog.h>
73#include <sys/errno.h>
74
75#include <net/ethernet.h>
76#include <net/if.h>
77#include <net/if_var.h>
78#include <net/if_arp.h>
79#include <net/if_dl.h>
80#include <net/if_media.h>
81#include <net/if_types.h>
82
83#include <net/bpf.h>
84
85#include <sys/bus.h>
86#include <machine/bus.h>
87#include <dev/snc/dp83932reg.h>
88#include <dev/snc/dp83932var.h>
89
90static void	sncwatchdog(void *);
91static void	sncinit(void *);
92static void	sncinit_locked(struct snc_softc *);
93static int	sncstop(struct snc_softc *sc);
94static int	sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
95static void	sncstart(struct ifnet *ifp);
96static void	sncstart_locked(struct ifnet *ifp);
97static void	sncreset(struct snc_softc *sc);
98
99static void	caminitialise(struct snc_softc *);
100static void	camentry(struct snc_softc *, int, u_char *ea);
101static void	camprogram(struct snc_softc *);
102static void	initialise_tda(struct snc_softc *);
103static void	initialise_rda(struct snc_softc *);
104static void	initialise_rra(struct snc_softc *);
105#ifdef SNCDEBUG
106static void	camdump(struct snc_softc *sc);
107#endif
108
109static void	sonictxint(struct snc_softc *);
110static void	sonicrxint(struct snc_softc *);
111
112static u_int	sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next);
113static int	sonic_read(struct snc_softc *, u_int32_t, int);
114static struct mbuf *sonic_get(struct snc_softc *, u_int32_t, int);
115
116int	snc_enable(struct snc_softc *);
117void	snc_disable(struct snc_softc *);
118
119int	snc_mediachange(struct ifnet *);
120void	snc_mediastatus(struct ifnet *, struct ifmediareq *);
121
122#undef assert
123#undef _assert
124
125#ifdef NDEBUG
126#define	assert(e)	((void)0)
127#define	_assert(e)	((void)0)
128#else
129#define	_assert(e)	assert(e)
130#ifdef __STDC__
131#define	assert(e)	((e) ? (void)0 : __assert("snc ", __FILE__, __LINE__, #e))
132#else	/* PCC */
133#define	assert(e)	((e) ? (void)0 : __assert("snc "__FILE__, __LINE__, "e"))
134#endif
135#endif
136
137#ifdef	SNCDEBUG
138#define	SNC_SHOWTXHDR	0x01	/* show tx ether_header */
139#define	SNC_SHOWRXHDR	0x02	/* show rx ether_header */
140#define	SNC_SHOWCAMENT	0x04	/* show CAM entry */
141#endif	/* SNCDEBUG */
142int sncdebug = 0;
143
144
145int
146sncconfig(struct snc_softc *sc, int *media, int nmedia, int defmedia,
147    u_int8_t *myea)
148{
149	struct ifnet *ifp;
150	int i;
151
152#ifdef SNCDEBUG
153	if ((sncdebug & SNC_SHOWCAMENT) != 0) {
154		camdump(sc);
155	}
156#endif
157
158	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
159	if (ifp == NULL) {
160		device_printf(sc->sc_dev, "can not if_alloc()\n");
161		return (ENOMEM);
162	}
163
164#ifdef SNCDEBUG
165	device_printf(sc->sc_dev,
166		      "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n",
167		      sc->v_rra[0], sc->v_cda,
168		      sc->v_rda, sc->mtda[0].mtd_vtxp);
169#endif
170
171	ifp->if_softc = sc;
172	if_initname(ifp, device_get_name(sc->sc_dev),
173	    device_get_unit(sc->sc_dev));
174	ifp->if_ioctl = sncioctl;
175	ifp->if_start = sncstart;
176	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
177        ifp->if_init = sncinit;
178	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
179
180	/* Initialize media goo. */
181	ifmedia_init(&sc->sc_media, 0, snc_mediachange,
182	    snc_mediastatus);
183	if (media != NULL) {
184		for (i = 0; i < nmedia; i++)
185			ifmedia_add(&sc->sc_media, media[i], 0, NULL);
186		ifmedia_set(&sc->sc_media, defmedia);
187	} else {
188		ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
189		ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
190	}
191
192	ether_ifattach(ifp, myea);
193	return (0);
194}
195
196void
197sncshutdown(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 */
208int
209snc_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 */
226void
227snc_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
245static int
246sncioctl(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 */
311static void
312sncstart(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
321static void
322sncstart_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
332outloop:
333	/* Check for room in the xmit buffer. */
334	if ((mtd_next = (sc->mtd_free + 1)) == NTDA)
335		mtd_next = 0;
336
337	if (mtd_next == sc->mtd_hw) {
338		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
339		return;
340	}
341
342	IF_DEQUEUE(&ifp->if_snd, m);
343	if (m == 0)
344		return;
345
346	/* We need the header for m_pkthdr.len. */
347	M_ASSERTPKTHDR(m);
348
349	/*
350	 * If there is nothing in the o/p queue, and there is room in
351	 * the Tx ring, then send the packet directly.  Otherwise append
352	 * it to the o/p queue.
353	 */
354	if ((sonicput(sc, m, mtd_next)) == 0) {
355		IF_PREPEND(&ifp->if_snd, m);
356		return;
357	}
358
359	/*
360	 * If bpf is listening on this interface, let it see the packet
361	 * before we commit it to the wire, but only if we are really
362	 * committed to send it.
363	 *
364	 * XXX: Locking must protect m against premature m_freem() in
365	 * sonictxint().
366	 */
367	BPF_MTAP(ifp, m);
368
369	sc->mtd_prev = sc->mtd_free;
370	sc->mtd_free = mtd_next;
371
372	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);		/* # of pkts */
373
374	/* Jump back for possibly more punishment. */
375	goto outloop;
376}
377
378/*
379 * reset and restart the SONIC.  Called in case of fatal
380 * hardware/software errors.
381 */
382static void
383sncreset(struct snc_softc *sc)
384{
385	sncstop(sc);
386	sncinit_locked(sc);
387}
388
389static void
390sncinit(void *xsc)
391{
392	struct snc_softc *sc = xsc;
393
394	SNC_LOCK(sc);
395	sncinit_locked(sc);
396	SNC_UNLOCK(sc);
397}
398
399static void
400sncinit_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 accessible 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 */
466static int
467sncstop(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 */
499static void
500sncwatchdog(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 */
525static u_int
526sonicput(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 */
615static void
616caminitialise(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
638static void
639camentry(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
652static void
653camprogram(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
713static void
714camdump(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
738static void
739initialise_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
759static void
760initialise_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
787static void
788initialise_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
819void
820sncintr(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 */
888static void
889sonictxint(struct snc_softc *sc)
890{
891	struct mtd	*mtd;
892	u_int32_t	txp;
893	unsigned short	txp_status;
894	int		mtd_hw;
895	struct ifnet	*ifp = sc->sc_ifp;
896
897	mtd_hw = sc->mtd_hw;
898
899	if (mtd_hw == sc->mtd_free)
900		return;
901
902	while (mtd_hw != sc->mtd_free) {
903		mtd = &sc->mtda[mtd_hw];
904
905		txp = mtd->mtd_vtxp;
906
907		if (SRO(sc, txp, TXP_STATUS) == 0) {
908			break; /* it hasn't really gone yet */
909		}
910
911#ifdef SNCDEBUG
912		if ((sncdebug & SNC_SHOWTXHDR) != 0)
913		{
914			struct ether_header eh;
915
916			(*sc->sc_copyfrombuf)(sc, &eh, mtd->mtd_vbuf, sizeof(eh));
917			device_printf(sc->sc_dev,
918			    "xmit status=0x%x len=%d type=0x%x from %6D",
919			    SRO(sc, txp, TXP_STATUS),
920			    SRO(sc, txp, TXP_PKTSIZE),
921			    htons(eh.ether_type),
922			    eh.ether_shost, ":");
923			printf(" (to %6D)\n", eh.ether_dhost, ":");
924		}
925#endif /* SNCDEBUG */
926
927		sc->sc_tx_timeout = 0;
928		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
929
930		if (mtd->mtd_mbuf != 0) {
931			m_freem(mtd->mtd_mbuf);
932			mtd->mtd_mbuf = 0;
933		}
934		if (++mtd_hw == NTDA) mtd_hw = 0;
935
936		txp_status = SRO(sc, txp, TXP_STATUS);
937
938		if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
939		    (txp_status & TCR_EXC) ? 16 :
940		    ((txp_status & TCR_NC) >> 12));
941
942		if ((txp_status & TCR_PTX) == 0) {
943			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
944			device_printf(sc->sc_dev, "Tx packet status=0x%x\n",
945				      txp_status);
946
947			/* XXX - DG This looks bogus */
948			if (mtd_hw != sc->mtd_free) {
949				printf("resubmitting remaining packets\n");
950				mtd = &sc->mtda[mtd_hw];
951				NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp));
952				NIC_PUT(sc, SNCR_CR, CR_TXP);
953				wbflush();
954				break;
955			}
956		}
957	}
958
959	sc->mtd_hw = mtd_hw;
960	return;
961}
962
963/*
964 * Receive interrupt routine
965 */
966static void
967sonicrxint(struct snc_softc *sc)
968{
969	u_int32_t rda;
970	int	orra;
971	int	len;
972	int	rramark;
973	int	rdamark;
974	u_int16_t rxpkt_ptr;
975
976	rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
977
978	while (SRO(sc, rda, RXPKT_INUSE) == 0) {
979		u_int status = SRO(sc, rda, RXPKT_STATUS);
980
981		orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK;
982		rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO);
983		/*
984		 * Do not trunc ether_header length.
985		 * Our sonic_read() and sonic_get() require it.
986		 */
987		len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE;
988		if (status & RCR_PRX) {
989			/* XXX: Does PAGE_MASK require? */
990			u_int32_t pkt =
991			    sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PAGE_MASK);
992			if (sonic_read(sc, pkt, len))
993				if_inc_counter(sc->sc_ifp, IFCOUNTER_IPACKETS, 1);
994			else
995				if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
996		} else
997			if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
998
999		/*
1000		 * give receive buffer area back to chip.
1001		 *
1002		 * If this was the last packet in the RRA, give the RRA to
1003		 * the chip again.
1004		 * If sonic read didn't copy it out then we would have to
1005		 * wait !!
1006		 * (dont bother add it back in again straight away)
1007		 *
1008		 * Really, we're doing v_rra[rramark] = v_rra[orra] but
1009		 * we have to use the macros because SONIC might be in
1010		 * 16 or 32 bit mode.
1011		 */
1012		if (status & RCR_LPKT) {
1013			u_int32_t tmp1, tmp2;
1014
1015			rramark = sc->sc_rramark;
1016			tmp1 = sc->v_rra[rramark];
1017			tmp2 = sc->v_rra[orra];
1018			SWO(sc, tmp1, RXRSRC_PTRLO,
1019				SRO(sc, tmp2, RXRSRC_PTRLO));
1020			SWO(sc, tmp1, RXRSRC_PTRHI,
1021				SRO(sc, tmp2, RXRSRC_PTRHI));
1022			SWO(sc, tmp1, RXRSRC_WCLO,
1023				SRO(sc, tmp2, RXRSRC_WCLO));
1024			SWO(sc, tmp1, RXRSRC_WCHI,
1025				SRO(sc, tmp2, RXRSRC_WCHI));
1026
1027			/* zap old rra for fun */
1028			SWO(sc, tmp2, RXRSRC_WCHI, 0);
1029			SWO(sc, tmp2, RXRSRC_WCLO, 0);
1030
1031			sc->sc_rramark = (++rramark) & RRAMASK;
1032			NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark]));
1033			wbflush();
1034		}
1035
1036		/*
1037		 * give receive descriptor back to chip simple
1038		 * list is circular
1039		 */
1040		rdamark = sc->sc_rdamark;
1041		SWO(sc, rda, RXPKT_INUSE, 1);
1042		SWO(sc, rda, RXPKT_RLINK,
1043			SRO(sc, rda, RXPKT_RLINK) | EOL);
1044		SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK,
1045			SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))),
1046			RXPKT_RLINK) & ~EOL);
1047		sc->sc_rdamark = sc->sc_rxmark;
1048
1049		if (++sc->sc_rxmark >= sc->sc_nrda)
1050			sc->sc_rxmark = 0;
1051		rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
1052	}
1053}
1054
1055/*
1056 * sonic_read -- pull packet off interface and forward to
1057 * appropriate protocol handler
1058 */
1059static int
1060sonic_read(struct snc_softc *sc, u_int32_t pkt, int len)
1061{
1062	struct ifnet *ifp = sc->sc_ifp;
1063	struct ether_header *et;
1064	struct mbuf *m;
1065
1066	if (len <= sizeof(struct ether_header) ||
1067	    len > ETHERMTU + sizeof(struct ether_header)) {
1068		device_printf(sc->sc_dev,
1069			      "invalid packet length %d bytes\n", len);
1070		return (0);
1071	}
1072
1073	/* Pull packet off interface. */
1074	m = sonic_get(sc, pkt, len);
1075	if (m == 0) {
1076		return (0);
1077	}
1078
1079	/* We assume that the header fit entirely in one mbuf. */
1080	et = mtod(m, struct ether_header *);
1081
1082#ifdef SNCDEBUG
1083	if ((sncdebug & SNC_SHOWRXHDR) != 0)
1084	{
1085		device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D",
1086		    pkt, len, htons(et->ether_type),
1087		    et->ether_shost, ":");
1088		printf(" (to %6D)\n", et->ether_dhost, ":");
1089	}
1090#endif /* SNCDEBUG */
1091
1092	/* Pass the packet up. */
1093	SNC_UNLOCK(sc);
1094	(*ifp->if_input)(ifp, m);
1095	SNC_LOCK(sc);
1096	return (1);
1097}
1098
1099
1100/*
1101 * munge the received packet into an mbuf chain
1102 */
1103static struct mbuf *
1104sonic_get(struct snc_softc *sc, u_int32_t pkt, int datalen)
1105{
1106	struct	mbuf *m, *top, **mp;
1107	int	len;
1108	/*
1109	 * Do not trunc ether_header length.
1110	 * Our sonic_read() and sonic_get() require it.
1111	 */
1112
1113	MGETHDR(m, M_NOWAIT, MT_DATA);
1114	if (m == 0)
1115		return (0);
1116	m->m_pkthdr.rcvif = sc->sc_ifp;
1117	m->m_pkthdr.len = datalen;
1118	len = MHLEN;
1119	top = 0;
1120	mp = &top;
1121
1122	while (datalen > 0) {
1123		if (top) {
1124			MGET(m, M_NOWAIT, MT_DATA);
1125			if (m == 0) {
1126				m_freem(top);
1127				return (0);
1128			}
1129			len = MLEN;
1130		}
1131		if (datalen >= MINCLSIZE) {
1132			if (!(MCLGET(m, M_NOWAIT))) {
1133				if (top) m_freem(top);
1134				return (0);
1135			}
1136			len = MCLBYTES;
1137		}
1138#if 0
1139		/* XXX: Require? */
1140		if (!top) {
1141			register int pad =
1142			    ALIGN(sizeof(struct ether_header)) -
1143			        sizeof(struct ether_header);
1144			m->m_data += pad;
1145			len -= pad;
1146		}
1147#endif
1148		m->m_len = len = min(datalen, len);
1149
1150		(*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), pkt, len);
1151		pkt += len;
1152		datalen -= len;
1153		*mp = m;
1154		mp = &m->m_next;
1155	}
1156
1157	return (top);
1158}
1159/*
1160 * Enable power on the interface.
1161 */
1162int
1163snc_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 */
1184void
1185snc_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
1199