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