1/*	$NetBSD: if_sn.c,v 1.32 2010/01/19 22:06:21 pooka Exp $	*/
2
3/*
4 * National Semiconductor  DP8393X SONIC Driver
5 * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
6 * You may use, copy, and modify this program so long as you retain the
7 * copyright line.
8 *
9 * This driver has been substantially modified since Algorithmics donated
10 * it.
11 *
12 *   Denton Gentry <denny1@home.com>
13 * and also
14 *   Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>
15 * did the work to get this running on the Macintosh.
16 */
17
18#include <sys/cdefs.h>
19__KERNEL_RCSID(0, "$NetBSD: if_sn.c,v 1.32 2010/01/19 22:06:21 pooka Exp $");
20
21#include "opt_inet.h"
22
23#include <sys/param.h>
24#include <sys/systm.h>
25#include <sys/mbuf.h>
26#include <sys/buf.h>
27#include <sys/protosw.h>
28#include <sys/socket.h>
29#include <sys/syslog.h>
30#include <sys/ioctl.h>
31#include <sys/errno.h>
32#include <sys/device.h>
33
34#include <net/if.h>
35#include <net/if_dl.h>
36#include <net/if_ether.h>
37
38#ifdef INET
39#include <netinet/in.h>
40#include <netinet/in_systm.h>
41#include <netinet/in_var.h>
42#include <netinet/ip.h>
43#include <netinet/if_inarp.h>
44#endif
45
46#include <uvm/uvm_extern.h>
47
48#include <net/bpf.h>
49#include <net/bpfdesc.h>
50
51#include <machine/cpu.h>
52#include <newsmips/apbus/apbusvar.h>
53#include <newsmips/apbus/if_snreg.h>
54#include <newsmips/apbus/if_snvar.h>
55
56/* #define SONIC_DEBUG */
57
58#ifdef SONIC_DEBUG
59# define DPRINTF printf
60#else
61# define DPRINTF while (0) printf
62#endif
63
64static void	snwatchdog(struct ifnet *);
65static int	sninit(struct sn_softc *sc);
66static int	snstop(struct sn_softc *sc);
67static int	snioctl(struct ifnet *ifp, u_long cmd, void *data);
68static void	snstart(struct ifnet *ifp);
69static void	snreset(struct sn_softc *sc);
70
71static void	caminitialise(struct sn_softc *);
72static void	camentry(struct sn_softc *, int, const u_char *ea);
73static void	camprogram(struct sn_softc *);
74static void	initialise_tda(struct sn_softc *);
75static void	initialise_rda(struct sn_softc *);
76static void	initialise_rra(struct sn_softc *);
77#ifdef SNDEBUG
78static void	camdump(struct sn_softc *sc);
79#endif
80
81static void	sonictxint(struct sn_softc *);
82static void	sonicrxint(struct sn_softc *);
83
84static inline u_int	sonicput(struct sn_softc *sc, struct mbuf *m0,
85    int mtd_next);
86static inline int	sonic_read(struct sn_softc *, void *, int);
87static inline struct mbuf *sonic_get(struct sn_softc *, void *, int);
88
89int sndebug = 0;
90
91/*
92 * SONIC buffers need to be aligned 16 or 32 bit aligned.
93 * These macros calculate and verify alignment.
94 */
95#define SOALIGN(m, array)	(m ? (roundup((int)array, 4)) : \
96				     (roundup((int)array, 2)))
97
98#define LOWER(x) ((unsigned)(x) & 0xffff)
99#define UPPER(x) ((unsigned)(x) >> 16)
100
101/*
102 * Interface exists: make available by filling in network interface
103 * record.  System will initialize the interface when it is ready
104 * to accept packets.
105 */
106int
107snsetup(struct sn_softc	*sc, uint8_t *lladdr)
108{
109	struct ifnet *ifp = &sc->sc_if;
110	uint8_t	*p;
111	uint8_t	*pp;
112	int	i;
113
114	if (sc->space == NULL) {
115		aprint_error_dev(sc->sc_dev,
116		    "memory allocation for descriptors failed\n");
117		return 1;
118	}
119
120	/*
121	 * Put the pup in reset mode (sninit() will fix it later),
122	 * stop the timer, disable all interrupts and clear any interrupts.
123	 */
124	NIC_PUT(sc, SNR_CR, CR_STP);
125	wbflush();
126	NIC_PUT(sc, SNR_CR, CR_RST);
127	wbflush();
128	NIC_PUT(sc, SNR_IMR, 0);
129	wbflush();
130	NIC_PUT(sc, SNR_ISR, ISR_ALL);
131	wbflush();
132
133	/*
134	 * because the SONIC is basically 16bit device it 'concatenates'
135	 * a higher buffer address to a 16 bit offset--this will cause wrap
136	 * around problems near the end of 64k !!
137	 */
138	p = sc->space;
139	pp = (uint8_t *)roundup((int)p, PAGE_SIZE);
140	p = pp;
141
142	for (i = 0; i < NRRA; i++) {
143		sc->p_rra[i] = (void *)p;
144		sc->v_rra[i] = SONIC_GETDMA(p);
145		p += RXRSRC_SIZE(sc);
146	}
147	sc->v_rea = SONIC_GETDMA(p);
148
149	p = (uint8_t *)SOALIGN(sc, p);
150
151	sc->p_cda = (void *)(p);
152	sc->v_cda = SONIC_GETDMA(p);
153	p += CDA_SIZE(sc);
154
155	p = (uint8_t *)SOALIGN(sc, p);
156
157	for (i = 0; i < NTDA; i++) {
158		struct mtd *mtdp = &sc->mtda[i];
159		mtdp->mtd_txp = (void *)p;
160		mtdp->mtd_vtxp = SONIC_GETDMA(p);
161		p += TXP_SIZE(sc);
162	}
163
164	p = (uint8_t *)SOALIGN(sc, p);
165
166	if ((p - pp) > PAGE_SIZE) {
167		aprint_error_dev(sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +"
168		    "TDA (%ld) > PAGE_SIZE (%d). Punt!\n",
169		    (ulong)sc->p_cda - (ulong)sc->p_rra[0],
170		    (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_cda,
171		    (ulong)p - (ulong)sc->mtda[0].mtd_txp,
172		    PAGE_SIZE);
173		return 1;
174	}
175
176	p = pp + PAGE_SIZE;
177	pp = p;
178
179	sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc);
180	sc->p_rda = (void *)p;
181	sc->v_rda = SONIC_GETDMA(p);
182
183	p = pp + PAGE_SIZE;
184
185	for (i = 0; i < NRBA; i++) {
186		sc->rbuf[i] = (void *)p;
187		p += PAGE_SIZE;
188	}
189
190	pp = p;
191	for (i = 0; i < NTDA; i++) {
192		struct mtd *mtdp = &sc->mtda[i];
193
194		mtdp->mtd_buf = p;
195		mtdp->mtd_vbuf = SONIC_GETDMA(p);
196		p += TXBSIZE;
197	}
198
199#ifdef SNDEBUG
200	camdump(sc);
201#endif
202	aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
203	    ether_sprintf(lladdr));
204
205#ifdef SNDEBUG
206	aprint_debug_dev(sc->sc_dev, "buffers: rra=%p cda=%p rda=%p tda=%p\n",
207	    sc->sc_dev.dv_xname, sc->p_rra[0], sc->p_cda,
208	    sc->p_rda, sc->mtda[0].mtd_txp);
209#endif
210
211	strcpy(ifp->if_xname, device_xname(sc->sc_dev));
212	ifp->if_softc = sc;
213	ifp->if_ioctl = snioctl;
214	ifp->if_start = snstart;
215	ifp->if_flags =
216	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
217	ifp->if_watchdog = snwatchdog;
218	if_attach(ifp);
219	ether_ifattach(ifp, lladdr);
220
221	return 0;
222}
223
224static int
225snioctl(struct ifnet *ifp, u_long cmd, void *data)
226{
227	struct ifaddr *ifa;
228	struct sn_softc *sc = ifp->if_softc;
229	int	s = splnet(), err = 0;
230	int	temp;
231
232	switch (cmd) {
233
234	case SIOCINITIFADDR:
235		ifa = (struct ifaddr *)data;
236		ifp->if_flags |= IFF_UP;
237		(void)sninit(sc);
238		switch (ifa->ifa_addr->sa_family) {
239#ifdef INET
240		case AF_INET:
241			arp_ifinit(ifp, ifa);
242			break;
243#endif
244		default:
245			break;
246		}
247		break;
248
249	case SIOCSIFFLAGS:
250		if ((err = ifioctl_common(ifp, cmd, data)) != 0)
251			break;
252		if ((ifp->if_flags & IFF_UP) == 0 &&
253		    (ifp->if_flags & IFF_RUNNING) != 0) {
254			/*
255			 * If interface is marked down and it is running,
256			 * then stop it.
257			 */
258			snstop(sc);
259			ifp->if_flags &= ~IFF_RUNNING;
260		} else if ((ifp->if_flags & IFF_UP) != 0 &&
261		    (ifp->if_flags & IFF_RUNNING) == 0) {
262			/*
263			 * If interface is marked up and it is stopped,
264			 * then start it.
265			 */
266			(void)sninit(sc);
267		} else {
268			/*
269			 * reset the interface to pick up any other changes
270			 * in flags
271			 */
272			temp = ifp->if_flags & IFF_UP;
273			snreset(sc);
274			ifp->if_flags |= temp;
275			snstart(ifp);
276		}
277		break;
278
279	case SIOCADDMULTI:
280	case SIOCDELMULTI:
281		if ((err = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
282			/*
283			 * Multicast list has changed; set the hardware
284			 * filter accordingly. But remember UP flag!
285			 */
286			if (ifp->if_flags & IFF_RUNNING) {
287				temp = ifp->if_flags & IFF_UP;
288				snreset(sc);
289				ifp->if_flags |= temp;
290			}
291			err = 0;
292		}
293		break;
294	default:
295		err = ether_ioctl(ifp, cmd, data);
296		break;
297	}
298	splx(s);
299	return err;
300}
301
302/*
303 * Encapsulate a packet of type family for the local net.
304 */
305static void
306snstart(struct ifnet *ifp)
307{
308	struct sn_softc	*sc = ifp->if_softc;
309	struct mbuf	*m;
310	int		mtd_next;
311
312	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
313		return;
314
315outloop:
316	/* Check for room in the xmit buffer. */
317	if ((mtd_next = (sc->mtd_free + 1)) == NTDA)
318		mtd_next = 0;
319
320	if (mtd_next == sc->mtd_hw) {
321		ifp->if_flags |= IFF_OACTIVE;
322		return;
323	}
324
325	IF_DEQUEUE(&ifp->if_snd, m);
326	if (m == 0)
327		return;
328
329	/* We need the header for m_pkthdr.len. */
330	if ((m->m_flags & M_PKTHDR) == 0)
331		panic("%s: snstart: no header mbuf", device_xname(sc->sc_dev));
332
333	/*
334	 * If bpf is listening on this interface, let it
335	 * see the packet before we commit it to the wire.
336	 */
337	bpf_mtap(ifp, m);
338
339	/*
340	 * If there is nothing in the o/p queue, and there is room in
341	 * the Tx ring, then send the packet directly.  Otherwise append
342	 * it to the o/p queue.
343	 */
344	if ((sonicput(sc, m, mtd_next)) == 0) {
345		IF_PREPEND(&ifp->if_snd, m);
346		return;
347	}
348
349	sc->mtd_prev = sc->mtd_free;
350	sc->mtd_free = mtd_next;
351
352	ifp->if_opackets++;		/* # of pkts */
353
354	/* Jump back for possibly more punishment. */
355	goto outloop;
356}
357
358/*
359 * reset and restart the SONIC.  Called in case of fatal
360 * hardware/software errors.
361 */
362static void
363snreset(struct sn_softc *sc)
364{
365
366	snstop(sc);
367	sninit(sc);
368}
369
370static int
371sninit(struct sn_softc *sc)
372{
373	u_long	s_rcr;
374	int	s;
375
376	if (sc->sc_if.if_flags & IFF_RUNNING)
377		/* already running */
378		return 0;
379
380	s = splnet();
381
382	NIC_PUT(sc, SNR_CR, CR_RST);	/* DCR only accessible in reset mode! */
383
384	/* config it */
385	NIC_PUT(sc, SNR_DCR, (sc->snr_dcr |
386		(sc->bitmode ? DCR_DW32 : DCR_DW16)));
387	NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2);
388
389	s_rcr = RCR_BRD | RCR_LBNONE;
390	if (sc->sc_if.if_flags & IFF_PROMISC)
391		s_rcr |= RCR_PRO;
392	if (sc->sc_if.if_flags & IFF_ALLMULTI)
393		s_rcr |= RCR_AMC;
394	NIC_PUT(sc, SNR_RCR, s_rcr);
395
396#if 0
397	NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN));
398#else
399	NIC_PUT(sc, SNR_IMR, IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN |
400			     IMR_BREN  | IMR_HBLEN | IMR_RDEEN  | IMR_RBEEN |
401			     IMR_RBAEEN | IMR_RFOEN);
402#endif
403
404	/* clear pending interrupts */
405	NIC_PUT(sc, SNR_ISR, ISR_ALL);
406
407	/* clear tally counters */
408	NIC_PUT(sc, SNR_CRCT, -1);
409	NIC_PUT(sc, SNR_FAET, -1);
410	NIC_PUT(sc, SNR_MPT, -1);
411
412	initialise_tda(sc);
413	initialise_rda(sc);
414	initialise_rra(sc);
415
416	sn_md_init(sc);			/* MD initialization */
417
418	/* enable the chip */
419	NIC_PUT(sc, SNR_CR, 0);
420	wbflush();
421
422	/* program the CAM */
423	camprogram(sc);
424
425	/* get it to read resource descriptors */
426	NIC_PUT(sc, SNR_CR, CR_RRRA);
427	wbflush();
428	while ((NIC_GET(sc, SNR_CR)) & CR_RRRA)
429		continue;
430
431	/* enable rx */
432	NIC_PUT(sc, SNR_CR, CR_RXEN);
433	wbflush();
434
435	/* flag interface as "running" */
436	sc->sc_if.if_flags |= IFF_RUNNING;
437	sc->sc_if.if_flags &= ~IFF_OACTIVE;
438
439	splx(s);
440	return 0;
441}
442
443/*
444 * close down an interface and free its buffers
445 * Called on final close of device, or if sninit() fails
446 * part way through.
447 */
448static int
449snstop(struct sn_softc *sc)
450{
451	struct mtd *mtd;
452	int	s = splnet();
453
454	/* stick chip in reset */
455	NIC_PUT(sc, SNR_CR, CR_RST);
456	wbflush();
457
458	/* free all receive buffers (currently static so nothing to do) */
459
460	/* free all pending transmit mbufs */
461	while (sc->mtd_hw != sc->mtd_free) {
462		mtd = &sc->mtda[sc->mtd_hw];
463		if (mtd->mtd_mbuf)
464			m_freem(mtd->mtd_mbuf);
465		if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
466	}
467
468	sc->sc_if.if_timer = 0;
469	sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP);
470
471	splx(s);
472	return 0;
473}
474
475/*
476 * Called if any Tx packets remain unsent after 5 seconds,
477 * In all cases we just reset the chip, and any retransmission
478 * will be handled by higher level protocol timeouts.
479 */
480static void
481snwatchdog(struct ifnet *ifp)
482{
483	struct sn_softc *sc = ifp->if_softc;
484	struct mtd *mtd;
485	int	temp;
486
487	if (sc->mtd_hw != sc->mtd_free) {
488		/* something still pending for transmit */
489		mtd = &sc->mtda[sc->mtd_hw];
490		if (SRO(sc->bitmode, mtd->mtd_txp, TXP_STATUS) == 0)
491			log(LOG_ERR, "%s: Tx - timeout\n",
492			    device_xname(sc->sc_dev));
493		else
494			log(LOG_ERR, "%s: Tx - lost interrupt\n",
495			    device_xname(sc->sc_dev));
496		temp = ifp->if_flags & IFF_UP;
497		snreset(sc);
498		ifp->if_flags |= temp;
499	}
500}
501
502/*
503 * stuff packet into sonic (at splnet)
504 */
505static inline u_int
506sonicput(struct sn_softc *sc, struct mbuf *m0, int mtd_next)
507{
508	struct mtd *mtdp;
509	struct mbuf *m;
510	u_char	*buff;
511	void	*txp;
512	u_int	len = 0;
513	u_int	totlen = 0;
514
515#ifdef whyonearthwouldyoudothis
516	if (NIC_GET(sc, SNR_CR) & CR_TXP)
517		return 0;
518#endif
519
520	/* grab the replacement mtd */
521	mtdp = &sc->mtda[sc->mtd_free];
522
523	buff = mtdp->mtd_buf;
524
525	/* this packet goes to mtdnext fill in the TDA */
526	mtdp->mtd_mbuf = m0;
527	txp = mtdp->mtd_txp;
528
529	/* Write to the config word. Every (NTDA/2)+1 packets we set an intr */
530	if (sc->mtd_pint == 0) {
531		sc->mtd_pint = NTDA/2;
532		SWO(sc->bitmode, txp, TXP_CONFIG, TCR_PINT);
533	} else {
534		sc->mtd_pint--;
535		SWO(sc->bitmode, txp, TXP_CONFIG, 0);
536	}
537
538	for (m = m0; m; m = m->m_next) {
539		u_char *data = mtod(m, u_char *);
540		len = m->m_len;
541		totlen += len;
542		memcpy(buff, data, len);
543		buff += len;
544	}
545	if (totlen >= TXBSIZE) {
546		panic("%s: sonicput: packet overflow",
547		    device_xname(sc->sc_dev));
548	}
549
550	SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO,
551	    LOWER(mtdp->mtd_vbuf));
552	SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI,
553	    UPPER(mtdp->mtd_vbuf));
554
555	if (totlen < ETHERMIN + ETHER_HDR_LEN) {
556		int pad = ETHERMIN + ETHER_HDR_LEN - totlen;
557		memset((char *)mtdp->mtd_buf + totlen, 0, pad);
558		totlen = ETHERMIN + ETHER_HDR_LEN;
559	}
560
561	SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE,
562	    totlen);
563	SWO(sc->bitmode, txp, TXP_FRAGCNT, 1);
564	SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen);
565
566	/* link onto the next mtd that will be used */
567	SWO(sc->bitmode, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO,
568	    LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);
569
570	/*
571	 * The previous txp.tlink currently contains a pointer to
572	 * our txp | EOL. Want to clear the EOL, so write our
573	 * pointer to the previous txp.
574	 */
575	SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko,
576	    LOWER(mtdp->mtd_vtxp));
577
578	/* make sure chip is running */
579	wbflush();
580	NIC_PUT(sc, SNR_CR, CR_TXP);
581	wbflush();
582	sc->sc_if.if_timer = 5;	/* 5 seconds to watch for failing to transmit */
583
584	return totlen;
585}
586
587/*
588 * These are called from sonicioctl() when /etc/ifconfig is run to set
589 * the address or switch the i/f on.
590 */
591/*
592 * CAM support
593 */
594static void
595caminitialise(struct sn_softc *sc)
596{
597	void	*p_cda = sc->p_cda;
598	int	i;
599	int	camoffset;
600
601	for (i = 0; i < MAXCAM; i++) {
602		camoffset = i * CDA_CAMDESC;
603		SWO(bitmode, p_cda, (camoffset + CDA_CAMEP), i);
604		SWO(bitmode, p_cda, (camoffset + CDA_CAMAP2), 0);
605		SWO(bitmode, p_cda, (camoffset + CDA_CAMAP1), 0);
606		SWO(bitmode, p_cda, (camoffset + CDA_CAMAP0), 0);
607	}
608	SWO(bitmode, p_cda, CDA_ENABLE, 0);
609}
610
611static void
612camentry(struct sn_softc *sc, int entry, const u_char *ea)
613{
614	void	*p_cda = sc->p_cda;
615	int	camoffset = entry * CDA_CAMDESC;
616
617	SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry);
618	SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]);
619	SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]);
620	SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]);
621	SWO(bitmode, p_cda, CDA_ENABLE,
622	    (SRO(bitmode, p_cda, CDA_ENABLE) | (1 << entry)));
623}
624
625static void
626camprogram(struct sn_softc *sc)
627{
628	struct ether_multistep step;
629	struct ether_multi *enm;
630	struct ifnet *ifp;
631	int	timeout;
632	int	mcount = 0;
633
634	caminitialise(sc);
635
636	ifp = &sc->sc_if;
637
638	/* Always load our own address first. */
639	camentry(sc, mcount, CLLADDR(ifp->if_sadl));
640	mcount++;
641
642	/* Assume we won't need allmulti bit. */
643	ifp->if_flags &= ~IFF_ALLMULTI;
644
645	/* Loop through multicast addresses */
646	ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
647	while (enm != NULL) {
648		if (mcount == MAXCAM) {
649			 ifp->if_flags |= IFF_ALLMULTI;
650			 break;
651		}
652
653		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
654		    sizeof(enm->enm_addrlo)) != 0) {
655			/*
656			 * SONIC's CAM is programmed with specific
657			 * addresses. It has no way to specify a range.
658			 * (Well, thats not exactly true. If the
659			 * range is small one could program each addr
660			 * within the range as a separate CAM entry)
661			 */
662			ifp->if_flags |= IFF_ALLMULTI;
663			break;
664		}
665
666		/* program the CAM with the specified entry */
667		camentry(sc, mcount, enm->enm_addrlo);
668		mcount++;
669
670		ETHER_NEXT_MULTI(step, enm);
671	}
672
673	NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda));
674	NIC_PUT(sc, SNR_CDC, MAXCAM);
675	NIC_PUT(sc, SNR_CR, CR_LCAM);
676	wbflush();
677
678	timeout = 10000;
679	while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--)
680		delay(10);
681	if (timeout == 0) {
682		/* XXX */
683		panic("%s: CAM initialisation failed",
684		    device_xname(sc->sc_dev));
685	}
686	timeout = 10000;
687	while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--)
688		delay(10);
689
690	if (NIC_GET(sc, SNR_ISR) & ISR_LCD)
691		NIC_PUT(sc, SNR_ISR, ISR_LCD);
692	else
693		printf("%s: CAM initialisation without interrupt\n",
694		    device_xname(sc->sc_dev));
695}
696
697#ifdef SNDEBUG
698static void
699camdump(struct sn_softc *sc)
700{
701	int	i;
702
703	printf("CAM entries:\n");
704	NIC_PUT(sc, SNR_CR, CR_RST);
705	wbflush();
706
707	for (i = 0; i < 16; i++) {
708		ushort  ap2, ap1, ap0;
709		NIC_PUT(sc, SNR_CEP, i);
710		wbflush();
711		ap2 = NIC_GET(sc, SNR_CAP2);
712		ap1 = NIC_GET(sc, SNR_CAP1);
713		ap0 = NIC_GET(sc, SNR_CAP0);
714		printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
715	}
716	printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CEP));
717
718	NIC_PUT(sc, SNR_CR, 0);
719	wbflush();
720}
721#endif
722
723static void
724initialise_tda(struct sn_softc *sc)
725{
726	struct mtd *mtd;
727	int	i;
728
729	for (i = 0; i < NTDA; i++) {
730		mtd = &sc->mtda[i];
731		mtd->mtd_mbuf = 0;
732	}
733
734	sc->mtd_hw = 0;
735	sc->mtd_prev = NTDA - 1;
736	sc->mtd_free = 0;
737	sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
738	sc->mtd_pint = NTDA/2;
739
740	NIC_PUT(sc, SNR_UTDA, UPPER(sc->mtda[0].mtd_vtxp));
741	NIC_PUT(sc, SNR_CTDA, LOWER(sc->mtda[0].mtd_vtxp));
742}
743
744static void
745initialise_rda(struct sn_softc *sc)
746{
747	int		i;
748	char 		*p_rda = 0;
749	uint32_t	v_rda = 0;
750
751	/* link the RDA's together into a circular list */
752	for (i = 0; i < (sc->sc_nrda - 1); i++) {
753		p_rda = (char *)sc->p_rda + (i * RXPKT_SIZE(sc));
754		v_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc));
755		SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(v_rda));
756		SWO(bitmode, p_rda, RXPKT_INUSE, 1);
757	}
758	p_rda = (char *)sc->p_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc));
759	SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL);
760	SWO(bitmode, p_rda, RXPKT_INUSE, 1);
761
762	/* mark end of receive descriptor list */
763	sc->sc_rdamark = sc->sc_nrda - 1;
764
765	sc->sc_rxmark = 0;
766
767	NIC_PUT(sc, SNR_URDA, UPPER(sc->v_rda));
768	NIC_PUT(sc, SNR_CRDA, LOWER(sc->v_rda));
769	wbflush();
770}
771
772static void
773initialise_rra(struct sn_softc *sc)
774{
775	int	i;
776	u_int	v;
777	int	bitmode = sc->bitmode;
778
779	if (bitmode)
780		NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 2);
781	else
782		NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 1);
783
784	NIC_PUT(sc, SNR_URRA, UPPER(sc->v_rra[0]));
785	NIC_PUT(sc, SNR_RSA, LOWER(sc->v_rra[0]));
786	/* rea must point just past the end of the rra space */
787	NIC_PUT(sc, SNR_REA, LOWER(sc->v_rea));
788	NIC_PUT(sc, SNR_RRP, LOWER(sc->v_rra[0]));
789	NIC_PUT(sc, SNR_RSC, 0);
790
791	/* fill up SOME of the rra with buffers */
792	for (i = 0; i < NRBA; i++) {
793		v = SONIC_GETDMA(sc->rbuf[i]);
794		SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v));
795		SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v));
796		SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(PAGE_SIZE/2));
797		SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(PAGE_SIZE/2));
798	}
799	sc->sc_rramark = NRBA;
800	NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[sc->sc_rramark]));
801	wbflush();
802}
803
804int
805snintr(void *arg)
806{
807	struct sn_softc *sc = (struct sn_softc *)arg;
808	int handled = 0;
809	int	isr;
810
811	while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) {
812		/* scrub the interrupts that we are going to service */
813		NIC_PUT(sc, SNR_ISR, isr);
814		handled = 1;
815		wbflush();
816
817		if (isr & (ISR_BR | ISR_LCD | ISR_TC))
818			printf("%s: unexpected interrupt status 0x%x\n",
819			    device_xname(sc->sc_dev), isr);
820
821		if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT))
822			sonictxint(sc);
823
824		if (isr & ISR_PKTRX)
825			sonicrxint(sc);
826
827		if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
828			if (isr & ISR_HBL)
829				/*
830				 * The repeater is not providing a heartbeat.
831				 * In itself this isn't harmful, lots of the
832				 * cheap repeater hubs don't supply a heartbeat.
833				 * So ignore the lack of heartbeat. Its only
834				 * if we can't detect a carrier that we have a
835				 * problem.
836				 */
837				;
838			if (isr & ISR_RDE)
839				printf("%s: receive descriptors exhausted\n",
840				    device_xname(sc->sc_dev));
841			if (isr & ISR_RBE)
842				printf("%s: receive buffers exhausted\n",
843				    device_xname(sc->sc_dev));
844			if (isr & ISR_RBAE)
845				printf("%s: receive buffer area exhausted\n",
846				    device_xname(sc->sc_dev));
847			if (isr & ISR_RFO)
848				printf("%s: receive FIFO overrun\n",
849				    device_xname(sc->sc_dev));
850		}
851		if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
852#ifdef notdef
853			if (isr & ISR_CRC)
854				sc->sc_crctally++;
855			if (isr & ISR_FAE)
856				sc->sc_faetally++;
857			if (isr & ISR_MP)
858				sc->sc_mptally++;
859#endif
860		}
861		snstart(&sc->sc_if);
862	}
863	return handled;
864}
865
866/*
867 * Transmit interrupt routine
868 */
869static void
870sonictxint(struct sn_softc *sc)
871{
872	struct mtd	*mtd;
873	void		*txp;
874	unsigned short	txp_status;
875	int		mtd_hw;
876	struct ifnet	*ifp = &sc->sc_if;
877
878	mtd_hw = sc->mtd_hw;
879
880	if (mtd_hw == sc->mtd_free)
881		return;
882
883	while (mtd_hw != sc->mtd_free) {
884		mtd = &sc->mtda[mtd_hw];
885
886		txp = mtd->mtd_txp;
887
888		if (SRO(sc->bitmode, txp, TXP_STATUS) == 0) {
889			break; /* it hasn't really gone yet */
890		}
891
892#ifdef SNDEBUG
893		{
894			struct ether_header *eh;
895
896			eh = (struct ether_header *) mtd->mtd_buf;
897			printf("%s: xmit status=0x%x len=%d type=0x%x from %s",
898			    device_xname(sc->sc_dev),
899			    SRO(sc->bitmode, txp, TXP_STATUS),
900			    SRO(sc->bitmode, txp, TXP_PKTSIZE),
901			    htons(eh->ether_type),
902			    ether_sprintf(eh->ether_shost));
903			printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
904		}
905#endif /* SNDEBUG */
906
907		ifp->if_flags &= ~IFF_OACTIVE;
908
909		if (mtd->mtd_mbuf != 0) {
910			m_freem(mtd->mtd_mbuf);
911			mtd->mtd_mbuf = 0;
912		}
913		if (++mtd_hw == NTDA) mtd_hw = 0;
914
915		txp_status = SRO(sc->bitmode, txp, TXP_STATUS);
916
917		ifp->if_collisions += (txp_status & TCR_EXC) ? 16 :
918			((txp_status & TCR_NC) >> 12);
919
920		if ((txp_status & TCR_PTX) == 0) {
921			ifp->if_oerrors++;
922			printf("%s: Tx packet status=0x%x\n",
923			    device_xname(sc->sc_dev), txp_status);
924
925			/* XXX - DG This looks bogus */
926			if (mtd_hw != sc->mtd_free) {
927				printf("resubmitting remaining packets\n");
928				mtd = &sc->mtda[mtd_hw];
929				NIC_PUT(sc, SNR_CTDA, LOWER(mtd->mtd_vtxp));
930				NIC_PUT(sc, SNR_CR, CR_TXP);
931				wbflush();
932				break;
933			}
934		}
935	}
936
937	sc->mtd_hw = mtd_hw;
938	return;
939}
940
941/*
942 * Receive interrupt routine
943 */
944static void
945sonicrxint(struct sn_softc *sc)
946{
947	void *	rda;
948	int	orra;
949	int	len;
950	int	rramark;
951	int	rdamark;
952	uint16_t rxpkt_ptr;
953
954	rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
955
956	while (SRO(bitmode, rda, RXPKT_INUSE) == 0) {
957		u_int status = SRO(bitmode, rda, RXPKT_STATUS);
958
959		orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK;
960		rxpkt_ptr = SRO(bitmode, rda, RXPKT_PTRLO);
961		len = SRO(bitmode, rda, RXPKT_BYTEC) - FCSSIZE;
962		if (status & RCR_PRX) {
963			void *pkt =
964			    (char *)sc->rbuf[orra & RBAMASK] +
965				 (rxpkt_ptr & PGOFSET);
966			if (sonic_read(sc, pkt, len))
967				sc->sc_if.if_ipackets++;
968			else
969				sc->sc_if.if_ierrors++;
970		} else
971			sc->sc_if.if_ierrors++;
972
973		/*
974		 * give receive buffer area back to chip.
975		 *
976		 * If this was the last packet in the RRA, give the RRA to
977		 * the chip again.
978		 * If sonic read didnt copy it out then we would have to
979		 * wait !!
980		 * (dont bother add it back in again straight away)
981		 *
982		 * Really, we're doing p_rra[rramark] = p_rra[orra] but
983		 * we have to use the macros because SONIC might be in
984		 * 16 or 32 bit mode.
985		 */
986		if (status & RCR_LPKT) {
987			void *tmp1, *tmp2;
988
989			rramark = sc->sc_rramark;
990			tmp1 = sc->p_rra[rramark];
991			tmp2 = sc->p_rra[orra];
992			SWO(bitmode, tmp1, RXRSRC_PTRLO,
993			    SRO(bitmode, tmp2, RXRSRC_PTRLO));
994			SWO(bitmode, tmp1, RXRSRC_PTRHI,
995			    SRO(bitmode, tmp2, RXRSRC_PTRHI));
996			SWO(bitmode, tmp1, RXRSRC_WCLO,
997			    SRO(bitmode, tmp2, RXRSRC_WCLO));
998			SWO(bitmode, tmp1, RXRSRC_WCHI,
999			    SRO(bitmode, tmp2, RXRSRC_WCHI));
1000
1001			/* zap old rra for fun */
1002			SWO(bitmode, tmp2, RXRSRC_WCHI, 0);
1003			SWO(bitmode, tmp2, RXRSRC_WCLO, 0);
1004
1005			sc->sc_rramark = (++rramark) & RRAMASK;
1006			NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[rramark]));
1007			wbflush();
1008		}
1009
1010		/*
1011		 * give receive descriptor back to chip simple
1012		 * list is circular
1013		 */
1014		rdamark = sc->sc_rdamark;
1015		SWO(bitmode, rda, RXPKT_INUSE, 1);
1016		SWO(bitmode, rda, RXPKT_RLINK,
1017		    SRO(bitmode, rda, RXPKT_RLINK) | EOL);
1018		SWO(bitmode, ((char *)sc->p_rda + (rdamark * RXPKT_SIZE(sc))),
1019		    RXPKT_RLINK,
1020		    SRO(bitmode, ((char *)sc->p_rda +
1021			(rdamark * RXPKT_SIZE(sc))),
1022		    RXPKT_RLINK) & ~EOL);
1023		sc->sc_rdamark = sc->sc_rxmark;
1024
1025		if (++sc->sc_rxmark >= sc->sc_nrda)
1026			sc->sc_rxmark = 0;
1027		rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
1028	}
1029}
1030
1031/*
1032 * sonic_read -- pull packet off interface and forward to
1033 * appropriate protocol handler
1034 */
1035static inline int
1036sonic_read(struct sn_softc *sc, void *pkt, int len)
1037{
1038	struct ifnet *ifp = &sc->sc_if;
1039	struct mbuf *m;
1040
1041#ifdef SNDEBUG
1042	{
1043		printf("%s: rcvd %p len=%d type=0x%x from %s",
1044		    devoce_xname(sc->sc_dev), et, len, htons(et->ether_type),
1045		    ether_sprintf(et->ether_shost));
1046		printf(" (to %s)\n", ether_sprintf(et->ether_dhost));
1047	}
1048#endif /* SNDEBUG */
1049
1050	if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN) ||
1051	    len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
1052		printf("%s: invalid packet length %d bytes\n",
1053		    device_xname(sc->sc_dev), len);
1054		return 0;
1055	}
1056
1057	m = sonic_get(sc, pkt, len);
1058	if (m == NULL)
1059		return 0;
1060	/* Pass the packet to any BPF listeners. */
1061	bpf_mtap(ifp, m);
1062	(*ifp->if_input)(ifp, m);
1063	return 1;
1064}
1065
1066/*
1067 * munge the received packet into an mbuf chain
1068 */
1069static inline struct mbuf *
1070sonic_get(struct sn_softc *sc, void *pkt, int datalen)
1071{
1072	struct	mbuf *m, *top, **mp;
1073	int	len;
1074
1075	MGETHDR(m, M_DONTWAIT, MT_DATA);
1076	if (m == 0)
1077		return 0;
1078	m->m_pkthdr.rcvif = &sc->sc_if;
1079	m->m_pkthdr.len = datalen;
1080	len = MHLEN;
1081	top = 0;
1082	mp = &top;
1083
1084	while (datalen > 0) {
1085		if (top) {
1086			MGET(m, M_DONTWAIT, MT_DATA);
1087			if (m == 0) {
1088				m_freem(top);
1089				return 0;
1090			}
1091			len = MLEN;
1092		}
1093		if (datalen >= MINCLSIZE) {
1094			MCLGET(m, M_DONTWAIT);
1095			if ((m->m_flags & M_EXT) == 0) {
1096				if (top) m_freem(top);
1097				return 0;
1098			}
1099			len = MCLBYTES;
1100		}
1101
1102		if (mp == &top) {
1103			char *newdata = (char *)
1104			    ALIGN((char *)m->m_data +
1105				sizeof(struct ether_header)) -
1106			    sizeof(struct ether_header);
1107			len -= newdata - m->m_data;
1108			m->m_data = newdata;
1109		}
1110
1111		m->m_len = len = min(datalen, len);
1112
1113		memcpy(mtod(m, void *), pkt, (unsigned) len);
1114		pkt = (char *)pkt + len;
1115		datalen -= len;
1116		*mp = m;
1117		mp = &m->m_next;
1118	}
1119
1120	return top;
1121}
1122