154359Sroberto/* $NetBSD: seeq8005.c,v 1.66 2020/01/30 04:56:11 thorpej Exp $ */
2182007Sroberto
354359Sroberto/*
4182007Sroberto * Copyright (c) 2000, 2001 Ben Harris
554359Sroberto * Copyright (c) 1995-1998 Mark Brinicombe
6285612Sdelphij * All rights reserved.
7285612Sdelphij *
854359Sroberto * Redistribution and use in source and binary forms, with or without
9182007Sroberto * modification, are permitted provided that the following conditions
10182007Sroberto * are met:
11182007Sroberto * 1. Redistributions of source code must retain the above copyright
12182007Sroberto *    notice, this list of conditions and the following disclaimer.
13182007Sroberto * 2. Redistributions in binary form must reproduce the above copyright
14182007Sroberto *    notice, this list of conditions and the following disclaimer in the
15182007Sroberto *    documentation and/or other materials provided with the distribution.
16182007Sroberto * 3. All advertising materials mentioning features or use of this software
17182007Sroberto *    must display the following acknowledgement:
18182007Sroberto *	This product includes software developed by Mark Brinicombe
19182007Sroberto *	for the NetBSD Project.
20182007Sroberto * 4. The name of the company nor the name of the author may be used to
21182007Sroberto *    endorse or promote products derived from this software without specific
22182007Sroberto *    prior written permission.
23182007Sroberto *
24182007Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25182007Sroberto * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26182007Sroberto * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27182007Sroberto * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28182007Sroberto * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29182007Sroberto * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30182007Sroberto * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31182007Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32182007Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3354359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3454359Sroberto * SUCH DAMAGE.
3554359Sroberto */
3654359Sroberto/*
3754359Sroberto * seeq8005.c - SEEQ 8005 device driver
38182007Sroberto */
3954359Sroberto/*
4054359Sroberto * This driver currently supports the following chips:
4154359Sroberto * SEEQ 8005 Advanced Ethernet Data Link Controller
4254359Sroberto * SEEQ 80C04 Ethernet Data Link Controller
4354359Sroberto * SEEQ 80C04A AutoDUPLEX CMOS Ethernet Data Link Controller
4454359Sroberto */
4554359Sroberto/*
4654359Sroberto * More information on the 8004 and 8005 AEDLC controllers can be found in
4754359Sroberto * the SEEQ Technology Inc 1992 Data Comm Devices data book.
4854359Sroberto *
4954359Sroberto * This data book may no longer be available as these are rather old chips
5054359Sroberto * (1991 - 1993)
5154359Sroberto */
5254359Sroberto/*
5354359Sroberto * This driver is based on the arm32 ea(4) driver, hence the names of many
5454359Sroberto * of the functions.
5554359Sroberto */
5654359Sroberto/*
5754359Sroberto * Bugs/possible improvements:
5854359Sroberto *	- Does not currently support DMA
5954359Sroberto *	- Does not transmit multiple packets in one go
6054359Sroberto *	- Does not support 8-bit busses
61285612Sdelphij */
62285612Sdelphij
63285612Sdelphij#include <sys/cdefs.h>
64285612Sdelphij__KERNEL_RCSID(0, "$NetBSD: seeq8005.c,v 1.66 2020/01/30 04:56:11 thorpej Exp $");
65285612Sdelphij
6654359Sroberto#include <sys/param.h>
6754359Sroberto#include <sys/systm.h>
6854359Sroberto#include <sys/endian.h>
6954359Sroberto#include <sys/errno.h>
7054359Sroberto#include <sys/ioctl.h>
7154359Sroberto#include <sys/mbuf.h>
7254359Sroberto#include <sys/socket.h>
7354359Sroberto#include <sys/syslog.h>
7454359Sroberto#include <sys/device.h>
7554359Sroberto
7654359Sroberto#include <net/if.h>
7754359Sroberto#include <net/if_dl.h>
7854359Sroberto#include <net/if_types.h>
7954359Sroberto#include <net/if_ether.h>
8054359Sroberto#include <net/if_media.h>
8154359Sroberto#include <net/bpf.h>
8254359Sroberto
8354359Sroberto#include <sys/rndsource.h>
8454359Sroberto
8554359Sroberto#include <sys/bus.h>
8654359Sroberto#include <sys/intr.h>
8754359Sroberto
8854359Sroberto#include <dev/ic/seeq8005reg.h>
8954359Sroberto#include <dev/ic/seeq8005var.h>
9054359Sroberto
9154359Sroberto/*#define SEEQ_DEBUG*/
9254359Sroberto
9354359Sroberto/* for debugging convenience */
9454359Sroberto#ifdef SEEQ8005_DEBUG
9554359Sroberto#define SEEQ_DEBUG_MISC		1
9654359Sroberto#define SEEQ_DEBUG_TX		2
9754359Sroberto#define SEEQ_DEBUG_RX		4
9854359Sroberto#define SEEQ_DEBUG_PKT		8
9954359Sroberto#define SEEQ_DEBUG_TXINT	16
10054359Sroberto#define SEEQ_DEBUG_RXINT	32
10154359Srobertoint seeq8005_debug = 0;
10254359Sroberto#define DPRINTF(f, x) { if (seeq8005_debug & (f)) printf x; }
10354359Sroberto#else
10454359Sroberto#define DPRINTF(f, x)
10554359Sroberto#endif
10654359Sroberto
10754359Sroberto#ifndef EA_TX_BUFFER_SIZE
108285612Sdelphij#define EA_TX_BUFFER_SIZE		0x800		/* (> ETHER_MAX_LEN) */
109285612Sdelphij#endif
110285612Sdelphij#ifndef EA_TX_BUFFER_COUNT
111285612Sdelphij#define EA_TX_BUFFER_COUNT		1		/* (> 0) */
112285612Sdelphij#endif
113285612Sdelphij
114285612Sdelphij#define SEEQ_READ16(sc, iot, ioh, reg)					\
11554359Sroberto	((sc)->sc_flags & SF_8BIT ?					\
11654359Sroberto	    (bus_space_read_1((iot), (ioh), (reg)) |			\
11754359Sroberto	     (bus_space_read_1((iot), (ioh), (reg) + 1) << 8)) :	\
11854359Sroberto	    (bus_space_read_2((iot), (ioh), (reg))))
11954359Sroberto
12054359Sroberto#define SEEQ_WRITE16(sc, iot, ioh, reg, val) do {			\
12154359Sroberto	if ((sc)->sc_flags & SF_8BIT) {					\
12254359Sroberto		bus_space_write_1((iot), (ioh), (reg), (val) & 0xff);	\
12354359Sroberto		bus_space_write_1((iot), (ioh), (reg) + 1, (val) >> 8);	\
12454359Sroberto	} else								\
12554359Sroberto		bus_space_write_2((iot), (ioh), (reg), (val));		\
12654359Sroberto} while (/*CONSTCOND*/0)
12754359Sroberto
12854359Sroberto/*
12954359Sroberto * prototypes
13054359Sroberto */
13154359Sroberto
13254359Srobertostatic int ea_init(struct ifnet *);
13354359Srobertostatic int ea_ioctl(struct ifnet *, u_long, void *);
13454359Srobertostatic void ea_start(struct ifnet *);
13554359Srobertostatic void ea_watchdog(struct ifnet *);
13654359Srobertostatic void ea_chipreset(struct seeq8005_softc *);
137285612Sdelphijstatic void ea_ramtest(struct seeq8005_softc *);
13854359Srobertostatic int ea_stoptx(struct seeq8005_softc *);
13954359Srobertostatic int ea_stoprx(struct seeq8005_softc *);
14054359Srobertostatic void ea_stop(struct ifnet *, int);
14154359Srobertostatic void ea_await_fifo_empty(struct seeq8005_softc *);
14254359Srobertostatic void ea_await_fifo_full(struct seeq8005_softc *);
14354359Srobertostatic void ea_writebuf(struct seeq8005_softc *, u_char *, int, size_t);
144285612Sdelphijstatic void ea_readbuf(struct seeq8005_softc *, u_char *, int, size_t);
14554359Srobertostatic void ea_select_buffer(struct seeq8005_softc *, int);
14654359Srobertostatic void ea_set_address(struct seeq8005_softc *, int, const uint8_t *);
14754359Srobertostatic void ea_read(struct seeq8005_softc *, int, int);
14854359Srobertostatic struct mbuf *ea_get(struct seeq8005_softc *, int, int, struct ifnet *);
14954359Srobertostatic void ea_txint(struct seeq8005_softc *);
15054359Srobertostatic void ea_rxint(struct seeq8005_softc *);
15154359Srobertostatic void ea_txpacket(struct seeq8005_softc *);
15254359Srobertostatic int ea_writembuf(struct seeq8005_softc *, struct mbuf *, int);
15354359Srobertostatic void ea_mc_reset(struct seeq8005_softc *);
15454359Srobertostatic void ea_mc_reset_8004(struct seeq8005_softc *);
155285612Sdelphijstatic void ea_mc_reset_8005(struct seeq8005_softc *);
15654359Srobertostatic int ea_mediachange(struct ifnet *);
15754359Srobertostatic void ea_mediastatus(struct ifnet *, struct ifmediareq *);
15854359Sroberto
15954359Srobertostatic u_char* padbuf = NULL;
16054359Sroberto
16154359Sroberto
16254359Sroberto/*
16354359Sroberto * Attach chip.
16454359Sroberto */
16554359Sroberto
166285612Sdelphijvoid
16754359Srobertoseeq8005_attach(struct seeq8005_softc *sc, const uint8_t *myaddr, int *media,
16854359Sroberto    int nmedia, int defmedia)
16954359Sroberto{
170285612Sdelphij	device_t dev = sc->sc_dev;
17154359Sroberto	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
17254359Sroberto	bus_space_tag_t iot = sc->sc_iot;
17354359Sroberto	bus_space_handle_t ioh = sc->sc_ioh;
17454359Sroberto	u_int id;
17554359Sroberto
17654359Sroberto	KASSERT(myaddr != NULL);
17754359Sroberto	printf(" address %s", ether_sprintf(myaddr));
17854359Sroberto
17954359Sroberto	/* Stop the board. */
18054359Sroberto
18154359Sroberto	ea_chipreset(sc);
182182007Sroberto
183182007Sroberto	/* Work out data bus width. */
184182007Sroberto	SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, 0x1234);
185182007Sroberto	if (SEEQ_READ16(sc, iot, ioh, SEEQ_RX_PTR) != 0x1234) {
186182007Sroberto		/* Try 8-bit mode */
18754359Sroberto		sc->sc_flags |= SF_8BIT;
18854359Sroberto		SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, 0x1234);
18954359Sroberto		if (SEEQ_READ16(sc, iot, ioh, SEEQ_RX_PTR) != 0x1234) {
19054359Sroberto			aprint_normal("\n");
19154359Sroberto			aprint_error_dev(dev,
19254359Sroberto			    "Cannot determine data bus width\n");
19354359Sroberto			return;
19454359Sroberto		}
195182007Sroberto	}
19654359Sroberto
19754359Sroberto	printf(", %d-bit", sc->sc_flags & SF_8BIT ? 8 : 16);
19854359Sroberto
19954359Sroberto	/* Get the product ID */
20054359Sroberto
20154359Sroberto	ea_select_buffer(sc, SEEQ_BUFCODE_PRODUCTID);
20254359Sroberto	id = SEEQ_READ16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_BUFWIN);
20354359Sroberto
20454359Sroberto	switch (id & SEEQ_PRODUCTID_MASK) {
20554359Sroberto	case SEEQ_PRODUCTID_8004:
20654359Sroberto		sc->sc_variant = SEEQ_8004;
20754359Sroberto		switch (id & SEEQ_PRODUCTID_REV_MASK) {
20854359Sroberto		case SEEQ_PRODUCTID_REV_80C04:
20954359Sroberto			printf(", SEEQ 80C04\n");
21054359Sroberto			break;
21154359Sroberto		case SEEQ_PRODUCTID_REV_80C04A:
21254359Sroberto			printf(", SEEQ 80C04A\n");
21354359Sroberto			break;
21454359Sroberto		default:
21554359Sroberto			/* Unknown SEEQ 8004 variants */
21654359Sroberto			printf(", SEEQ 8004 rev %x\n",
21754359Sroberto			    id & SEEQ_PRODUCTID_REV_MASK);
21854359Sroberto			break;
21954359Sroberto		}
22054359Sroberto		break;
22154359Sroberto	default:	/* XXX */
22254359Sroberto		sc->sc_variant = SEEQ_8005;
22354359Sroberto		printf(", SEEQ 8005\n");
22454359Sroberto		break;
22554359Sroberto	}
22654359Sroberto
22754359Sroberto	/* Both the 8004 and 8005 are designed for 64K Buffer memory */
22854359Sroberto	sc->sc_buffersize = SEEQ_MAX_BUFFER_SIZE;
22954359Sroberto
23054359Sroberto	/*
23154359Sroberto	 * Set up tx and rx buffers.
23254359Sroberto	 *
23354359Sroberto	 * We set aside EA_TX_BUFFER_SIZE * EA_TX_BUFFER_COUNT for TX
23454359Sroberto	 * buffers and the rest for RX buffers
23554359Sroberto	 */
23654359Sroberto	sc->sc_tx_bufs = EA_TX_BUFFER_COUNT;
23754359Sroberto	sc->sc_tx_bufsize = sc->sc_tx_bufs * EA_TX_BUFFER_SIZE;
23854359Sroberto	sc->sc_rx_bufsize = sc->sc_buffersize - sc->sc_tx_bufsize;
239285612Sdelphij	sc->sc_enabled = 0;
240285612Sdelphij
24154359Sroberto	/* Test the RAM */
24254359Sroberto	ea_ramtest(sc);
24354359Sroberto
24454359Sroberto	printf("%s: %dKB packet memory, txbuf=%dKB (%d buffers), rxbuf=%dKB",
245285612Sdelphij	    device_xname(dev), sc->sc_buffersize >> 10,
24654359Sroberto	    sc->sc_tx_bufsize >> 10, sc->sc_tx_bufs, sc->sc_rx_bufsize >> 10);
24754359Sroberto
24854359Sroberto	if (padbuf == NULL) {
24954359Sroberto		padbuf = malloc(ETHER_MIN_LEN - ETHER_CRC_LEN, M_DEVBUF,
25054359Sroberto		    M_ZERO | M_WAITOK);
25154359Sroberto	}
25254359Sroberto
25354359Sroberto	/* Initialise ifnet structure. */
25454359Sroberto
25554359Sroberto	strlcpy(ifp->if_xname, device_xname(dev), IFNAMSIZ);
25654359Sroberto	ifp->if_softc = sc;
25754359Sroberto	ifp->if_start = ea_start;
25854359Sroberto	ifp->if_ioctl = ea_ioctl;
25954359Sroberto	ifp->if_init = ea_init;
26054359Sroberto	ifp->if_stop = ea_stop;
26154359Sroberto	ifp->if_watchdog = ea_watchdog;
26254359Sroberto	ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
26354359Sroberto	if (sc->sc_variant == SEEQ_8004)
26454359Sroberto		ifp->if_flags |= IFF_SIMPLEX;
26554359Sroberto	IFQ_SET_READY(&ifp->if_snd);
26654359Sroberto
26754359Sroberto	/* Initialize media goo. */
268285612Sdelphij	ifmedia_init(&sc->sc_media, 0, ea_mediachange, ea_mediastatus);
26954359Sroberto	if (media != NULL) {
27054359Sroberto		int i;
27154359Sroberto
27254359Sroberto		for (i = 0; i < nmedia; i++)
27354359Sroberto			ifmedia_add(&sc->sc_media, media[i], 0, NULL);
27454359Sroberto		ifmedia_set(&sc->sc_media, defmedia);
27554359Sroberto	} else {
276285612Sdelphij		ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
27754359Sroberto		ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL);
27854359Sroberto	}
27954359Sroberto
28054359Sroberto	/* We can support 802.1Q VLAN-sized frames. */
28154359Sroberto	sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
28254359Sroberto
28354359Sroberto	/* Now we can attach the interface. */
28454359Sroberto
28554359Sroberto	if_attach(ifp);
28654359Sroberto	ether_ifattach(ifp, myaddr);
28754359Sroberto
28854359Sroberto	printf("\n");
28954359Sroberto
29054359Sroberto	/* After \n because it can print a line of its own. */
29154359Sroberto	rnd_attach_source(&sc->rnd_source, device_xname(dev),
29254359Sroberto	    RND_TYPE_NET, RND_FLAG_DEFAULT);
29354359Sroberto}
29454359Sroberto
29554359Sroberto/*
296285612Sdelphij * Media change callback.
29754359Sroberto */
29854359Srobertostatic int
29954359Srobertoea_mediachange(struct ifnet *ifp)
30054359Sroberto{
30154359Sroberto	struct seeq8005_softc *sc = ifp->if_softc;
30254359Sroberto
30354359Sroberto	if (sc->sc_mediachange)
30454359Sroberto		return (*sc->sc_mediachange)(sc);
30554359Sroberto	return EINVAL;
30654359Sroberto}
30754359Sroberto
30854359Sroberto/*
30954359Sroberto * Media status callback.
31054359Sroberto */
31154359Srobertostatic void
31254359Srobertoea_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
31354359Sroberto{
31454359Sroberto	struct seeq8005_softc *sc = ifp->if_softc;
31554359Sroberto
31654359Sroberto	if (sc->sc_enabled == 0) {
31754359Sroberto		ifmr->ifm_active = IFM_ETHER | IFM_NONE;
31854359Sroberto		ifmr->ifm_status = 0;
31954359Sroberto		return;
32054359Sroberto	}
32154359Sroberto
32254359Sroberto	if (sc->sc_mediastatus)
32354359Sroberto		(*sc->sc_mediastatus)(sc, ifmr);
32454359Sroberto}
32554359Sroberto
32654359Sroberto/*
32754359Sroberto * Test the RAM on the ethernet card.
32854359Sroberto */
32954359Sroberto
33054359Srobertovoid
33154359Srobertoea_ramtest(struct seeq8005_softc *sc)
33254359Sroberto{
33354359Sroberto	bus_space_tag_t iot = sc->sc_iot;
33454359Sroberto	bus_space_handle_t ioh = sc->sc_ioh;
33554359Sroberto	int loop;
33654359Sroberto	u_int sum = 0;
33754359Sroberto
33854359Sroberto	/*
33954359Sroberto	 * Test the buffer memory on the board.
34054359Sroberto	 * Write simple pattens to it and read them back.
34154359Sroberto	 */
34254359Sroberto
34354359Sroberto	/* Set up the whole buffer RAM for writing */
34454359Sroberto
34554359Sroberto	ea_select_buffer(sc, SEEQ_BUFCODE_TX_EAP);
34654359Sroberto	SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, (SEEQ_MAX_BUFFER_SIZE >> 8) - 1);
347285612Sdelphij	SEEQ_WRITE16(sc, iot, ioh, SEEQ_TX_PTR, 0x0000);
348285612Sdelphij	SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, SEEQ_MAX_BUFFER_SIZE - 2);
349285612Sdelphij
350285612Sdelphij#define SEEQ_RAMTEST_LOOP(value)					\
35154359Srobertodo {									\
35254359Sroberto	/* Set the write start address and write a pattern */		\
35354359Sroberto	ea_writebuf(sc, NULL, 0x0000, 0);				\
354285612Sdelphij	for (loop = 0; loop < SEEQ_MAX_BUFFER_SIZE; loop += 2)		\
35554359Sroberto		SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, (value));	\
356285612Sdelphij									\
35754359Sroberto	/* Set the read start address and verify the pattern */		\
35854359Sroberto	ea_readbuf(sc, NULL, 0x0000, 0);				\
359285612Sdelphij	for (loop = 0; loop < SEEQ_MAX_BUFFER_SIZE; loop += 2)		\
36054359Sroberto		if (SEEQ_READ16(sc, iot, ioh, SEEQ_BUFWIN) != (value))	\
36154359Sroberto			++sum;						\
36254359Sroberto} while (/*CONSTCOND*/0)
36354359Sroberto
36454359Sroberto	SEEQ_RAMTEST_LOOP(loop);
36554359Sroberto	SEEQ_RAMTEST_LOOP(loop ^ (SEEQ_MAX_BUFFER_SIZE - 1));
36654359Sroberto	SEEQ_RAMTEST_LOOP(0xaa55);
36754359Sroberto	SEEQ_RAMTEST_LOOP(0x55aa);
36854359Sroberto
36954359Sroberto	/* Report */
37054359Sroberto
37154359Sroberto	if (sum > 0)
37254359Sroberto		aprint_error_dev(sc->sc_dev,
373285612Sdelphij		    "buffer RAM failed self test, %d faults\n", sum);
374285612Sdelphij}
375285612Sdelphij
376285612Sdelphij
377285612Sdelphij/*
378285612Sdelphij * Stop the tx interface.
379285612Sdelphij *
380285612Sdelphij * Returns 0 if the tx was already stopped or 1 if it was active
381285612Sdelphij */
38254359Sroberto
383285612Sdelphijstatic int
384285612Sdelphijea_stoptx(struct seeq8005_softc *sc)
385285612Sdelphij{
38654359Sroberto	bus_space_tag_t iot = sc->sc_iot;
387285612Sdelphij	bus_space_handle_t ioh = sc->sc_ioh;
388285612Sdelphij	int timeout;
38954359Sroberto	int status;
390285612Sdelphij
391285612Sdelphij	DPRINTF(SEEQ_DEBUG_TX, ("ea_stoptx()\n"));
392285612Sdelphij
393285612Sdelphij	sc->sc_enabled = 0;
394285612Sdelphij
395285612Sdelphij	status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS);
396285612Sdelphij	if (!(status & SEEQ_STATUS_TX_ON))
39754359Sroberto		return 0;
39854359Sroberto
39954359Sroberto	/* Stop any tx and wait for confirmation */
40054359Sroberto	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
40154359Sroberto	    sc->sc_command | SEEQ_CMD_TX_OFF);
40254359Sroberto
40354359Sroberto	timeout = 20000;
404182007Sroberto	do {
405182007Sroberto		status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS);
406182007Sroberto		delay(1);
407182007Sroberto	} while ((status & SEEQ_STATUS_TX_ON) && --timeout > 0);
408182007Sroberto	if (timeout == 0)
409182007Sroberto		log(LOG_ERR, "%s: timeout waiting for tx termination\n",
410182007Sroberto		    device_xname(sc->sc_dev));
41154359Sroberto
41254359Sroberto	/* Clear any pending tx interrupt */
41354359Sroberto	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
41454359Sroberto		   sc->sc_command | SEEQ_CMD_TX_INTACK);
41554359Sroberto	return 1;
41654359Sroberto}
41754359Sroberto
41854359Sroberto
41954359Sroberto/*
42054359Sroberto * Stop the rx interface.
42154359Sroberto *
42254359Sroberto * Returns 0 if the tx was already stopped or 1 if it was active
42354359Sroberto */
42454359Sroberto
42554359Srobertostatic int
42654359Srobertoea_stoprx(struct seeq8005_softc *sc)
42754359Sroberto{
42854359Sroberto	bus_space_tag_t iot = sc->sc_iot;
42954359Sroberto	bus_space_handle_t ioh = sc->sc_ioh;
43054359Sroberto	int timeout;
43154359Sroberto	int status;
43254359Sroberto
433	DPRINTF(SEEQ_DEBUG_RX, ("ea_stoprx()\n"));
434
435	status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS);
436	if (!(status & SEEQ_STATUS_RX_ON))
437		return 0;
438
439	/* Stop any rx and wait for confirmation */
440
441	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
442			  sc->sc_command | SEEQ_CMD_RX_OFF);
443
444	timeout = 20000;
445	do {
446		status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS);
447		delay(1);
448	} while ((status & SEEQ_STATUS_RX_ON) && --timeout > 0);
449	if (timeout == 0)
450		log(LOG_ERR, "%s: timeout waiting for rx termination\n",
451		    device_xname(sc->sc_dev));
452
453	/* Clear any pending rx interrupt */
454
455	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
456		   sc->sc_command | SEEQ_CMD_RX_INTACK);
457	return 1;
458}
459
460
461/*
462 * Stop interface.
463 * Stop all IO and shut the interface down
464 */
465
466/* ARGSUSED */
467static void
468ea_stop(struct ifnet *ifp, int disable)
469{
470	struct seeq8005_softc *sc = ifp->if_softc;
471	bus_space_tag_t iot = sc->sc_iot;
472	bus_space_handle_t ioh = sc->sc_ioh;
473
474	DPRINTF(SEEQ_DEBUG_MISC, ("ea_stop()\n"));
475
476	/* Stop all IO */
477	ea_stoptx(sc);
478	ea_stoprx(sc);
479
480	/* Disable rx and tx interrupts */
481	sc->sc_command &= ~(SEEQ_CMD_RX_INTEN | SEEQ_CMD_TX_INTEN);
482
483	/* Clear any pending interrupts */
484	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
485	    sc->sc_command | SEEQ_CMD_RX_INTACK | SEEQ_CMD_TX_INTACK |
486	    SEEQ_CMD_DMA_INTACK | SEEQ_CMD_BW_INTACK);
487
488	if (sc->sc_variant == SEEQ_8004) {
489		/* Put the chip to sleep */
490		ea_select_buffer(sc, SEEQ_BUFCODE_CONFIG3);
491		SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN,
492		    sc->sc_config3 | SEEQ_CFG3_SLEEP);
493	}
494
495	/* Cancel any watchdog timer */
496	sc->sc_ethercom.ec_if.if_timer = 0;
497}
498
499
500/*
501 * Reset the chip
502 * Following this the software registers are reset
503 */
504
505static void
506ea_chipreset(struct seeq8005_softc *sc)
507{
508	bus_space_tag_t iot = sc->sc_iot;
509	bus_space_handle_t ioh = sc->sc_ioh;
510
511	DPRINTF(SEEQ_DEBUG_MISC, ("ea_chipreset()\n"));
512
513	/* Reset the controller. Min of 4us delay here */
514
515	/*
516	 * This can be called before we know whether the chip is in 8- or
517	 * 16-bit mode, so we do a reset in both modes.  The 16-bit reset is
518	 * harmless in 8-bit mode, so we do that second.
519	 */
520
521	/* In 16-bit mode, this will munge the PreamSelect bit. */
522	bus_space_write_1(iot, ioh, SEEQ_CONFIG2 + 1, SEEQ_CFG2_RESET >> 8);
523	delay(4);
524	/* In 8-bit mode, this will zero the bottom half of config reg 2. */
525	bus_space_write_2(iot, ioh, SEEQ_CONFIG2, SEEQ_CFG2_RESET);
526	delay(4);
527
528	sc->sc_command = 0;
529	sc->sc_config1 = 0;
530	sc->sc_config2 = 0;
531	sc->sc_config3 = 0;
532}
533
534
535/*
536 * If the DMA FIFO's in write mode, wait for it to empty.  Needed when
537 * switching the FIFO from write to read.  We also use it when changing
538 * the address for writes.
539 */
540static void
541ea_await_fifo_empty(struct seeq8005_softc *sc)
542{
543	bus_space_tag_t iot = sc->sc_iot;
544	bus_space_handle_t ioh = sc->sc_ioh;
545	int timeout;
546
547	timeout = 20000;
548	if ((SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS) &
549	     SEEQ_STATUS_FIFO_DIR) != 0)
550		return; /* FIFO is reading anyway. */
551	while (--timeout > 0)
552		if (SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS) &
553		    SEEQ_STATUS_FIFO_EMPTY)
554			return;
555	log(LOG_ERR, "%s: DMA FIFO failed to empty\n",
556	    device_xname(sc->sc_dev));
557}
558
559/*
560 * Wait for the DMA FIFO to fill before reading from it.
561 */
562static void
563ea_await_fifo_full(struct seeq8005_softc *sc)
564{
565	bus_space_tag_t iot = sc->sc_iot;
566	bus_space_handle_t ioh = sc->sc_ioh;
567	int timeout;
568
569	timeout = 20000;
570	while (--timeout > 0)
571		if (SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS) &
572		    SEEQ_STATUS_FIFO_FULL)
573			return;
574	log(LOG_ERR, "%s: DMA FIFO failed to fill\n", device_xname(sc->sc_dev));
575}
576
577/*
578 * write to the buffer memory on the interface
579 *
580 * The buffer address is set to ADDR.
581 * If len != 0 then data is copied from the address starting at buf
582 * to the interface buffer.
583 * BUF must be usable as a uint16_t *.
584 * If LEN is odd, it must be safe to overwrite one extra byte.
585 */
586
587static void
588ea_writebuf(struct seeq8005_softc *sc, u_char *buf, int addr, size_t len)
589{
590	bus_space_tag_t iot = sc->sc_iot;
591	bus_space_handle_t ioh = sc->sc_ioh;
592
593	DPRINTF(SEEQ_DEBUG_MISC, ("writebuf: st=%04x\n",
594	    SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS)));
595
596#ifdef DIAGNOSTIC
597	if (__predict_false(!ALIGNED_POINTER(buf, uint16_t)))
598		panic("%s: unaligned writebuf", device_xname(sc->sc_dev));
599	if (__predict_false(addr >= SEEQ_MAX_BUFFER_SIZE))
600		panic("%s: writebuf out of range", device_xname(sc->sc_dev));
601#endif
602
603	if (addr != -1) {
604		ea_await_fifo_empty(sc);
605
606		ea_select_buffer(sc, SEEQ_BUFCODE_LOCAL_MEM);
607		SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
608		    sc->sc_command | SEEQ_CMD_FIFO_WRITE);
609
610		ea_await_fifo_empty(sc);
611
612		SEEQ_WRITE16(sc, iot, ioh, SEEQ_DMA_ADDR, addr);
613	}
614
615	if (len > 0) {
616		if (sc->sc_flags & SF_8BIT)
617			bus_space_write_multi_1(iot, ioh, SEEQ_BUFWIN,
618			    (uint8_t *)buf, len);
619		else
620			bus_space_write_multi_2(iot, ioh, SEEQ_BUFWIN,
621			    /* LINTED: alignment checked above */
622			    (uint16_t *)buf, len / 2);
623	}
624	if (!(sc->sc_flags & SF_8BIT) && len % 2) {
625		/* Write the last byte */
626		bus_space_write_2(iot, ioh, SEEQ_BUFWIN, buf[len - 1]);
627	}
628	/* Leave FIFO to empty in the background */
629}
630
631
632/*
633 * read from the buffer memory on the interface
634 *
635 * The buffer address is set to ADDR.
636 * If len != 0 then data is copied from the interface buffer to the
637 * address starting at buf.
638 * BUF must be usable as a uint16_t *.
639 * If LEN is odd, it must be safe to overwrite one extra byte.
640 */
641
642static void
643ea_readbuf(struct seeq8005_softc *sc, u_char *buf, int addr, size_t len)
644{
645	bus_space_tag_t iot = sc->sc_iot;
646	bus_space_handle_t ioh = sc->sc_ioh;
647	int runup;
648
649	DPRINTF(SEEQ_DEBUG_MISC, ("readbuf: st=%04x addr=%04x len=%d\n",
650	    SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS), addr, len));
651
652#ifdef DIAGNOSTIC
653	if (__predict_false(!ALIGNED_POINTER(buf, uint16_t)))
654		panic("%s: unaligned readbuf", device_xname(sc->sc_dev));
655	if (__predict_false(addr >= SEEQ_MAX_BUFFER_SIZE))
656		panic("%s: readbuf out of range", device_xname(sc->sc_dev));
657#endif
658
659	if (addr != -1) {
660		/*
661		 * SEEQ 80C04 bug:
662		 * Starting reading from certain addresses seems to cause
663		 * us to get bogus results, so we avoid them.
664		 */
665		runup = 0;
666		if (sc->sc_variant == SEEQ_8004 &&
667		    ((addr & 0x00ff) == 0x00ea ||
668		     (addr & 0x00ff) == 0x00ee ||
669		     (addr & 0x00ff) == 0x00f0))
670			runup = (addr & 0x00ff) - 0x00e8;
671
672		ea_await_fifo_empty(sc);
673
674		ea_select_buffer(sc, SEEQ_BUFCODE_LOCAL_MEM);
675
676		/*
677		 * 80C04 bug workaround.  I found this in the old arm32 "eb"
678		 * driver.  I've no idea what it does, but it seems to stop
679		 * the chip mangling data so often.
680		 */
681		SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
682		    sc->sc_command | SEEQ_CMD_FIFO_WRITE);
683		ea_await_fifo_empty(sc);
684
685		SEEQ_WRITE16(sc, iot, ioh, SEEQ_DMA_ADDR, addr - runup);
686		SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
687		    sc->sc_command | SEEQ_CMD_FIFO_READ);
688
689		ea_await_fifo_full(sc);
690		while (runup > 0) {
691			/* LINTED: Reading a volatile _does_ have an effect */
692			(void)SEEQ_READ16(sc, iot, ioh, SEEQ_BUFWIN);
693			runup -= 2;
694		}
695	}
696
697	if (len > 0) {
698		if (sc->sc_flags & SF_8BIT)
699			bus_space_read_multi_1(iot, ioh, SEEQ_BUFWIN,
700			    (uint8_t *)buf, len);
701		else
702			bus_space_read_multi_2(iot, ioh, SEEQ_BUFWIN,
703			    /* LINTED: pointer alignment checked above */
704			    (uint16_t *)buf, len / 2);
705	}
706	if (!(sc->sc_flags & SF_8BIT) && len % 2) {
707		/* Read the last byte */
708		buf[len - 1] = bus_space_read_2(iot, ioh, SEEQ_BUFWIN);
709	}
710}
711
712static void
713ea_select_buffer(struct seeq8005_softc *sc, int bufcode)
714{
715
716	SEEQ_WRITE16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_CONFIG1,
717			  sc->sc_config1 | bufcode);
718}
719
720/* Must be called at splnet */
721static void
722ea_set_address(struct seeq8005_softc *sc, int which, const uint8_t *ea)
723{
724	int i;
725
726	ea_select_buffer(sc, SEEQ_BUFCODE_STATION_ADDR0 + which);
727	for (i = 0; i < ETHER_ADDR_LEN; ++i)
728		SEEQ_WRITE16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_BUFWIN, ea[i]);
729}
730
731/*
732 * Initialize interface.
733 *
734 * This should leave the interface in a state for packet reception and
735 * transmission.
736 */
737
738static int
739ea_init(struct ifnet *ifp)
740{
741	struct seeq8005_softc *sc = ifp->if_softc;
742	bus_space_tag_t iot = sc->sc_iot;
743	bus_space_handle_t ioh = sc->sc_ioh;
744	int s;
745
746	DPRINTF(SEEQ_DEBUG_MISC, ("ea_init()\n"));
747
748	s = splnet();
749
750	/* First, reset the board. */
751
752	ea_chipreset(sc);
753
754	/* Set up defaults for the registers */
755
756	sc->sc_command = 0;
757	sc->sc_config1 = 0;
758#if BYTE_ORDER == BIG_ENDIAN
759	sc->sc_config2 = SEEQ_CFG2_BYTESWAP;
760#else
761	sc->sc_config2 = 0;
762#endif
763	sc->sc_config3 = 0;
764
765	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, sc->sc_command);
766	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG1, sc->sc_config1);
767	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2);
768	if (sc->sc_variant == SEEQ_8004) {
769		ea_select_buffer(sc, SEEQ_BUFCODE_CONFIG3);
770		SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, sc->sc_config3);
771	}
772
773	/* Write the station address - the receiver must be off */
774	ea_set_address(sc, 0, (const uint8_t *)CLLADDR(ifp->if_sadl));
775
776	/* Split board memory into Rx and Tx. */
777	ea_select_buffer(sc, SEEQ_BUFCODE_TX_EAP);
778	SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, (sc->sc_tx_bufsize>> 8) - 1);
779
780	if (sc->sc_variant == SEEQ_8004) {
781		/* Make the interface IFF_SIMPLEX. */
782		sc->sc_config2 |= SEEQ_CFG2_RX_TX_DISABLE;
783		/* Enable reception of long packets (for vlan(4)). */
784		sc->sc_config2 |= SEEQ_CFG2_PASS_LONGSHORT;
785	}
786
787	/* Configure rx. */
788	ea_mc_reset(sc);
789	if (ifp->if_flags & IFF_PROMISC)
790		sc->sc_config1 = SEEQ_CFG1_PROMISCUOUS;
791	else if ((ifp->if_flags & IFF_ALLMULTI) || sc->sc_variant == SEEQ_8004)
792		sc->sc_config1 = SEEQ_CFG1_MULTICAST;
793	else
794		sc->sc_config1 = SEEQ_CFG1_BROADCAST;
795	sc->sc_config1 |= SEEQ_CFG1_STATION_ADDR0;
796	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG1, sc->sc_config1);
797
798	/* Setup the Rx pointers */
799	sc->sc_rx_ptr = sc->sc_tx_bufsize;
800
801	SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, sc->sc_rx_ptr);
802	SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_END, sc->sc_rx_ptr >> 8);
803
804
805	/* Place a NULL header at the beginning of the receive area */
806	ea_writebuf(sc, NULL, sc->sc_rx_ptr, 0);
807
808	SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000);
809	SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000);
810
811
812	/* Configure TX. */
813	DPRINTF(SEEQ_DEBUG_MISC, ("Configuring tx...\n"));
814
815	SEEQ_WRITE16(sc, iot, ioh, SEEQ_TX_PTR, 0x0000);
816
817	sc->sc_config2 |= SEEQ_CFG2_OUTPUT;
818	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2);
819
820	/* Reset tx buffer pointers */
821	sc->sc_tx_cur = 0;
822	sc->sc_tx_used = 0;
823	sc->sc_tx_next = 0;
824
825	/* Place a NULL header at the beginning of the transmit area */
826	ea_writebuf(sc, NULL, 0x0000, 0);
827
828	SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000);
829	SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000);
830
831	sc->sc_command |= SEEQ_CMD_TX_INTEN;
832	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, sc->sc_command);
833
834	/* Turn on Rx */
835	sc->sc_command |= SEEQ_CMD_RX_INTEN;
836	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
837			  sc->sc_command | SEEQ_CMD_RX_ON);
838
839	/* TX_ON gets set by ea_txpacket when there's something to transmit. */
840
841
842	/* Set flags appropriately. */
843	ifp->if_flags |= IFF_RUNNING;
844	ifp->if_flags &= ~IFF_OACTIVE;
845	sc->sc_enabled = 1;
846
847	/* And start output. */
848	ea_start(ifp);
849
850	splx(s);
851	return 0;
852}
853
854/*
855 * Start output on interface. Get datagrams from the queue and output them,
856 * giving the receiver a chance between datagrams. Call only from splnet or
857 * interrupt level!
858 */
859
860static void
861ea_start(struct ifnet *ifp)
862{
863	struct seeq8005_softc *sc = ifp->if_softc;
864	int s;
865
866	s = splnet();
867	DPRINTF(SEEQ_DEBUG_TX, ("ea_start()...\n"));
868
869	/*
870	 * Don't do anything if output is active.  seeq8005intr() will call
871	 * us (actually ea_txpacket()) back when the card's ready for more
872	 * frames.
873	 */
874	if (ifp->if_flags & IFF_OACTIVE) {
875		splx(s);
876		return;
877	}
878
879	/* Mark interface as output active */
880
881	ifp->if_flags |= IFF_OACTIVE;
882
883	/* tx packets */
884
885	ea_txpacket(sc);
886	splx(s);
887}
888
889
890/*
891 * Transfer a packet to the interface buffer and start transmission
892 *
893 * Called at splnet()
894 */
895
896static void
897ea_txpacket(struct seeq8005_softc *sc)
898{
899	bus_space_tag_t iot = sc->sc_iot;
900	bus_space_handle_t ioh = sc->sc_ioh;
901	struct mbuf *m0;
902	struct ifnet *ifp;
903
904	ifp = &sc->sc_ethercom.ec_if;
905
906	/* Dequeue the next packet. */
907	IFQ_DEQUEUE(&ifp->if_snd, m0);
908
909	/* If there's nothing to send, return. */
910	if (m0 == NULL) {
911		ifp->if_flags &= ~IFF_OACTIVE;
912		sc->sc_config2 |= SEEQ_CFG2_OUTPUT;
913		SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2);
914		DPRINTF(SEEQ_DEBUG_TX, ("tx finished\n"));
915		return;
916	}
917
918	/* Give the packet to the bpf, if any. */
919	bpf_mtap(ifp, m0, BPF_D_OUT);
920
921	DPRINTF(SEEQ_DEBUG_TX, ("Tx new packet\n"));
922
923	sc->sc_config2 &= ~SEEQ_CFG2_OUTPUT;
924	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2);
925
926	ea_writembuf(sc, m0, 0x0000);
927	m_freem(m0);
928
929	SEEQ_WRITE16(sc, iot, ioh, SEEQ_TX_PTR, 0x0000);
930
931	/* Now transmit the datagram. */
932	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
933			  sc->sc_command | SEEQ_CMD_TX_ON);
934
935	/* Make sure we notice if the chip goes silent on us. */
936	ifp->if_timer = 5;
937
938	DPRINTF(SEEQ_DEBUG_TX,
939	    ("st=%04x\n", SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS)));
940	DPRINTF(SEEQ_DEBUG_TX, ("tx: queued\n"));
941}
942
943/*
944 * Copy a packet from an mbuf to the transmit buffer on the card.
945 *
946 * Puts a valid Tx header at the start of the packet, and a null header at
947 * the end.
948 */
949static int
950ea_writembuf(struct seeq8005_softc *sc, struct mbuf *m0, int bufstart)
951{
952	struct mbuf *m;
953	int len, nextpacket;
954	uint8_t hdr[4];
955
956	/*
957	 * Copy the datagram to the packet buffer.
958	 */
959	len = 0;
960	for (m = m0; m; m = m->m_next) {
961		if (m->m_len == 0)
962			continue;
963		ea_writebuf(sc, mtod(m, u_char *), bufstart + 4 + len,
964		    m->m_len);
965		len += m->m_len;
966	}
967
968	if (len < ETHER_MIN_LEN) {
969		ea_writebuf(sc, padbuf, bufstart + 4 + len,
970		    ETHER_MIN_LEN - len);
971		len = ETHER_MIN_LEN;
972	}
973
974	/* Follow it with a NULL packet header */
975	memset(hdr, 0, 4);
976	ea_writebuf(sc, hdr, bufstart + 4 + len, 4);
977
978	/* Ok we now have a packet len bytes long in our packet buffer */
979	DPRINTF(SEEQ_DEBUG_TX, ("ea_writembuf: length=%d\n", len));
980
981	/* Write the packet header */
982	nextpacket = bufstart + len + 4;
983	hdr[0] = (nextpacket >> 8) & 0xff;
984	hdr[1] = nextpacket & 0xff;
985	hdr[2] = SEEQ_PKTCMD_TX | SEEQ_PKTCMD_DATA_FOLLOWS |
986		SEEQ_TXCMD_XMIT_SUCCESS_INT | SEEQ_TXCMD_COLLISION_INT;
987	hdr[3] = 0; /* Status byte -- will be updated by hardware. */
988	ea_writebuf(sc, hdr, bufstart, 4);
989
990	return len;
991}
992
993/*
994 * Ethernet controller interrupt.
995 */
996
997int
998seeq8005intr(void *arg)
999{
1000	struct seeq8005_softc *sc = arg;
1001	bus_space_tag_t iot = sc->sc_iot;
1002	bus_space_handle_t ioh = sc->sc_ioh;
1003	int status, handled;
1004
1005	handled = 0;
1006
1007	/* Get the controller status */
1008	status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS);
1009
1010	/* Tx interrupt ? */
1011	if (status & SEEQ_STATUS_TX_INT) {
1012		handled = 1;
1013
1014		/* Acknowledge the interrupt */
1015		SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
1016				  sc->sc_command | SEEQ_CMD_TX_INTACK);
1017
1018		ea_txint(sc);
1019	}
1020
1021
1022	/* Rx interrupt ? */
1023	if (status & SEEQ_STATUS_RX_INT) {
1024		handled = 1;
1025
1026		/* Acknowledge the interrupt */
1027		SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
1028				  sc->sc_command | SEEQ_CMD_RX_INTACK);
1029
1030		/* Processes the received packets */
1031		ea_rxint(sc);
1032	}
1033
1034	if (handled)
1035		rnd_add_uint32(&sc->rnd_source, status);
1036
1037	return handled;
1038}
1039
1040static void
1041ea_txint(struct seeq8005_softc *sc)
1042{
1043	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1044	bus_space_tag_t iot = sc->sc_iot;
1045	bus_space_handle_t ioh = sc->sc_ioh;
1046	uint8_t txhdr[4];
1047	u_int txstatus;
1048
1049	ea_readbuf(sc, txhdr, 0x0000, 4);
1050
1051	DPRINTF(SEEQ_DEBUG_TX, ("txstatus=%02x %02x %02x %02x\n",
1052	    txhdr[0], txhdr[1], txhdr[2], txhdr[3]));
1053	txstatus = txhdr[3];
1054
1055	/*
1056	 * If SEEQ_TXSTAT_COLLISION is set then we received at least
1057	 * one collision. On the 8004 we can find out exactly how many
1058	 * collisions occurred.
1059	 *
1060	 * The SEEQ_PKTSTAT_DONE will be set if the transmission has
1061	 * completed.
1062	 *
1063	 * If SEEQ_TXSTAT_COLLISION16 is set then 16 collisions
1064	 * occurred and the packet transmission was aborted.
1065	 * This situation is untested as present.
1066	 *
1067	 * The SEEQ_TXSTAT_BABBLE is untested as it should only be set
1068	 * when we deliberately transmit oversized packets (e.g. for
1069	 * 802.1Q).
1070	 */
1071	if (txstatus & SEEQ_TXSTAT_COLLISION) {
1072		switch (sc->sc_variant) {
1073		case SEEQ_8004: {
1074			int colls;
1075
1076			/*
1077			 * The 8004 contains a 4 bit collision count
1078			 * in the status register.
1079			 */
1080#if 0
1081			/* This appears to be broken on 80C04.AE */
1082			if_statadd(ifp, if_collisions,
1083			    (txstatus >> SEEQ_TXSTAT_COLLISIONS_SHIFT)
1084			    & SEEQ_TXSTAT_COLLISION_MASK;
1085#endif
1086
1087			/* Use the TX Collision register */
1088			ea_select_buffer(sc, SEEQ_BUFCODE_TX_COLLS);
1089			colls = bus_space_read_1(iot, ioh, SEEQ_BUFWIN);
1090			if_statadd(ifp, if_collisions, colls);
1091			break;
1092		}
1093		case SEEQ_8005:
1094			/* We known there was at least 1 collision */
1095			if_statinc(ifp, if_collisions);
1096			break;
1097		}
1098	} else if (txstatus & SEEQ_TXSTAT_COLLISION16) {
1099		printf("seeq_intr: col16 %x\n", txstatus);
1100		if_statadd2(ifp, if_collisions, 16, if_oerrors, 1);
1101	}
1102
1103	/* Have we completed transmission on the packet ? */
1104	if (txstatus & SEEQ_PKTSTAT_DONE) {
1105		/* Clear watchdog timer. */
1106		ifp->if_timer = 0;
1107		ifp->if_flags &= ~IFF_OACTIVE;
1108
1109		/* Update stats */
1110		if_statinc(ifp, if_opackets);
1111
1112		/* Tx next packet */
1113
1114		ea_txpacket(sc);
1115	}
1116}
1117
1118static void
1119ea_rxint(struct seeq8005_softc *sc)
1120{
1121	bus_space_tag_t iot = sc->sc_iot;
1122	bus_space_handle_t ioh = sc->sc_ioh;
1123	u_int addr;
1124	int len;
1125	int ctrl;
1126	int ptr;
1127	int status;
1128	uint8_t rxhdr[4];
1129	struct ifnet *ifp;
1130
1131	ifp = &sc->sc_ethercom.ec_if;
1132
1133
1134	/* We start from the last rx pointer position */
1135	addr = sc->sc_rx_ptr;
1136	sc->sc_config2 &= ~SEEQ_CFG2_OUTPUT;
1137	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2);
1138
1139	do {
1140		/* Read rx header */
1141		ea_readbuf(sc, rxhdr, addr, 4);
1142
1143		/* Split the packet header */
1144		ptr = (rxhdr[0] << 8) | rxhdr[1];
1145		ctrl = rxhdr[2];
1146		status = rxhdr[3];
1147
1148		DPRINTF(SEEQ_DEBUG_RX,
1149		    ("addr=%04x ptr=%04x ctrl=%02x status=%02x\n",
1150			addr, ptr, ctrl, status));
1151
1152		/* Zero packet ptr ? then must be null header so exit */
1153		if (ptr == 0) break;
1154
1155		/* Sanity-check the next-packet pointer and flags. */
1156		if (__predict_false(ptr < sc->sc_tx_bufsize ||
1157		    (ctrl & SEEQ_PKTCMD_TX))) {
1158			if_statinc(ifp, if_ierrors);
1159			log(LOG_ERR,
1160			    "%s: Rx chain corrupt at %04x (ptr = %04x)\n",
1161			    device_xname(sc->sc_dev), addr, ptr);
1162			ea_init(ifp);
1163			return;
1164		}
1165
1166		/* Get packet length */
1167		len = (ptr - addr) - 4;
1168
1169		if (len < 0)
1170			len += sc->sc_rx_bufsize;
1171		DPRINTF(SEEQ_DEBUG_RX, ("len=%04x\n", len));
1172
1173		/* Has the packet rx completed ? if not then exit */
1174		if ((status & SEEQ_PKTSTAT_DONE) == 0)
1175			break;
1176
1177		/*
1178		 * Did we have any errors? then note error and go to
1179		 * next packet
1180		 */
1181		if (__predict_false(status &
1182			(SEEQ_RXSTAT_CRC_ERROR | SEEQ_RXSTAT_DRIBBLE_ERROR |
1183			 SEEQ_RXSTAT_SHORT_FRAME))) {
1184			if_statinc(ifp, if_ierrors);
1185			log(LOG_WARNING,
1186			    "%s: rx packet error at %04x (err=%02x)\n",
1187			    device_xname(sc->sc_dev), addr, status & 0x0f);
1188			/* XXX shouldn't need to reset if it's genuine. */
1189			ea_init(ifp);
1190			return;
1191		}
1192		/*
1193		 * Is the packet too big?  We allow slightly oversize packets
1194		 * for vlan(4) and tcpdump purposes, but the rest of the world
1195		 * wants incoming packets in a single mbuf cluster.
1196		 */
1197		if (__predict_false(len > MCLBYTES)) {
1198			if_statinc(ifp, if_ierrors);
1199			log(LOG_ERR,
1200			    "%s: rx packet size error at %04x (len=%d)\n",
1201			    device_xname(sc->sc_dev), addr, len);
1202			ea_init(ifp);
1203			return;
1204		}
1205
1206		/* Pass data up to upper levels. */
1207		ea_read(sc, addr + 4, len);
1208
1209		addr = ptr;
1210	} while (len != 0);
1211
1212	sc->sc_config2 |= SEEQ_CFG2_OUTPUT;
1213	SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2);
1214
1215	DPRINTF(SEEQ_DEBUG_RX, ("new rx ptr=%04x\n", addr));
1216
1217	/* Store new rx pointer */
1218	sc->sc_rx_ptr = addr;
1219	SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_END, sc->sc_rx_ptr >> 8);
1220
1221	/* Make sure the receiver is on */
1222	SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND,
1223			  sc->sc_command | SEEQ_CMD_RX_ON);
1224}
1225
1226
1227/*
1228 * Pass a packet up to the higher levels.
1229 */
1230
1231static void
1232ea_read(struct seeq8005_softc *sc, int addr, int len)
1233{
1234	struct mbuf *m;
1235	struct ifnet *ifp;
1236
1237	ifp = &sc->sc_ethercom.ec_if;
1238
1239	/* Pull packet off interface. */
1240	m = ea_get(sc, addr, len, ifp);
1241	if (m == NULL)
1242		return;
1243
1244	if_percpuq_enqueue(ifp->if_percpuq, m);
1245}
1246
1247/*
1248 * Pull read data off a interface.  Len is length of data, with local net
1249 * header stripped.  We copy the data into mbufs.  When full cluster sized
1250 * units are present we copy into clusters.
1251 */
1252
1253struct mbuf *
1254ea_get(struct seeq8005_softc *sc, int addr, int totlen, struct ifnet *ifp)
1255{
1256	struct mbuf *top, **mp, *m;
1257	int len;
1258	u_int cp, epkt;
1259
1260	cp = addr;
1261	epkt = cp + totlen;
1262
1263	MGETHDR(m, M_DONTWAIT, MT_DATA);
1264	if (m == NULL)
1265		return NULL;
1266	m_set_rcvif(m, ifp);
1267	m->m_pkthdr.len = totlen;
1268	m->m_len = MHLEN;
1269	top = NULL;
1270	mp = &top;
1271
1272	while (totlen > 0) {
1273		if (top) {
1274			MGET(m, M_DONTWAIT, MT_DATA);
1275			if (m == NULL) {
1276				m_freem(top);
1277				return NULL;
1278			}
1279			m->m_len = MLEN;
1280		}
1281		len = uimin(totlen, epkt - cp);
1282		if (len >= MINCLSIZE) {
1283			MCLGET(m, M_DONTWAIT);
1284			if (m->m_flags & M_EXT)
1285				m->m_len = len = uimin(len, MCLBYTES);
1286			else
1287				len = m->m_len;
1288		} else {
1289			/*
1290			 * Place initial small packet/header at end of mbuf.
1291			 */
1292			if (len < m->m_len) {
1293				if (top == NULL && len + max_linkhdr <= m->m_len)
1294					m->m_data += max_linkhdr;
1295				m->m_len = len;
1296			} else
1297				len = m->m_len;
1298		}
1299		if (top == NULL) {
1300			/* Make sure the payload is aligned */
1301			char *newdata = (char *)
1302			    ALIGN((char*)m->m_data +
1303				sizeof(struct ether_header)) -
1304			    sizeof(struct ether_header);
1305			len -= newdata - m->m_data;
1306			m->m_len = len;
1307			m->m_data = newdata;
1308		}
1309		ea_readbuf(sc, mtod(m, u_char *),
1310		    cp < SEEQ_MAX_BUFFER_SIZE ? cp : cp - sc->sc_rx_bufsize,
1311		    len);
1312		cp += len;
1313		*mp = m;
1314		mp = &m->m_next;
1315		totlen -= len;
1316		if (cp == epkt)
1317			cp = addr;
1318	}
1319
1320	return top;
1321}
1322
1323/*
1324 * Process an ioctl request.  Mostly boilerplate.
1325 */
1326static int
1327ea_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1328{
1329	struct seeq8005_softc *sc = ifp->if_softc;
1330	int s, error = 0;
1331
1332	s = splnet();
1333	switch (cmd) {
1334
1335	default:
1336		error = ether_ioctl(ifp, cmd, data);
1337		if (error == ENETRESET) {
1338			/*
1339			 * Multicast list has changed; set the hardware filter
1340			 * accordingly.
1341			 */
1342			if (ifp->if_flags & IFF_RUNNING)
1343				ea_mc_reset(sc);
1344			error = 0;
1345		}
1346		break;
1347	}
1348
1349	splx(s);
1350	return error;
1351}
1352
1353/* Must be called at splnet() */
1354
1355static void
1356ea_mc_reset(struct seeq8005_softc *sc)
1357{
1358
1359	switch (sc->sc_variant) {
1360	case SEEQ_8004:
1361		ea_mc_reset_8004(sc);
1362		return;
1363	case SEEQ_8005:
1364		ea_mc_reset_8005(sc);
1365		return;
1366	}
1367}
1368
1369static void
1370ea_mc_reset_8004(struct seeq8005_softc *sc)
1371{
1372	struct ethercom *ec = &sc->sc_ethercom;
1373	struct ifnet *ifp = &ec->ec_if;
1374	struct ether_multi *enm;
1375	uint32_t crc;
1376	int i;
1377	struct ether_multistep step;
1378	uint8_t af[8];
1379
1380	/*
1381	 * Set up multicast address filter by passing all multicast addresses
1382	 * through a crc generator, and then using bits 2 - 7 as an index
1383	 * into the 64 bit logical address filter.  The high order bits
1384	 * selects the word, while the rest of the bits select the bit within
1385	 * the word.
1386	 */
1387
1388	if (ifp->if_flags & IFF_PROMISC) {
1389		ifp->if_flags |= IFF_ALLMULTI;
1390		for (i = 0; i < 8; i++)
1391			af[i] = 0xff;
1392		return;
1393	}
1394	for (i = 0; i < 8; i++)
1395		af[i] = 0;
1396
1397	ETHER_LOCK(ec);
1398	ETHER_FIRST_MULTI(step, ec, enm);
1399	while (enm != NULL) {
1400		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
1401		    sizeof(enm->enm_addrlo)) != 0) {
1402			/*
1403			 * We must listen to a range of multicast addresses.
1404			 * For now, just accept all multicasts, rather than
1405			 * trying to set only those filter bits needed to match
1406			 * the range.  (At this time, the only use of address
1407			 * ranges is for IP multicast routing, for which the
1408			 * range is big enough to require all bits set.)
1409			 */
1410			ifp->if_flags |= IFF_ALLMULTI;
1411			for (i = 0; i < 8; i++)
1412				af[i] = 0xff;
1413			break;
1414		}
1415
1416		crc = ether_crc32_be(enm->enm_addrlo, sizeof(enm->enm_addrlo));
1417
1418		/* Just want the 6 most significant bits. */
1419		crc = (crc >> 2) & 0x3f;
1420
1421		/* Turn on the corresponding bit in the filter. */
1422		af[crc >> 3] |= 1 << (crc & 0x7);
1423
1424		ETHER_NEXT_MULTI(step, enm);
1425	}
1426	ETHER_UNLOCK(ec);
1427	ifp->if_flags &= ~IFF_ALLMULTI;
1428
1429	ea_select_buffer(sc, SEEQ_BUFCODE_MULTICAST);
1430		for (i = 0; i < 8; ++i)
1431			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
1432			    SEEQ_BUFWIN, af[i]);
1433}
1434
1435static void
1436ea_mc_reset_8005(struct seeq8005_softc *sc)
1437{
1438	struct ethercom *ec = &sc->sc_ethercom;
1439	struct ether_multi *enm;
1440	struct ether_multistep step;
1441	int naddr, maxaddrs;
1442
1443	naddr = 0;
1444	maxaddrs = 5;
1445	ETHER_LOCK(ec);
1446	ETHER_FIRST_MULTI(step, ec, enm);
1447	while (enm != NULL) {
1448		/* Have we got space? */
1449		if (naddr >= maxaddrs ||
1450		    memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
1451			ec->ec_if.if_flags |= IFF_ALLMULTI;
1452			ETHER_UNLOCK(ec);
1453			ea_ioctl(&ec->ec_if, SIOCSIFFLAGS, NULL);
1454			return;
1455		}
1456		ea_set_address(sc, 1 + naddr, enm->enm_addrlo);
1457		sc->sc_config1 |= SEEQ_CFG1_STATION_ADDR1 << naddr;
1458		naddr++;
1459		ETHER_NEXT_MULTI(step, enm);
1460	}
1461	ETHER_UNLOCK(ec);
1462
1463	for (; naddr < maxaddrs; naddr++)
1464		sc->sc_config1 &= ~(SEEQ_CFG1_STATION_ADDR1 << naddr);
1465	SEEQ_WRITE16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_CONFIG1,
1466			  sc->sc_config1);
1467}
1468
1469/*
1470 * Device timeout routine.
1471 */
1472
1473static void
1474ea_watchdog(struct ifnet *ifp)
1475{
1476	struct seeq8005_softc *sc = ifp->if_softc;
1477
1478	log(LOG_ERR, "%s: lost Tx interrupt (status = 0x%04x)\n",
1479	    device_xname(sc->sc_dev),
1480	    SEEQ_READ16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_STATUS));
1481	if_statinc(ifp, if_oerrors);
1482
1483	/* Kick the interface */
1484
1485	ea_init(ifp);
1486
1487	ifp->if_timer = 0;
1488}
1489
1490/* End of seeq8005.c */
1491