1139749Simp/*-
254773Simp * Copyright (c) 1996 Gardner Buchanan <gbuchanan@shl.com>
354773Simp * All rights reserved.
454773Simp *
554773Simp * Redistribution and use in source and binary forms, with or without
654773Simp * modification, are permitted provided that the following conditions
754773Simp * are met:
854773Simp * 1. Redistributions of source code must retain the above copyright
954773Simp *    notice, this list of conditions and the following disclaimer.
1054773Simp * 2. Redistributions in binary form must reproduce the above copyright
1154773Simp *    notice, this list of conditions and the following disclaimer in the
1254773Simp *    documentation and/or other materials provided with the distribution.
1354773Simp * 3. All advertising materials mentioning features or use of this software
1454773Simp *    must display the following acknowledgement:
1554773Simp *      This product includes software developed by Gardner Buchanan.
1654773Simp * 4. The name of Gardner Buchanan may not be used to endorse or promote
1754773Simp *    products derived from this software without specific prior written
1854773Simp *    permission.
1954773Simp *
2054773Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2154773Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2254773Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2354773Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2454773Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2554773Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2654773Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2754773Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2854773Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2954773Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3054773Simp */
3154773Simp
32119419Sobrien#include <sys/cdefs.h>
33119419Sobrien__FBSDID("$FreeBSD$");
34119419Sobrien
3554773Simp/*
3654773Simp * This is a driver for SMC's 9000 series of Ethernet adapters.
3754773Simp *
3854773Simp * This FreeBSD driver is derived from the smc9194 Linux driver by
3954773Simp * Erik Stahlman and is Copyright (C) 1996 by Erik Stahlman.
4054773Simp * This driver also shamelessly borrows from the FreeBSD ep driver
4154773Simp * which is Copyright (C) 1994 Herb Peyerl <hpeyerl@novatel.ca>
4254773Simp * All rights reserved.
4354773Simp *
4454773Simp * It is set up for my SMC91C92 equipped Ampro LittleBoard embedded
4554773Simp * PC.  It is adapted from Erik Stahlman's Linux driver which worked
4654773Simp * with his EFA Info*Express SVC VLB adaptor.  According to SMC's databook,
4754773Simp * it will work for the entire SMC 9xxx series. (Ha Ha)
4854773Simp *
4954773Simp * "Features" of the SMC chip:
5054773Simp *   4608 byte packet memory. (for the 91C92.  Others have more)
5154773Simp *   EEPROM for configuration
5254773Simp *   AUI/TP selection
5354773Simp *
5454773Simp * Authors:
5554773Simp *      Erik Stahlman                   erik@vt.edu
5654773Simp *      Herb Peyerl                     hpeyerl@novatel.ca
5754773Simp *      Andres Vega Garcia              avega@sophia.inria.fr
5854773Simp *      Serge Babkin                    babkin@hq.icb.chel.su
5954773Simp *      Gardner Buchanan                gbuchanan@shl.com
6054773Simp *
6154773Simp * Sources:
6254773Simp *    o   SMC databook
6354773Simp *    o   "smc9194.c:v0.10(FIXED) 02/15/96 by Erik Stahlman (erik@vt.edu)"
6454773Simp *    o   "if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp"
6554773Simp *
6654773Simp * Known Bugs:
6754773Simp *    o   Setting of the hardware address isn't supported.
6854773Simp *    o   Hardware padding isn't used.
6954773Simp */
7054773Simp
7154773Simp/*
7254773Simp * Modifications for Megahertz X-Jack Ethernet Card (XJ-10BT)
7354773Simp *
7454773Simp * Copyright (c) 1996 by Tatsumi Hosokawa <hosokawa@jp.FreeBSD.org>
7554773Simp *                       BSD-nomads, Tokyo, Japan.
7654773Simp */
7754773Simp/*
7854773Simp * Multicast support by Kei TANAKA <kei@pal.xerox.com>
7954773Simp * Special thanks to itojun@itojun.org
8054773Simp */
8154773Simp
8254773Simp#include <sys/param.h>
8354773Simp#include <sys/systm.h>
8454773Simp#include <sys/errno.h>
85199559Sjhb#include <sys/kernel.h>
8654773Simp#include <sys/sockio.h>
8754773Simp#include <sys/mbuf.h>
8854773Simp#include <sys/socket.h>
8954773Simp#include <sys/syslog.h>
9054773Simp
9154994Simp#include <sys/module.h>
9254994Simp#include <sys/bus.h>
9354994Simp
9454994Simp#include <machine/bus.h>
9554994Simp#include <machine/resource.h>
9654994Simp#include <sys/rman.h>
9754994Simp
9854773Simp#include <net/ethernet.h>
9954773Simp#include <net/if.h>
10054773Simp#include <net/if_arp.h>
10154773Simp#include <net/if_dl.h>
10254773Simp#include <net/if_types.h>
10354773Simp#include <net/if_mib.h>
10454773Simp
10554773Simp#ifdef INET
10654773Simp#include <netinet/in.h>
10754773Simp#include <netinet/in_systm.h>
10854773Simp#include <netinet/in_var.h>
10954773Simp#include <netinet/ip.h>
11054773Simp#endif
11154773Simp
11254773Simp#include <net/bpf.h>
11354773Simp#include <net/bpfdesc.h>
11454773Simp
11554773Simp#include <dev/sn/if_snreg.h>
11654994Simp#include <dev/sn/if_snvar.h>
11754773Simp
11854994Simp/* Exported variables */
11954994Simpdevclass_t sn_devclass;
12054773Simp
12154994Simpstatic int snioctl(struct ifnet * ifp, u_long, caddr_t);
12254773Simp
12354994Simpstatic void snresume(struct ifnet *);
12454773Simp
125199559Sjhbstatic void snintr_locked(struct sn_softc *);
126121589Simpstatic void sninit_locked(void *);
127121589Simpstatic void snstart_locked(struct ifnet *);
12854773Simp
129121589Simpstatic void sninit(void *);
130121589Simpstatic void snread(struct ifnet *);
131121589Simpstatic void snstart(struct ifnet *);
132121589Simpstatic void snstop(struct sn_softc *);
133199559Sjhbstatic void snwatchdog(void *);
134121589Simp
13554773Simpstatic void sn_setmcast(struct sn_softc *);
136147256Sbrooksstatic int sn_getmcf(struct ifnet *ifp, u_char *mcf);
13754773Simp
13854773Simp/* I (GB) have been unlucky getting the hardware padding
13954773Simp * to work properly.
14054773Simp */
14154773Simp#define SW_PAD
14254773Simp
14354994Simpstatic const char *chip_ids[15] = {
14454994Simp	NULL, NULL, NULL,
14554994Simp	 /* 3 */ "SMC91C90/91C92",
146148144Simp	 /* 4 */ "SMC91C94/91C96",
14754994Simp	 /* 5 */ "SMC91C95",
14854994Simp	NULL,
14954994Simp	 /* 7 */ "SMC91C100",
15071060Stoshi	 /* 8 */ "SMC91C100FD",
151147872Simp	 /* 9 */ "SMC91C110",
152147872Simp	NULL, NULL,
15354994Simp	NULL, NULL, NULL
15454773Simp};
15554773Simp
15654773Simpint
15754994Simpsn_attach(device_t dev)
15854773Simp{
15954994Simp	struct sn_softc *sc = device_get_softc(dev);
160147256Sbrooks	struct ifnet    *ifp;
161147797Simp	uint16_t        i;
162121589Simp	uint8_t         *p;
16354773Simp	int             rev;
164121589Simp	uint16_t        address;
165122427Simp	int		err;
166147256Sbrooks	u_char		eaddr[6];
16754773Simp
168147256Sbrooks	ifp = sc->ifp = if_alloc(IFT_ETHER);
169147256Sbrooks	if (ifp == NULL) {
170147256Sbrooks		device_printf(dev, "can not if_alloc()\n");
171147256Sbrooks		return (ENOSPC);
172147256Sbrooks	}
173147256Sbrooks
174121589Simp	SN_LOCK_INIT(sc);
175199559Sjhb	callout_init_mtx(&sc->watchdog, &sc->sc_mtx, 0);
17654994Simp	snstop(sc);
17754773Simp	sc->pages_wanted = -1;
17854773Simp
179147797Simp	if (bootverbose || 1) {
180147797Simp		SMC_SELECT_BANK(sc, 3);
181147797Simp		rev = (CSR_READ_2(sc, REVISION_REG_W) >> 4) & 0xf;
182147797Simp		if (chip_ids[rev])
183147797Simp			device_printf(dev, " %s ", chip_ids[rev]);
184147797Simp		else
185149095Simp			device_printf(dev, " unsupported chip: rev %d ", rev);
186147797Simp		SMC_SELECT_BANK(sc, 1);
187147797Simp		i = CSR_READ_2(sc, CONFIG_REG_W);
188147797Simp		printf("%s\n", i & CR_AUI_SELECT ? "AUI" : "UTP");
189147797Simp	}
19054773Simp
19154773Simp	/*
19254773Simp	 * Read the station address from the chip. The MAC address is bank 1,
19354773Simp	 * regs 4 - 9
19454773Simp	 */
195121514Simp	SMC_SELECT_BANK(sc, 1);
196147256Sbrooks	p = (uint8_t *) eaddr;
19754773Simp	for (i = 0; i < 6; i += 2) {
198121514Simp		address = CSR_READ_2(sc, IAR_ADDR0_REG_W + i);
19954773Simp		p[i + 1] = address >> 8;
20054773Simp		p[i] = address & 0xFF;
20154773Simp	}
20254773Simp	ifp->if_softc = sc;
203121816Sbrooks	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
20454773Simp	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
20554773Simp	ifp->if_start = snstart;
20654773Simp	ifp->if_ioctl = snioctl;
20754773Simp	ifp->if_init = sninit;
208155280Simp	ifp->if_baudrate = 10000000;
209207554Ssobomax	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
210207554Ssobomax	ifp->if_snd.ifq_maxlen = ifqmaxlen;
211155280Simp	IFQ_SET_READY(&ifp->if_snd);
21254773Simp
213147256Sbrooks	ether_ifattach(ifp, eaddr);
21454994Simp
21554773Simp	/*
216122427Simp	 * Activate the interrupt so we can get card interrupts.  This
217122427Simp	 * needs to be done last so that we don't have/hold the lock
218122427Simp	 * during startup to avoid LORs in the network layer.
219122427Simp	 */
220122427Simp	if ((err = bus_setup_intr(dev, sc->irq_res,
221166901Spiso	    INTR_TYPE_NET | INTR_MPSAFE, NULL, sn_intr, sc,
222166901Spiso	    &sc->intrhand)) != 0) {
223122427Simp		sn_detach(dev);
224122427Simp		return err;
225122427Simp	}
22654994Simp	return 0;
22754773Simp}
22854773Simp
22954773Simp
23069955Simpint
23169955Simpsn_detach(device_t dev)
23269955Simp{
233147256Sbrooks	struct sn_softc	*sc = device_get_softc(dev);
234147256Sbrooks	struct ifnet	*ifp = sc->ifp;
23569955Simp
236199559Sjhb	ether_ifdetach(ifp);
237199559Sjhb	SN_LOCK(sc);
238121589Simp	snstop(sc);
239199559Sjhb	SN_UNLOCK(sc);
240199559Sjhb	callout_drain(&sc->watchdog);
241150306Simp	sn_deactivate(dev);
242147256Sbrooks	if_free(ifp);
243150183Sru	SN_LOCK_DESTROY(sc);
24469955Simp	return 0;
24569955Simp}
24669955Simp
247121589Simpstatic void
248121589Simpsninit(void *xsc)
249121589Simp{
250121589Simp	struct sn_softc *sc = xsc;
251121589Simp	SN_LOCK(sc);
252121589Simp	sninit_locked(sc);
253121589Simp	SN_UNLOCK(sc);
254121589Simp}
255121589Simp
25654773Simp/*
25754773Simp * Reset and initialize the chip
25854773Simp */
259121589Simpstatic void
260121589Simpsninit_locked(void *xsc)
26154773Simp{
262121553Simp	struct sn_softc *sc = xsc;
263147256Sbrooks	struct ifnet *ifp = sc->ifp;
26454773Simp	int             flags;
26554773Simp	int             mask;
26654773Simp
267121589Simp	SN_ASSERT_LOCKED(sc);
26854773Simp
26954773Simp	/*
27054773Simp	 * This resets the registers mostly to defaults, but doesn't affect
27154773Simp	 * EEPROM.  After the reset cycle, we pause briefly for the chip to
27254773Simp	 * be happy.
27354773Simp	 */
274121514Simp	SMC_SELECT_BANK(sc, 0);
275121514Simp	CSR_WRITE_2(sc, RECV_CONTROL_REG_W, RCR_SOFTRESET);
276121514Simp	SMC_DELAY(sc);
277121514Simp	CSR_WRITE_2(sc, RECV_CONTROL_REG_W, 0x0000);
278121514Simp	SMC_DELAY(sc);
279121514Simp	SMC_DELAY(sc);
28054773Simp
281121514Simp	CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, 0x0000);
28254773Simp
28354773Simp	/*
28454773Simp	 * Set the control register to automatically release succesfully
28554773Simp	 * transmitted packets (making the best use out of our limited
28654773Simp	 * memory) and to enable the EPH interrupt on certain TX errors.
28754773Simp	 */
288121514Simp	SMC_SELECT_BANK(sc, 1);
289121514Simp	CSR_WRITE_2(sc, CONTROL_REG_W, (CTR_AUTO_RELEASE | CTR_TE_ENABLE |
29054773Simp				    CTR_CR_ENABLE | CTR_LE_ENABLE));
29154773Simp
29254773Simp	/* Set squelch level to 240mV (default 480mV) */
293121514Simp	flags = CSR_READ_2(sc, CONFIG_REG_W);
29454773Simp	flags |= CR_SET_SQLCH;
295121514Simp	CSR_WRITE_2(sc, CONFIG_REG_W, flags);
29654773Simp
29754773Simp	/*
29854773Simp	 * Reset the MMU and wait for it to be un-busy.
29954773Simp	 */
300121514Simp	SMC_SELECT_BANK(sc, 2);
301121514Simp	CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_RESET);
302121514Simp	while (CSR_READ_2(sc, MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
30354773Simp		;
30454773Simp
30554773Simp	/*
30654773Simp	 * Disable all interrupts
30754773Simp	 */
308121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, 0x00);
30954773Simp
31054773Simp	sn_setmcast(sc);
31154773Simp
31254773Simp	/*
31354773Simp	 * Set the transmitter control.  We want it enabled.
31454773Simp	 */
31554773Simp	flags = TCR_ENABLE;
31654773Simp
31754773Simp#ifndef SW_PAD
31854773Simp	/*
31954773Simp	 * I (GB) have been unlucky getting this to work.
32054773Simp	 */
32154773Simp	flags |= TCR_PAD_ENABLE;
32254773Simp#endif	/* SW_PAD */
32354773Simp
324121514Simp	CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, flags);
32554773Simp
32654773Simp
32754773Simp	/*
32854773Simp	 * Now, enable interrupts
32954773Simp	 */
330121514Simp	SMC_SELECT_BANK(sc, 2);
33154773Simp
33254773Simp	mask = IM_EPH_INT |
33354773Simp		IM_RX_OVRN_INT |
33454773Simp		IM_RCV_INT |
33554773Simp		IM_TX_INT;
33654773Simp
337121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
33854773Simp	sc->intr_mask = mask;
33954773Simp	sc->pages_wanted = -1;
34054773Simp
34154773Simp
34254773Simp	/*
34354773Simp	 * Mark the interface running but not active.
34454773Simp	 */
345148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
346148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
347199559Sjhb	callout_reset(&sc->watchdog, hz, snwatchdog, sc);
34854773Simp
34954773Simp	/*
35054773Simp	 * Attempt to push out any waiting packets.
35154773Simp	 */
352121589Simp	snstart_locked(ifp);
353121589Simp}
35454773Simp
355121589Simpstatic void
356121589Simpsnstart(struct ifnet *ifp)
357121589Simp{
358121589Simp	struct sn_softc *sc = ifp->if_softc;
359121589Simp	SN_LOCK(sc);
360121589Simp	snstart_locked(ifp);
361121589Simp	SN_UNLOCK(sc);
36254773Simp}
36354773Simp
36454773Simp
365121589Simpstatic void
366121589Simpsnstart_locked(struct ifnet *ifp)
36754773Simp{
368121553Simp	struct sn_softc *sc = ifp->if_softc;
369121589Simp	u_int		len;
370121589Simp	struct mbuf	*m;
371121589Simp	struct mbuf	*top;
372121589Simp	int             pad;
37354773Simp	int             mask;
374121589Simp	uint16_t        length;
375121589Simp	uint16_t        numPages;
376121589Simp	uint8_t         packet_no;
37754773Simp	int             time_out;
37866058Simp	int		junk = 0;
37954773Simp
380121589Simp	SN_ASSERT_LOCKED(sc);
38154773Simp
382154100Simp	if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
38354773Simp		return;
38454773Simp	if (sc->pages_wanted != -1) {
385104257Sbrooks		if_printf(ifp, "snstart() while memory allocation pending\n");
38654773Simp		return;
38754773Simp	}
38854773Simpstartagain:
38954773Simp
39054773Simp	/*
39154773Simp	 * Sneak a peek at the next packet
39254773Simp	 */
393154100Simp	m = ifp->if_snd.ifq_head;
394121589Simp	if (m == 0)
39554773Simp		return;
39654773Simp	/*
39754773Simp	 * Compute the frame length and set pad to give an overall even
39854773Simp	 * number of bytes.  Below we assume that the packet length is even.
39954773Simp	 */
40054773Simp	for (len = 0, top = m; m; m = m->m_next)
40154773Simp		len += m->m_len;
40254773Simp
40354773Simp	pad = (len & 1);
40454773Simp
40554773Simp	/*
40654773Simp	 * We drop packets that are too large. Perhaps we should truncate
40754773Simp	 * them instead?
40854773Simp	 */
40954773Simp	if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) {
410104257Sbrooks		if_printf(ifp, "large packet discarded (A)\n");
411154100Simp		++ifp->if_oerrors;
412155283Simp		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
41354773Simp		m_freem(m);
41454773Simp		goto readcheck;
41554773Simp	}
41654773Simp#ifdef SW_PAD
41754773Simp
41854773Simp	/*
41954773Simp	 * If HW padding is not turned on, then pad to ETHER_MIN_LEN.
42054773Simp	 */
42154773Simp	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
42254773Simp		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
42354773Simp
42454773Simp#endif	/* SW_PAD */
42554773Simp
42654773Simp	length = pad + len;
42754773Simp
42854773Simp	/*
42954773Simp	 * The MMU wants the number of pages to be the number of 256 byte
43054773Simp	 * 'pages', minus 1 (A packet can't ever have 0 pages. We also
43154773Simp	 * include space for the status word, byte count and control bytes in
43254773Simp	 * the allocation request.
43354773Simp	 */
43454773Simp	numPages = (length + 6) >> 8;
43554773Simp
43654773Simp
43754773Simp	/*
43854773Simp	 * Now, try to allocate the memory
43954773Simp	 */
440121514Simp	SMC_SELECT_BANK(sc, 2);
441121514Simp	CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_ALLOC | numPages);
44254773Simp
44354773Simp	/*
44454773Simp	 * Wait a short amount of time to see if the allocation request
44554773Simp	 * completes.  Otherwise, I enable the interrupt and wait for
446250460Seadler	 * completion asynchronously.
44754773Simp	 */
44854773Simp
44954773Simp	time_out = MEMORY_WAIT_TIME;
45054773Simp	do {
451121514Simp		if (CSR_READ_1(sc, INTR_STAT_REG_B) & IM_ALLOC_INT)
45254773Simp			break;
45354773Simp	} while (--time_out);
45454773Simp
45566058Simp	if (!time_out || junk > 10) {
45654773Simp
45754773Simp		/*
45854773Simp		 * No memory now.  Oh well, wait until the chip finds memory
45954773Simp		 * later.   Remember how many pages we were asking for and
46054773Simp		 * enable the allocation completion interrupt. Also set a
46154773Simp		 * watchdog in case  we miss the interrupt. We mark the
46254773Simp		 * interface active since there is no point in attempting an
46354773Simp		 * snstart() until after the memory is available.
46454773Simp		 */
465121514Simp		mask = CSR_READ_1(sc, INTR_MASK_REG_B) | IM_ALLOC_INT;
466121514Simp		CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
46754773Simp		sc->intr_mask = mask;
46854773Simp
469199559Sjhb		sc->timer = 1;
470154100Simp		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
47154773Simp		sc->pages_wanted = numPages;
47254773Simp		return;
47354773Simp	}
47454773Simp	/*
47554773Simp	 * The memory allocation completed.  Check the results.
47654773Simp	 */
477121514Simp	packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B);
47854773Simp	if (packet_no & ARR_FAILED) {
47966058Simp		if (junk++ > 10)
480104257Sbrooks			if_printf(ifp, "Memory allocation failed\n");
48154773Simp		goto startagain;
48254773Simp	}
48354773Simp	/*
48454773Simp	 * We have a packet number, so tell the card to use it.
48554773Simp	 */
486121514Simp	CSR_WRITE_1(sc, PACKET_NUM_REG_B, packet_no);
48754773Simp
48854773Simp	/*
48954773Simp	 * Point to the beginning of the packet
49054773Simp	 */
491121514Simp	CSR_WRITE_2(sc, POINTER_REG_W, PTR_AUTOINC | 0x0000);
49254773Simp
49354773Simp	/*
49454773Simp	 * Send the packet length (+6 for status, length and control byte)
49554773Simp	 * and the status word (set to zeros)
49654773Simp	 */
497121514Simp	CSR_WRITE_2(sc, DATA_REG_W, 0);
498121514Simp	CSR_WRITE_1(sc, DATA_REG_B, (length + 6) & 0xFF);
499121514Simp	CSR_WRITE_1(sc, DATA_REG_B, (length + 6) >> 8);
50054773Simp
50154773Simp	/*
50254773Simp	 * Get the packet from the kernel.  This will include the Ethernet
50354773Simp	 * frame header, MAC Addresses etc.
50454773Simp	 */
505155283Simp	IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
50654773Simp
50754773Simp	/*
50854773Simp	 * Push out the data to the card.
50954773Simp	 */
51054773Simp	for (top = m; m != 0; m = m->m_next) {
51154773Simp
51254773Simp		/*
51354773Simp		 * Push out words.
51454773Simp		 */
515121514Simp		CSR_WRITE_MULTI_2(sc, DATA_REG_W, mtod(m, uint16_t *),
516121514Simp		    m->m_len / 2);
51754773Simp
51854773Simp		/*
51954773Simp		 * Push out remaining byte.
52054773Simp		 */
52154773Simp		if (m->m_len & 1)
522121514Simp			CSR_WRITE_1(sc, DATA_REG_B,
523121514Simp			    *(mtod(m, caddr_t) + m->m_len - 1));
52454773Simp	}
52554773Simp
52654773Simp	/*
52754773Simp	 * Push out padding.
52854773Simp	 */
52954773Simp	while (pad > 1) {
530121514Simp		CSR_WRITE_2(sc, DATA_REG_W, 0);
53154773Simp		pad -= 2;
53254773Simp	}
53354773Simp	if (pad)
534121514Simp		CSR_WRITE_1(sc, DATA_REG_B, 0);
53554773Simp
53654773Simp	/*
53754773Simp	 * Push out control byte and unused packet byte The control byte is 0
53854773Simp	 * meaning the packet is even lengthed and no special CRC handling is
53954773Simp	 * desired.
54054773Simp	 */
541121514Simp	CSR_WRITE_2(sc, DATA_REG_W, 0);
54254773Simp
54354773Simp	/*
54454773Simp	 * Enable the interrupts and let the chipset deal with it Also set a
54554773Simp	 * watchdog in case we miss the interrupt.
54654773Simp	 */
547121514Simp	mask = CSR_READ_1(sc, INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
548121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
54954773Simp	sc->intr_mask = mask;
55054773Simp
551121514Simp	CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_ENQUEUE);
55254773Simp
553154100Simp	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
554199559Sjhb	sc->timer = 1;
55554773Simp
556106937Ssam	BPF_MTAP(ifp, top);
55754773Simp
558154100Simp	ifp->if_opackets++;
55954773Simp	m_freem(top);
56054773Simp
56154773Simp
56254773Simpreadcheck:
56354773Simp
56454773Simp	/*
56554773Simp	 * Is another packet coming in?  We don't want to overflow the tiny
56654773Simp	 * RX FIFO.  If nothing has arrived then attempt to queue another
56754773Simp	 * transmit packet.
56854773Simp	 */
569121514Simp	if (CSR_READ_2(sc, FIFO_PORTS_REG_W) & FIFO_REMPTY)
57054773Simp		goto startagain;
57154773Simp	return;
57254773Simp}
57354773Simp
57454773Simp
57554773Simp
57654773Simp/* Resume a packet transmit operation after a memory allocation
57754773Simp * has completed.
57854773Simp *
57954773Simp * This is basically a hacked up copy of snstart() which handles
58054773Simp * a completed memory allocation the same way snstart() does.
58154773Simp * It then passes control to snstart to handle any other queued
58254773Simp * packets.
58354773Simp */
58454773Simpstatic void
58554773Simpsnresume(struct ifnet *ifp)
58654773Simp{
587121553Simp	struct sn_softc *sc = ifp->if_softc;
588121589Simp	u_int		len;
589121589Simp	struct mbuf	*m;
59054773Simp	struct mbuf    *top;
59154773Simp	int             pad;
59254773Simp	int             mask;
593121589Simp	uint16_t        length;
594121589Simp	uint16_t        numPages;
595121589Simp	uint16_t        pages_wanted;
596121589Simp	uint8_t         packet_no;
59754773Simp
59854773Simp	if (sc->pages_wanted < 0)
59954773Simp		return;
60054773Simp
60154773Simp	pages_wanted = sc->pages_wanted;
60254773Simp	sc->pages_wanted = -1;
60354773Simp
60454773Simp	/*
60554773Simp	 * Sneak a peek at the next packet
60654773Simp	 */
607154100Simp	m = ifp->if_snd.ifq_head;
60854773Simp	if (m == 0) {
609104257Sbrooks		if_printf(ifp, "snresume() with nothing to send\n");
61054773Simp		return;
61154773Simp	}
61254773Simp	/*
61354773Simp	 * Compute the frame length and set pad to give an overall even
61454773Simp	 * number of bytes.  Below we assume that the packet length is even.
61554773Simp	 */
61654773Simp	for (len = 0, top = m; m; m = m->m_next)
61754773Simp		len += m->m_len;
61854773Simp
61954773Simp	pad = (len & 1);
62054773Simp
62154773Simp	/*
62254773Simp	 * We drop packets that are too large. Perhaps we should truncate
62354773Simp	 * them instead?
62454773Simp	 */
62554773Simp	if (len + pad > ETHER_MAX_LEN - ETHER_CRC_LEN) {
626104257Sbrooks		if_printf(ifp, "large packet discarded (B)\n");
627154100Simp		++ifp->if_oerrors;
628155283Simp		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
62954773Simp		m_freem(m);
63054773Simp		return;
63154773Simp	}
63254773Simp#ifdef SW_PAD
63354773Simp
63454773Simp	/*
63554773Simp	 * If HW padding is not turned on, then pad to ETHER_MIN_LEN.
63654773Simp	 */
63754773Simp	if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
63854773Simp		pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
63954773Simp
64054773Simp#endif	/* SW_PAD */
64154773Simp
64254773Simp	length = pad + len;
64354773Simp
64454773Simp
64554773Simp	/*
64654773Simp	 * The MMU wants the number of pages to be the number of 256 byte
64754773Simp	 * 'pages', minus 1 (A packet can't ever have 0 pages. We also
64854773Simp	 * include space for the status word, byte count and control bytes in
64954773Simp	 * the allocation request.
65054773Simp	 */
65154773Simp	numPages = (length + 6) >> 8;
65254773Simp
65354773Simp
654121514Simp	SMC_SELECT_BANK(sc, 2);
65554773Simp
65654773Simp	/*
65754773Simp	 * The memory allocation completed.  Check the results. If it failed,
65854773Simp	 * we simply set a watchdog timer and hope for the best.
65954773Simp	 */
660121514Simp	packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B);
66154773Simp	if (packet_no & ARR_FAILED) {
662104257Sbrooks		if_printf(ifp, "Memory allocation failed.  Weird.\n");
663199559Sjhb		sc->timer = 1;
66454773Simp		goto try_start;
66554773Simp	}
66654773Simp	/*
66754773Simp	 * We have a packet number, so tell the card to use it.
66854773Simp	 */
669121514Simp	CSR_WRITE_1(sc, PACKET_NUM_REG_B, packet_no);
67054773Simp
67154773Simp	/*
67254773Simp	 * Now, numPages should match the pages_wanted recorded when the
67354773Simp	 * memory allocation was initiated.
67454773Simp	 */
67554773Simp	if (pages_wanted != numPages) {
676104257Sbrooks		if_printf(ifp, "memory allocation wrong size.  Weird.\n");
67754773Simp		/*
67854773Simp		 * If the allocation was the wrong size we simply release the
67954773Simp		 * memory once it is granted. Wait for the MMU to be un-busy.
68054773Simp		 */
681121514Simp		while (CSR_READ_2(sc, MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
68254773Simp			;
683121514Simp		CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_FREEPKT);
68454773Simp
68554773Simp		return;
68654773Simp	}
68754773Simp	/*
68854773Simp	 * Point to the beginning of the packet
68954773Simp	 */
690121514Simp	CSR_WRITE_2(sc, POINTER_REG_W, PTR_AUTOINC | 0x0000);
69154773Simp
69254773Simp	/*
69354773Simp	 * Send the packet length (+6 for status, length and control byte)
69454773Simp	 * and the status word (set to zeros)
69554773Simp	 */
696121514Simp	CSR_WRITE_2(sc, DATA_REG_W, 0);
697121514Simp	CSR_WRITE_1(sc, DATA_REG_B, (length + 6) & 0xFF);
698121514Simp	CSR_WRITE_1(sc, DATA_REG_B, (length + 6) >> 8);
69954773Simp
70054773Simp	/*
70154773Simp	 * Get the packet from the kernel.  This will include the Ethernet
70254773Simp	 * frame header, MAC Addresses etc.
70354773Simp	 */
704155283Simp	IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
70554773Simp
70654773Simp	/*
70754773Simp	 * Push out the data to the card.
70854773Simp	 */
70954773Simp	for (top = m; m != 0; m = m->m_next) {
71054773Simp
71154773Simp		/*
71254773Simp		 * Push out words.
71354773Simp		 */
714121514Simp		CSR_WRITE_MULTI_2(sc, DATA_REG_W, mtod(m, uint16_t *),
715121514Simp		    m->m_len / 2);
71654773Simp		/*
71754773Simp		 * Push out remaining byte.
71854773Simp		 */
71954773Simp		if (m->m_len & 1)
720121514Simp			CSR_WRITE_1(sc, DATA_REG_B,
721121514Simp			    *(mtod(m, caddr_t) + m->m_len - 1));
72254773Simp	}
72354773Simp
72454773Simp	/*
72554773Simp	 * Push out padding.
72654773Simp	 */
72754773Simp	while (pad > 1) {
728121514Simp		CSR_WRITE_2(sc, DATA_REG_W, 0);
72954773Simp		pad -= 2;
73054773Simp	}
73154773Simp	if (pad)
732121514Simp		CSR_WRITE_1(sc, DATA_REG_B, 0);
73354773Simp
73454773Simp	/*
73554773Simp	 * Push out control byte and unused packet byte The control byte is 0
73654773Simp	 * meaning the packet is even lengthed and no special CRC handling is
73754773Simp	 * desired.
73854773Simp	 */
739121514Simp	CSR_WRITE_2(sc, DATA_REG_W, 0);
74054773Simp
74154773Simp	/*
74254773Simp	 * Enable the interrupts and let the chipset deal with it Also set a
74354773Simp	 * watchdog in case we miss the interrupt.
74454773Simp	 */
745121514Simp	mask = CSR_READ_1(sc, INTR_MASK_REG_B) | (IM_TX_INT | IM_TX_EMPTY_INT);
746121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
74754773Simp	sc->intr_mask = mask;
748121514Simp	CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_ENQUEUE);
74954773Simp
750106937Ssam	BPF_MTAP(ifp, top);
75154773Simp
752154100Simp	ifp->if_opackets++;
75354773Simp	m_freem(top);
75454773Simp
75554773Simptry_start:
75654773Simp
75754773Simp	/*
75854773Simp	 * Now pass control to snstart() to queue any additional packets
75954773Simp	 */
760154100Simp	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
761199559Sjhb	snstart_locked(ifp);
76254773Simp
76354773Simp	/*
76454773Simp	 * We've sent something, so we're active.  Set a watchdog in case the
76554773Simp	 * TX_EMPTY interrupt is lost.
76654773Simp	 */
767154100Simp	ifp->if_drv_flags |= IFF_DRV_OACTIVE;
768199559Sjhb	sc->timer = 1;
76954773Simp
77054773Simp	return;
77154773Simp}
77254773Simp
77354773Simpvoid
77454994Simpsn_intr(void *arg)
77554773Simp{
776199559Sjhb	struct sn_softc *sc = (struct sn_softc *) arg;
777199559Sjhb
778199559Sjhb	SN_LOCK(sc);
779199559Sjhb	snintr_locked(sc);
780199559Sjhb	SN_UNLOCK(sc);
781199559Sjhb}
782199559Sjhb
783199559Sjhbstatic void
784199559Sjhbsnintr_locked(struct sn_softc *sc)
785199559Sjhb{
78654773Simp	int             status, interrupts;
787147256Sbrooks	struct ifnet   *ifp = sc->ifp;
78854773Simp
78954773Simp	/*
79054773Simp	 * Chip state registers
79154773Simp	 */
792121589Simp	uint8_t          mask;
793121589Simp	uint8_t         packet_no;
794121589Simp	uint16_t        tx_status;
795121589Simp	uint16_t        card_stats;
79654773Simp
79754773Simp	/*
79854773Simp	 * Clear the watchdog.
79954773Simp	 */
800199559Sjhb	sc->timer = 0;
80154773Simp
802121514Simp	SMC_SELECT_BANK(sc, 2);
80354773Simp
80454773Simp	/*
80554773Simp	 * Obtain the current interrupt mask and clear the hardware mask
80654773Simp	 * while servicing interrupts.
80754773Simp	 */
808121514Simp	mask = CSR_READ_1(sc, INTR_MASK_REG_B);
809121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, 0x00);
81054773Simp
81154773Simp	/*
81254773Simp	 * Get the set of interrupts which occurred and eliminate any which
81354773Simp	 * are masked.
81454773Simp	 */
815121514Simp	interrupts = CSR_READ_1(sc, INTR_STAT_REG_B);
81654773Simp	status = interrupts & mask;
81754773Simp
81854773Simp	/*
81954773Simp	 * Now, process each of the interrupt types.
82054773Simp	 */
82154773Simp
82254773Simp	/*
82354773Simp	 * Receive Overrun.
82454773Simp	 */
82554773Simp	if (status & IM_RX_OVRN_INT) {
82654773Simp		/*
82754773Simp		 * Acknowlege Interrupt
82854773Simp		 */
829121514Simp		SMC_SELECT_BANK(sc, 2);
830121514Simp		CSR_WRITE_1(sc, INTR_ACK_REG_B, IM_RX_OVRN_INT);
83154773Simp
832154100Simp		++ifp->if_ierrors;
83354773Simp	}
83454773Simp	/*
83554773Simp	 * Got a packet.
83654773Simp	 */
83754773Simp	if (status & IM_RCV_INT) {
83854773Simp		int             packet_number;
83954773Simp
840121514Simp		SMC_SELECT_BANK(sc, 2);
841121514Simp		packet_number = CSR_READ_2(sc, FIFO_PORTS_REG_W);
84254773Simp
84354773Simp		if (packet_number & FIFO_REMPTY) {
84454773Simp			/*
84554773Simp			 * we got called , but nothing was on the FIFO
84654773Simp			 */
84754773Simp			printf("sn: Receive interrupt with nothing on FIFO\n");
84854773Simp			goto out;
84954773Simp		}
85054773Simp		snread(ifp);
85154773Simp	}
85254773Simp	/*
85354773Simp	 * An on-card memory allocation came through.
85454773Simp	 */
85554773Simp	if (status & IM_ALLOC_INT) {
85654773Simp		/*
85754773Simp		 * Disable this interrupt.
85854773Simp		 */
85954773Simp		mask &= ~IM_ALLOC_INT;
860154100Simp		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
861154100Simp		snresume(ifp);
86254773Simp	}
86354773Simp	/*
86454773Simp	 * TX Completion.  Handle a transmit error message. This will only be
86554773Simp	 * called when there is an error, because of the AUTO_RELEASE mode.
86654773Simp	 */
86754773Simp	if (status & IM_TX_INT) {
86854773Simp		/*
86954773Simp		 * Acknowlege Interrupt
87054773Simp		 */
871121514Simp		SMC_SELECT_BANK(sc, 2);
872121514Simp		CSR_WRITE_1(sc, INTR_ACK_REG_B, IM_TX_INT);
87354773Simp
874121514Simp		packet_no = CSR_READ_2(sc, FIFO_PORTS_REG_W);
87554773Simp		packet_no &= FIFO_TX_MASK;
87654773Simp
87754773Simp		/*
87854773Simp		 * select this as the packet to read from
87954773Simp		 */
880121514Simp		CSR_WRITE_1(sc, PACKET_NUM_REG_B, packet_no);
88154773Simp
88254773Simp		/*
88354773Simp		 * Position the pointer to the first word from this packet
88454773Simp		 */
885121514Simp		CSR_WRITE_2(sc, POINTER_REG_W, PTR_AUTOINC | PTR_READ | 0x0000);
88654773Simp
88754773Simp		/*
88854773Simp		 * Fetch the TX status word.  The value found here will be a
88954773Simp		 * copy of the EPH_STATUS_REG_W at the time the transmit
89054773Simp		 * failed.
89154773Simp		 */
892121514Simp		tx_status = CSR_READ_2(sc, DATA_REG_W);
89354773Simp
89454773Simp		if (tx_status & EPHSR_TX_SUC) {
89554994Simp			device_printf(sc->dev,
89654994Simp			    "Successful packet caused interrupt\n");
89754773Simp		} else {
898154100Simp			++ifp->if_oerrors;
89954773Simp		}
90054773Simp
90154773Simp		if (tx_status & EPHSR_LATCOL)
902154100Simp			++ifp->if_collisions;
90354773Simp
90454773Simp		/*
90554773Simp		 * Some of these errors will have disabled transmit.
90654773Simp		 * Re-enable transmit now.
90754773Simp		 */
908121514Simp		SMC_SELECT_BANK(sc, 0);
90954773Simp
91054773Simp#ifdef SW_PAD
911121514Simp		CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, TCR_ENABLE);
91254773Simp#else
913121514Simp		CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, TCR_ENABLE | TCR_PAD_ENABLE);
91454773Simp#endif	/* SW_PAD */
91554773Simp
91654773Simp		/*
91754773Simp		 * kill the failed packet. Wait for the MMU to be un-busy.
91854773Simp		 */
919121514Simp		SMC_SELECT_BANK(sc, 2);
920121514Simp		while (CSR_READ_2(sc, MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
92154773Simp			;
922121514Simp		CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_FREEPKT);
92354773Simp
92454773Simp		/*
92554773Simp		 * Attempt to queue more transmits.
92654773Simp		 */
927154100Simp		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
928154100Simp		snstart_locked(ifp);
92954773Simp	}
93054773Simp	/*
93154773Simp	 * Transmit underrun.  We use this opportunity to update transmit
93254773Simp	 * statistics from the card.
93354773Simp	 */
93454773Simp	if (status & IM_TX_EMPTY_INT) {
93554773Simp
93654773Simp		/*
93754773Simp		 * Acknowlege Interrupt
93854773Simp		 */
939121514Simp		SMC_SELECT_BANK(sc, 2);
940121514Simp		CSR_WRITE_1(sc, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
94154773Simp
94254773Simp		/*
94354773Simp		 * Disable this interrupt.
94454773Simp		 */
94554773Simp		mask &= ~IM_TX_EMPTY_INT;
94654773Simp
947121514Simp		SMC_SELECT_BANK(sc, 0);
948121514Simp		card_stats = CSR_READ_2(sc, COUNTER_REG_W);
94954773Simp
95054773Simp		/*
95154773Simp		 * Single collisions
95254773Simp		 */
953154100Simp		ifp->if_collisions += card_stats & ECR_COLN_MASK;
95454773Simp
95554773Simp		/*
95654773Simp		 * Multiple collisions
95754773Simp		 */
958154100Simp		ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
95954773Simp
960121514Simp		SMC_SELECT_BANK(sc, 2);
96154773Simp
96254773Simp		/*
96354773Simp		 * Attempt to enqueue some more stuff.
96454773Simp		 */
965154100Simp		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
966154100Simp		snstart_locked(ifp);
96754773Simp	}
96854773Simp	/*
96954773Simp	 * Some other error.  Try to fix it by resetting the adapter.
97054773Simp	 */
97154773Simp	if (status & IM_EPH_INT) {
97254994Simp		snstop(sc);
973121589Simp		sninit_locked(sc);
97454773Simp	}
97554773Simp
97654773Simpout:
97754773Simp	/*
97854773Simp	 * Handled all interrupt sources.
97954773Simp	 */
98054773Simp
981121514Simp	SMC_SELECT_BANK(sc, 2);
98254773Simp
98354773Simp	/*
98454773Simp	 * Reestablish interrupts from mask which have not been deselected
98554773Simp	 * during this interrupt.  Note that the hardware mask, which was set
98654773Simp	 * to 0x00 at the start of this service routine, may have been
98754773Simp	 * updated by one or more of the interrupt handers and we must let
98854773Simp	 * those new interrupts stay enabled here.
98954773Simp	 */
990121514Simp	mask |= CSR_READ_1(sc, INTR_MASK_REG_B);
991121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, mask);
99254773Simp	sc->intr_mask = mask;
99354773Simp}
99454773Simp
995121589Simpstatic void
996121553Simpsnread(struct ifnet *ifp)
99754773Simp{
99854994Simp        struct sn_softc *sc = ifp->if_softc;
99954773Simp	struct ether_header *eh;
100054773Simp	struct mbuf    *m;
100154773Simp	short           status;
100254773Simp	int             packet_number;
1003121589Simp	uint16_t        packet_length;
1004121589Simp	uint8_t        *data;
100554773Simp
1006121514Simp	SMC_SELECT_BANK(sc, 2);
100754773Simp#if 0
1008121514Simp	packet_number = CSR_READ_2(sc, FIFO_PORTS_REG_W);
100954773Simp
101054773Simp	if (packet_number & FIFO_REMPTY) {
101154773Simp
101254773Simp		/*
101354773Simp		 * we got called , but nothing was on the FIFO
101454773Simp		 */
101554773Simp		printf("sn: Receive interrupt with nothing on FIFO\n");
101654773Simp		return;
101754773Simp	}
101854773Simp#endif
101954773Simpread_another:
102054773Simp
102154773Simp	/*
102254773Simp	 * Start reading from the start of the packet. Since PTR_RCV is set,
102354773Simp	 * packet number is found in FIFO_PORTS_REG_W, FIFO_RX_MASK.
102454773Simp	 */
1025121514Simp	CSR_WRITE_2(sc, POINTER_REG_W, PTR_READ | PTR_RCV | PTR_AUTOINC | 0x0000);
102654773Simp
102754773Simp	/*
102854773Simp	 * First two words are status and packet_length
102954773Simp	 */
1030121514Simp	status = CSR_READ_2(sc, DATA_REG_W);
1031121514Simp	packet_length = CSR_READ_2(sc, DATA_REG_W) & RLEN_MASK;
103254773Simp
103354773Simp	/*
103454773Simp	 * The packet length contains 3 extra words: status, length, and a
103554773Simp	 * extra word with the control byte.
103654773Simp	 */
103754773Simp	packet_length -= 6;
103854773Simp
103954773Simp	/*
104054773Simp	 * Account for receive errors and discard.
104154773Simp	 */
104254773Simp	if (status & RS_ERRORS) {
1043154100Simp		++ifp->if_ierrors;
104454773Simp		goto out;
104554773Simp	}
104654773Simp	/*
104754773Simp	 * A packet is received.
104854773Simp	 */
104954773Simp
105054773Simp	/*
105154773Simp	 * Adjust for odd-length packet.
105254773Simp	 */
105354773Simp	if (status & RS_ODDFRAME)
105454773Simp		packet_length++;
105554773Simp
105654773Simp	/*
105754773Simp	 * Allocate a header mbuf from the kernel.
105854773Simp	 */
1059243857Sglebius	MGETHDR(m, M_NOWAIT, MT_DATA);
106054773Simp	if (m == NULL)
106154773Simp		goto out;
106254773Simp
1063154100Simp	m->m_pkthdr.rcvif = ifp;
106454773Simp	m->m_pkthdr.len = m->m_len = packet_length;
106554773Simp
106654773Simp	/*
106754773Simp	 * Attach an mbuf cluster
106854773Simp	 */
1069243857Sglebius	MCLGET(m, M_NOWAIT);
107054773Simp
107154773Simp	/*
107254773Simp	 * Insist on getting a cluster
107354773Simp	 */
107454773Simp	if ((m->m_flags & M_EXT) == 0) {
107554773Simp		m_freem(m);
1076154100Simp		++ifp->if_ierrors;
107754773Simp		printf("sn: snread() kernel memory allocation problem\n");
107854773Simp		goto out;
107954773Simp	}
108054773Simp	eh = mtod(m, struct ether_header *);
108154773Simp
108254773Simp	/*
108354773Simp	 * Get packet, including link layer address, from interface.
108454773Simp	 */
1085121589Simp	data = (uint8_t *) eh;
1086121514Simp	CSR_READ_MULTI_2(sc, DATA_REG_W, (uint16_t *) data, packet_length >> 1);
108754773Simp	if (packet_length & 1) {
108854773Simp		data += packet_length & ~1;
1089121514Simp		*data = CSR_READ_1(sc, DATA_REG_B);
109054773Simp	}
1091154100Simp	++ifp->if_ipackets;
109254773Simp
109354773Simp	/*
109454773Simp	 * Remove link layer addresses and whatnot.
109554773Simp	 */
1096106937Ssam	m->m_pkthdr.len = m->m_len = packet_length;
109754773Simp
1098121589Simp	/*
1099121589Simp	 * Drop locks before calling if_input() since it may re-enter
1100121589Simp	 * snstart() in the netisr case.  This would result in a
1101121589Simp	 * lock reversal.  Better performance might be obtained by
1102121589Simp	 * chaining all packets received, dropping the lock, and then
1103121589Simp	 * calling if_input() on each one.
1104121589Simp	 */
1105121589Simp	SN_UNLOCK(sc);
1106106937Ssam	(*ifp->if_input)(ifp, m);
1107121589Simp	SN_LOCK(sc);
110854773Simp
110954773Simpout:
111054773Simp
111154773Simp	/*
111254773Simp	 * Error or good, tell the card to get rid of this packet Wait for
111354773Simp	 * the MMU to be un-busy.
111454773Simp	 */
1115121514Simp	SMC_SELECT_BANK(sc, 2);
1116121514Simp	while (CSR_READ_2(sc, MMU_CMD_REG_W) & MMUCR_BUSY)	/* NOTHING */
111754773Simp		;
1118121514Simp	CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_RELEASE);
111954773Simp
112054773Simp	/*
112154773Simp	 * Check whether another packet is ready
112254773Simp	 */
1123121514Simp	packet_number = CSR_READ_2(sc, FIFO_PORTS_REG_W);
112454773Simp	if (packet_number & FIFO_REMPTY) {
112554773Simp		return;
112654773Simp	}
112754773Simp	goto read_another;
112854773Simp}
112954773Simp
113054773Simp
113154773Simp/*
113254773Simp * Handle IOCTLS.  This function is completely stolen from if_ep.c
113354773Simp * As with its progenitor, it does not handle hardware address
113454773Simp * changes.
113554773Simp */
113654773Simpstatic int
1137121553Simpsnioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
113854773Simp{
113954994Simp	struct sn_softc *sc = ifp->if_softc;
1140121589Simp	int             error = 0;
114154773Simp
114254773Simp	switch (cmd) {
114354773Simp	case SIOCSIFFLAGS:
1144121589Simp		SN_LOCK(sc);
1145148887Srwatson		if ((ifp->if_flags & IFF_UP) == 0 &&
1146148887Srwatson		    ifp->if_drv_flags & IFF_DRV_RUNNING) {
114754994Simp			snstop(sc);
114854773Simp		} else {
114954773Simp			/* reinitialize card on any parameter change */
1150121589Simp			sninit_locked(sc);
115154773Simp		}
1152121589Simp		SN_UNLOCK(sc);
115354773Simp		break;
115454773Simp
115554773Simp	case SIOCADDMULTI:
115654773Simp	case SIOCDELMULTI:
1157121589Simp		/* update multicast filter list. */
1158121589Simp		SN_LOCK(sc);
1159121589Simp		sn_setmcast(sc);
1160121589Simp		error = 0;
1161121589Simp		SN_UNLOCK(sc);
1162121589Simp		break;
116354773Simp	default:
1164106937Ssam		error = ether_ioctl(ifp, cmd, data);
1165106937Ssam		break;
116654773Simp	}
116754773Simp	return (error);
116854773Simp}
116954773Simp
1170121589Simpstatic void
1171199559Sjhbsnwatchdog(void *arg)
117254773Simp{
1173199559Sjhb	struct sn_softc *sc;
1174199559Sjhb
1175199559Sjhb	sc = arg;
1176199559Sjhb	SN_ASSERT_LOCKED(sc);
1177199559Sjhb	callout_reset(&sc->watchdog, hz, snwatchdog, sc);
1178199559Sjhb	if (sc->timer == 0 || --sc->timer > 0)
1179199559Sjhb		return;
1180199559Sjhb	snintr_locked(sc);
118154773Simp}
118254773Simp
118354773Simp
118454773Simp/* 1. zero the interrupt mask
118554773Simp * 2. clear the enable receive flag
118654773Simp * 3. clear the enable xmit flags
118754773Simp */
1188121589Simpstatic void
118954994Simpsnstop(struct sn_softc *sc)
119054773Simp{
119154994Simp
1192147256Sbrooks	struct ifnet   *ifp = sc->ifp;
119354773Simp
119454773Simp	/*
119554773Simp	 * Clear interrupt mask; disable all interrupts.
119654773Simp	 */
1197121514Simp	SMC_SELECT_BANK(sc, 2);
1198121514Simp	CSR_WRITE_1(sc, INTR_MASK_REG_B, 0x00);
119954773Simp
120054773Simp	/*
120154773Simp	 * Disable transmitter and Receiver
120254773Simp	 */
1203121514Simp	SMC_SELECT_BANK(sc, 0);
1204121514Simp	CSR_WRITE_2(sc, RECV_CONTROL_REG_W, 0x0000);
1205121514Simp	CSR_WRITE_2(sc, TXMIT_CONTROL_REG_W, 0x0000);
120654773Simp
120754773Simp	/*
120854773Simp	 * Cancel watchdog.
120954773Simp	 */
1210199559Sjhb	sc->timer = 0;
1211199559Sjhb	callout_stop(&sc->watchdog);
1212199559Sjhb	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
121354773Simp}
121454773Simp
121554773Simp
121654994Simpint
121754994Simpsn_activate(device_t dev)
121854994Simp{
121954994Simp	struct sn_softc *sc = device_get_softc(dev);
122054773Simp
122154994Simp	sc->port_rid = 0;
122254994Simp	sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
122354994Simp	    0, ~0, SMC_IO_EXTENT, RF_ACTIVE);
122454994Simp	if (!sc->port_res) {
122566058Simp		if (bootverbose)
122666058Simp			device_printf(dev, "Cannot allocate ioport\n");
122754994Simp		return ENOMEM;
122854994Simp	}
122954994Simp
123054994Simp	sc->irq_rid = 0;
1231127135Snjl	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
1232127135Snjl	    RF_ACTIVE);
123354994Simp	if (!sc->irq_res) {
123466058Simp		if (bootverbose)
123566058Simp			device_printf(dev, "Cannot allocate irq\n");
123654994Simp		sn_deactivate(dev);
123754994Simp		return ENOMEM;
123854994Simp	}
123954994Simp	return (0);
124054994Simp}
124154994Simp
124254994Simpvoid
124354994Simpsn_deactivate(device_t dev)
124454994Simp{
124554994Simp	struct sn_softc *sc = device_get_softc(dev);
124654994Simp
124754994Simp	if (sc->intrhand)
124854994Simp		bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
124954994Simp	sc->intrhand = 0;
125054994Simp	if (sc->port_res)
125154994Simp		bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
125254994Simp		    sc->port_res);
125354994Simp	sc->port_res = 0;
1254149095Simp	if (sc->modem_res)
1255149095Simp		bus_release_resource(dev, SYS_RES_IOPORT, sc->modem_rid,
1256149095Simp		    sc->modem_res);
1257149095Simp	sc->modem_res = 0;
125854994Simp	if (sc->irq_res)
125954994Simp		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
126054994Simp		    sc->irq_res);
126154994Simp	sc->irq_res = 0;
126254994Simp	return;
126354994Simp}
126454994Simp
126554773Simp/*
1266149095Simp * Function: sn_probe(device_t dev)
126754773Simp *
126854773Simp * Purpose:
126954773Simp *      Tests to see if a given ioaddr points to an SMC9xxx chip.
127054773Simp *      Tries to cause as little damage as possible if it's not a SMC chip.
127154773Simp *      Returns a 0 on success
127254773Simp *
127354773Simp * Algorithm:
127454773Simp *      (1) see if the high byte of BANK_SELECT is 0x33
127554773Simp *      (2) compare the ioaddr with the base register's address
127654773Simp *      (3) see if I recognize the chip ID in the appropriate register
127754773Simp *
127854773Simp *
127954773Simp */
128054994Simpint
1281147797Simpsn_probe(device_t dev)
128254773Simp{
128354994Simp	struct sn_softc *sc = device_get_softc(dev);
1284121589Simp	uint16_t        bank;
1285121589Simp	uint16_t        revision_register;
1286121589Simp	uint16_t        base_address_register;
128754994Simp	int		err;
128854773Simp
128954994Simp	if ((err = sn_activate(dev)) != 0)
129054994Simp		return err;
129154994Simp
129254773Simp	/*
129354773Simp	 * First, see if the high byte is 0x33
129454773Simp	 */
1295121514Simp	bank = CSR_READ_2(sc, BANK_SELECT_REG_W);
129654773Simp	if ((bank & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
129754773Simp#ifdef	SN_DEBUG
129854994Simp		device_printf(dev, "test1 failed\n");
129954773Simp#endif
130054994Simp		goto error;
130154773Simp	}
130254773Simp	/*
130354773Simp	 * The above MIGHT indicate a device, but I need to write to further
130454773Simp	 * test this.  Go to bank 0, then test that the register still
130554773Simp	 * reports the high byte is 0x33.
130654773Simp	 */
1307121514Simp	CSR_WRITE_2(sc, BANK_SELECT_REG_W, 0x0000);
1308121514Simp	bank = CSR_READ_2(sc, BANK_SELECT_REG_W);
130954773Simp	if ((bank & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
131054773Simp#ifdef	SN_DEBUG
131154994Simp		device_printf(dev, "test2 failed\n");
131254773Simp#endif
131354994Simp		goto error;
131454773Simp	}
131554773Simp	/*
131654773Simp	 * well, we've already written once, so hopefully another time won't
131754773Simp	 * hurt.  This time, I need to switch the bank register to bank 1, so
131854773Simp	 * I can access the base address register.  The contents of the
131954773Simp	 * BASE_ADDR_REG_W register, after some jiggery pokery, is expected
132054773Simp	 * to match the I/O port address where the adapter is being probed.
132154773Simp	 */
1322121514Simp	CSR_WRITE_2(sc, BANK_SELECT_REG_W, 0x0001);
1323121514Simp	base_address_register = (CSR_READ_2(sc, BASE_ADDR_REG_W) >> 3) & 0x3e0;
132454773Simp
1325147797Simp	if (rman_get_start(sc->port_res) != base_address_register) {
132654773Simp
132754773Simp		/*
132854773Simp		 * Well, the base address register didn't match.  Must not
132954773Simp		 * have been a SMC chip after all.
133054773Simp		 */
133154773Simp#ifdef	SN_DEBUG
133254994Simp		device_printf(dev, "test3 failed ioaddr = 0x%x, "
1333121514Simp		    "base_address_register = 0x%x\n",
1334121514Simp		    rman_get_start(sc->port_res), base_address_register);
133554773Simp#endif
133654994Simp		goto error;
133754773Simp	}
133866058Simp
133954773Simp	/*
134054773Simp	 * Check if the revision register is something that I recognize.
134154773Simp	 * These might need to be added to later, as future revisions could
134254773Simp	 * be added.
134354773Simp	 */
1344121514Simp	CSR_WRITE_2(sc, BANK_SELECT_REG_W, 0x3);
1345121514Simp	revision_register = CSR_READ_2(sc, REVISION_REG_W);
134654773Simp	if (!chip_ids[(revision_register >> 4) & 0xF]) {
134754773Simp
134854773Simp		/*
134954773Simp		 * I don't regonize this chip, so...
135054773Simp		 */
135154773Simp#ifdef	SN_DEBUG
135254994Simp		device_printf(dev, "test4 failed\n");
135354773Simp#endif
135454994Simp		goto error;
135554773Simp	}
135666058Simp
135754773Simp	/*
135854773Simp	 * at this point I'll assume that the chip is an SMC9xxx. It might be
135954773Simp	 * prudent to check a listing of MAC addresses against the hardware
136054773Simp	 * address, or do some other tests.
136154773Simp	 */
136254994Simp	sn_deactivate(dev);
136354773Simp	return 0;
136454994Simp error:
136554994Simp	sn_deactivate(dev);
136654994Simp	return ENXIO;
136754773Simp}
136854773Simp
136954773Simp#define MCFSZ 8
137054773Simp
137154773Simpstatic void
137254773Simpsn_setmcast(struct sn_softc *sc)
137354773Simp{
1374147256Sbrooks	struct ifnet *ifp = sc->ifp;
137554773Simp	int flags;
1376121589Simp	uint8_t mcf[MCFSZ];
137754773Simp
1378121589Simp	SN_ASSERT_LOCKED(sc);
1379121589Simp
138054773Simp	/*
138154773Simp	 * Set the receiver filter.  We want receive enabled and auto strip
138254773Simp	 * of CRC from received packet.  If we are promiscuous then set that
138354773Simp	 * bit too.
138454773Simp	 */
138554773Simp	flags = RCR_ENABLE | RCR_STRIP_CRC;
138654773Simp
138754773Simp	if (ifp->if_flags & IFF_PROMISC) {
138854773Simp		flags |= RCR_PROMISC | RCR_ALMUL;
138954773Simp	} else if (ifp->if_flags & IFF_ALLMULTI) {
139054773Simp		flags |= RCR_ALMUL;
139154773Simp	} else {
1392147256Sbrooks		if (sn_getmcf(ifp, mcf)) {
139354773Simp			/* set filter */
1394121514Simp			SMC_SELECT_BANK(sc, 3);
1395121514Simp			CSR_WRITE_2(sc, MULTICAST1_REG_W,
1396121589Simp			    ((uint16_t)mcf[1] << 8) |  mcf[0]);
1397121514Simp			CSR_WRITE_2(sc, MULTICAST2_REG_W,
1398121589Simp			    ((uint16_t)mcf[3] << 8) |  mcf[2]);
1399121514Simp			CSR_WRITE_2(sc, MULTICAST3_REG_W,
1400121589Simp			    ((uint16_t)mcf[5] << 8) |  mcf[4]);
1401121514Simp			CSR_WRITE_2(sc, MULTICAST4_REG_W,
1402121589Simp			    ((uint16_t)mcf[7] << 8) |  mcf[6]);
140354773Simp		} else {
140454773Simp			flags |= RCR_ALMUL;
140554773Simp		}
140654773Simp	}
1407121514Simp	SMC_SELECT_BANK(sc, 0);
1408121514Simp	CSR_WRITE_2(sc, RECV_CONTROL_REG_W, flags);
140954773Simp}
141054773Simp
141154773Simpstatic int
1412147256Sbrookssn_getmcf(struct ifnet *ifp, uint8_t *mcf)
141354773Simp{
141454773Simp	int i;
1415121589Simp	uint32_t index, index2;
1416121589Simp	uint8_t *af = mcf;
141754773Simp	struct ifmultiaddr *ifma;
141854773Simp
141954773Simp	bzero(mcf, MCFSZ);
142054773Simp
1421195049Srwatson	if_maddr_rlock(ifp);
1422147256Sbrooks	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1423148654Srwatson	    if (ifma->ifma_addr->sa_family != AF_LINK) {
1424195049Srwatson		if_maddr_runlock(ifp);
142554773Simp		return 0;
1426148654Srwatson	    }
1427130270Snaddy	    index = ether_crc32_le(LLADDR((struct sockaddr_dl *)
1428130270Snaddy		ifma->ifma_addr), ETHER_ADDR_LEN) & 0x3f;
142954773Simp	    index2 = 0;
143054773Simp	    for (i = 0; i < 6; i++) {
143154773Simp		index2 <<= 1;
143254773Simp		index2 |= (index & 0x01);
143354773Simp		index >>= 1;
143454773Simp	    }
143554773Simp	    af[index2 >> 3] |= 1 << (index2 & 7);
143654773Simp	}
1437195049Srwatson	if_maddr_runlock(ifp);
143854773Simp	return 1;  /* use multicast filter */
143954773Simp}
1440