[Midnightbsd-cvs] src [10115] trunk/sys/dev/altera: add altera

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun May 27 20:11:41 EDT 2018


Revision: 10115
          http://svnweb.midnightbsd.org/src/?rev=10115
Author:   laffer1
Date:     2018-05-27 20:11:41 -0400 (Sun, 27 May 2018)
Log Message:
-----------
 add altera

Added Paths:
-----------
    trunk/sys/dev/altera/
    trunk/sys/dev/altera/atse/
    trunk/sys/dev/altera/atse/a_api.h
    trunk/sys/dev/altera/atse/if_atse.c
    trunk/sys/dev/altera/atse/if_atse_fdt.c
    trunk/sys/dev/altera/atse/if_atse_nexus.c
    trunk/sys/dev/altera/atse/if_atsereg.h
    trunk/sys/dev/altera/avgen/
    trunk/sys/dev/altera/avgen/altera_avgen.c
    trunk/sys/dev/altera/avgen/altera_avgen.h
    trunk/sys/dev/altera/avgen/altera_avgen_fdt.c
    trunk/sys/dev/altera/avgen/altera_avgen_nexus.c
    trunk/sys/dev/altera/jtag_uart/
    trunk/sys/dev/altera/jtag_uart/altera_jtag_uart.h
    trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
    trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
    trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
    trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c
    trunk/sys/dev/altera/sdcard/
    trunk/sys/dev/altera/sdcard/altera_sdcard.c
    trunk/sys/dev/altera/sdcard/altera_sdcard.h
    trunk/sys/dev/altera/sdcard/altera_sdcard_disk.c
    trunk/sys/dev/altera/sdcard/altera_sdcard_fdt.c
    trunk/sys/dev/altera/sdcard/altera_sdcard_io.c
    trunk/sys/dev/altera/sdcard/altera_sdcard_nexus.c

Added: trunk/sys/dev/altera/atse/a_api.h
===================================================================
--- trunk/sys/dev/altera/atse/a_api.h	                        (rev 0)
+++ trunk/sys/dev/altera/atse/a_api.h	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,99 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/altera/atse/a_api.h 271969 2014-09-22 15:32:31Z bz $
+ */
+/*
+ * Altera, Embedded Peripherals IP, User Guide, v. 11.0, June 2011.
+ * UG-01085-11.0.
+ */
+
+#ifndef _A_API_H
+#define _A_API_H
+
+/* Table 16-1. Memory Map. */
+#define	A_ONCHIP_FIFO_MEM_CORE_DATA		0x00
+#define	A_ONCHIP_FIFO_MEM_CORE_METADATA		0x04
+
+#define	A_ONCHIP_FIFO_MEM_CORE_SOP		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_EOP		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK	0x000000f7
+#define	A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT	2
+	/* Reserved				(1<<7)	   */
+#define	A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK	0x0000ff00
+#define	A_ONCHIP_FIFO_MEM_CORE_CHANNEL_SHIFT	8
+#define	A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK	0x00ff0000
+#define	A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT	16
+	/* Reserved				0xff000000 */
+
+/* Table 16-3. FIFO Status Register Memory Map. */
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL	0x00
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS	0x04
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT		0x08
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE	0x0c
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_ALMOSTFULL	0x10
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_ALMOSTEMPTY	0x14
+
+/* Table 16-5. Status Bit Field Descriptions. */
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_FULL		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_EMPTY		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_ALMOSTFULL	(1<<2)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_ALMOSTEMPTY	(1<<3)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_OVERFLOW		(1<<4)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_UNDERFLOW		(1<<5)
+
+/* Table 16-6. Event Bit Field Descriptions. */
+/* XXX Datasheet has incorrect bit fields. Validate. */
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_FULL		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_EMPTY		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_ALMOSTFULL		(1<<2)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_ALMOSTEMPTY	(1<<3)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW		(1<<4)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW		(1<<5)
+
+/* Table 16-7. InterruptEnable Bit Field Descriptions. */
+/* XXX Datasheet has incorrect bit fields. Validate. */
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_FULL		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTFULL		(1<<2)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTEMPTY		(1<<3)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW		(1<<4)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW		(1<<5)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_ALL			\
+	    (A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY|		\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_FULL|		\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTEMPTY|	\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTFULL|	\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW|	\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
+
+#endif /* _A_API_H */
+
+/* end */


Property changes on: trunk/sys/dev/altera/atse/a_api.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/atse/if_atse.c
===================================================================
--- trunk/sys/dev/altera/atse/if_atse.c	                        (rev 0)
+++ trunk/sys/dev/altera/atse/if_atse.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,2092 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012,2013 Bjoern A. Zeeb
+ * Copyright (c) 2014 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Altera Triple-Speed Ethernet MegaCore, Function User Guide
+ * UG-01008-3.0, Software Version: 12.0, June 2012.
+ * Available at the time of writing at:
+ * http://www.altera.com/literature/ug/ug_ethernet.pdf
+ *
+ * We are using an Marvell E1111 (Alaska) PHY on the DE4.  See mii/e1000phy.c.
+ */
+/*
+ * XXX-BZ NOTES:
+ * - ifOutBroadcastPkts are only counted if both ether dst and src are all-1s;
+ *   seems an IP core bug, they count ether broadcasts as multicast.  Is this
+ *   still the case?
+ * - figure out why the TX FIFO fill status and intr did not work as expected.
+ * - test 100Mbit/s and 10Mbit/s
+ * - blacklist the one special factory programmed ethernet address (for now
+ *   hardcoded, later from loader?)
+ * - resolve all XXX, left as reminders to shake out details later
+ * - Jumbo frame support
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/atse/if_atse.c 271969 2014-09-22 15:32:31Z bz $");
+
+#include "opt_device_polling.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/jail.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/types.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <net/bpf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/altera/atse/if_atsereg.h>
+#include <dev/altera/atse/a_api.h>
+
+MODULE_DEPEND(atse, ether, 1, 1, 1);
+MODULE_DEPEND(atse, miibus, 1, 1, 1);
+
+
+#define	ATSE_WATCHDOG_TIME	5
+
+#ifdef DEVICE_POLLING
+static poll_handler_t atse_poll;
+#endif
+
+/* XXX once we'd do parallel attach, we need a global lock for this. */
+#define	ATSE_ETHERNET_OPTION_BITS_UNDEF	0
+#define	ATSE_ETHERNET_OPTION_BITS_READ	1
+static int atse_ethernet_option_bits_flag = ATSE_ETHERNET_OPTION_BITS_UNDEF;
+static uint8_t atse_ethernet_option_bits[ALTERA_ETHERNET_OPTION_BITS_LEN];
+
+static int	atse_intr_debug_enable = 0;
+SYSCTL_INT(_debug, OID_AUTO, atse_intr_debug_enable, CTLFLAG_RW,
+    &atse_intr_debug_enable, 0,
+   "Extra debugging output for atse interrupts");
+
+/*
+ * Softc and critical resource locking.
+ */
+#define	ATSE_LOCK(_sc)		mtx_lock(&(_sc)->atse_mtx)
+#define	ATSE_UNLOCK(_sc)	mtx_unlock(&(_sc)->atse_mtx)
+#define	ATSE_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->atse_mtx, MA_OWNED)
+
+#define	ATSE_TX_PENDING(sc)	(sc->atse_tx_m != NULL ||		\
+				    !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+
+#ifdef DEBUG
+#define	DPRINTF(format, ...)	printf(format, __VA_ARGS__)
+#else
+#define	DPRINTF(format, ...)
+#endif
+
+/* a_api.c functions; factor out? */
+static inline void
+a_onchip_fifo_mem_core_write(struct resource *res, uint32_t off,
+    uint32_t val4, const char *desc, const char *f, const int l)
+{
+
+	val4 = htole32(val4);
+	DPRINTF("[%s:%d] FIFOW %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
+	bus_write_4(res, off, val4);
+}
+static inline uint32_t
+a_onchip_fifo_mem_core_read(struct resource *res, uint32_t off,
+    const char *desc, const char *f, const int l)
+{
+	uint32_t val4;
+
+	val4 = le32toh(bus_read_4(res, off));
+	DPRINTF("[%s:%d] FIFOR %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
+	return (val4);
+}
+
+/* The FIFO does an endian convertion, so we must not do it as well. */
+/* XXX-BZ in fact we should do a htobe32 so le would be fine as well? */
+#define	ATSE_TX_DATA_WRITE(sc, val4)					\
+	bus_write_4((sc)->atse_tx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA, val4)
+
+#define	ATSE_TX_META_WRITE(sc, val4)					\
+	a_onchip_fifo_mem_core_write((sc)->atse_tx_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_METADATA,				\
+	    (val4), "TXM", __func__, __LINE__)
+#define	ATSE_TX_META_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_tx_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_METADATA,				\
+	    "TXM", __func__, __LINE__)
+
+#define	ATSE_TX_READ_FILL_LEVEL(sc)					\
+	a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL,		\
+	    "TX_FILL", __func__, __LINE__)
+#define	ATSE_RX_READ_FILL_LEVEL(sc)					\
+	a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL,		\
+	    "RX_FILL", __func__, __LINE__)
+
+/* The FIFO does an endian convertion, so we must not do it as well. */
+/* XXX-BZ in fact we shoudl do a htobe32 so le would be fine as well? */
+#define	ATSE_RX_DATA_READ(sc)						\
+	bus_read_4((sc)->atse_rx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA)
+#define	ATSE_RX_META_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_rx_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_METADATA,				\
+	    "RXM", __func__, __LINE__)
+
+#define	ATSE_RX_STATUS_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS,			\
+	    "RX_EVENT", __func__, __LINE__)
+
+#define	ATSE_TX_STATUS_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS,			\
+	    "TX_EVENT", __func__, __LINE__)
+
+#define	ATSE_RX_EVENT_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,			\
+	    "RX_EVENT", __func__, __LINE__)
+
+#define	ATSE_TX_EVENT_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,			\
+	    "TX_EVENT", __func__, __LINE__)
+
+#define	ATSE_RX_EVENT_CLEAR(sc)						\
+	do {								\
+		uint32_t val4;						\
+									\
+		val4 = a_onchip_fifo_mem_core_read(			\
+		    (sc)->atse_rxc_mem_res,				\
+		    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,		\
+		    "RX_EVENT", __func__, __LINE__);			\
+		if (val4 != 0x00)					\
+			a_onchip_fifo_mem_core_write(			\
+			    (sc)->atse_rxc_mem_res,			\
+			    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,	\
+			    val4, "RX_EVENT", __func__, __LINE__);	\
+	} while(0)
+#define	ATSE_TX_EVENT_CLEAR(sc)						\
+	do {								\
+		uint32_t val4;						\
+									\
+		val4 = a_onchip_fifo_mem_core_read(			\
+		    (sc)->atse_txc_mem_res,				\
+		    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,		\
+		    "TX_EVENT", __func__, __LINE__);			\
+		if (val4 != 0x00)					\
+			a_onchip_fifo_mem_core_write(			\
+			    (sc)->atse_txc_mem_res,			\
+			    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,	\
+			    val4, "TX_EVENT", __func__, __LINE__);	\
+	} while(0)
+
+#define	ATSE_RX_EVENTS	(A_ONCHIP_FIFO_MEM_CORE_INTR_FULL |	\
+			    A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW |	\
+			    A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
+#define	ATSE_RX_INTR_ENABLE(sc)						\
+	a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,		\
+	    ATSE_RX_EVENTS,						\
+	    "RX_INTR", __func__, __LINE__)	/* XXX-BZ review later. */
+#define	ATSE_RX_INTR_DISABLE(sc)					\
+	a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0,		\
+	    "RX_INTR", __func__, __LINE__)
+#define	ATSE_RX_INTR_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,		\
+	    "RX_INTR", __func__, __LINE__)
+
+#define	ATSE_TX_EVENTS	(A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY |		\
+			    A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW |	\
+			    A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
+#define	ATSE_TX_INTR_ENABLE(sc)						\
+	a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,		\
+	    ATSE_TX_EVENTS,						\
+	    "TX_INTR", __func__, __LINE__)	/* XXX-BZ review later. */
+#define	ATSE_TX_INTR_DISABLE(sc)					\
+	a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0,		\
+	    "TX_INTR", __func__, __LINE__)
+#define	ATSE_TX_INTR_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,		\
+	    "TX_INTR", __func__, __LINE__)
+
+static int	atse_rx_locked(struct atse_softc *sc);
+
+/*
+ * Register space access macros.
+ */
+static inline void
+csr_write_4(struct atse_softc *sc, uint32_t reg, uint32_t val4,
+    const char *f, const int l)
+{
+
+	val4 = htole32(val4);
+	DPRINTF("[%s:%d] CSR W %s 0x%08x (0x%08x) = 0x%08x\n", f, l,
+	    "atse_mem_res", reg, reg * 4, val4);
+	bus_write_4(sc->atse_mem_res, reg * 4, val4);
+}
+
+static inline uint32_t
+csr_read_4(struct atse_softc *sc, uint32_t reg, const char *f, const int l)
+{
+	uint32_t val4;
+
+	val4 = le32toh(bus_read_4(sc->atse_mem_res, reg * 4));
+	DPRINTF("[%s:%d] CSR R %s 0x%08x (0x%08x) = 0x%08x\n", f, l, 
+	    "atse_mem_res", reg, reg * 4, val4);
+	return (val4);
+}
+
+/*
+ * See page 5-2 that it's all dword offsets and the MS 16 bits need to be zero
+ * on write and ignored on read.
+ */
+static inline void
+pxx_write_2(struct atse_softc *sc, bus_addr_t bmcr, uint32_t reg, uint16_t val,
+    const char *f, const int l, const char *s)
+{
+	uint32_t val4;
+
+	val4 = htole32(val & 0x0000ffff);
+	DPRINTF("[%s:%d] %s W %s 0x%08x (0x%08jx) = 0x%08x\n", f, l, s,
+	    "atse_mem_res", reg, (bmcr + reg) * 4, val4);
+	bus_write_4(sc->atse_mem_res, (bmcr + reg) * 4, val4);
+}
+
+static inline uint16_t
+pxx_read_2(struct atse_softc *sc, bus_addr_t bmcr, uint32_t reg, const char *f,
+    const int l, const char *s)
+{
+	uint32_t val4;
+	uint16_t val;
+
+	val4 = bus_read_4(sc->atse_mem_res, (bmcr + reg) * 4);
+	val = le32toh(val4) & 0x0000ffff;
+	DPRINTF("[%s:%d] %s R %s 0x%08x (0x%08jx) = 0x%04x\n", f, l, s,
+	    "atse_mem_res", reg, (bmcr + reg) * 4, val);
+	return (val);
+}
+
+#define	CSR_WRITE_4(sc, reg, val)	\
+	csr_write_4((sc), (reg), (val), __func__, __LINE__)
+#define	CSR_READ_4(sc, reg)		\
+	csr_read_4((sc), (reg), __func__, __LINE__)
+#define	PCS_WRITE_2(sc, reg, val)	\
+	pxx_write_2((sc), sc->atse_bmcr0, (reg), (val), __func__, __LINE__, \
+	    "PCS")
+#define	PCS_READ_2(sc, reg)		\
+	pxx_read_2((sc), sc->atse_bmcr0, (reg), __func__, __LINE__, "PCS")
+#define	PHY_WRITE_2(sc, reg, val)	\
+	pxx_write_2((sc), sc->atse_bmcr1, (reg), (val), __func__, __LINE__, \
+	    "PHY")
+#define	PHY_READ_2(sc, reg)		\
+	pxx_read_2((sc), sc->atse_bmcr1, (reg), __func__, __LINE__, "PHY")
+
+static void atse_tick(void *);
+static int atse_detach(device_t);
+
+devclass_t atse_devclass;
+
+static int
+atse_tx_locked(struct atse_softc *sc, int *sent)
+{
+	struct mbuf *m;
+	uint32_t val4, fill_level;
+	int c;
+
+	ATSE_LOCK_ASSERT(sc);
+
+	m = sc->atse_tx_m;
+	KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc));
+	KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m));
+
+	/*
+	 * Copy to buffer to minimize our pain as we can only store
+	 * double words which, after the first mbuf gets out of alignment
+	 * quite quickly.
+	 */
+	if (sc->atse_tx_m_offset == 0) {
+		m_copydata(m, 0, m->m_pkthdr.len, sc->atse_tx_buf);
+		sc->atse_tx_buf_len = m->m_pkthdr.len;
+	}
+
+	fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
+#if 0	/* Returns 0xdeadc0de. */
+	val4 = ATSE_TX_META_READ(sc);
+#endif
+	if (sc->atse_tx_m_offset == 0) {
+		/* Write start of packet. */
+		val4 = A_ONCHIP_FIFO_MEM_CORE_SOP;
+		val4 &= ~A_ONCHIP_FIFO_MEM_CORE_EOP;
+		ATSE_TX_META_WRITE(sc, val4);
+	}
+
+	/* TX FIFO is single clock mode, so we have the full FIFO. */
+	c = 0;
+	while ((sc->atse_tx_buf_len - sc->atse_tx_m_offset) > 4 &&
+	     fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+
+		bcopy(&sc->atse_tx_buf[sc->atse_tx_m_offset], &val4,
+		    sizeof(val4));
+		ATSE_TX_DATA_WRITE(sc, val4);
+		sc->atse_tx_m_offset += sizeof(val4);
+		c += sizeof(val4);
+
+		fill_level++;
+		if (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
+			fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
+	}
+	if (sent != NULL)
+		*sent += c;
+
+	/* Set EOP *before* writing the last symbol. */
+	if (sc->atse_tx_m_offset >= (sc->atse_tx_buf_len - 4) &&
+	    fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+		int leftm;
+		uint32_t x;
+
+		/* Set EndOfPacket. */
+		val4 = A_ONCHIP_FIFO_MEM_CORE_EOP;
+		/* Set EMPTY. */
+		leftm = sc->atse_tx_buf_len - sc->atse_tx_m_offset;
+		val4 |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
+		x = val4;
+		ATSE_TX_META_WRITE(sc, val4);
+
+		/* Write last symbol. */
+		val4 = 0;
+		bcopy(sc->atse_tx_buf + sc->atse_tx_m_offset, &val4, leftm);
+		ATSE_TX_DATA_WRITE(sc, val4);
+
+		if (sent != NULL)
+			*sent += leftm;
+
+		/* OK, the packet is gone. */
+		sc->atse_tx_m = NULL;
+		sc->atse_tx_m_offset = 0;
+
+		/* If anyone is interested give them a copy. */
+		BPF_MTAP(sc->atse_ifp, m);
+
+		m_freem(m);
+		return (0);
+	}
+
+	return (EBUSY);
+}
+
+static void
+atse_start_locked(struct ifnet *ifp)
+{
+	struct atse_softc *sc;
+	int error, sent;
+
+	sc = ifp->if_softc;
+	ATSE_LOCK_ASSERT(sc);
+
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING || (sc->atse_flags & ATSE_FLAGS_LINK) == 0)
+		return;
+
+#if 1
+	/* 
+	 * Disable the watchdog while sending, we are batching packets.
+	 * Though we should never reach 5 seconds, and are holding the lock,
+	 * but who knows.
+	 */
+	sc->atse_watchdog_timer = 0;
+#endif
+
+	if (sc->atse_tx_m != NULL) {
+		error = atse_tx_locked(sc, &sent);
+		if (error != 0)
+			goto done;
+	}
+	/* We have more space to send so continue ... */
+	for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
+
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, sc->atse_tx_m);
+		sc->atse_tx_m_offset = 0;
+		if (sc->atse_tx_m == NULL)
+			break;
+		error = atse_tx_locked(sc, &sent);
+		if (error != 0)
+			goto done;
+	}
+
+done:
+	/* If the IP core walks into Nekromanteion try to bail out. */
+	if (sent > 0)
+		sc->atse_watchdog_timer = ATSE_WATCHDOG_TIME;
+}
+
+static void
+atse_start(struct ifnet *ifp)
+{
+	struct atse_softc *sc;
+
+	sc = ifp->if_softc;
+	ATSE_LOCK(sc);
+	atse_start_locked(ifp);
+	ATSE_UNLOCK(sc);
+}
+
+static int
+atse_stop_locked(struct atse_softc *sc)
+{
+	struct ifnet *ifp;
+	uint32_t mask, val4;
+	int i;
+
+	ATSE_LOCK_ASSERT(sc);
+
+	sc->atse_watchdog_timer = 0;
+	callout_stop(&sc->atse_tick);
+
+	ifp = sc->atse_ifp;
+	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+	ATSE_RX_INTR_DISABLE(sc);
+	ATSE_TX_INTR_DISABLE(sc);
+	ATSE_RX_EVENT_CLEAR(sc);
+	ATSE_TX_EVENT_CLEAR(sc);
+
+	/* Disable MAC transmit and receive datapath. */
+	mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	val4 &= ~mask;
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+	/* Wait for bits to be cleared; i=100 is excessive. */
+	for (i = 0; i < 100; i++) {
+		val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+		if ((val4 & mask) == 0)
+			break;
+		DELAY(10);
+	}
+	if ((val4 & mask) != 0)
+		device_printf(sc->atse_dev, "Disabling MAC TX/RX timed out.\n");
+		/* Punt. */
+
+	sc->atse_flags &= ~ATSE_FLAGS_LINK;
+
+	/* XXX-BZ free the RX/TX rings. */
+
+	return (0);
+}
+
+static uint8_t
+atse_mchash(struct atse_softc *sc __unused, const uint8_t *addr)
+{
+	int i, j;
+	uint8_t x, y;
+
+	x = 0;
+	for (i = 0; i < ETHER_ADDR_LEN; i++) {
+		y = addr[i] & 0x01;
+		for (j = 1; j < 8; j++)
+			y ^= (addr[i] >> j) & 0x01;
+		x |= (y << i);
+	}
+	return (x);
+}
+
+static int
+atse_rxfilter_locked(struct atse_softc *sc)
+{
+	struct ifnet *ifp;
+	struct ifmultiaddr *ifma;
+	uint32_t val4;
+	int i;
+
+	/* XXX-BZ can we find out if we have the MHASH synthesized? */
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	/* For simplicity always hash full 48 bits of addresses. */
+	if ((val4 & BASE_CFG_COMMAND_CONFIG_MHASH_SEL) != 0)
+		val4 &= ~BASE_CFG_COMMAND_CONFIG_MHASH_SEL;
+
+	ifp = sc->atse_ifp;
+	if (ifp->if_flags & IFF_PROMISC)
+		val4 |= BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
+	else
+		val4 &= ~BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
+
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+
+	if (ifp->if_flags & IFF_ALLMULTI) {
+		/* Accept all multicast addresses. */
+		for (i = 0; i <= MHASH_LEN; i++)
+			CSR_WRITE_4(sc, MHASH_START + i, 0x1);
+	} else {
+		/* 
+		 * Can hold MHASH_LEN entries.
+		 * XXX-BZ bitstring.h would be more general.
+		 */
+		uint64_t h;
+
+		h = 0;
+		/*
+		 * Re-build and re-program hash table.  First build the
+		 * bit-field "yes" or "no" for each slot per address, then
+		 * do all the programming afterwards.
+		 */
+		if_maddr_rlock(ifp);
+		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+			if (ifma->ifma_addr->sa_family != AF_LINK)
+				continue;
+
+			h |= (1 << atse_mchash(sc,
+			    LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
+		}
+		if_maddr_runlock(ifp);
+		for (i = 0; i <= MHASH_LEN; i++)
+			CSR_WRITE_4(sc, MHASH_START + i,
+			    (h & (1 << i)) ? 0x01 : 0x00);
+	}
+
+	return (0);
+}
+
+static int
+atse_ethernet_option_bits_read_fdt(device_t dev)
+{
+	struct resource *res;
+	device_t fdev;
+	int i, rid;
+
+	if (atse_ethernet_option_bits_flag & ATSE_ETHERNET_OPTION_BITS_READ)
+		return (0);
+
+	fdev = device_find_child(device_get_parent(dev), "cfi", 0);
+	if (fdev == NULL)
+		return (ENOENT);
+
+	rid = 0;
+	res = bus_alloc_resource_any(fdev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (res == NULL)
+		return (ENXIO);
+
+	for (i = 0; i < ALTERA_ETHERNET_OPTION_BITS_LEN; i++)
+		atse_ethernet_option_bits[i] = bus_read_1(res,
+		    ALTERA_ETHERNET_OPTION_BITS_OFF + i);
+
+	bus_release_resource(fdev, SYS_RES_MEMORY, rid, res);
+	atse_ethernet_option_bits_flag |= ATSE_ETHERNET_OPTION_BITS_READ;
+
+	return (0);
+}
+
+static int
+atse_ethernet_option_bits_read(device_t dev)
+{
+	int error;
+
+	error = atse_ethernet_option_bits_read_fdt(dev);
+	if (error == 0)
+		return (0);
+	
+	device_printf(dev, "Cannot read Ethernet addresses from flash.\n");
+	return (error);
+}
+
+static int
+atse_get_eth_address(struct atse_softc *sc)
+{
+	unsigned long hostid;
+	uint32_t val4;
+	int unit;
+
+	/*
+	 * Make sure to only ever do this once.  Otherwise a reset would
+	 * possibly change our ethernet address, which is not good at all.
+	 */
+	if (sc->atse_eth_addr[0] != 0x00 || sc->atse_eth_addr[1] != 0x00 ||
+	    sc->atse_eth_addr[2] != 0x00)
+		return (0);
+
+	if ((atse_ethernet_option_bits_flag &
+	    ATSE_ETHERNET_OPTION_BITS_READ) == 0)
+		goto get_random;
+
+	val4 = atse_ethernet_option_bits[0] << 24;
+	val4 |= atse_ethernet_option_bits[1] << 16;
+	val4 |= atse_ethernet_option_bits[2] << 8;
+	val4 |= atse_ethernet_option_bits[3];
+	/* They chose "safe". */
+	if (val4 != le32toh(0x00005afe)) {
+		device_printf(sc->atse_dev, "Magic '5afe' is not safe: 0x%08x. "
+		    "Falling back to random numbers for hardware address.\n",
+		     val4);
+		goto get_random;
+	}
+
+	sc->atse_eth_addr[0] = atse_ethernet_option_bits[4];
+	sc->atse_eth_addr[1] = atse_ethernet_option_bits[5];
+	sc->atse_eth_addr[2] = atse_ethernet_option_bits[6];
+	sc->atse_eth_addr[3] = atse_ethernet_option_bits[7];
+	sc->atse_eth_addr[4] = atse_ethernet_option_bits[8];
+	sc->atse_eth_addr[5] = atse_ethernet_option_bits[9];
+
+	/* Handle factory default ethernet addresss: 00:07:ed:ff:ed:15 */
+	if (sc->atse_eth_addr[0] == 0x00 && sc->atse_eth_addr[1] == 0x07 &&
+	    sc->atse_eth_addr[2] == 0xed && sc->atse_eth_addr[3] == 0xff &&
+	    sc->atse_eth_addr[4] == 0xed && sc->atse_eth_addr[5] == 0x15) {
+
+		device_printf(sc->atse_dev, "Factory programmed Ethernet "
+		    "hardware address blacklisted.  Falling back to random "
+		    "address to avoid collisions.\n");
+		device_printf(sc->atse_dev, "Please re-program your flash.\n");
+		goto get_random;
+	}
+
+	if (sc->atse_eth_addr[0] == 0x00 && sc->atse_eth_addr[1] == 0x00 &&
+	    sc->atse_eth_addr[2] == 0x00 && sc->atse_eth_addr[3] == 0x00 &&
+	    sc->atse_eth_addr[4] == 0x00 && sc->atse_eth_addr[5] == 0x00) {
+		device_printf(sc->atse_dev, "All zero's Ethernet hardware "
+		    "address blacklisted.  Falling back to random address.\n");
+		device_printf(sc->atse_dev, "Please re-program your flash.\n");
+		goto get_random;
+	}
+
+	if (ETHER_IS_MULTICAST(sc->atse_eth_addr)) {
+		device_printf(sc->atse_dev, "Multicast Ethernet hardware "
+		    "address blacklisted.  Falling back to random address.\n");
+		device_printf(sc->atse_dev, "Please re-program your flash.\n");
+		goto get_random;
+	}
+
+	/*
+	 * If we find an Altera prefixed address with a 0x0 ending
+	 * adjust by device unit.  If not and this is not the first
+	 * Ethernet, go to random.
+	 */
+	unit = device_get_unit(sc->atse_dev);
+	if (unit == 0x00)
+		return (0);
+
+	if (unit > 0x0f) {
+		device_printf(sc->atse_dev, "We do not support Ethernet "
+		    "addresses for more than 16 MACs. Falling back to "
+		    "random hadware address.\n");
+		goto get_random;
+	}
+	if ((sc->atse_eth_addr[0] & ~0x2) != 0 ||
+	    sc->atse_eth_addr[1] != 0x07 || sc->atse_eth_addr[2] != 0xed ||
+	    (sc->atse_eth_addr[5] & 0x0f) != 0x0) {
+		device_printf(sc->atse_dev, "Ethernet address not meeting our "
+		    "multi-MAC standards. Falling back to random hadware "
+		    "address.\n");
+		goto get_random;
+	}
+	sc->atse_eth_addr[5] |= (unit & 0x0f);
+
+	return (0);
+
+get_random:
+	/*
+	 * Fall back to random code we also use on bridge(4).
+	 */
+	getcredhostid(curthread->td_ucred, &hostid);
+	if (hostid == 0) {
+		arc4rand(sc->atse_eth_addr, ETHER_ADDR_LEN, 1);
+		sc->atse_eth_addr[0] &= ~1;/* clear multicast bit */
+		sc->atse_eth_addr[0] |= 2; /* set the LAA bit */
+	} else {
+		sc->atse_eth_addr[0] = 0x2;
+		sc->atse_eth_addr[1] = (hostid >> 24)	& 0xff;
+		sc->atse_eth_addr[2] = (hostid >> 16)	& 0xff;
+		sc->atse_eth_addr[3] = (hostid >> 8 )	& 0xff;
+		sc->atse_eth_addr[4] = hostid		& 0xff;
+		sc->atse_eth_addr[5] = sc->atse_unit	& 0xff;
+	}
+
+	return (0);
+}
+
+static int
+atse_set_eth_address(struct atse_softc *sc, int n)
+{
+	uint32_t v0, v1;
+
+	v0 = (sc->atse_eth_addr[3] << 24) | (sc->atse_eth_addr[2] << 16) |
+	    (sc->atse_eth_addr[1] << 8) | sc->atse_eth_addr[0];
+	v1 = (sc->atse_eth_addr[5] << 8) | sc->atse_eth_addr[4];
+
+	if (n & ATSE_ETH_ADDR_DEF) {
+		CSR_WRITE_4(sc, BASE_CFG_MAC_0, v0);
+		CSR_WRITE_4(sc, BASE_CFG_MAC_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP1) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_0_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_0_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP2) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_1_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_1_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP3) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_2_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_2_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP4) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_3_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_3_1, v1);
+	}
+
+	return (0);
+}
+
+static int
+atse_reset(struct atse_softc *sc)
+{
+	int i;
+	uint32_t val4, mask;
+	uint16_t val;
+
+	/* 1. External PHY Initialization using MDIO. */
+	/*
+	 * We select the right MDIO space in atse_attach() and let MII do
+	 * anything else.
+	 */
+
+	/* 2. PCS Configuration Register Initialization. */
+	/* a. Set auto negotiation link timer to 1.6ms for SGMII. */
+	PCS_WRITE_2(sc, PCS_EXT_LINK_TIMER_0, 0x0D40);
+	PCS_WRITE_2(sc, PCS_EXT_LINK_TIMER_1, 0x0003);
+
+	/* b. Configure SGMII. */
+	val = PCS_EXT_IF_MODE_SGMII_ENA|PCS_EXT_IF_MODE_USE_SGMII_AN;
+	PCS_WRITE_2(sc, PCS_EXT_IF_MODE, val);
+
+	/* c. Enable auto negotiation. */
+	/* Ignore Bits 6,8,13; should be set,set,unset. */
+	val = PCS_READ_2(sc, PCS_CONTROL);
+	val &= ~(PCS_CONTROL_ISOLATE|PCS_CONTROL_POWERDOWN);
+	val &= ~PCS_CONTROL_LOOPBACK;		/* Make this a -link1 option? */
+	val |= PCS_CONTROL_AUTO_NEGOTIATION_ENABLE;
+	PCS_WRITE_2(sc, PCS_CONTROL, val);
+
+	/* d. PCS reset. */
+	val = PCS_READ_2(sc, PCS_CONTROL);
+	val |= PCS_CONTROL_RESET;
+	PCS_WRITE_2(sc, PCS_CONTROL, val);
+	/* Wait for reset bit to clear; i=100 is excessive. */
+	for (i = 0; i < 100; i++) {
+		val = PCS_READ_2(sc, PCS_CONTROL);
+		if ((val & PCS_CONTROL_RESET) == 0)
+			break;
+		DELAY(10);
+	}
+	if ((val & PCS_CONTROL_RESET) != 0) {
+		device_printf(sc->atse_dev, "PCS reset timed out.\n");
+		return (ENXIO);
+	}
+
+	/* 3. MAC Configuration Register Initialization. */
+	/* a. Disable MAC transmit and receive datapath. */
+	mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	val4 &= ~mask;
+	/* Samples in the manual do have the SW_RESET bit set here, why? */
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+	/* Wait for bits to be cleared; i=100 is excessive. */
+	for (i = 0; i < 100; i++) {
+		val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+		if ((val4 & mask) == 0)
+			break;
+		DELAY(10);
+	}
+	if ((val4 & mask) != 0) {
+		device_printf(sc->atse_dev, "Disabling MAC TX/RX timed out.\n");
+		return (ENXIO);
+	}
+	/* b. MAC FIFO configuration. */
+	CSR_WRITE_4(sc, BASE_CFG_TX_SECTION_EMPTY, FIFO_DEPTH_TX - 16);
+	CSR_WRITE_4(sc, BASE_CFG_TX_ALMOST_FULL, 3);
+	CSR_WRITE_4(sc, BASE_CFG_TX_ALMOST_EMPTY, 8);
+	CSR_WRITE_4(sc, BASE_CFG_RX_SECTION_EMPTY, FIFO_DEPTH_RX - 16);
+	CSR_WRITE_4(sc, BASE_CFG_RX_ALMOST_FULL, 8);
+	CSR_WRITE_4(sc, BASE_CFG_RX_ALMOST_EMPTY, 8);
+#if 0
+	CSR_WRITE_4(sc, BASE_CFG_TX_SECTION_FULL, 16);
+	CSR_WRITE_4(sc, BASE_CFG_RX_SECTION_FULL, 16);
+#else
+	/* For store-and-forward mode, set this threshold to 0. */
+	CSR_WRITE_4(sc, BASE_CFG_TX_SECTION_FULL, 0);
+	CSR_WRITE_4(sc, BASE_CFG_RX_SECTION_FULL, 0);
+#endif
+	/* c. MAC address configuration. */
+	/* Also intialize supplementary addresses to our primary one. */
+	/* XXX-BZ FreeBSD really needs to grow and API for using these. */
+	atse_get_eth_address(sc);
+	atse_set_eth_address(sc, ATSE_ETH_ADDR_ALL);
+
+	/* d. MAC function configuration. */
+	CSR_WRITE_4(sc, BASE_CFG_FRM_LENGTH, 1518);	/* Default. */
+	CSR_WRITE_4(sc, BASE_CFG_TX_IPG_LENGTH, 12);
+	CSR_WRITE_4(sc, BASE_CFG_PAUSE_QUANT, 0xFFFF);
+
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	/*	
+	 * If 1000BASE-X/SGMII PCS is initialized, set the ETH_SPEED (bit 3)
+	 * and ENA_10 (bit 25) in command_config register to 0.  If half duplex
+	 * is reported in the PHY/PCS status register, set the HD_ENA (bit 10)
+	 * to 1 in command_config register.
+	 * BZ: We shoot for 1000 instead.
+	 */
+#if 0
+	val4 |= BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
+#else
+	val4 &= ~BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
+#endif
+	val4 &= ~BASE_CFG_COMMAND_CONFIG_ENA_10;
+#if 0
+	/*
+	 * We do not want to set this, otherwise, we could not even send
+	 * random raw ethernet frames for various other research.  By default
+	 * FreeBSD will use the right ether source address.
+	 */
+	val4 |= BASE_CFG_COMMAND_CONFIG_TX_ADDR_INS;
+#endif
+	val4 |= BASE_CFG_COMMAND_CONFIG_PAD_EN;
+	val4 &= ~BASE_CFG_COMMAND_CONFIG_CRC_FWD;
+#if 0
+	val4 |= BASE_CFG_COMMAND_CONFIG_CNTL_FRM_ENA;
+#endif
+#if 1
+	val4 |= BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC;
+#endif
+	val &= ~BASE_CFG_COMMAND_CONFIG_LOOP_ENA;		/* link0? */
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+
+	/*
+	 * Make sure we do not enable 32bit alignment;  FreeBSD cannot
+	 * cope with the additional padding (though we should!?).
+	 * Also make sure we get the CRC appended.
+	 */
+	val4 = CSR_READ_4(sc, TX_CMD_STAT);
+	val4 &= ~(TX_CMD_STAT_OMIT_CRC|TX_CMD_STAT_TX_SHIFT16);
+	CSR_WRITE_4(sc, TX_CMD_STAT, val4);
+	val4 = CSR_READ_4(sc, RX_CMD_STAT);
+	val4 &= ~RX_CMD_STAT_RX_SHIFT16;
+	CSR_WRITE_4(sc, RX_CMD_STAT, val4);
+
+	/* e. Reset MAC. */
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	val4 |= BASE_CFG_COMMAND_CONFIG_SW_RESET;
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+	/* Wait for bits to be cleared; i=100 is excessive. */
+	for (i = 0; i < 100; i++) {
+		val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+		if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) == 0)
+			break;
+		DELAY(10);
+	}
+	if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) != 0) {
+		device_printf(sc->atse_dev, "MAC reset timed out.\n");
+		return (ENXIO);
+	}
+	
+	/* f. Enable MAC transmit and receive datapath. */
+	mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	val4 |= mask;
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+	/* Wait for bits to be cleared; i=100 is excessive. */
+	for (i = 0; i < 100; i++) {
+		val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+		if ((val4 & mask) == mask)
+			break;
+		DELAY(10);
+	}
+	if ((val4 & mask) != mask) {
+		device_printf(sc->atse_dev, "Enabling MAC TX/RX timed out.\n");
+		return (ENXIO);
+	}
+
+	return (0);
+}
+
+static void
+atse_init_locked(struct atse_softc *sc)
+{
+	struct ifnet *ifp;
+	struct mii_data *mii;
+	uint8_t *eaddr;
+
+	ATSE_LOCK_ASSERT(sc);
+	ifp = sc->atse_ifp;
+
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+		return;
+
+	/*
+	 * Must update the ether address if changed.  Given we do not handle
+	 * in atse_ioctl() but it's in the general framework, just always
+	 * do it here before atse_reset().
+	 */
+	eaddr = IF_LLADDR(sc->atse_ifp);
+	bcopy(eaddr, &sc->atse_eth_addr, ETHER_ADDR_LEN);
+
+	/* Make things frind to halt, cleanup, ... */
+	atse_stop_locked(sc);
+	/* ... reset, ... */
+	atse_reset(sc);
+
+	/* ... and fire up the engine again. */
+	atse_rxfilter_locked(sc);
+
+	/* Memory rings?  DMA engine? */
+
+	sc->atse_rx_buf_len = 0;
+	sc->atse_flags &= ATSE_FLAGS_LINK;	/* Preserve. */
+
+#ifdef DEVICE_POLLING
+        /* Only enable interrupts if we are not polling. */
+	if (ifp->if_capenable & IFCAP_POLLING) {
+		ATSE_RX_INTR_DISABLE(sc);
+		ATSE_TX_INTR_DISABLE(sc);
+		ATSE_RX_EVENT_CLEAR(sc);
+		ATSE_TX_EVENT_CLEAR(sc);
+	} else
+#endif
+	{
+		ATSE_RX_INTR_ENABLE(sc);
+		ATSE_TX_INTR_ENABLE(sc);
+	}
+
+	mii = device_get_softc(sc->atse_miibus);
+
+	sc->atse_flags &= ~ATSE_FLAGS_LINK;
+	mii_mediachg(mii);
+
+	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+	callout_reset(&sc->atse_tick, hz, atse_tick, sc);
+}
+
+static void
+atse_init(void *xsc)
+{
+	struct atse_softc *sc;
+
+	/*
+	 * XXXRW: There is some argument that we should immediately do RX
+	 * processing after enabling interrupts, or one may not fire if there
+	 * are buffered packets.
+	 */
+	sc = (struct atse_softc *)xsc;
+	ATSE_LOCK(sc);
+	atse_init_locked(sc);
+	ATSE_UNLOCK(sc);
+}
+
+static int
+atse_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+	struct atse_softc *sc;
+	struct ifreq *ifr;
+	int error, mask;
+
+
+	error = 0;
+	sc = ifp->if_softc;
+	ifr = (struct ifreq *)data;
+
+	switch (command) {
+	case SIOCSIFFLAGS:
+		ATSE_LOCK(sc);
+		if (ifp->if_flags & IFF_UP) {
+			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
+			    ((ifp->if_flags ^ sc->atse_if_flags) &
+			    (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+				atse_rxfilter_locked(sc);
+			else
+				atse_init_locked(sc);
+		} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+			atse_stop_locked(sc);
+                sc->atse_if_flags = ifp->if_flags;
+		ATSE_UNLOCK(sc);
+		break;
+	case SIOCSIFCAP:
+		ATSE_LOCK(sc);
+		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+#ifdef DEVICE_POLLING
+		if ((mask & IFCAP_POLLING) != 0 &&
+		    (IFCAP_POLLING & ifp->if_capabilities) != 0) {
+			ifp->if_capenable ^= IFCAP_POLLING;
+			if ((IFCAP_POLLING & ifp->if_capenable) != 0) {
+
+				error = ether_poll_register(atse_poll, ifp);
+				if (error != 0) {
+					ATSE_UNLOCK(sc);
+					break;
+				}
+				/* Disable interrupts. */
+				ATSE_RX_INTR_DISABLE(sc);
+				ATSE_TX_INTR_DISABLE(sc);
+				ATSE_RX_EVENT_CLEAR(sc);
+				ATSE_TX_EVENT_CLEAR(sc);
+
+			/*
+			 * Do not allow disabling of polling if we do
+			 * not have interrupts.
+			 */
+			} else if (sc->atse_rx_irq_res != NULL ||
+			    sc->atse_tx_irq_res != NULL) {
+				error = ether_poll_deregister(ifp);
+				/* Enable interrupts. */
+				ATSE_RX_INTR_ENABLE(sc);
+				ATSE_TX_INTR_ENABLE(sc);
+			} else {
+				ifp->if_capenable ^= IFCAP_POLLING;
+				error = EINVAL;
+			}
+		}
+#endif /* DEVICE_POLLING */
+		ATSE_UNLOCK(sc);
+		break;
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+		ATSE_LOCK(sc);
+		atse_rxfilter_locked(sc);
+		ATSE_UNLOCK(sc);
+		break;
+	case SIOCGIFMEDIA:
+	case SIOCSIFMEDIA:
+	{
+		struct mii_data *mii;
+		struct ifreq *ifr;
+
+		mii = device_get_softc(sc->atse_miibus);
+		ifr = (struct ifreq *)data;
+		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+		break;
+	}
+	default:
+		error = ether_ioctl(ifp, command, data);
+		break;
+	}
+
+	return (error);
+}
+
+static void
+atse_intr_debug(struct atse_softc *sc, const char *intrname)
+{
+	uint32_t rxs, rxe, rxi, rxf, txs, txe, txi, txf;
+
+	if (!atse_intr_debug_enable)
+		return;
+
+	rxs = ATSE_RX_STATUS_READ(sc);
+	rxe = ATSE_RX_EVENT_READ(sc);
+	rxi = ATSE_RX_INTR_READ(sc);
+	rxf = ATSE_RX_READ_FILL_LEVEL(sc);
+
+	txs = ATSE_TX_STATUS_READ(sc);
+	txe = ATSE_TX_EVENT_READ(sc);
+	txi = ATSE_TX_INTR_READ(sc);
+	txf = ATSE_TX_READ_FILL_LEVEL(sc);
+
+	printf(
+	    "%s - %s: "
+	    "rxs 0x%x rxe 0x%x rxi 0x%x rxf 0x%x "
+	    "txs 0x%x txe 0x%x txi 0x%x txf 0x%x\n",
+	    __func__, intrname,
+	    rxs, rxe, rxi, rxf,
+	    txs, txe, txi, txf);
+}
+
+static void
+atse_watchdog(struct atse_softc *sc)
+{
+
+	ATSE_LOCK_ASSERT(sc);
+
+	if (sc->atse_watchdog_timer == 0 || --sc->atse_watchdog_timer > 0)
+		return;
+
+	device_printf(sc->atse_dev, "watchdog timeout\n");
+	sc->atse_ifp->if_oerrors++;
+
+	atse_intr_debug(sc, "poll");
+
+	sc->atse_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+	atse_init_locked(sc);
+
+	atse_rx_locked(sc);
+	if (!IFQ_DRV_IS_EMPTY(&sc->atse_ifp->if_snd))
+		atse_start_locked(sc->atse_ifp);
+}
+
+static void
+atse_tick(void *xsc)
+{
+	struct atse_softc *sc;
+	struct mii_data *mii;
+	struct ifnet *ifp;
+
+	sc = (struct atse_softc *)xsc;
+	ATSE_LOCK_ASSERT(sc);
+	ifp = sc->atse_ifp;
+
+	mii = device_get_softc(sc->atse_miibus);
+	mii_tick(mii);
+	atse_watchdog(sc);
+	if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0)
+		atse_miibus_statchg(sc->atse_dev);
+	callout_reset(&sc->atse_tick, hz, atse_tick, sc);
+}
+
+/*
+ * Set media options.
+ */
+static int 
+atse_ifmedia_upd(struct ifnet *ifp)
+{
+	struct atse_softc *sc;
+	struct mii_data *mii;
+	struct mii_softc *miisc;
+	int error;
+
+	sc = ifp->if_softc;
+
+	ATSE_LOCK(sc);
+	mii = device_get_softc(sc->atse_miibus);
+	LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+		PHY_RESET(miisc);
+	error = mii_mediachg(mii);
+	ATSE_UNLOCK(sc);
+
+	return (error);
+}
+
+static void
+atse_update_rx_err(struct atse_softc *sc, uint32_t mask)
+{
+	int i;
+
+	/* RX error are 6 bits, we only know 4 of them. */
+	for (i = 0; i < ATSE_RX_ERR_MAX; i++)
+		if ((mask & (1 << i)) != 0)
+			sc->atse_rx_err[i]++;
+}
+
+static int
+atse_rx_locked(struct atse_softc *sc)
+{
+	struct ifnet *ifp;
+	struct mbuf *m;
+	uint32_t fill, i, j;
+	uint32_t data, meta;
+	int rx_npkts = 0;
+
+	ATSE_LOCK_ASSERT(sc);
+
+	ifp = sc->atse_ifp;
+	j = 0;
+	meta = 0;
+	do {
+outer:
+		if (sc->atse_rx_m == NULL) {
+			m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+			if (m == NULL)
+				return (rx_npkts);
+			m->m_len = m->m_pkthdr.len = MCLBYTES;
+			/* Make sure upper layers will be aligned. */
+			m_adj(m, ETHER_ALIGN);
+			sc->atse_rx_m = m;
+		}
+
+		fill = ATSE_RX_READ_FILL_LEVEL(sc);
+		for (i = 0; i < fill; i++) {
+			/*
+			 * XXX-BZ for whatever reason the FIFO requires the
+			 * the data read before we can access the meta data.
+			 */
+			data = ATSE_RX_DATA_READ(sc);
+			meta = ATSE_RX_META_READ(sc);
+			if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) {
+				/* XXX-BZ evaluate error. */
+				atse_update_rx_err(sc, ((meta &
+				    A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
+				    A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
+				ifp->if_ierrors++;
+				sc->atse_rx_buf_len = 0;
+				/*
+				 * Should still read till EOP or next SOP.
+				 *
+				 * XXX-BZ might also depend on
+				 * BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC
+				 */
+				sc->atse_flags |= ATSE_FLAGS_ERROR;
+				return (rx_npkts);
+			}
+			if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0)
+				device_printf(sc->atse_dev, "%s: unexpected "
+				    "channel %u\n", __func__, (meta &
+				    A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) >>
+				    A_ONCHIP_FIFO_MEM_CORE_CHANNEL_SHIFT);
+
+			if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) {
+				/*
+				 * There is no need to clear SOP between 1st
+				 * and subsequent packet data junks.
+				 */
+				if (sc->atse_rx_buf_len != 0 &&
+				    (sc->atse_flags & ATSE_FLAGS_SOP_SEEN) == 0)
+				{
+					device_printf(sc->atse_dev, "%s: SOP "
+					    "without empty buffer: %u\n",
+					    __func__, sc->atse_rx_buf_len);
+					/* XXX-BZ any better counter? */
+					ifp->if_ierrors++;
+				}
+				
+				if ((sc->atse_flags & ATSE_FLAGS_SOP_SEEN) == 0)
+				{
+					sc->atse_flags |= ATSE_FLAGS_SOP_SEEN;
+					sc->atse_rx_buf_len = 0;
+				}
+			}
+#if 0 /* We had to read the data before we could access meta data. See above. */
+			data = ATSE_RX_DATA_READ(sc);
+#endif
+			/* Make sure to not overflow the mbuf data size. */
+			if (sc->atse_rx_buf_len >= sc->atse_rx_m->m_len -
+			    sizeof(data)) {
+				/*
+				 * XXX-BZ Error.  We need more mbufs and are
+				 * not setup for this yet.
+				 */
+				ifp->if_ierrors++;
+				sc->atse_flags |= ATSE_FLAGS_ERROR;
+			}
+			if ((sc->atse_flags & ATSE_FLAGS_ERROR) == 0)
+				/*
+				 * MUST keep this bcopy as m_data after m_adj
+				 * for IP header aligment is on half-word
+				 * and not word alignment.
+				 */
+				bcopy(&data, (uint8_t *)(sc->atse_rx_m->m_data +
+				    sc->atse_rx_buf_len), sizeof(data));
+			if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) {
+				uint8_t empty;
+
+				empty = (meta &
+				    A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >>
+				    A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT;
+				sc->atse_rx_buf_len += (4 - empty);
+
+				ifp->if_ipackets++;
+				rx_npkts++;
+
+				m = sc->atse_rx_m;
+				m->m_pkthdr.len = m->m_len =
+				    sc->atse_rx_buf_len;
+				sc->atse_rx_m = NULL;
+
+				sc->atse_rx_buf_len = 0;
+				sc->atse_flags &= ~ATSE_FLAGS_SOP_SEEN;
+				if (sc->atse_flags & ATSE_FLAGS_ERROR) {
+					sc->atse_flags &= ~ATSE_FLAGS_ERROR;
+					m_freem(m);
+				} else {
+					m->m_pkthdr.rcvif = ifp;
+					ATSE_UNLOCK(sc);
+					(*ifp->if_input)(ifp, m);
+					ATSE_LOCK(sc);
+				}
+#ifdef DEVICE_POLLING
+				if (ifp->if_capenable & IFCAP_POLLING) {
+					if (sc->atse_rx_cycles <= 0)
+						return (rx_npkts);
+					sc->atse_rx_cycles--;
+				}
+#endif
+				goto outer;	/* Need a new mbuf. */
+			} else {
+				sc->atse_rx_buf_len += sizeof(data);
+			}
+		} /* for */
+
+	/* XXX-BZ could optimize in case of another packet waiting. */
+	} while (fill > 0);
+
+	return (rx_npkts);
+}
+
+
+/*
+ * Report current media status.
+ */
+static void
+atse_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+	struct atse_softc *sc;
+	struct mii_data *mii;
+
+	sc = ifp->if_softc;
+
+	ATSE_LOCK(sc);
+	mii = device_get_softc(sc->atse_miibus);
+	mii_pollstat(mii);
+	ifmr->ifm_active = mii->mii_media_active;
+	ifmr->ifm_status = mii->mii_media_status;
+	ATSE_UNLOCK(sc);
+}
+
+static void
+atse_rx_intr(void *arg)
+{
+	struct atse_softc *sc;
+	struct ifnet *ifp;
+	uint32_t rxe;
+
+	sc = (struct atse_softc *)arg;
+	ifp = sc->atse_ifp;
+
+	ATSE_LOCK(sc);
+#ifdef DEVICE_POLLING
+	if (ifp->if_capenable & IFCAP_POLLING) {
+		ATSE_UNLOCK(sc);
+		return;
+	}  
+#endif
+
+	atse_intr_debug(sc, "rx");
+	rxe = ATSE_RX_EVENT_READ(sc);
+	if (rxe & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
+	    A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
+		/* XXX-BZ ERROR HANDLING. */
+		atse_update_rx_err(sc, ((rxe &
+		    A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
+		    A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
+		ifp->if_ierrors++;
+	}
+
+	/*
+	 * There is considerable subtlety in the race-free handling of rx
+	 * interrupts: we must disable interrupts whenever we manipulate the
+	 * FIFO to prevent further interrupts from firing before we are done;
+	 * we must clear the event after processing to prevent the event from
+	 * being immediately reposted due to data remaining; we must clear the
+	 * event mask before reenabling interrupts or risk missing a positive
+	 * edge; and we must recheck everything after completing in case the
+	 * event posted between clearing events and reenabling interrupts.  If
+	 * a race is experienced, we must restart the whole mechanism.
+	 */
+	do {
+		ATSE_RX_INTR_DISABLE(sc);
+#if 0
+		sc->atse_rx_cycles = RX_CYCLES_IN_INTR;
+#endif
+		atse_rx_locked(sc);
+		ATSE_RX_EVENT_CLEAR(sc);
+
+		/* Disable interrupts if interface is down. */
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+			ATSE_RX_INTR_ENABLE(sc);
+	} while (!(ATSE_RX_STATUS_READ(sc) &
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_EMPTY));
+	ATSE_UNLOCK(sc);
+
+}
+
+static void
+atse_tx_intr(void *arg)
+{
+	struct atse_softc *sc;
+	struct ifnet *ifp;
+	uint32_t txe;
+
+	sc = (struct atse_softc *)arg;
+	ifp = sc->atse_ifp;
+
+	ATSE_LOCK(sc);
+#ifdef DEVICE_POLLING
+	if (ifp->if_capenable & IFCAP_POLLING) {
+		ATSE_UNLOCK(sc);
+		return;
+	}  
+#endif
+
+	/* XXX-BZ build histogram. */
+	atse_intr_debug(sc, "tx");
+	txe = ATSE_TX_EVENT_READ(sc);
+	if (txe & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
+	    A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
+		/* XXX-BZ ERROR HANDLING. */
+		ifp->if_oerrors++;
+	}
+
+	/*
+	 * There is also considerable subtlety in the race-free handling of
+	 * tx interrupts: all processing occurs with interrupts disabled to
+	 * prevent spurious refiring while transmit is in progress (which
+	 * could occur if the FIFO drains while sending -- quite likely); we
+	 * must not clear the event mask until after we've sent, also to
+	 * prevent spurious refiring; once we've cleared the event mask we can
+	 * reenable interrupts, but there is a possible race between clear and
+	 * enable, so we must recheck and potentially repeat the whole process
+	 * if it is detected.
+	 */
+	do {
+		ATSE_TX_INTR_DISABLE(sc);
+		sc->atse_watchdog_timer = 0;
+		atse_start_locked(ifp);
+		ATSE_TX_EVENT_CLEAR(sc);
+
+		/* Disable interrupts if interface is down. */
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+			ATSE_TX_INTR_ENABLE(sc);
+	} while (ATSE_TX_PENDING(sc) &&
+	    !(ATSE_TX_STATUS_READ(sc) & A_ONCHIP_FIFO_MEM_CORE_STATUS_FULL));
+	ATSE_UNLOCK(sc);
+}
+
+#ifdef DEVICE_POLLING
+static int
+atse_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+	struct atse_softc *sc;
+	int rx_npkts = 0;
+
+	sc = ifp->if_softc;
+	ATSE_LOCK(sc);
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+		ATSE_UNLOCK(sc);
+		return (rx_npkts); 
+	}
+
+	sc->atse_rx_cycles = count;
+	rx_npkts = atse_rx_locked(sc);
+	atse_start_locked(ifp);
+
+	if (sc->atse_rx_cycles > 0 || cmd == POLL_AND_CHECK_STATUS) {
+		uint32_t rx, tx;
+
+		rx = ATSE_RX_EVENT_READ(sc);
+		tx = ATSE_TX_EVENT_READ(sc);
+
+		if (rx & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
+		    A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
+			/* XXX-BZ ERROR HANDLING. */
+			atse_update_rx_err(sc, ((rx &
+			    A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
+			    A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
+			ifp->if_ierrors++;
+		}
+		if (tx & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW|
+		    A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) {
+			/* XXX-BZ ERROR HANDLING. */
+			ifp->if_oerrors++;
+		}
+		if (ATSE_TX_READ_FILL_LEVEL(sc) == 0)
+			sc->atse_watchdog_timer = 0;
+
+#if 0
+		if (/* Severe error; if only we could find out. */) {
+			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+			atse_init_locked(sc);
+		}
+#endif
+	}
+
+	ATSE_UNLOCK(sc);
+	return (rx_npkts);
+}
+#endif /* DEVICE_POLLING */
+
+static struct atse_mac_stats_regs {
+	const char *name;
+	const char *descr;	/* Mostly copied from Altera datasheet. */
+} atse_mac_stats_regs[] = {
+	[0x1a] =
+	{ "aFramesTransmittedOK",
+	    "The number of frames that are successfully transmitted including "
+	    "the pause frames." },
+	{ "aFramesReceivedOK",
+	    "The number of frames that are successfully received including the "
+	    "pause frames." },
+	{ "aFrameCheckSequenceErrors",
+	    "The number of receive frames with CRC error." },
+	{ "aAlignmentErrors",
+	    "The number of receive frames with alignment error." },
+	{ "aOctetsTransmittedOK",
+	    "The lower 32 bits of the number of data and padding octets that "
+	    "are successfully transmitted." },
+	{ "aOctetsReceivedOK",
+	    "The lower 32 bits of the number of data and padding octets that "
+	    " are successfully received." },
+	{ "aTxPAUSEMACCtrlFrames",
+	    "The number of pause frames transmitted." },
+	{ "aRxPAUSEMACCtrlFrames",
+	    "The number received pause frames received." },
+	{ "ifInErrors",
+	    "The number of errored frames received." },
+	{ "ifOutErrors",
+	    "The number of transmit frames with either a FIFO overflow error, "
+	    "a FIFO underflow error, or a error defined by the user "
+	    "application." },
+	{ "ifInUcastPkts",
+	    "The number of valid unicast frames received." },
+	{ "ifInMulticastPkts",
+	    "The number of valid multicast frames received. The count does "
+	    "not include pause frames." },
+	{ "ifInBroadcastPkts",
+	    "The number of valid broadcast frames received." },
+	{ "ifOutDiscards",
+	    "This statistics counter is not in use.  The MAC function does not "
+	    "discard frames that are written to the FIFO buffer by the user "
+	    "application." },
+	{ "ifOutUcastPkts",
+	    "The number of valid unicast frames transmitted." },
+	{ "ifOutMulticastPkts",
+	    "The number of valid multicast frames transmitted, excluding pause "
+	    "frames." },
+	{ "ifOutBroadcastPkts",
+	    "The number of valid broadcast frames transmitted." },
+	{ "etherStatsDropEvents",
+	    "The number of frames that are dropped due to MAC internal errors "
+	    "when FIFO buffer overflow persists." },
+	{ "etherStatsOctets",
+	    "The lower 32 bits of the total number of octets received. This "
+	    "count includes both good and errored frames." },
+	{ "etherStatsPkts",
+	    "The total number of good and errored frames received." },
+	{ "etherStatsUndersizePkts",
+	    "The number of frames received with length less than 64 bytes. "
+	    "This count does not include errored frames." },
+	{ "etherStatsOversizePkts",
+	    "The number of frames received that are longer than the value "
+	    "configured in the frm_length register. This count does not "
+	    "include errored frames." },
+	{ "etherStatsPkts64Octets",
+	    "The number of 64-byte frames received. This count includes good "
+	    "and errored frames." },
+	{ "etherStatsPkts65to127Octets",
+	    "The number of received good and errored frames between the length "
+	    "of 65 and 127 bytes." },
+	{ "etherStatsPkts128to255Octets",
+	    "The number of received good and errored frames between the length "
+	    "of 128 and 255 bytes." },
+	{ "etherStatsPkts256to511Octets",
+	    "The number of received good and errored frames between the length "
+	    "of 256 and 511 bytes." },
+	{ "etherStatsPkts512to1023Octets",
+	    "The number of received good and errored frames between the length "
+	    "of 512 and 1023 bytes." },
+	{ "etherStatsPkts1024to1518Octets",
+	    "The number of received good and errored frames between the length "
+	    "of 1024 and 1518 bytes." },
+	{ "etherStatsPkts1519toXOctets",
+	    "The number of received good and errored frames between the length "
+	    "of 1519 and the maximum frame length configured in the frm_length "
+	    "register." },
+	{ "etherStatsJabbers",
+	    "Too long frames with CRC error." },
+	{ "etherStatsFragments",
+	    "Too short frames with CRC error." },
+	/* 0x39 unused, 0x3a/b non-stats. */
+	[0x3c] =
+	/* Extended Statistics Counters */
+	{ "msb_aOctetsTransmittedOK",
+	    "Upper 32 bits of the number of data and padding octets that are "
+	    "successfully transmitted." },
+	{ "msb_aOctetsReceivedOK",
+	    "Upper 32 bits of the number of data and padding octets that are "
+	    "successfully received." },
+	{ "msb_etherStatsOctets",
+	    "Upper 32 bits of the total number of octets received. This count "
+	    "includes both good and errored frames." }
+};
+
+static int
+sysctl_atse_mac_stats_proc(SYSCTL_HANDLER_ARGS)
+{
+	struct atse_softc *sc;
+        int error, offset, s;
+
+        sc = arg1;
+	offset = arg2;
+
+	s = CSR_READ_4(sc, offset);
+	error = sysctl_handle_int(oidp, &s, 0, req);
+	if (error || !req->newptr)
+		return (error);
+
+        return (0);
+}
+
+static struct atse_rx_err_stats_regs {
+	const char *name;
+	const char *descr;
+} atse_rx_err_stats_regs[] = {
+
+#define ATSE_RX_ERR_FIFO_THRES_EOP      0 /* FIFO threshold reached, on EOP. */
+#define ATSE_RX_ERR_ELEN                1 /* Frame/payload length not valid. */
+#define ATSE_RX_ERR_CRC32               2 /* CRC-32 error. */
+#define ATSE_RX_ERR_FIFO_THRES_TRUNC    3 /* FIFO thresh., truncated frame. */
+#define ATSE_RX_ERR_4                   4 /* ? */
+#define ATSE_RX_ERR_5                   5 /* / */
+
+	{ "rx_err_fifo_thres_eop",
+	    "FIFO threshold reached, reported on EOP." },
+	{ "rx_err_fifo_elen",
+	    "Frame or payload length not valid." },
+	{ "rx_err_fifo_crc32",
+	    "CRC-32 error." },
+	{ "rx_err_fifo_thres_trunc",
+	    "FIFO threshold reached, truncated frame" },
+	{ "rx_err_4",
+	    "?" },
+	{ "rx_err_5",
+	    "?" },
+};
+
+static int
+sysctl_atse_rx_err_stats_proc(SYSCTL_HANDLER_ARGS)
+{
+	struct atse_softc *sc;
+        int error, offset, s;
+
+        sc = arg1;
+	offset = arg2;
+
+	s = sc->atse_rx_err[offset];
+	error = sysctl_handle_int(oidp, &s, 0, req);
+	if (error || !req->newptr)
+		return (error);
+
+        return (0);
+}
+
+static void
+atse_sysctl_stats_attach(device_t dev)
+{
+	struct sysctl_ctx_list *sctx;
+	struct sysctl_oid *soid;
+	struct atse_softc *sc;
+	int i;
+
+	sc = device_get_softc(dev);
+        sctx = device_get_sysctl_ctx(dev);
+        soid = device_get_sysctl_tree(dev);
+
+	/* MAC statistics. */
+	for (i = 0; i < sizeof(atse_mac_stats_regs) /
+	    sizeof(*atse_mac_stats_regs); i++) {
+		if (atse_mac_stats_regs[i].name == NULL ||
+		    atse_mac_stats_regs[i].descr == NULL)
+			continue;
+
+		SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
+		    atse_mac_stats_regs[i].name, CTLTYPE_UINT|CTLFLAG_RD,
+		    sc, i, sysctl_atse_mac_stats_proc, "IU",
+		    atse_mac_stats_regs[i].descr);
+	}
+
+	/* rx_err[]. */
+	for (i = 0; i < ATSE_RX_ERR_MAX; i++) {
+		if (atse_rx_err_stats_regs[i].name == NULL ||
+		    atse_rx_err_stats_regs[i].descr == NULL)
+			continue;
+
+		SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
+		    atse_rx_err_stats_regs[i].name, CTLTYPE_UINT|CTLFLAG_RD,
+		    sc, i, sysctl_atse_rx_err_stats_proc, "IU",
+		    atse_rx_err_stats_regs[i].descr);
+	}
+}
+
+/*
+ * Generic device handling routines.
+ */
+int
+atse_attach(device_t dev)
+{
+	struct atse_softc *sc;
+	struct ifnet *ifp;
+	int error;
+
+	sc = device_get_softc(dev);
+
+	atse_ethernet_option_bits_read(dev);
+
+	mtx_init(&sc->atse_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+	    MTX_DEF);
+
+	callout_init_mtx(&sc->atse_tick, &sc->atse_mtx, 0);
+
+	sc->atse_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK);
+
+	/*
+	 * We are only doing single-PHY with this driver currently.  The
+	 * defaults would be right so that BASE_CFG_MDIO_ADDR0 points to the
+	 * 1st PHY address (0) apart from the fact that BMCR0 is always
+	 * the PCS mapping, so we always use BMCR1. See Table 5-1 0xA0-0xBF.
+	 */
+#if 0	/* Always PCS. */
+	sc->atse_bmcr0 = MDIO_0_START;
+	CSR_WRITE_4(sc, BASE_CFG_MDIO_ADDR0, 0x00);
+#endif
+	/* Always use matching PHY for atse[0..]. */
+	sc->atse_phy_addr = device_get_unit(dev);
+	sc->atse_bmcr1 = MDIO_1_START;
+	CSR_WRITE_4(sc, BASE_CFG_MDIO_ADDR1, sc->atse_phy_addr);
+
+	/* Reset the adapter. */
+	atse_reset(sc);
+
+	/* Setup interface. */
+	ifp = sc->atse_ifp = if_alloc(IFT_ETHER);
+	if (ifp == NULL) {
+		device_printf(dev, "if_alloc() failed\n");
+		error = ENOSPC;
+		goto err;
+	}
+	ifp->if_softc = sc;
+	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_ioctl = atse_ioctl;
+	ifp->if_start = atse_start;
+	ifp->if_init = atse_init;
+	IFQ_SET_MAXLEN(&ifp->if_snd, ATSE_TX_LIST_CNT - 1);
+	ifp->if_snd.ifq_drv_maxlen = ATSE_TX_LIST_CNT - 1;
+	IFQ_SET_READY(&ifp->if_snd);
+
+	/* MII setup. */
+	error = mii_attach(dev, &sc->atse_miibus, ifp, atse_ifmedia_upd,
+	    atse_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+	if (error != 0) {
+		device_printf(dev, "attaching PHY failed: %d\n", error);
+		goto err;
+	}
+
+	/* Call media-indepedent attach routine. */
+	ether_ifattach(ifp, sc->atse_eth_addr);
+
+	/* Tell the upper layer(s) about vlan mtu support. */
+	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
+	ifp->if_capabilities |= IFCAP_VLAN_MTU;
+	ifp->if_capenable = ifp->if_capabilities;
+#ifdef DEVICE_POLLING
+	/* We will enable polling by default if no irqs available. See below. */
+	ifp->if_capabilities |= IFCAP_POLLING;
+#endif
+
+	/* Hook up interrupts. */
+	if (sc->atse_rx_irq_res != NULL) {
+		error = bus_setup_intr(dev, sc->atse_rx_irq_res, INTR_TYPE_NET |
+		    INTR_MPSAFE, NULL, atse_rx_intr, sc, &sc->atse_rx_intrhand);
+		if (error != 0) {
+			device_printf(dev, "enabling RX IRQ failed\n");
+			ether_ifdetach(ifp);
+			goto err;
+		}
+	}
+
+	if (sc->atse_tx_irq_res != NULL) {
+		error = bus_setup_intr(dev, sc->atse_tx_irq_res, INTR_TYPE_NET |
+		    INTR_MPSAFE, NULL, atse_tx_intr, sc, &sc->atse_tx_intrhand);
+		if (error != 0) {
+			bus_teardown_intr(dev, sc->atse_rx_irq_res,
+			    sc->atse_rx_intrhand);
+			device_printf(dev, "enabling TX IRQ failed\n");
+			ether_ifdetach(ifp);
+			goto err;
+		}
+	}
+
+	if ((ifp->if_capenable & IFCAP_POLLING) != 0 ||
+	   (sc->atse_rx_irq_res == NULL && sc->atse_tx_irq_res == NULL)) {
+#ifdef DEVICE_POLLING
+		/* If not on and no IRQs force it on. */
+		if (sc->atse_rx_irq_res == NULL && sc->atse_tx_irq_res == NULL){
+			ifp->if_capenable |= IFCAP_POLLING;
+			device_printf(dev, "forcing to polling due to no "
+			    "interrupts\n");
+		}
+		error = ether_poll_register(atse_poll, ifp);
+		if (error != 0)
+			goto err;
+#else
+		device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
+		error = ENXIO;
+#endif
+	} else {
+		ATSE_RX_INTR_ENABLE(sc);
+		ATSE_TX_INTR_ENABLE(sc);
+	}
+
+err:
+	if (error != 0)
+		atse_detach(dev);
+
+	if (error == 0)
+		atse_sysctl_stats_attach(dev);
+
+	return (error);
+}
+
+static int
+atse_detach(device_t dev)
+{
+	struct atse_softc *sc;
+	struct ifnet *ifp;
+
+	sc = device_get_softc(dev);
+	KASSERT(mtx_initialized(&sc->atse_mtx), ("%s: mutex not initialized",
+	    device_get_nameunit(dev)));
+	ifp = sc->atse_ifp;
+
+#ifdef DEVICE_POLLING
+	if (ifp->if_capenable & IFCAP_POLLING)
+		ether_poll_deregister(ifp);
+#endif
+
+	/* Only cleanup if attach succeeded. */
+	if (device_is_attached(dev)) {
+		ATSE_LOCK(sc);
+		atse_stop_locked(sc);
+		ATSE_UNLOCK(sc);
+		callout_drain(&sc->atse_tick);
+		ether_ifdetach(ifp);
+	}
+	if (sc->atse_miibus != NULL)
+		device_delete_child(dev, sc->atse_miibus);
+
+	if (sc->atse_tx_intrhand)
+		bus_teardown_intr(dev, sc->atse_tx_irq_res,
+		    sc->atse_tx_intrhand);
+	if (sc->atse_rx_intrhand)
+		bus_teardown_intr(dev, sc->atse_rx_irq_res,
+		    sc->atse_rx_intrhand);
+
+	if (ifp != NULL)
+		if_free(ifp);
+
+	if (sc->atse_tx_buf != NULL)
+		free(sc->atse_tx_buf, M_DEVBUF);
+
+	mtx_destroy(&sc->atse_mtx);
+
+	return (0);
+}
+
+/* Shared between nexus and fdt implementation. */
+void
+atse_detach_resources(device_t dev)
+{
+	struct atse_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (sc->atse_txc_mem_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_txc_mem_rid,
+		    sc->atse_txc_mem_res);
+		sc->atse_txc_mem_res = NULL;
+	}
+	if (sc->atse_tx_mem_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_tx_mem_rid,
+		    sc->atse_tx_mem_res);
+		sc->atse_tx_mem_res = NULL;
+	}
+	if (sc->atse_tx_irq_res != NULL) {
+		bus_release_resource(dev, SYS_RES_IRQ, sc->atse_tx_irq_rid,
+		    sc->atse_tx_irq_res);
+		sc->atse_tx_irq_res = NULL;
+	}
+	if (sc->atse_rxc_mem_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_rxc_mem_rid,
+		    sc->atse_rxc_mem_res);
+		sc->atse_rxc_mem_res = NULL;
+	}
+	if (sc->atse_rx_mem_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_rx_mem_rid,
+		    sc->atse_rx_mem_res);
+		sc->atse_rx_mem_res = NULL;
+	}
+	if (sc->atse_rx_irq_res != NULL) {
+		bus_release_resource(dev, SYS_RES_IRQ, sc->atse_rx_irq_rid,
+		    sc->atse_rx_irq_res);
+		sc->atse_rx_irq_res = NULL;
+	}
+	if (sc->atse_mem_res != NULL) {
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->atse_mem_rid,
+		    sc->atse_mem_res);
+		sc->atse_mem_res = NULL;
+	}
+}
+
+int
+atse_detach_dev(device_t dev)
+{
+	int error;
+
+	error = atse_detach(dev);
+	if (error) {
+		/* We are basically in undefined state now. */
+		device_printf(dev, "atse_detach() failed: %d\n", error);
+		return (error);
+	}
+
+	atse_detach_resources(dev);
+
+	return (0);
+}
+
+int
+atse_miibus_readreg(device_t dev, int phy, int reg)
+{
+	struct atse_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	/*
+	 * We currently do not support re-mapping of MDIO space on-the-fly
+	 * but de-facto hard-code the phy#.
+	 */
+	if (phy != sc->atse_phy_addr)
+		return (0);
+
+	return (PHY_READ_2(sc, reg));
+}
+
+int
+atse_miibus_writereg(device_t dev, int phy, int reg, int data)
+{
+	struct atse_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	/*
+	 * We currently do not support re-mapping of MDIO space on-the-fly
+	 * but de-facto hard-code the phy#.
+	 */
+	if (phy != sc->atse_phy_addr)
+		return (0);
+
+	PHY_WRITE_2(sc, reg, data);
+	return (0);
+}
+
+void
+atse_miibus_statchg(device_t dev)
+{
+	struct atse_softc *sc;
+	struct mii_data *mii;
+	struct ifnet *ifp;
+	uint32_t val4;
+
+	sc = device_get_softc(dev);
+	ATSE_LOCK_ASSERT(sc);
+
+        mii = device_get_softc(sc->atse_miibus);
+        ifp = sc->atse_ifp;
+        if (mii == NULL || ifp == NULL ||
+            (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+                return;
+
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+
+	/* Assume no link. */
+	sc->atse_flags &= ~ATSE_FLAGS_LINK;
+
+	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+	    (IFM_ACTIVE | IFM_AVALID)) {
+
+		switch (IFM_SUBTYPE(mii->mii_media_active)) {
+		case IFM_10_T:
+			val4 |= BASE_CFG_COMMAND_CONFIG_ENA_10;
+			val4 &= ~BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
+			sc->atse_flags |= ATSE_FLAGS_LINK;
+			break;
+		case IFM_100_TX:
+			val4 &= ~BASE_CFG_COMMAND_CONFIG_ENA_10;
+			val4 &= ~BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
+			sc->atse_flags |= ATSE_FLAGS_LINK;
+			break;
+		case IFM_1000_T:
+			val4 &= ~BASE_CFG_COMMAND_CONFIG_ENA_10;
+			val4 |= BASE_CFG_COMMAND_CONFIG_ETH_SPEED;
+			sc->atse_flags |= ATSE_FLAGS_LINK;
+			break;
+		default:
+			break;
+		}
+	}
+
+        if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) {
+		/* XXX-BZ need to stop the MAC? */
+                return;
+        }
+
+	if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0)
+		val4 &= ~BASE_CFG_COMMAND_CONFIG_HD_ENA;
+        else
+		val4 |= BASE_CFG_COMMAND_CONFIG_HD_ENA;
+	/* XXX-BZ flow control? */
+
+	/* Make sure the MAC is activated. */
+	val4 |= BASE_CFG_COMMAND_CONFIG_TX_ENA;
+	val4 |= BASE_CFG_COMMAND_CONFIG_RX_ENA;
+
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+}
+
+/* end */


Property changes on: trunk/sys/dev/altera/atse/if_atse.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/atse/if_atse_fdt.c
===================================================================
--- trunk/sys/dev/altera/atse/if_atse_fdt.c	                        (rev 0)
+++ trunk/sys/dev/altera/atse/if_atse_fdt.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,220 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2013 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/atse/if_atse_fdt.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/altera/atse/if_atsereg.h>
+
+/* "device miibus" required.  See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+static int
+atse_probe_fdt(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_is_compatible(dev, "altera,atse")) {
+		device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
+		return (BUS_PROBE_DEFAULT);
+	}
+        return (ENXIO);
+}
+
+static int
+atse_attach_fdt(device_t dev)
+{
+	struct atse_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	sc->atse_dev = dev;
+	sc->atse_unit = device_get_unit(dev);
+
+	/*
+	 * FDT has the list of our resources.  Given we are using multiple
+	 * memory regions and possibly multiple interrupts, we need to attach
+	 * them in the order specified in .dts:
+	 * MAC, RX and RXC FIFO, TX and TXC FIFO; RX INTR, TX INTR.
+	 */
+
+	/* MAC: Avalon-MM, atse management register region. */
+	sc->atse_mem_rid = 0;
+	sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->atse_mem_rid, RF_ACTIVE);
+	if (sc->atse_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for ctrl region\n");
+		error = ENXIO;
+		goto err;
+	}
+	if (bootverbose)
+		device_printf(sc->atse_dev, "MAC ctrl region at mem %p-%p\n",
+		    (void *)rman_get_start(sc->atse_mem_res),
+		    (void *)(rman_get_start(sc->atse_mem_res) +
+		    rman_get_size(sc->atse_mem_res)));
+
+	/*
+	 * RX and RXC FIFO memory regions.
+	 * 0x00: 2 * 32bit FIFO data,
+	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave.
+	 */
+	sc->atse_rx_mem_rid = 1;
+	sc->atse_rx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->atse_rx_mem_rid, RF_ACTIVE);
+	if (sc->atse_rx_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for RX FIFO\n");
+		error = ENXIO;
+		goto err;
+	}
+	if (bootverbose)
+		device_printf(sc->atse_dev, "RX FIFO at mem %p-%p\n",
+		    (void *)rman_get_start(sc->atse_rx_mem_res),
+		    (void *)(rman_get_start(sc->atse_rx_mem_res) +
+		    rman_get_size(sc->atse_rx_mem_res)));
+
+	sc->atse_rxc_mem_rid = 2;
+	sc->atse_rxc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->atse_rxc_mem_rid, RF_ACTIVE);
+	if (sc->atse_rxc_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for RXC FIFO\n");
+		error = ENXIO;
+		goto err;
+	}
+	if (bootverbose)
+		device_printf(sc->atse_dev, "RXC FIFO at mem %p-%p\n",
+		    (void *)rman_get_start(sc->atse_rxc_mem_res),
+		    (void *)(rman_get_start(sc->atse_rxc_mem_res) +
+		    rman_get_size(sc->atse_rxc_mem_res)));
+
+	/*
+	 * TX and TXC FIFO memory regions.
+	 * 0x00: 2 * 32bit FIFO data,
+	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source.
+	 */
+	sc->atse_tx_mem_rid = 3;
+	sc->atse_tx_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->atse_tx_mem_rid, RF_ACTIVE);
+	if (sc->atse_tx_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for TX FIFO\n");
+		error = ENXIO;
+		goto err;
+	}
+	if (bootverbose)
+		device_printf(sc->atse_dev, "TX FIFO at mem %p-%p\n",
+		    (void *)rman_get_start(sc->atse_tx_mem_res),
+		    (void *)(rman_get_start(sc->atse_tx_mem_res) +
+		    rman_get_size(sc->atse_tx_mem_res)));
+
+	sc->atse_txc_mem_rid = 4;
+	sc->atse_txc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->atse_txc_mem_rid, RF_ACTIVE);
+	if (sc->atse_txc_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for TXC FIFO\n");
+		error = ENXIO;
+		goto err;
+	}
+	if (bootverbose)
+		device_printf(sc->atse_dev, "TXC FIFO at mem %p-%p\n",
+		    (void *)rman_get_start(sc->atse_txc_mem_res),
+		    (void *)(rman_get_start(sc->atse_txc_mem_res) +
+		    rman_get_size(sc->atse_txc_mem_res)));
+
+	/* (Optional) RX and TX IRQ. */
+	sc->atse_rx_irq_rid = 0;
+	sc->atse_rx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &sc->atse_rx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+	sc->atse_tx_irq_rid = 1;
+	sc->atse_tx_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &sc->atse_tx_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+
+	error = atse_attach(dev);
+	if (error)
+		goto err;
+
+	return (0);
+
+err:
+	/* Cleanup. */
+	atse_detach_resources(dev);
+
+	return (error);
+}
+
+static device_method_t atse_methods_fdt[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		atse_probe_fdt),
+	DEVMETHOD(device_attach,	atse_attach_fdt),
+	DEVMETHOD(device_detach,	atse_detach_dev),
+
+	/* MII interface */
+	DEVMETHOD(miibus_readreg,	atse_miibus_readreg),
+	DEVMETHOD(miibus_writereg,	atse_miibus_writereg),
+	DEVMETHOD(miibus_statchg,	atse_miibus_statchg),
+
+	DEVMETHOD_END
+};
+
+static driver_t atse_driver_fdt = {
+	"atse",
+	atse_methods_fdt,
+	sizeof(struct atse_softc)
+};
+
+DRIVER_MODULE(atse, simplebus, atse_driver_fdt, atse_devclass, 0, 0);
+DRIVER_MODULE(miibus, atse, miibus_driver, miibus_devclass, 0, 0);
+
+/* end */


Property changes on: trunk/sys/dev/altera/atse/if_atse_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/atse/if_atse_nexus.c
===================================================================
--- trunk/sys/dev/altera/atse/if_atse_nexus.c	                        (rev 0)
+++ trunk/sys/dev/altera/atse/if_atse_nexus.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,259 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012,2013 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/atse/if_atse_nexus.c 265999 2014-05-14 01:35:43Z ian $");
+
+#include "opt_device_polling.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/altera/atse/if_atsereg.h>
+
+/* "device miibus" required.  See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+MODULE_DEPEND(atse, ether, 1, 1, 1);
+MODULE_DEPEND(atse, miibus, 1, 1, 1);
+
+/*
+ * Device routines for interacting with nexus (probe, attach, detach) & helpers.
+ * XXX We should add suspend/resume later.
+ */
+static int
+atse_resource_int(device_t dev, const char *resname, int *v)
+{
+	int error;
+
+	error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+	    resname, v);
+	if (error != 0) {
+		/* If it does not exist, we fail, so not ingoring ENOENT. */
+		device_printf(dev, "could not fetch '%s' hint\n", resname);
+		return (error);
+	}
+
+	return (0);
+}
+
+static int
+atse_resource_long(device_t dev, const char *resname, long *v)
+{
+	int error;
+
+	error = resource_long_value(device_get_name(dev), device_get_unit(dev),
+	    resname, v);
+	if (error != 0) {
+		/* If it does not exist, we fail, so not ingoring ENOENT. */
+		device_printf(dev, "could not fetch '%s' hint\n", resname);
+		return (error);
+	}
+
+	return (0);
+}
+
+static int
+atse_probe_nexus(device_t dev)
+{
+	struct resource *res;
+	long l;
+	int error, rid;
+
+	/*
+	 * It is almost impossible to properly probe this device.  We must
+	 * rely on hints being set correctly.  So try to get hints and
+	 * one memory mapping.  Must cleanup and do again in attach but
+	 * should not probe successfully if not able to attach later.
+	 */
+	error = atse_resource_int(dev, "rx_irq", &rid);
+	error += atse_resource_long(dev, "rx_maddr", &l);
+	error += atse_resource_long(dev, "rx_msize", &l);
+	error += atse_resource_long(dev, "rxc_maddr", &l);
+	error += atse_resource_long(dev, "rxc_msize", &l);
+	error += atse_resource_int(dev, "tx_irq", &rid);
+	error += atse_resource_long(dev, "tx_maddr", &l);
+	error += atse_resource_long(dev, "tx_msize", &l);
+	error += atse_resource_long(dev, "txc_maddr", &l);
+	error += atse_resource_long(dev, "txc_msize", &l);
+	if (error != 0)
+		return (ENXIO);
+
+	rid = 0;
+	res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+	if (res == NULL)
+		return (ENXIO);
+	bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
+
+	/* Success. */
+	device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore");
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+atse_attach_nexus(device_t dev)
+{
+	struct atse_softc *sc;
+	int error;
+
+	sc = device_get_softc(dev);
+	sc->atse_dev = dev;
+	sc->atse_unit = device_get_unit(dev);
+
+	/* Get RX and TX IRQ and FIFO information from hints. */
+	error = atse_resource_int(dev, "rx_irq", &sc->atse_rx_irq);
+	error += atse_resource_long(dev, "rx_maddr", &sc->atse_rx_maddr);
+	error += atse_resource_long(dev, "rx_msize", &sc->atse_rx_msize);
+	error += atse_resource_long(dev, "rxc_maddr", &sc->atse_rxc_maddr);
+	error += atse_resource_long(dev, "rxc_msize", &sc->atse_rxc_msize);
+	error += atse_resource_int(dev, "tx_irq", &sc->atse_tx_irq);
+	error += atse_resource_long(dev, "tx_maddr", &sc->atse_tx_maddr);
+	error += atse_resource_long(dev, "tx_msize", &sc->atse_tx_msize);
+	error += atse_resource_long(dev, "txc_maddr", &sc->atse_txc_maddr);
+	error += atse_resource_long(dev, "txc_msize", &sc->atse_txc_msize);
+	if (error != 0)
+		return (error);
+
+	/* Avalon-MM, atse management register region. */
+	sc->atse_mem_rid = 0;
+	sc->atse_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->atse_mem_rid, RF_ACTIVE);
+	if (sc->atse_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for ctrl region\n");
+		return (ENXIO);
+	}
+
+	/*
+	 * (Optional) RX IRQ and memory mapped regions.
+	 * 0x00: 2 * 32bit FIFO data,
+	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-ST Sink to Avalon-MM R-Slave.
+	 */
+	sc->atse_rx_irq_rid = 0;
+	sc->atse_rx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
+	    &sc->atse_rx_irq_rid, sc->atse_rx_irq, sc->atse_rx_irq, 1,
+	    RF_ACTIVE | RF_SHAREABLE);
+
+	sc->atse_rx_mem_rid = 0;
+	sc->atse_rx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+	    &sc->atse_rx_mem_rid, sc->atse_rx_maddr, sc->atse_rx_maddr +
+	    sc->atse_rx_msize, sc->atse_rx_msize, RF_ACTIVE);
+	if (sc->atse_rx_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for RX\n");
+		goto err;
+        }
+	sc->atse_rxc_mem_rid = 0;
+	sc->atse_rxc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+	    &sc->atse_rxc_mem_rid, sc->atse_rxc_maddr, sc->atse_rxc_maddr +
+	    sc->atse_rxc_msize, sc->atse_rxc_msize, RF_ACTIVE);
+	if (sc->atse_rxc_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for RX control\n");
+		goto err;
+        }
+
+	/*
+	 * (Optional) TX IRQ and memory mapped regions.
+	 * 0x00: 2 * 32bit FIFO data,
+	 * 0x20: 8 * 32bit FIFO ctrl, Avalon-MM W-Slave to Avalon-ST Source.
+	 */
+	sc->atse_tx_irq_rid = 0;
+	sc->atse_tx_irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
+	    &sc->atse_tx_irq_rid, sc->atse_tx_irq, sc->atse_tx_irq, 1,
+	    RF_ACTIVE | RF_SHAREABLE);
+
+	sc->atse_tx_mem_rid = 0;
+	sc->atse_tx_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+	    &sc->atse_tx_mem_rid, sc->atse_tx_maddr, sc->atse_tx_maddr +
+	    sc->atse_tx_msize, sc->atse_tx_msize, RF_ACTIVE);
+	if (sc->atse_tx_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for TX\n");
+		goto err;
+	}
+	sc->atse_txc_mem_rid = 0;
+	sc->atse_txc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
+	    &sc->atse_txc_mem_rid, sc->atse_txc_maddr, sc->atse_txc_maddr +
+	    sc->atse_txc_msize, sc->atse_txc_msize, RF_ACTIVE);
+	if (sc->atse_txc_mem_res == NULL) {
+		device_printf(dev, "failed to map memory for TX control\n");
+		goto err;
+	}
+
+	error = atse_attach(dev);
+	if (error)
+		goto err;
+
+	return (0);
+
+err:
+	/* Cleanup. */
+	atse_detach_resources(dev);
+
+	return (error);
+}
+
+static device_method_t atse_methods_nexus[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		atse_probe_nexus),
+	DEVMETHOD(device_attach,	atse_attach_nexus),
+	DEVMETHOD(device_detach,	atse_detach_dev),
+
+	/* MII interface */
+	DEVMETHOD(miibus_readreg,	atse_miibus_readreg),
+	DEVMETHOD(miibus_writereg,	atse_miibus_writereg),
+	DEVMETHOD(miibus_statchg,	atse_miibus_statchg),
+
+	DEVMETHOD_END
+};
+
+static driver_t atse_driver_nexus = {
+	"atse",
+	atse_methods_nexus,
+	sizeof(struct atse_softc)
+};
+
+DRIVER_MODULE(atse, nexus, atse_driver_nexus, atse_devclass, 0, 0);
+DRIVER_MODULE(miibus, atse, miibus_driver, miibus_devclass, 0, 0);
+
+/* end */


Property changes on: trunk/sys/dev/altera/atse/if_atse_nexus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/atse/if_atsereg.h
===================================================================
--- trunk/sys/dev/altera/atse/if_atsereg.h	                        (rev 0)
+++ trunk/sys/dev/altera/atse/if_atsereg.h	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,487 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/altera/atse/if_atsereg.h 256752 2013-10-18 20:44:19Z brooks $
+ */
+
+#ifndef _DEV_IF_ATSEREG_H
+#define _DEV_IF_ATSEREG_H
+
+#define	ATSE_VENDOR			0x6af7
+#define	ATSE_DEVICE			0x00bd
+
+/* See hints file/fdt for ctrl port and Avalon FIFO addresses. */
+
+/* Section 3. Parameter Settings. */
+/*
+ * This is a lot of options that affect the way things are synthesized.
+ * We cannot really make them all hints and most of them might be stale.
+ */
+
+/* 3-1 Core Configuration */
+#if 0
+static const char *atse_core_core_variation[] = {
+	[0] = "10/100/1000 Mbps Ethernet MAC only",
+	[1] = "10/100/1000 Mbps Ethernet MAC with 1000BASE-X/SGMII PCS",
+	[2] = "1000BASE-X/SGMII PCS only",
+	[3] = "1000 Mbps Small MAC",
+	[4] = "10/100 Mbps Small MAC",
+	NULL
+};
+static const char *atse_core_interface[] = {
+	[0] = "MII",				/* Core variation 4. */
+	[1] = "GMII",				/* Core variation 3. */
+	[2] = "RGMII",				/* Core variation 0,1,3. */
+	[3] = "MII/GMII",			/* Core variation 0,1. */
+	NULL
+};
+#endif
+#define	CORE_CORE_VARIATION		1	/* atse_core_core_variation[] */
+#define	CORE_INTERFACE			3	/* atse_core_interface[] */
+#define	CORE_USE_INTERNAL_FIFO		1
+#define	CORE_NUMBER_OF_PORTS		1	/* Internal FIFO count. */
+#define	CORE_USE_TRANSCEIVER_BLOCK	1	/* SGMII PCS transceiver:
+						 * LVDS I/O. */
+
+/* 3-2 MAC Options. */
+/* Ethernet MAC Options. */
+#define	MAC_ENABLE_10_100_HDX_SUPPORT	0
+#define	MAC_ENABLE_RG_G_MII_LOOPBACK	0
+#define	MAC_ENABLE_SUPL_MAC_UCAST_ADDR	0	/* Supplementary MAC unicast. */
+#define	MAC_INCLUDE_STATISTICS_COUNTERS	0
+#define	MAC_STATISTICS_COUNTERS_64BIT	0
+#define	MAC_INCLUDE_MC_HASHTABLE	0	/* Multicast. */
+#define	MAC_ALIGN_PKTHDR_32BIT		1
+#define	MAC_ENABLE_FDX_FLOW_CTRL	0
+#define	MAC_ENABLE_VLAN_DETECTION	0	/* VLAN and stacked VLANs. */
+#define	MAC_ENABLE_MAGIC_PKT_DETECTION	0
+/* MDIO Module. */
+#define	MAC_MDIO_INCLUDE_MDIO_MODULE	1
+#define	MAC_MDIO_HOST_CLOCK_DIVISOR	40	/* Not just On/Off. */
+
+/* 3-4 FIFO Options. */
+/* Width and Memory Type. */
+#if 0
+static char *fifo_memory_block[] = {
+	[0] = "M4K",
+	[1] = "M9K",
+	[2] = "M144K",
+	[3] = "MRAM",
+	[4] = "AUTO",
+	NULL
+};
+#endif
+#define	FIFO_MEMORY_BLOCK		4
+#define	FIFO_WITDH			32	/* Other: 8 bits. */
+/* Depth. */
+#define	FIFO_DEPTH_TX			2048	/* 64 .. 64k, 2048x32bits. */
+#define	FIFO_DEPTH_RX			2048	/* 64 .. 64k, 2048x32bits. */
+
+#define	ATSE_TX_LIST_CNT		5	/* Certainly not bufferbloat. */
+
+/* 3-4 PCS/Transceiver Options */
+/* PCS Options. */
+#define	PCS_TXRX_PHY_ID			0x00000000	/* 32 bits */
+#define	PCS_TXRX_ENABLE_SGMII_BRIDGE	0
+/* Transceiver Options. */
+#define	PCS_TXRX_EXP_POWER_DOWN_SIGNAL	0	/* Export power down signal. */
+#define	PCS_TXRX_ENABLE_DYNAMIC_RECONF	0	/* Dynamic trans. reconfig. */
+#define	PCS_TXRX_STARTING_CHANNEL	0	/* 0..284. */
+
+
+/* -------------------------------------------------------------------------- */
+
+/* XXX more values based on the bitmaps provided. Cleanup. */
+/* See regs above. */
+#define	AVALON_FIFO_TX_BLOCK_DIAGRAM		0
+#define	AVALON_FIFO_TX_BLOCK_DIAGRAM_SHOW_SIGANLS	0
+#define	AVALON_FIFO_TX_PARAM_SINGLE_RESET_MODE	0
+#define	AVALON_FIFO_TX_BASIC_OPTS_DEPTH		16
+#define	AVALON_FIFO_TX_BASIC_OPTS_ALLOW_BACKPRESSURE	1
+#define	AVALON_FIFO_TX_BASIC_OPTS_CLOCK_SETTING	"Single Clock Mode"
+#define	AVALON_FIFO_TX_BASIC_OPTS_FIFO_IMPL	"Construct FIFO from embedded memory blocks"
+#define	AVALON_FIFO_TX_STATUS_PORT_CREATE_STATUS_INT_FOR_INPUT	1
+#define	AVALON_FIFO_TX_STATUS_PORT_CREATE_STATUS_INT_FOR_OUTPUT	0
+#define	AVALON_FIFO_TX_STATUS_PORT_ENABLE_IRQ_FOR_STATUS_PORT	1
+#define	AVALON_FIFO_TX_INPUT_TYPE			"AVALONMM_WRITE"
+#define	AVALON_FIFO_TX_OUTPUT_TYPE			"AVALONST_SOURCE"
+#define	AVALON_FIFO_TX_AVALON_MM_PORT_SETTINGS_DATA_WIDTH	""
+#define	AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_BITS_PER_SYMBOL	8
+#define	AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_SYM_PER_BEAT	4
+#define	AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_ERROR_WIDTH		1
+#define	AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_CHANNEL_WIDTH	0
+#define	AVALON_FIFO_TX_AVALON_ST_PORT_SETTINGS_ENABLE_PACKET_DATA	1
+
+#define	AVALON_FIFO_RX_BLOCK_DIAGRAM		0
+#define	AVALON_FIFO_RX_BLOCK_DIAGRAM_SHOW_SIGNALS		0
+#define	AVALON_FIFO_RX_PARAM_SINGLE_RESET_MODE	0
+#define	AVALON_FIFO_RX_BASIC_OPTS_DEPTH		16
+#define	AVALON_FIFO_RX_BASIC_OPTS_ALLOW_BACKPRESSURE	1
+#define	AVALON_FIFO_RX_BASIC_OPTS_CLOCK_SETTING	"Single Clock Mode"
+#define	AVALON_FIFO_RX_BASIC_OPTS_FIFO_IMPL	"Construct FIFO from embedded memory blocks"
+#define	AVALON_FIFO_RX_STATUS_PORT_CREATE_STATUS_INT_FOR_INPUT	1
+#define	AVALON_FIFO_RX_STATUS_PORT_CREATE_STATUS_INT_FOR_OUTPUT	0
+#define	AVALON_FIFO_RX_STATUS_PORT_ENABLE_IRQ_FOR_STATUS_PORT	1
+#define	AVALON_FIFO_RX_INPUT_TYPE			"AVALONST_SINK"
+#define	AVALON_FIFO_RX_OUTPUT_TYPE			"AVALONMM_READ"
+#define	AVALON_FIFO_RX_AVALON_MM_PORT_SETTINGS_DATA_WIDTH	""
+#define	AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_BITS_PER_SYMBOL	8
+#define	AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_SYM_PER_BEAT	4
+#define	AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_ERROR_WIDTH		6
+#define	AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_CHANNEL_WIDTH	0
+#define	AVALON_FIFO_RX_AVALON_ST_PORT_SETTINGS_ENABLE_PACKET_DATA	1
+
+/* -------------------------------------------------------------------------- */
+
+/* 5. Configuration Register Space. */
+
+/* 5-1, MAC Configuration Register Space; Dword offsets. */
+/* 0x00 - 0x17, Base Configuration. */
+#define	BASE_CONFIG_REV			0x00		/* ro, IP Core ver. */
+#define	BASE_CFG_REV_VER_MASK			0x0000FFFF
+#define	BASE_CFG_REV_CUST_VERSION__MASK		0xFFFF0000
+
+#define	BASE_CFG_SCRATCH		0x01		/* rw, 0 */
+
+#define	BASE_CFG_COMMAND_CONFIG		0x02		/* rw, 0 */
+#define	BASE_CFG_COMMAND_CONFIG_TX_ENA		(1<<0)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_RX_ENA		(1<<1)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_XON_GEN		(1<<2)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_ETH_SPEED	(1<<3)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_PROMIS_EN	(1<<4)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_PAD_EN		(1<<5)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_CRC_FWD		(1<<6)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_PAUSE_FWD	(1<<7)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_PAUSE_IGNORE	(1<<8)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_TX_ADDR_INS	(1<<9)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_HD_ENA		(1<<10)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_EXCESS_COL	(1<<11)	/* ro */
+#define	BASE_CFG_COMMAND_CONFIG_LATE_COL	(1<<12)	/* ro */
+#define	BASE_CFG_COMMAND_CONFIG_SW_RESET	(1<<13)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_MHASH_SEL	(1<<14)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_LOOP_ENA	(1<<15)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_TX_ADDR_SEL	(1<<16|1<<17|1<<18) /* rw */
+#define	BASE_CFG_COMMAND_CONFIG_MAGIC_ENA	(1<<19)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_SLEEP		(1<<20)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_WAKEUP		(1<<21)	/* ro */
+#define	BASE_CFG_COMMAND_CONFIG_XOFF_GEN	(1<<22)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_CNTL_FRM_ENA	(1<<23)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_NO_LGTH_CHECK	(1<<24)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_ENA_10		(1<<25)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC	(1<<26)	/* rw */
+#define	BASE_CFG_COMMAND_CONFIG_DISABLE_READ_TIMEOUT	(1<<27)	/* rw */
+	/* 28-30 Reserved. */				/* - */
+#define	BASE_CFG_COMMAND_CONFIG_CNT_RESET	(1<<31)	/* rw */
+
+#define	BASE_CFG_MAC_0			0x03		/* rw, 0 */
+#define	BASE_CFG_MAC_1			0x04		/* rw, 0 */
+#define	BASE_CFG_FRM_LENGTH		0x05		/* rw/ro, 1518 */
+#define	BASE_CFG_PAUSE_QUANT		0x06		/* rw, 0 */
+#define	BASE_CFG_RX_SECTION_EMPTY	0x07		/* rw/ro, 0 */
+#define	BASE_CFG_RX_SECTION_FULL	0x08		/* rw/ro, 0 */
+#define	BASE_CFG_TX_SECTION_EMPTY	0x09		/* rw/ro, 0 */
+#define	BASE_CFG_TX_SECTION_FULL	0x0A		/* rw/ro, 0 */
+#define	BASE_CFG_RX_ALMOST_EMPTY	0x0B		/* rw/ro, 0 */
+#define	BASE_CFG_RX_ALMOST_FULL		0x0C		/* rw/ro, 0 */
+#define	BASE_CFG_TX_ALMOST_EMPTY	0x0D		/* rw/ro, 0 */
+#define	BASE_CFG_TX_ALMOST_FULL		0x0E		/* rw/ro, 0 */
+#define	BASE_CFG_MDIO_ADDR0		0x0F		/* rw, 0 */
+#define	BASE_CFG_MDIO_ADDR1		0x10		/* rw, 1 */
+#define	BASE_CFG_HOLDOFF_QUANT		0x11		/* rw, 0xFFFF */
+/* 0x12-0x16 Reserved. */				/* -, 0 */
+#define	BASE_CFG_TX_IPG_LENGTH		0x17		/* rw, 0 */
+
+/* 0x18 - 0x38, Statistics Counters. */
+#define	STATS_A_MAC_ID_0		0x18		/* ro */
+#define	STATS_A_MAC_ID_1		0x19		/* ro */
+#define	STATS_A_FRAMES_TX_OK		0x1A		/* ro */
+#define	STATS_A_FRAMES_RX_OK		0x1B		/* ro */
+#define	STATS_A_FCS_ERRORS		0x1C		/* ro */
+#define	STATS_A_ALIGNMENT_ERRORS	0x1D		/* ro */
+#define	STATS_A_OCTETS_TX_OK		0x1E		/* ro */
+#define	STATS_A_OCTETS_RX_OK		0x1F		/* ro */
+#define	STATS_A_TX_PAUSE_MAX_CTRL_FRAME	0x20		/* ro */
+#define	STATS_A_RX_PAUSE_MAX_CTRL_FRAME	0x21		/* ro */
+#define	STATS_IF_IN_ERRORS		0x22		/* ro */
+#define	STATS_IF_OUT_ERRORS		0x23		/* ro */
+#define	STATS_IF_IN_UCAST_PKTS		0x24		/* ro */
+#define	STATS_IF_IN_MULTICAST_PKTS	0x25		/* ro */
+#define	STATS_IF_IN_BROADCAST_PKTS	0x26		/* ro */
+#define	STATS_IF_OUT_DISCARDS		0x27		/* ro */
+#define	STATS_IF_OUT_UCAST_PKTS		0x28		/* ro */
+#define	STATS_IF_OUT_MULTICAST_PKTS	0x29		/* ro */
+#define	STATS_IF_OUT_BROADCAST_PKTS	0x2A		/* ro */
+#define	STATS_ETHER_STATS_DROP_EVENT	0x2B		/* ro */
+#define	STATS_ETHER_STATS_OCTETS	0x2C		/* ro */
+#define	STATS_ETHER_STATS_PKTS		0x2D		/* ro */
+#define	STATS_ETHER_STATS_USIZE_PKTS	0x2E		/* ro */
+#define	STATS_ETHER_STATS_OSIZE_PKTS	0x2F		/* ro */
+#define	STATS_ETHER_STATS_PKTS_64_OCTETS 0x30		/* ro */
+#define	STATS_ETHER_STATS_PKTS_65_TO_127_OCTETS	 0x31	/* ro */
+#define	STATS_ETHER_STATS_PKTS_128_TO_255_OCTETS 0x32	/* ro */
+#define	STATS_ETHER_STATS_PKTS_256_TO_511_OCTETS 0x33	/* ro */
+#define	STATS_ETHER_STATS_PKTS_512_TO_1023_OCTETS 0x34	/* ro */
+#define	STATS_ETHER_STATS_PKTS_1024_TO_1518_OCTETS 0x35	/* ro */
+#define	STATS_ETHER_STATS_PKTS_1519_TO_X_OCTETS	0x36	/* ro */
+#define	STATS_ETHER_STATS_JABBERS	0x37		/* ro */
+#define	STATS_ETHER_STATS_FRAGMENTS	0x38		/* ro */
+	/* 0x39, Reserved. */				/* - */
+
+/* 0x3A, Transmit Command. */
+#define	TX_CMD_STAT			0x3A		/* rw */
+#define	TX_CMD_STAT_OMIT_CRC			(1<<17)
+#define	TX_CMD_STAT_TX_SHIFT16			(1<<18)
+
+/* 0x3B, Receive Command. */
+#define	RX_CMD_STAT			0x3B		/* rw */
+#define	RX_CMD_STAT_RX_SHIFT16			(1<<25)
+
+/* 0x3C - 0x3E, Extended Statistics Counters. */
+#define	ESTATS_MSB_A_OCTETS_TX_OK	0x3C		/* ro */
+#define	ESTATS_MSB_A_OCTETS_RX_OK	0x3D		/* ro */
+#define	ESTATS_MSB_ETHER_STATS_OCTETS	0x3E		/* ro */
+
+/* 0x3F, Reserved. */
+
+/* 0x40 - 0x7F, Multicast Hash Table. */
+#define	MHASH_START			0x40
+#define	MHASH_LEN			0x3F
+
+/* 0x80 - 0x9F, MDIO Space 0 or PCS Function Configuration. */
+#define	MDIO_0_START			0x80
+
+/* The following are offsets to the first PCS register at 0x80. */
+/* See sys/dev/mii/mii.h. */
+#define	PCS_CONTROL			0x00		/* rw */
+	/* Bits 0:4, Reserved. */			/* - */
+#define	PCS_CONTROL_UNIDIRECTIONAL_ENABLE	(1<<5)	/* rw */
+#define	PCS_CONTROL_SPEED_SELECTION		(1<<6|1<<13) /* ro */
+#define	PCS_CONTROL_COLLISION_TEST		(1<<7)	/* ro */
+#define	PCS_CONTROL_DUPLEX_MODE			(1<<8)	/* ro */
+#define	PCS_CONTROL_RESTART_AUTO_NEGOTIATION	(1<<9)	/* rw */
+#define	PCS_CONTROL_ISOLATE			(1<<10)	/* rw */
+#define	PCS_CONTROL_POWERDOWN			(1<<11)	/* rw */
+#define	PCS_CONTROL_AUTO_NEGOTIATION_ENABLE	(1<<12)	/* rw */
+	/* See bit 6 above. */				/* ro */
+#define	PCS_CONTROL_LOOPBACK			(1<<14)	/* rw */
+#define	PCS_CONTROL_RESET			(1<<15)	/* rw */
+
+#define	PCS_STATUS			0x01		/* ro */
+#define	PCS_STATUS_EXTENDED_CAPABILITY		(1<<0)	/* ro */
+#define	PCS_STATUS_JABBER_DETECT		(1<<1)	/* -, 0 */
+#define	PCS_STATUS_LINK_STATUS			(1<<2)	/* ro */
+#define	PCS_STATUS_AUTO_NEGOTIATION_ABILITY	(1<<3)	/* ro */
+#define	PCS_STATUS_REMOTE_FAULT			(1<<4)	/* -, 0 */
+#define	PCS_STATUS_AUTO_NEGOTIATION_COMPLETE	(1<<5)	/* ro */
+#define	PCS_STATUS_MF_PREAMBLE_SUPPRESSION	(1<<6)	/* -, 0 */
+#define	PCS_STATUS_UNIDIRECTIONAL_ABILITY	(1<<7)	/* ro */
+#define	PCS_STATUS_EXTENDED_STATUS		(1<<8)	/* -, 0 */
+#define	PCS_STATUS_100BASET2_HALF_DUPLEX	(1<<9)	/* ro */
+#define	PCS_STATUS_100BASET2_FULL_DUPLEX	(1<<10)	/* ro */
+#define	PCS_STATUS_10MBPS_HALF_DUPLEX		(1<<11)	/* ro */
+#define	PCS_STATUS_10MBPS_FULL_DUPLEX		(1<<12)	/* ro */
+#define	PCS_STATUS_100BASE_X_HALF_DUPLEX	(1<<13)	/* ro */
+#define	PCS_STATUS_100BASE_X_FULL_DUPLEX	(1<<14)	/* ro */
+#define	PCS_STATUS_100BASE_T4			(1<<15)	/* ro */
+
+#define	PCS_PHY_IDENTIFIER_0		0x02		/* ro */
+#define	PCS_PHY_IDENTIFIER_1		0x03		/* ro */
+
+#define	PCS_DEV_ABILITY			0x04		/* rw */
+	/* 1000BASE-X */
+	/* Bits 0:4, Reserved. */			/* - */
+#define	PCS_DEV_ABILITY_1000BASE_X_FD		(1<<5)	/* rw */
+#define	PCS_DEV_ABILITY_1000BASE_X_HD		(1<<6)	/* rw */
+#define	PCS_DEV_ABILITY_1000BASE_X_PS1		(1<<7)	/* rw */
+#define	PCS_DEV_ABILITY_1000BASE_X_PS2		(1<<8)	/* rw */
+	/* Bits 9:11, Reserved. */			/* - */
+#define	PCS_DEV_ABILITY_1000BASE_X_RF1		(1<<12)	/* rw */
+#define	PCS_DEV_ABILITY_1000BASE_X_RF2		(1<<13)	/* rw */
+#define	PCS_DEV_ABILITY_1000BASE_X_ACK		(1<<14)	/* rw */
+#define	PCS_DEV_ABILITY_1000BASE_X_NP		(1<<15)	/* rw */
+
+#define	PCS_PARTNER_ABILITY		0x05		/* ro */
+	/* 1000BASE-X */
+	/* Bits 0:4, Reserved. */			/* - */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_FD	(1<<5)	/* ro */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_HD	(1<<6)	/* ro */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_PS1	(1<<7)	/* ro */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_PS2	(1<<8)	/* ro */
+	/* Bits 9:11, Reserved. */			/* - */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_RF1	(1<<12)	/* ro */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_RF2	(1<<13)	/* ro */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_ACK	(1<<14)	/* ro */
+#define	PCS_PARTNER_ABILITY_1000BASE_X_NP	(1<<15)	/* ro */
+	/* SGMII */
+	/* Bits 0:9, Reserved. */			/* - */
+#define	PCS_PARTNER_ABILITY_SGMII_COPPER_SPEED0	(1<<10)	/* ro */
+#define	PCS_PARTNER_ABILITY_SGMII_COPPER_SPEED1	(1<<11)	/* ro */
+#define	PCS_PARTNER_ABILITY_SGMII_COPPER_DUPLEX_STATUS	(1<<12)	/* ro */
+	/* Bit 13, Reserved. */				/* - */
+#define	PCS_PARTNER_ABILITY_SGMII_ACK		(1<<14)	/* ro */
+#define	PCS_PARTNER_ABILITY_SGMII_COPPER_LINK_STATUS	(1<<15)	/* ro */
+
+#define	PCS_AN_EXPANSION		0x06		/* ro */
+#define	PCS_AN_EXPANSION_LINK_PARTNER_AUTO_NEGOTIATION_ABLE	(1<<0)	/* ro */
+#define	PCS_AN_EXPANSION_PAGE_RECEIVE		(1<<1)	/* ro */
+#define	PCS_AN_EXPANSION_NEXT_PAGE_ABLE		(1<<2)	/* -, 0 */
+	/* Bits 3:15, Reserved. */			/* - */
+
+#define	PCS_DEVICE_NEXT_PAGE		0x07		/* ro */
+#define	PCS_PARTNER_NEXT_PAGE		0x08		/* ro */
+#define	PCS_MASTER_SLAVE_CNTL		0x09		/* ro */
+#define	PCS_MASTER_SLAVE_STAT		0x0A		/* ro */
+	/* 0x0B - 0x0E, Reserved */			/* - */
+#define	PCS_EXTENDED_STATUS		0x0F		/* ro */
+/* Specific Extended Registers. */
+#define	PCS_EXT_SCRATCH			0x10		/* rw */
+#define	PCS_EXT_REV			0x11		/* ro */
+#define	PCS_EXT_LINK_TIMER_0		0x12		/* rw */
+#define	PCS_EXT_LINK_TIMER_1		0x13		/* rw */
+#define	PCS_EXT_IF_MODE			0x14		/* rw */
+#define	PCS_EXT_IF_MODE_SGMII_ENA		(1<<0)	/* rw */
+#define	PCS_EXT_IF_MODE_USE_SGMII_AN		(1<<1)	/* rw */
+#define	PCS_EXT_IF_MODE_SGMII_SPEED1		(1<<2)	/* rw */
+#define	PCS_EXT_IF_MODE_SGMII_SPEED0		(1<<3)	/* rw */
+#define	PCS_EXT_IF_MODE_SGMII_DUPLEX		(1<<4)	/* rw */
+	/* Bits 5:15, Reserved. */			/* - */
+
+#define	PCS_EXT_DISABLE_READ_TIMEOUT	0x15		/* rw */
+#define	PCS_EXT_READ_TIMEOUT		0x16		/* r0 */
+	/* 0x17-0x1F, Reserved. */
+
+/* 0xA0 - 0xBF, MDIO Space 1. */
+#define	MDIO_1_START			0xA0
+#define	ATSE_BMCR			MDIO_1_START
+
+/* 0xC0 - 0xC7, Supplementary Address. */
+#define	SUPPL_ADDR_SMAC_0_0		0xC0		/* rw */
+#define	SUPPL_ADDR_SMAC_0_1		0xC1		/* rw */
+#define	SUPPL_ADDR_SMAC_1_0		0xC2		/* rw */
+#define	SUPPL_ADDR_SMAC_1_1		0xC3		/* rw */
+#define	SUPPL_ADDR_SMAC_2_0		0xC4		/* rw */
+#define	SUPPL_ADDR_SMAC_2_1		0xC5		/* rw */
+#define	SUPPL_ADDR_SMAC_3_0		0xC6		/* rw */
+#define	SUPPL_ADDR_SMAC_3_1		0xC7		/* rw */
+
+/* 0xC8 - 0xCF, Reserved; set to zero, ignore on read. */
+/* 0xD7 - 0xFF, Reserved; set to zero, ignore on read. */
+
+
+/* -------------------------------------------------------------------------- */
+
+/* DE4 Intel Strata Flash Ethernet Option Bits area. */
+/* XXX-BZ this is something a loader will have to handle for us. */
+#define	ALTERA_ETHERNET_OPTION_BITS_OFF	0x00008000
+#define	ALTERA_ETHERNET_OPTION_BITS_LEN	0x00007fff
+
+/* -------------------------------------------------------------------------- */
+
+struct atse_softc {
+	struct ifnet		*atse_ifp;
+	struct mbuf		*atse_rx_m;
+	struct mbuf		*atse_tx_m;
+	uint8_t			*atse_tx_buf;
+	struct resource		*atse_mem_res;
+	struct resource		*atse_rx_irq_res;
+	struct resource		*atse_rx_mem_res;
+	struct resource		*atse_rxc_mem_res;
+	struct resource		*atse_tx_irq_res;
+	struct resource		*atse_tx_mem_res;
+	struct resource		*atse_txc_mem_res;
+	device_t		atse_miibus;
+	device_t		atse_dev;
+	int			atse_unit;
+	int			atse_mem_rid;
+	int			atse_rx_irq_rid;
+	int			atse_rx_mem_rid;
+	int			atse_rxc_mem_rid;
+	int			atse_tx_irq_rid;
+	int			atse_tx_mem_rid;
+	int			atse_txc_mem_rid;
+	int			atse_phy_addr;
+	int			atse_if_flags;
+	int			atse_rx_irq;
+	int			atse_tx_irq;
+	u_long			atse_rx_maddr;
+	u_long			atse_rx_msize;
+	u_long			atse_tx_maddr;
+	u_long			atse_tx_msize;
+	u_long			atse_rxc_maddr;
+	u_long			atse_rxc_msize;
+	u_long			atse_txc_maddr;
+	u_long			atse_txc_msize;
+	void			*atse_rx_intrhand;
+	void			*atse_tx_intrhand;
+	bus_addr_t		atse_bmcr0;
+	bus_addr_t		atse_bmcr1;
+	uint32_t		atse_flags;
+#define	ATSE_FLAGS_LINK			0x00000001
+#define	ATSE_FLAGS_ERROR		0x00000002
+#define	ATSE_FLAGS_SOP_SEEN		0x00000004
+	uint8_t			atse_eth_addr[ETHER_ADDR_LEN];
+#define	ATSE_ETH_ADDR_DEF	0x01
+#define	ATSE_ETH_ADDR_SUPP1	0x02
+#define	ATSE_ETH_ADDR_SUPP2	0x04
+#define	ATSE_ETH_ADDR_SUPP3	0x08
+#define	ATSE_ETH_ADDR_SUPP4	0x10
+#define	ATSE_ETH_ADDR_ALL	0x1f
+	uint16_t		atse_watchdog_timer;
+	uint16_t		atse_tx_m_offset;
+	uint16_t		atse_tx_buf_len;
+	uint16_t		atse_rx_buf_len;
+	int16_t			atse_rx_cycles;		/* POLLING */
+#define	RX_CYCLES_IN_INTR	5
+	uint32_t		atse_rx_err[6];
+#define	ATSE_RX_ERR_FIFO_THRES_EOP	0 /* FIFO threshold reached, on EOP. */
+#define	ATSE_RX_ERR_ELEN		1 /* Frame/payload length not valid. */
+#define	ATSE_RX_ERR_CRC32		2 /* CRC-32 error. */
+#define	ATSE_RX_ERR_FIFO_THRES_TRUNC	3 /* FIFO thresh., truncated frame. */
+#define	ATSE_RX_ERR_4			4 /* ? */
+#define	ATSE_RX_ERR_5			5 /* / */
+#define	ATSE_RX_ERR_MAX			6
+	struct callout		atse_tick;
+	struct mtx		atse_mtx;
+};
+
+
+int	atse_attach(device_t);
+int	atse_detach_dev(device_t);
+void	atse_detach_resources(device_t);
+
+int	atse_miibus_readreg(device_t, int, int);
+int	atse_miibus_writereg(device_t, int, int, int);
+void	atse_miibus_statchg(device_t);
+
+extern devclass_t atse_devclass;
+
+#endif /* _DEV_IF_ATSEREG_H */
+
+/* end */


Property changes on: trunk/sys/dev/altera/atse/if_atsereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/avgen/altera_avgen.c
===================================================================
--- trunk/sys/dev/altera/avgen/altera_avgen.c	                        (rev 0)
+++ trunk/sys/dev/altera/avgen/altera_avgen.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,369 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/avgen/altera_avgen.c 275428 2014-12-02 21:23:13Z brooks $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+/*
+ * Generic device driver for allowing read(), write(), and mmap() on
+ * memory-mapped, Avalon-attached devices.  There is no actual dependence on
+ * Avalon, so conceivably this should just be soc_dev or similar, since many
+ * system-on-chip bus environments would work fine with the same code.
+ */
+
+devclass_t altera_avgen_devclass;
+
+static d_mmap_t altera_avgen_mmap;
+static d_read_t altera_avgen_read;
+static d_write_t altera_avgen_write;
+
+static struct cdevsw avg_cdevsw = {
+	.d_version =	D_VERSION,
+	.d_mmap =	altera_avgen_mmap,
+	.d_read =	altera_avgen_read,
+	.d_write =	altera_avgen_write,
+	.d_name =	"altera_avgen",
+};
+
+static int
+altera_avgen_read(struct cdev *dev, struct uio *uio, int flag)
+{
+	struct altera_avgen_softc *sc;
+	u_long offset, size;
+#ifdef NOTYET
+	uint64_t v8;
+#endif
+	uint32_t v4;
+	uint16_t v2;
+	uint8_t v1;
+	u_int width;
+	int error;
+
+	sc = dev->si_drv1;
+	if ((sc->avg_flags & ALTERA_AVALON_FLAG_READ) == 0)
+		return (EACCES);
+	width = sc->avg_width;
+	if (uio->uio_offset < 0 || uio->uio_offset % width != 0 ||
+	    uio->uio_resid % width != 0)
+		return (ENODEV);
+	size = rman_get_size(sc->avg_res);
+	if ((uio->uio_offset + uio->uio_resid < 0) ||
+	    (uio->uio_offset + uio->uio_resid > size))
+		return (ENODEV);
+	while (uio->uio_resid > 0) {
+		offset = uio->uio_offset;
+		if (offset + width > size)
+			return (ENODEV);
+		switch (width) {
+		case 1:
+			v1 = bus_read_1(sc->avg_res, offset);
+			error = uiomove(&v1, sizeof(v1), uio);
+			break;
+			
+		case 2:
+			v2 = bus_read_2(sc->avg_res, offset);
+			error = uiomove(&v2, sizeof(v2), uio);
+			break;
+			
+		case 4:
+			v4 = bus_read_4(sc->avg_res, offset);
+			error = uiomove(&v4, sizeof(v4), uio);
+			break;
+			
+#ifdef NOTYET
+		case 8:
+			v8 = bus_read_8(sc->avg_res, offset);
+			error = uiomove(&v8, sizeof(v8), uio);
+			break;
+			
+#endif
+
+		default:
+			panic("%s: unexpected widthment %u", __func__, width);
+		}
+		if (error)
+			return (error);
+	}
+	return (0);
+}
+
+static int
+altera_avgen_write(struct cdev *dev, struct uio *uio, int flag)
+{
+	struct altera_avgen_softc *sc;
+	u_long offset, size;
+#ifdef NOTYET
+	uint64_t v8;
+#endif
+	uint32_t v4;
+	uint16_t v2;
+	uint8_t v1;
+	u_int width;
+	int error;
+
+	sc = dev->si_drv1;
+	if ((sc->avg_flags & ALTERA_AVALON_FLAG_WRITE) == 0)
+		return (EACCES);
+	width = sc->avg_width;
+	if (uio->uio_offset < 0 || uio->uio_offset % width != 0 ||
+	    uio->uio_resid % width != 0)
+		return (ENODEV);
+	size = rman_get_size(sc->avg_res);
+	while (uio->uio_resid > 0) {
+		offset = uio->uio_offset;
+		if (offset + width > size)
+			return (ENODEV);
+		switch (width) {
+		case 1:
+			error = uiomove(&v1, sizeof(v1), uio);
+			if (error)
+				return (error);
+			bus_write_1(sc->avg_res, offset, v1);
+			break;
+
+		case 2:
+			error = uiomove(&v2, sizeof(v2), uio);
+			if (error)
+				return (error);
+			bus_write_2(sc->avg_res, offset, v2);
+			break;
+
+		case 4:
+			error = uiomove(&v4, sizeof(v4), uio);
+			if (error)
+				return (error);
+			bus_write_4(sc->avg_res, offset, v4);
+			break;
+
+#ifdef NOTYET
+		case 8:
+			error = uiomove(&v8, sizeof(v8), uio);
+			if (error)
+				return (error);
+			bus_write_8(sc->avg_res, offset, v8);
+			break;
+#endif
+
+		default:
+			panic("%s: unexpected width %u", __func__, width);
+		}
+	}
+	return (0);
+}
+
+static int
+altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
+    int nprot, vm_memattr_t *memattr)
+{
+	struct altera_avgen_softc *sc;
+
+	sc = dev->si_drv1;
+	if (nprot & VM_PROT_READ) {
+		if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_READ) == 0)
+			return (EACCES);
+	}
+	if (nprot & VM_PROT_WRITE) {
+		if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_WRITE) == 0)
+			return (EACCES);
+	}
+	if (nprot & VM_PROT_EXECUTE) {
+		if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_EXEC) == 0)
+			return (EACCES);
+	}
+	if (trunc_page(offset) == offset &&
+	    rman_get_size(sc->avg_res) >= offset + PAGE_SIZE) {
+		*paddr = rman_get_start(sc->avg_res) + offset;
+		*memattr = VM_MEMATTR_UNCACHEABLE;
+	} else
+		return (ENODEV);
+	return (0);
+}
+
+
+static int
+altera_avgen_process_options(struct altera_avgen_softc *sc,
+    const char *str_fileio, const char *str_mmapio, const char *str_devname,
+    int devunit)
+{
+	const char *cp;
+	device_t dev = sc->avg_dev;
+
+	/*
+	 * Check for valid combinations of options.
+	 */
+	if (str_fileio == NULL && str_mmapio == NULL) {
+		device_printf(dev,
+		    "at least one of %s or %s must be specified\n",
+		    ALTERA_AVALON_STR_FILEIO, ALTERA_AVALON_STR_MMAPIO);
+		return (ENXIO);
+	}
+	if (str_devname == NULL && devunit != -1) {
+		device_printf(dev, "%s requires %s be specified\n",
+		    ALTERA_AVALON_STR_DEVUNIT, ALTERA_AVALON_STR_DEVNAME);
+		return (ENXIO);
+	}
+
+	/*
+	 * Extract, digest, and save values.
+	 */
+	switch (sc->avg_width) {
+	case 1:
+	case 2:
+	case 4:
+#ifdef NOTYET
+	case 8:
+#endif
+		break;
+
+	default:
+		device_printf(dev, "%s unsupported value %u\n",
+		    ALTERA_AVALON_STR_WIDTH, sc->avg_width);
+		return (ENXIO);
+	}
+	sc->avg_flags = 0;
+	if (str_fileio != NULL) {
+		for (cp = str_fileio; *cp != '\0'; cp++) {
+			switch (*cp) {
+			case ALTERA_AVALON_CHAR_READ:
+				sc->avg_flags |= ALTERA_AVALON_FLAG_READ;
+				break;
+
+			case ALTERA_AVALON_CHAR_WRITE:
+				sc->avg_flags |= ALTERA_AVALON_FLAG_WRITE;
+				break;
+
+			default:
+				device_printf(dev,
+				    "invalid %s character %c\n", 
+				    ALTERA_AVALON_STR_FILEIO, *cp);
+				return (ENXIO);
+			}
+		}
+	}
+	if (str_mmapio != NULL) {
+		for (cp = str_mmapio; *cp != '\0'; cp++) {
+			switch (*cp) {
+			case ALTERA_AVALON_CHAR_READ:
+				sc->avg_flags |= ALTERA_AVALON_FLAG_MMAP_READ;
+				break;
+
+			case ALTERA_AVALON_CHAR_WRITE:
+				sc->avg_flags |=
+				    ALTERA_AVALON_FLAG_MMAP_WRITE;
+				break;
+
+			case ALTERA_AVALON_CHAR_EXEC:
+				sc->avg_flags |= ALTERA_AVALON_FLAG_MMAP_EXEC;
+				break;
+
+			default:
+				device_printf(dev,
+				    "invalid %s character %c\n",
+				    ALTERA_AVALON_STR_MMAPIO, *cp);
+				return (ENXIO);
+			}
+		}
+	}
+	return (0);
+}
+
+int
+altera_avgen_attach(struct altera_avgen_softc *sc, const char *str_fileio,
+    const char *str_mmapio, const char *str_devname, int devunit)
+{
+	device_t dev = sc->avg_dev;
+	int error;
+
+	error = altera_avgen_process_options(sc, str_fileio, str_mmapio,
+	    str_devname, devunit);
+	if (error)
+		return (error);
+
+	if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) {
+		if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) {
+			device_printf(dev,
+			    "memory region not even multiple of page size\n");
+			return (ENXIO);
+		}
+		if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) {
+			device_printf(dev, "memory region not page-aligned\n");
+			return (ENXIO);
+		}
+	}
+
+	/* Device node allocation. */
+	if (str_devname == NULL) {
+		str_devname = "altera_avgen%d";
+		devunit = sc->avg_unit;
+	}
+	if (devunit != -1)
+		sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit, UID_ROOT,
+		    GID_WHEEL, S_IRUSR | S_IWUSR, str_devname, devunit);
+	else
+		sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit, UID_ROOT,
+		    GID_WHEEL, S_IRUSR | S_IWUSR, str_devname);
+	if (sc->avg_cdev == NULL) {
+		device_printf(sc->avg_dev, "%s: make_dev failed\n", __func__);
+		return (ENXIO);
+	}
+	/* XXXRW: Slight race between make_dev(9) and here. */
+	sc->avg_cdev->si_drv1 = sc;
+	return (0);
+}
+
+void
+altera_avgen_detach(struct altera_avgen_softc *sc)
+{
+
+	destroy_dev(sc->avg_cdev);
+}


Property changes on: trunk/sys/dev/altera/avgen/altera_avgen.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/avgen/altera_avgen.h
===================================================================
--- trunk/sys/dev/altera/avgen/altera_avgen.h	                        (rev 0)
+++ trunk/sys/dev/altera/avgen/altera_avgen.h	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,88 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/altera/avgen/altera_avgen.h 245380 2013-01-13 16:57:11Z rwatson $
+ */
+
+#ifndef _DEV_ALTERA_AVALON_H_
+#define	_DEV_ALTERA_AVALON_H_
+
+struct altera_avgen_softc {
+	/*
+	 * Bus-related fields.
+	 */
+	device_t	 avg_dev;
+	int		 avg_unit;
+
+	/*
+	 * The device node and memory-mapped I/O region.
+	 */
+	struct cdev	*avg_cdev;
+	struct resource	*avg_res;
+	int		 avg_rid;
+
+	/*
+	 * Access properties configured by device.hints.
+	 */
+	u_int		 avg_flags;
+	u_int		 avg_width;
+};
+
+/*
+ * Various flags extracted from device.hints to configure operations on the
+ * device.
+ */
+#define	ALTERA_AVALON_FLAG_READ			0x01
+#define	ALTERA_AVALON_FLAG_WRITE		0x02
+#define	ALTERA_AVALON_FLAG_MMAP_READ		0x04
+#define	ALTERA_AVALON_FLAG_MMAP_WRITE		0x08
+#define	ALTERA_AVALON_FLAG_MMAP_EXEC		0x10
+
+#define	ALTERA_AVALON_CHAR_READ			'r'
+#define	ALTERA_AVALON_CHAR_WRITE		'w'
+#define	ALTERA_AVALON_CHAR_EXEC			'x'
+
+#define	ALTERA_AVALON_STR_WIDTH			"width"
+#define	ALTERA_AVALON_STR_FILEIO		"fileio"
+#define	ALTERA_AVALON_STR_MMAPIO		"mmapio"
+#define ALTERA_AVALON_STR_DEVNAME		"devname"
+#define	ALTERA_AVALON_STR_DEVUNIT		"devunit"
+
+/*
+ * Driver setup routines from the bus attachment/teardown.
+ */
+int	altera_avgen_attach(struct altera_avgen_softc *sc,
+	    const char *str_fileio, const char *str_mmapio,
+	    const char *str_devname, int devunit);
+void	altera_avgen_detach(struct altera_avgen_softc *sc);
+
+extern devclass_t	altera_avgen_devclass;
+
+#endif /* _DEV_ALTERA_AVALON_H_ */


Property changes on: trunk/sys/dev/altera/avgen/altera_avgen.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/avgen/altera_avgen_fdt.c
===================================================================
--- trunk/sys/dev/altera/avgen/altera_avgen_fdt.c	                        (rev 0)
+++ trunk/sys/dev/altera/avgen/altera_avgen_fdt.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,158 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/avgen/altera_avgen_fdt.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+static int
+altera_avgen_fdt_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_is_compatible(dev, "sri-cambridge,avgen")) {
+		device_set_desc(dev, "Generic Altera Avalon device attachment");
+		return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+static int
+altera_avgen_fdt_attach(device_t dev)
+{
+	struct altera_avgen_softc *sc;
+	char *str_fileio, *str_mmapio;
+	char *str_devname;
+	phandle_t node;
+	pcell_t cell;
+	int devunit, error;
+
+	sc = device_get_softc(dev);
+	sc->avg_dev = dev;
+	sc->avg_unit = device_get_unit(dev);
+
+	/*
+	 * Query driver-specific OpenFirmware properties to determine how to
+	 * expose the device via /dev.
+	 */
+	str_fileio = NULL;
+	str_mmapio = NULL;
+	str_devname = NULL;
+	devunit = -1;
+	sc->avg_width = 1;
+	node = ofw_bus_get_node(dev);
+	if (OF_getprop(node, "sri-cambridge,width", &cell, sizeof(cell)) > 0)
+		sc->avg_width = cell;
+	(void)OF_getprop_alloc(node, "sri-cambridge,fileio", sizeof(char),
+	    (void **)&str_fileio);
+	(void)OF_getprop_alloc(node, "sri-cambridge,mmapio", sizeof(char),
+	    (void **)&str_mmapio);
+	(void)OF_getprop_alloc(node,  "sri-cambridge,devname", sizeof(char),
+	    (void **)&str_devname);
+	if (OF_getprop(node, "sri-cambridge,devunit", &cell, sizeof(cell)) > 0)
+		devunit = cell;
+
+	/* Memory allocation and checking. */
+	sc->avg_rid = 0;
+	sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->avg_rid, RF_ACTIVE);
+	if (sc->avg_res == NULL) {
+		device_printf(dev, "couldn't map memory\n");
+		return (ENXIO);
+	}
+	error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+	    devunit);
+	if (error != 0)
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+		    sc->avg_res);
+	if (str_fileio != NULL)
+		free(str_fileio, M_OFWPROP);
+	if (str_mmapio != NULL)
+		free(str_mmapio, M_OFWPROP);
+	if (str_devname != NULL)
+		free(str_devname, M_OFWPROP);
+	return (error);
+}
+
+static int
+altera_avgen_fdt_detach(device_t dev)
+{
+	struct altera_avgen_softc *sc;
+
+	sc = device_get_softc(dev);
+	altera_avgen_detach(sc);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+	return (0);
+}
+
+static device_method_t altera_avgen_fdt_methods[] = {
+	DEVMETHOD(device_probe,		altera_avgen_fdt_probe),
+	DEVMETHOD(device_attach,	altera_avgen_fdt_attach),
+	DEVMETHOD(device_detach,	altera_avgen_fdt_detach),
+	{ 0, 0 }
+};
+
+static driver_t altera_avgen_fdt_driver = {
+	"altera_avgen",
+	altera_avgen_fdt_methods,
+	sizeof(struct altera_avgen_softc),
+};
+
+DRIVER_MODULE(avgen, simplebus, altera_avgen_fdt_driver,
+    altera_avgen_devclass, 0, 0);


Property changes on: trunk/sys/dev/altera/avgen/altera_avgen_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/avgen/altera_avgen_nexus.c
===================================================================
--- trunk/sys/dev/altera/avgen/altera_avgen_nexus.c	                        (rev 0)
+++ trunk/sys/dev/altera/avgen/altera_avgen_nexus.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,142 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012-2013 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/avgen/altera_avgen_nexus.c 265999 2014-05-14 01:35:43Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/stat.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/vm.h>
+
+#include <vm/vm.h>
+
+#include <dev/altera/avgen/altera_avgen.h>
+
+static int
+altera_avgen_nexus_probe(device_t dev)
+{
+
+	device_set_desc(dev, "Generic Altera Avalon device attachment");
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+altera_avgen_nexus_attach(device_t dev)
+{
+	struct altera_avgen_softc *sc;
+	const char *str_fileio, *str_mmapio;
+	const char *str_devname;
+	int devunit, error;
+
+	sc = device_get_softc(dev);
+	sc->avg_dev = dev;
+	sc->avg_unit = device_get_unit(dev);
+
+	/*
+	 * Query non-standard hints to find out what operations are permitted
+	 * on the device, and whether it is cached.
+	 */
+	str_fileio = NULL;
+	str_mmapio = NULL;
+	str_devname = NULL;
+	devunit = -1;
+	sc->avg_width = 1;
+	error = resource_int_value(device_get_name(dev), device_get_unit(dev),
+	    ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
+	if (error != 0 && error != ENOENT) {
+		device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
+		return (error);
+	}
+	(void)resource_string_value(device_get_name(dev),
+	    device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
+	(void)resource_string_value(device_get_name(dev),
+	    device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
+	(void)resource_string_value(device_get_name(dev),
+	    device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
+	(void)resource_int_value(device_get_name(dev), device_get_unit(dev),
+	    ALTERA_AVALON_STR_DEVUNIT, &devunit);
+
+	/* Memory allocation and checking. */
+	sc->avg_rid = 0;
+	sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->avg_rid, RF_ACTIVE);
+	if (sc->avg_res == NULL) {
+		device_printf(dev, "couldn't map memory\n");
+		return (ENXIO);
+	}
+	error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+	    devunit);
+	if (error != 0)
+		bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+		    sc->avg_res);
+	return (error);
+}
+
+static int
+altera_avgen_nexus_detach(device_t dev)
+{
+	struct altera_avgen_softc *sc;
+
+	sc = device_get_softc(dev);
+	altera_avgen_detach(sc);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+	return (0);
+}
+
+static device_method_t altera_avgen_nexus_methods[] = {
+	DEVMETHOD(device_probe,		altera_avgen_nexus_probe),
+	DEVMETHOD(device_attach,	altera_avgen_nexus_attach),
+	DEVMETHOD(device_detach,	altera_avgen_nexus_detach),
+	{ 0, 0 }
+};
+
+static driver_t altera_avgen_nexus_driver = {
+	"altera_avgen",
+	altera_avgen_nexus_methods,
+	sizeof(struct altera_avgen_softc),
+};
+
+DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass,
+    0, 0);


Property changes on: trunk/sys/dev/altera/avgen/altera_avgen_nexus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart.h
===================================================================
--- trunk/sys/dev/altera/jtag_uart/altera_jtag_uart.h	                        (rev 0)
+++ trunk/sys/dev/altera/jtag_uart/altera_jtag_uart.h	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,200 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/altera/jtag_uart/altera_jtag_uart.h 250113 2013-04-30 18:29:05Z brooks $
+ */
+
+#ifndef _DEV_ALTERA_JTAG_UART_H_
+#define	_DEV_ALTERA_JTAG_UART_H_
+
+struct altera_jtag_uart_softc {
+	device_t		 ajus_dev;
+	int			 ajus_unit;
+
+	/*
+	 * Hardware resources.
+	 */
+	struct resource		*ajus_irq_res;
+	int			 ajus_irq_rid;
+	void			*ajus_irq_cookie;
+	struct resource		*ajus_mem_res;
+	int			 ajus_mem_rid;
+
+	/*
+	 * TTY resources.
+	 */
+	struct tty		*ajus_ttyp;
+	int			 ajus_alt_break_state;
+
+	/*
+	 * Driver resources.
+	 */
+	u_int			 ajus_flags;
+	struct mtx		*ajus_lockp;
+	struct mtx		 ajus_lock;
+	struct callout		 ajus_io_callout;
+	struct callout		 ajus_ac_callout;
+
+	/*
+	 * One-character buffer required because it's not possible to peek at
+	 * the input FIFO without reading it.
+	 */
+	int			 ajus_buffer_valid;
+	int			*ajus_buffer_validp;
+	uint8_t			 ajus_buffer_data;
+	uint8_t			*ajus_buffer_datap;
+	int			 ajus_jtag_present;
+	int			*ajus_jtag_presentp;
+	u_int			 ajus_jtag_missed;
+	u_int			*ajus_jtag_missedp;
+};
+
+#define	AJU_TTYNAME	"ttyj"
+
+/*
+ * Flag values for ajus_flags.
+ */
+#define	ALTERA_JTAG_UART_FLAG_CONSOLE	0x00000001	/* Is console. */
+
+/*
+ * Because tty-level use of the I/O ports completes with low-level console
+ * use, spinlocks must be employed here.
+ */
+#define	AJU_CONSOLE_LOCK_INIT() do {					\
+	mtx_init(&aju_cons_lock, "aju_cons_lock", NULL, MTX_SPIN);	\
+} while (0)
+
+#define	AJU_CONSOLE_LOCK() do {						\
+	if (!kdb_active)						\
+		mtx_lock_spin(&aju_cons_lock);				\
+} while (0)
+
+#define	AJU_CONSOLE_LOCK_ASSERT() {					\
+	if (!kdb_active)						\
+		mtx_assert(&aju_cons_lock, MA_OWNED);			\
+} while (0)
+
+#define	AJU_CONSOLE_UNLOCK() do {					\
+	if (!kdb_active)						\
+		mtx_unlock_spin(&aju_cons_lock);			\
+} while (0)
+
+#define	AJU_LOCK_INIT(sc) do {						\
+	mtx_init(&(sc)->ajus_lock, "aju_lock", NULL, MTX_SPIN);		\
+} while (0)
+
+#define	AJU_LOCK_DESTROY(sc) do {					\
+	mtx_destroy(&(sc)->ajus_lock);					\
+} while (0)
+
+#define	AJU_LOCK(sc) do {						\
+	mtx_lock_spin((sc)->ajus_lockp);				\
+} while (0)
+
+#define	AJU_LOCK_ASSERT(sc) do {					\
+	mtx_assert((sc)->ajus_lockp, MA_OWNED);				\
+} while (0)
+
+#define	AJU_UNLOCK(sc) do {						\
+	mtx_unlock_spin((sc)->ajus_lockp);				\
+} while (0)
+
+/*
+ * When a TTY-level Altera JTAG UART instance is also the low-level console,
+ * the TTY layer borrows the console-layer lock and buffer rather than using
+ * its own.
+ */
+extern struct mtx	aju_cons_lock;
+extern char  		aju_cons_buffer_data;
+extern int		aju_cons_buffer_valid;
+extern int		aju_cons_jtag_present;
+extern u_int		aju_cons_jtag_missed;
+
+/*
+ * Base physical address of the JTAG UART in BERI.
+ */
+#define	BERI_UART_BASE		0x7f000000	/* JTAG UART */
+
+/*-
+ * Routines for interacting with the BERI console JTAG UART.  Programming
+ * details from the June 2011 "Embedded Peripherals User Guide" by Altera
+ * Corporation, tables 6-2 (JTAG UART Core Register Map), 6-3 (Data Register
+ * Bits), and 6-4 (Control Register Bits).
+ *
+ * Offsets of data and control registers relative to the base.  Altera
+ * conventions are maintained in BERI.
+ */
+#define	ALTERA_JTAG_UART_DATA_OFF	0x00000000
+#define	ALTERA_JTAG_UART_CONTROL_OFF	0x00000004
+
+/*
+ * Offset 0: 'data' register -- bits 31-16 (RAVAIL), 15 (RVALID),
+ * 14-8 (Reserved), 7-0 (DATA).
+ *
+ * DATA - One byte read or written.
+ * RAVAIL - Bytes available to read (excluding the current byte).
+ * RVALID - Whether the byte in DATA is valid.
+ */
+#define	ALTERA_JTAG_UART_DATA_DATA		0x000000ff
+#define	ALTERA_JTAG_UART_DATA_RESERVED		0x00007f00
+#define	ALTERA_JTAG_UART_DATA_RVALID		0x00008000
+#define	ALTERA_JTAG_UART_DATA_RAVAIL		0xffff0000
+#define	ALTERA_JTAG_UART_DATA_RAVAIL_SHIFT	16
+
+/*-
+ * Offset 1: 'control' register -- bits 31-16 (WSPACE), 15-11 (Reserved),
+ * 10 (AC), 9 (WI), 8 (RI), 7..2 (Reserved), 1 (WE), 0 (RE).
+ *
+ * RE - Enable read interrupts.
+ * WE - Enable write interrupts.
+ * RI - Read interrupt pending.
+ * WI - Write interrupt pending.
+ * AC - Activity bit; set to '1' to clear to '0'.
+ * WSPACE - Space available in the write FIFO.
+ */
+#define	ALTERA_JTAG_UART_CONTROL_RE		0x00000001
+#define	ALTERA_JTAG_UART_CONTROL_WE		0x00000002
+#define	ALTERA_JTAG_UART_CONTROL_RESERVED0	0x000000fc
+#define	ALTERA_JTAG_UART_CONTROL_RI		0x00000100
+#define	ALTERA_JTAG_UART_CONTROL_WI		0x00000200
+#define	ALTERA_JTAG_UART_CONTROL_AC		0x00000400
+#define	ALTERA_JTAG_UART_CONTROL_RESERVED1	0x0000f800
+#define	ALTERA_JTAG_UART_CONTROL_WSPACE		0xffff0000
+#define	ALTERA_JTAG_UART_CONTROL_WSPACE_SHIFT	16
+
+/*
+ * Driver attachment functions for Nexus.
+ */
+int	altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc);
+void	altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc);
+
+extern devclass_t	altera_jtag_uart_devclass;
+
+#endif /* _DEV_ALTERA_JTAG_UART_H_ */


Property changes on: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
===================================================================
--- trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c	                        (rev 0)
+++ trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,325 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c 275429 2014-12-02 22:04:27Z brooks $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/reboot.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+
+#include <ddb/ddb.h>
+
+#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+
+devclass_t	altera_jtag_uart_devclass;
+
+/*
+ * One-byte buffer as we can't check whether the UART is readable without
+ * actually reading from it, synchronised by a spinlock; this lock also
+ * synchronises access to the I/O ports for non-atomic sequences.  These
+ * symbols are public so that the TTY layer can use them when working on an
+ * instance of the UART that is also a low-level console.
+ */
+char		aju_cons_buffer_data;
+int		aju_cons_buffer_valid;
+int		aju_cons_jtag_present;
+u_int		aju_cons_jtag_missed;
+struct mtx	aju_cons_lock;
+
+/*
+ * Low-level console driver functions.
+ */
+static cn_probe_t	aju_cnprobe;
+static cn_init_t	aju_cninit;
+static cn_term_t	aju_cnterm;
+static cn_getc_t	aju_cngetc;
+static cn_putc_t	aju_cnputc;
+static cn_grab_t	aju_cngrab;
+static cn_ungrab_t	aju_cnungrab;
+
+/*
+ * JTAG sets the ALTERA_JTAG_UART_CONTROL_AC bit whenever it accesses the
+ * FIFO.  This allows us to (sort of) tell when JTAG is present, so that we
+ * can adopt lossy, rather than blocking, behaviour when JTAG isn't there.
+ * When it is present, we do full flow control.  This delay is how long we
+ * wait to see if JTAG has really disappeared when finding a full buffer and
+ * no AC bit set.
+ */
+#define	ALTERA_JTAG_UART_AC_POLL_DELAY	10000
+
+/*
+ * I/O routines lifted from Deimos.  This is not only MIPS-specific, but also
+ * BERI-specific, as we're hard coding the address at which we expect to
+ * find the Altera JTAG UART and using it unconditionally.  We use these
+ * low-level routines so that we can perform console I/O long before newbus
+ * has initialised and devices have attached.  The TTY layer of the driver
+ * knows about this, and uses the console-layer spinlock instead of the
+ * TTY-layer lock to avoid confusion between layers for the console UART.
+ *
+ * XXXRW: The only place this inter-layer behaviour breaks down is if the
+ * low-level console is used for polled read while the TTY driver is also
+ * looking for input.  Probably we should also share buffers between layers.
+ */
+#define	MIPS_XKPHYS_UNCACHED_BASE	0x9000000000000000
+
+typedef	uint64_t	paddr_t;
+typedef	uint64_t	vaddr_t;
+
+static inline vaddr_t
+mips_phys_to_uncached(paddr_t phys)            
+{
+
+	return (phys | MIPS_XKPHYS_UNCACHED_BASE);
+}
+
+static inline uint32_t
+mips_ioread_uint32(vaddr_t vaddr)
+{
+	uint32_t v;
+
+	__asm__ __volatile__ ("lw %0, 0(%1)" : "=r" (v) : "r" (vaddr));
+	return (v);
+}
+
+static inline void
+mips_iowrite_uint32(vaddr_t vaddr, uint32_t v)
+{
+
+	__asm__ __volatile__ ("sw %0, 0(%1)" : : "r" (v), "r" (vaddr));
+}
+
+/*
+ * Little-endian versions of 32-bit I/O routines.
+ */
+static inline uint32_t
+mips_ioread_uint32le(vaddr_t vaddr)
+{
+
+	return (le32toh(mips_ioread_uint32(vaddr)));
+}
+
+static inline void
+mips_iowrite_uint32le(vaddr_t vaddr, uint32_t v)
+{
+
+	mips_iowrite_uint32(vaddr, htole32(v));
+}
+
+/*
+ * Low-level read and write register routines; the Altera UART is little
+ * endian, so we byte swap 32-bit reads and writes.
+ */
+static inline uint32_t
+aju_cons_data_read(void)
+{
+
+	return (mips_ioread_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
+	    ALTERA_JTAG_UART_DATA_OFF)));
+}
+
+static inline void
+aju_cons_data_write(uint32_t v)
+{
+
+	mips_iowrite_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
+	    ALTERA_JTAG_UART_DATA_OFF), v);
+}
+
+static inline uint32_t
+aju_cons_control_read(void)
+{
+
+	return (mips_ioread_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
+	    ALTERA_JTAG_UART_CONTROL_OFF)));
+}
+
+static inline void
+aju_cons_control_write(uint32_t v)
+{
+
+	mips_iowrite_uint32le(mips_phys_to_uncached(BERI_UART_BASE +
+	    ALTERA_JTAG_UART_CONTROL_OFF), v);
+}
+
+/*
+ * Slightly higher-level routines aware of buffering and flow control.
+ */
+static int
+aju_cons_readable(void)
+{
+	uint32_t v;
+
+	AJU_CONSOLE_LOCK_ASSERT();
+
+	if (aju_cons_buffer_valid)
+		return (1);
+	v = aju_cons_data_read();
+	if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
+		aju_cons_buffer_valid = 1;
+		aju_cons_buffer_data = (v & ALTERA_JTAG_UART_DATA_DATA);
+		return (1);
+	}
+	return (0);
+}
+
+static void
+aju_cons_write(char ch)
+{
+	uint32_t v;
+
+	AJU_CONSOLE_LOCK_ASSERT();
+
+	/*
+	 * The flow control logic here is somewhat subtle: we want to wait for
+	 * write buffer space only while JTAG is present.  However, we can't
+	 * directly ask if JTAG is present -- just whether it's been seen
+	 * since we last cleared the ALTERA_JTAG_UART_CONTROL_AC bit.  As
+	 * such, implement a polling loop in which we both wait for space and
+	 * try to decide whether JTAG has disappeared on us.  We will have to
+	 * wait one complete polling delay to detect that JTAG has gone away,
+	 * but otherwise shouldn't wait any further once it has gone.  And we
+	 * had to wait for buffer space anyway, if it was there.
+	 *
+	 * If JTAG is spotted, reset the TTY-layer miss counter so console-
+	 * layer clearing of the bit doesn't trigger a TTY-layer
+	 * disconnection.
+	 *
+	 * XXXRW: The polling delay may require tuning.
+	 *
+	 * XXXRW: Notice the inherent race with hardware: in clearing the
+	 * bit, we may race with hardware setting the same bit.
+	 */
+	v = aju_cons_control_read();
+	if (v & ALTERA_JTAG_UART_CONTROL_AC) {
+		aju_cons_jtag_present = 1;
+		aju_cons_jtag_missed = 0;
+		v &= ~ALTERA_JTAG_UART_CONTROL_AC;
+		aju_cons_control_write(v);
+	}
+	while ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) == 0) {
+		if (!aju_cons_jtag_present)
+			return;
+		DELAY(ALTERA_JTAG_UART_AC_POLL_DELAY);
+		v = aju_cons_control_read();
+		if (v & ALTERA_JTAG_UART_CONTROL_AC) {
+			aju_cons_jtag_present = 1;
+			v &= ~ALTERA_JTAG_UART_CONTROL_AC;
+			aju_cons_control_write(v);
+		} else
+			aju_cons_jtag_present = 0;
+	}
+	aju_cons_data_write(ch);
+}
+
+static char
+aju_cons_read(void)
+{
+
+	AJU_CONSOLE_LOCK_ASSERT();
+
+	while (!aju_cons_readable());
+	aju_cons_buffer_valid = 0;
+	return (aju_cons_buffer_data);
+}
+
+/*
+ * Implementation of a FreeBSD low-level, polled console driver.
+ */
+static void
+aju_cnprobe(struct consdev *cp)
+{
+
+	sprintf(cp->cn_name, "%s%d", AJU_TTYNAME, 0);
+	cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL;
+}
+
+static void
+aju_cninit(struct consdev *cp)
+{
+	uint32_t v;
+
+	AJU_CONSOLE_LOCK_INIT();
+
+	AJU_CONSOLE_LOCK();
+	v = aju_cons_control_read();
+	v &= ~ALTERA_JTAG_UART_CONTROL_AC;
+	aju_cons_control_write(v);
+	AJU_CONSOLE_UNLOCK();
+}
+
+static void
+aju_cnterm(struct consdev *cp)
+{
+
+}
+
+static int
+aju_cngetc(struct consdev *cp)
+{
+	int ret;
+
+	AJU_CONSOLE_LOCK();
+	ret = aju_cons_read();
+	AJU_CONSOLE_UNLOCK();
+	return (ret);
+}
+
+static void
+aju_cnputc(struct consdev *cp, int c)
+{
+
+	AJU_CONSOLE_LOCK();
+	aju_cons_write(c);
+	AJU_CONSOLE_UNLOCK();
+}
+
+static void
+aju_cngrab(struct consdev *cp)
+{
+
+}
+
+static void
+aju_cnungrab(struct consdev *cp)
+{
+
+}
+
+CONSOLE_DRIVER(aju);


Property changes on: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
===================================================================
--- trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c	                        (rev 0)
+++ trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,151 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * FDT bus attachment for Altera JTAG UARTs.
+ */
+static int
+altera_jtag_uart_fdt_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_is_compatible(dev, "altera,jtag_uart-11_0")) {
+		device_set_desc(dev, "Altera JTAG UART");
+		return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+static int
+altera_jtag_uart_fdt_attach(device_t dev)
+{
+	struct altera_jtag_uart_softc *sc;
+	int error;
+
+	error = 0;
+	sc = device_get_softc(dev);
+	sc->ajus_dev = dev;
+	sc->ajus_unit = device_get_unit(dev);
+	sc->ajus_mem_rid = 0;
+	sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->ajus_mem_rid, RF_ACTIVE);
+	if (sc->ajus_mem_res == NULL) {
+		device_printf(dev, "couldn't map memory\n");
+		error = ENXIO;
+		goto out;
+	}
+
+	/*
+	 * Interrupt support is optional -- if we can't allocate an IRQ, then
+	 * we fall back on polling.
+	 */
+	sc->ajus_irq_rid = 0;
+	sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+	if (sc->ajus_irq_res == NULL)
+		device_printf(dev,
+		    "IRQ unavailable; selecting polled operation\n");
+	error = altera_jtag_uart_attach(sc);
+out:
+	if (error) {
+		if (sc->ajus_irq_res != NULL)
+			bus_release_resource(dev, SYS_RES_IRQ,
+			    sc->ajus_irq_rid, sc->ajus_irq_res);
+		if (sc->ajus_mem_res != NULL)
+			bus_release_resource(dev, SYS_RES_MEMORY,
+			    sc->ajus_mem_rid, sc->ajus_mem_res);
+	}
+	return (error);
+}
+
+static int
+altera_jtag_uart_fdt_detach(device_t dev)
+{
+	struct altera_jtag_uart_softc *sc;
+
+	sc = device_get_softc(dev);
+	KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated",
+	    __func__));
+
+	altera_jtag_uart_detach(sc);
+	bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid,
+	    sc->ajus_irq_res);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid,
+	    sc->ajus_mem_res);
+	return (0);
+}
+
+static device_method_t altera_jtag_uart_fdt_methods[] = {
+	DEVMETHOD(device_probe,		altera_jtag_uart_fdt_probe),
+	DEVMETHOD(device_attach,	altera_jtag_uart_fdt_attach),
+	DEVMETHOD(device_detach,	altera_jtag_uart_fdt_detach),
+	{ 0, 0 }
+};
+
+static driver_t altera_jtag_uart_fdt_driver = {
+	"altera_jtag_uart",
+	altera_jtag_uart_fdt_methods,
+	sizeof(struct altera_jtag_uart_softc),
+};
+
+DRIVER_MODULE(altera_jtag_uart, simplebus, altera_jtag_uart_fdt_driver,
+    altera_jtag_uart_devclass, 0, 0);


Property changes on: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
===================================================================
--- trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c	                        (rev 0)
+++ trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,142 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c 265999 2014-05-14 01:35:43Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+
+/*
+ * Nexus bus attachment for Altera JTAG UARTs.  Appropriate for most Altera
+ * FPGA SoC-style configurations in which the IP core will be exposed to the
+ * processor via a memory-mapped Avalon bus.
+ */
+static int
+altera_jtag_uart_nexus_probe(device_t dev)
+{
+
+	device_set_desc(dev, "Altera JTAG UART");
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+altera_jtag_uart_nexus_attach(device_t dev)
+{
+	struct altera_jtag_uart_softc *sc;
+	int error;
+
+	error = 0;
+	sc = device_get_softc(dev);
+	sc->ajus_dev = dev;
+	sc->ajus_unit = device_get_unit(dev);
+	sc->ajus_mem_rid = 0;
+	sc->ajus_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->ajus_mem_rid, RF_ACTIVE);
+	if (sc->ajus_mem_res == NULL) {
+		device_printf(dev, "couldn't map memory\n");
+		error = ENXIO;
+		goto out;
+	}
+
+	/*
+	 * Interrupt support is optional -- if we can't allocate an IRQ, then
+	 * we fall back on polling.
+	 */
+	sc->ajus_irq_rid = 0;
+	sc->ajus_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+	    &sc->ajus_irq_rid, RF_ACTIVE | RF_SHAREABLE);
+	if (sc->ajus_irq_res == NULL)
+		device_printf(dev,
+		    "IRQ unavailable; selecting polled operation\n");
+	error = altera_jtag_uart_attach(sc);
+out:
+	if (error) {
+		if (sc->ajus_irq_res != NULL)
+			bus_release_resource(dev, SYS_RES_IRQ,
+			    sc->ajus_irq_rid, sc->ajus_irq_res);
+		if (sc->ajus_mem_res != NULL)
+			bus_release_resource(dev, SYS_RES_MEMORY,
+			    sc->ajus_mem_rid, sc->ajus_mem_res);
+	}
+	return (error);
+}
+
+static int
+altera_jtag_uart_nexus_detach(device_t dev)
+{
+	struct altera_jtag_uart_softc *sc;
+
+	sc = device_get_softc(dev);
+	KASSERT(sc->ajus_mem_res != NULL, ("%s: resources not allocated",
+	    __func__));
+
+	altera_jtag_uart_detach(sc);
+	bus_release_resource(dev, SYS_RES_IRQ, sc->ajus_irq_rid,
+	    sc->ajus_irq_res);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->ajus_mem_rid,
+	    sc->ajus_mem_res);
+	return (0);
+}
+
+static device_method_t altera_jtag_uart_nexus_methods[] = {
+	DEVMETHOD(device_probe,		altera_jtag_uart_nexus_probe),
+	DEVMETHOD(device_attach,	altera_jtag_uart_nexus_attach),
+	DEVMETHOD(device_detach,	altera_jtag_uart_nexus_detach),
+	{ 0, 0 }
+};
+
+static driver_t altera_jtag_uart_nexus_driver = {
+	"altera_jtag_uart",
+	altera_jtag_uart_nexus_methods,
+	sizeof(struct altera_jtag_uart_softc),
+};
+
+DRIVER_MODULE(altera_jtag_uart, nexus, altera_jtag_uart_nexus_driver,
+    altera_jtag_uart_devclass, 0, 0);


Property changes on: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c
===================================================================
--- trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c	                        (rev 0)
+++ trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,491 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2011-2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c 314667 2017-03-04 13:03:31Z avg $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cons.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+#include <sys/tty.h>
+
+#include <ddb/ddb.h>
+
+#include <machine/bus.h>
+
+#include <dev/altera/jtag_uart/altera_jtag_uart.h>
+
+/*
+ * If one of the Altera JTAG UARTs is currently the system console, register
+ * it here.
+ */
+static struct altera_jtag_uart_softc	*aju_cons_sc;
+
+static tsw_outwakeup_t	aju_outwakeup;
+static void		aju_ac_callout(void *);
+static void		aju_io_callout(void *);
+
+static struct ttydevsw aju_ttydevsw = {
+	.tsw_flags	= TF_NOPREFIX,
+	.tsw_outwakeup	= aju_outwakeup,
+};
+
+/*
+ * When polling for the AC bit, the number of times we have to not see it
+ * before assuming JTAG has disappeared on us.  By default, two seconds.
+ */
+#define	AJU_JTAG_MAXMISS		10
+
+/*
+ * Polling intervals for input/output and JTAG connection events.
+ */
+#define	AJU_IO_POLLINTERVAL		(hz/100)
+#define	AJU_AC_POLLINTERVAL		(hz/5)
+
+/*
+ * Low-level read and write register routines; the Altera UART is little
+ * endian, so we byte swap 32-bit reads and writes.
+ */
+static inline uint32_t
+aju_data_read(struct altera_jtag_uart_softc *sc)
+{
+
+	return (le32toh(bus_read_4(sc->ajus_mem_res,
+	    ALTERA_JTAG_UART_DATA_OFF)));
+}
+
+static inline void
+aju_data_write(struct altera_jtag_uart_softc *sc, uint32_t v)
+{
+
+	bus_write_4(sc->ajus_mem_res, ALTERA_JTAG_UART_DATA_OFF, htole32(v));
+}
+
+static inline uint32_t
+aju_control_read(struct altera_jtag_uart_softc *sc)
+{
+
+	return (le32toh(bus_read_4(sc->ajus_mem_res,
+	    ALTERA_JTAG_UART_CONTROL_OFF)));
+}
+
+static inline void
+aju_control_write(struct altera_jtag_uart_softc *sc, uint32_t v)
+{
+
+	bus_write_4(sc->ajus_mem_res, ALTERA_JTAG_UART_CONTROL_OFF,
+	    htole32(v));
+}
+
+/*
+ * Slightly higher-level routines aware of buffering and flow control.
+ */
+static inline int
+aju_writable(struct altera_jtag_uart_softc *sc)
+{
+
+	return ((aju_control_read(sc) &
+	    ALTERA_JTAG_UART_CONTROL_WSPACE) != 0);
+}
+
+static inline int
+aju_readable(struct altera_jtag_uart_softc *sc)
+{
+	uint32_t v;
+
+	AJU_LOCK_ASSERT(sc);
+
+	if (*sc->ajus_buffer_validp)
+		return (1);
+	v = aju_data_read(sc);
+	if ((v & ALTERA_JTAG_UART_DATA_RVALID) != 0) {
+		*sc->ajus_buffer_validp = 1;
+		*sc->ajus_buffer_datap = (v & ALTERA_JTAG_UART_DATA_DATA);
+		return (1);
+	}
+	return (0);
+}
+
+static char
+aju_read(struct altera_jtag_uart_softc *sc)
+{
+
+	AJU_LOCK_ASSERT(sc);
+
+	while (!aju_readable(sc));
+	*sc->ajus_buffer_validp = 0;
+	return (*sc->ajus_buffer_datap);
+}
+
+/*
+ * Routines for enabling and disabling interrupts for read and write.
+ */
+static void
+aju_intr_readable_enable(struct altera_jtag_uart_softc *sc)
+{
+	uint32_t v;
+
+	AJU_LOCK_ASSERT(sc);
+
+	v = aju_control_read(sc);
+	v |= ALTERA_JTAG_UART_CONTROL_RE;
+	aju_control_write(sc, v);
+}
+
+static void
+aju_intr_writable_enable(struct altera_jtag_uart_softc *sc)
+{
+	uint32_t v;
+
+	AJU_LOCK_ASSERT(sc);
+
+	v = aju_control_read(sc);
+	v |= ALTERA_JTAG_UART_CONTROL_WE;
+	aju_control_write(sc, v);
+}
+
+static void
+aju_intr_writable_disable(struct altera_jtag_uart_softc *sc)
+{
+	uint32_t v;
+
+	AJU_LOCK_ASSERT(sc);
+
+	v = aju_control_read(sc);
+	v &= ~ALTERA_JTAG_UART_CONTROL_WE;
+	aju_control_write(sc, v);
+}
+
+static void
+aju_intr_disable(struct altera_jtag_uart_softc *sc)
+{
+	uint32_t v;
+
+	AJU_LOCK_ASSERT(sc);
+
+	v = aju_control_read(sc);
+	v &= ~(ALTERA_JTAG_UART_CONTROL_RE | ALTERA_JTAG_UART_CONTROL_WE);
+	aju_control_write(sc, v);
+}
+
+/*
+ * The actual work of checking for, and handling, available reads.  This is
+ * used in both polled and interrupt-driven modes, as JTAG UARTs may be hooked
+ * up with, or without, IRQs allocated.
+ */
+static void
+aju_handle_input(struct altera_jtag_uart_softc *sc, struct tty *tp)
+{
+	int c;
+
+	tty_lock_assert(tp, MA_OWNED);
+	AJU_LOCK_ASSERT(sc);
+
+	while (aju_readable(sc)) {
+		c = aju_read(sc);
+		AJU_UNLOCK(sc);
+#ifdef KDB
+		if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE)
+			kdb_alt_break(c, &sc->ajus_alt_break_state);
+#endif
+		ttydisc_rint(tp, c, 0);
+		AJU_LOCK(sc);
+	}
+	AJU_UNLOCK(sc);
+	ttydisc_rint_done(tp);
+	AJU_LOCK(sc);
+}
+
+/*
+ * Send output to the UART until either there's none left to send, or we run
+ * out of room and need to await an interrupt so that we can start sending
+ * again.
+ *
+ * XXXRW: It would be nice to query WSPACE at the beginning and write to the
+ * FIFO in bugger chunks.
+ */
+static void
+aju_handle_output(struct altera_jtag_uart_softc *sc, struct tty *tp)
+{
+	uint32_t v;
+	uint8_t ch;
+
+	tty_lock_assert(tp, MA_OWNED);
+	AJU_LOCK_ASSERT(sc);
+
+	AJU_UNLOCK(sc);
+	while (ttydisc_getc_poll(tp) != 0) {
+		AJU_LOCK(sc);
+		v = aju_control_read(sc);
+		if ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) != 0) {
+			AJU_UNLOCK(sc);
+			if (ttydisc_getc(tp, &ch, sizeof(ch)) != sizeof(ch))
+				panic("%s: ttydisc_getc", __func__);
+			AJU_LOCK(sc);
+
+			/*
+			 * XXXRW: There is a slight race here in which we test
+			 * for writability, drop the lock, get the character
+			 * from the tty layer, re-acquire the lock, and then
+			 * write.  It's possible for other code --
+			 * specifically, the low-level console -- to have
+			 * written in the mean time, which might mean that
+			 * there is no longer space.  The BERI memory bus will
+			 * cause this write to block, wedging the processor
+			 * until space is available -- which could be a while
+			 * if JTAG is not attached!
+			 *
+			 * The 'easy' fix is to drop the character if WSPACE
+			 * has become unset.  Not sure what the 'hard' fix is.
+			 */
+			aju_data_write(sc, ch);
+		} else {
+			/*
+			 * If JTAG is not present, then we will drop this
+			 * character instead of perhaps scheduling an
+			 * interrupt to let us know when there is buffer
+			 * space.  Otherwise we might get a write interrupt
+			 * later even though we aren't interested in sending
+			 * anymore.  Loop to drain TTY-layer buffer.
+			 */
+			if (*sc->ajus_jtag_presentp == 0) {
+				if (ttydisc_getc(tp, &ch, sizeof(ch)) !=
+				    sizeof(ch))
+					panic("%s: ttydisc_getc 2", __func__);
+				AJU_UNLOCK(sc);
+				continue;
+			}
+			if (sc->ajus_irq_res != NULL)
+				aju_intr_writable_enable(sc);
+			return;
+		}
+		AJU_UNLOCK(sc);
+	}
+	AJU_LOCK(sc);
+	aju_intr_writable_disable(sc);
+}
+
+static void
+aju_outwakeup(struct tty *tp)
+{
+	struct altera_jtag_uart_softc *sc = tty_softc(tp);
+
+	tty_lock_assert(tp, MA_OWNED);
+
+	AJU_LOCK(sc);
+	aju_handle_output(sc, tp);
+	AJU_UNLOCK(sc);
+}
+
+static void
+aju_io_callout(void *arg)
+{
+	struct altera_jtag_uart_softc *sc = arg;
+	struct tty *tp = sc->ajus_ttyp;
+
+	tty_lock(tp);
+	AJU_LOCK(sc);
+
+	/*
+	 * It would be convenient if we could share code with aju_intr() here
+	 * by testing the control register for ALTERA_JTAG_UART_CONTROL_RI and
+	 * ALTERA_JTAG_UART_CONTROL_WI.  Unfortunately, it's not clear that
+	 * this is supported, so do all the work to poll for both input and
+	 * output.
+	 */
+	aju_handle_input(sc, tp);
+	aju_handle_output(sc, tp);
+
+	/*
+	 * Reschedule next poll attempt.  There's some argument that we should
+	 * do adaptive polling based on the expectation of I/O: is something
+	 * pending in the output buffer, or have we recently had input, but we
+	 * don't.
+	 */
+	callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL,
+	    aju_io_callout, sc);
+	AJU_UNLOCK(sc);
+	tty_unlock(tp);
+}
+
+static void
+aju_ac_callout(void *arg)
+{
+	struct altera_jtag_uart_softc *sc = arg;
+	struct tty *tp = sc->ajus_ttyp;
+	uint32_t v;
+
+	tty_lock(tp);
+	AJU_LOCK(sc);
+	v = aju_control_read(sc);
+	if (v & ALTERA_JTAG_UART_CONTROL_AC) {
+		v &= ~ALTERA_JTAG_UART_CONTROL_AC;
+		aju_control_write(sc, v);
+		if (*sc->ajus_jtag_presentp == 0) {
+			*sc->ajus_jtag_missedp = 0;
+			*sc->ajus_jtag_presentp = 1;
+			aju_handle_output(sc, tp);
+		}
+	} else if (*sc->ajus_jtag_presentp != 0) {
+		(*sc->ajus_jtag_missedp)++;
+		if (*sc->ajus_jtag_missedp >= AJU_JTAG_MAXMISS) {
+			*sc->ajus_jtag_presentp = 0;
+			aju_handle_output(sc, tp);
+		}
+	}
+	callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL,
+	    aju_ac_callout, sc);
+	AJU_UNLOCK(sc);
+	tty_unlock(tp);
+}
+
+static void
+aju_intr(void *arg)
+{
+	struct altera_jtag_uart_softc *sc = arg;
+	struct tty *tp = sc->ajus_ttyp;
+	uint32_t v;
+
+	tty_lock(tp);
+	AJU_LOCK(sc);
+	v = aju_control_read(sc);
+	if (v & ALTERA_JTAG_UART_CONTROL_RI)
+		aju_handle_input(sc, tp);
+	if (v & ALTERA_JTAG_UART_CONTROL_WI)
+		aju_handle_output(sc, tp);
+	AJU_UNLOCK(sc);
+	tty_unlock(tp);
+}
+
+int
+altera_jtag_uart_attach(struct altera_jtag_uart_softc *sc)
+{
+	struct tty *tp;
+	int error;
+
+	AJU_LOCK_INIT(sc);
+
+	/*
+	 * XXXRW: Currently, we detect the console solely based on it using a
+	 * reserved address, and borrow console-level locks and buffer if so.
+	 * Is there a better way?
+	 */
+	if (rman_get_start(sc->ajus_mem_res) == BERI_UART_BASE) {
+		sc->ajus_lockp = &aju_cons_lock;
+		sc->ajus_buffer_validp = &aju_cons_buffer_valid;
+		sc->ajus_buffer_datap = &aju_cons_buffer_data;
+		sc->ajus_jtag_presentp = &aju_cons_jtag_present;
+		sc->ajus_jtag_missedp = &aju_cons_jtag_missed;
+		sc->ajus_flags |= ALTERA_JTAG_UART_FLAG_CONSOLE;
+	} else {
+		sc->ajus_lockp = &sc->ajus_lock;
+		sc->ajus_buffer_validp = &sc->ajus_buffer_valid;
+		sc->ajus_buffer_datap = &sc->ajus_buffer_data;
+		sc->ajus_jtag_presentp = &sc->ajus_jtag_present;
+		sc->ajus_jtag_missedp = &sc->ajus_jtag_missed;
+	}
+
+	/*
+	 * Disable interrupts regardless of whether or not we plan to use
+	 * them.  We will register an interrupt handler now if they will be
+	 * used, but not re-enable intil later once the remainder of the tty
+	 * layer is properly initialised, as we're not ready for input yet.
+	 */
+	AJU_LOCK(sc);
+	aju_intr_disable(sc);
+	AJU_UNLOCK(sc);
+	if (sc->ajus_irq_res != NULL) {
+		error = bus_setup_intr(sc->ajus_dev, sc->ajus_irq_res,
+		    INTR_ENTROPY | INTR_TYPE_TTY | INTR_MPSAFE, NULL,
+		    aju_intr, sc, &sc->ajus_irq_cookie);
+		if (error) {
+			device_printf(sc->ajus_dev,
+			    "could not activate interrupt\n");
+			AJU_LOCK_DESTROY(sc);
+			return (error);
+		}
+	}
+	tp = sc->ajus_ttyp = tty_alloc(&aju_ttydevsw, sc);
+	if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE) {
+		aju_cons_sc = sc;
+		tty_init_console(tp, 0);
+	}
+	tty_makedev(tp, NULL, "%s%d", AJU_TTYNAME, sc->ajus_unit);
+
+	/*
+	 * If we will be using interrupts, enable them now; otherwise, start
+	 * polling.  From this point onwards, input can arrive.
+	 */
+	if (sc->ajus_irq_res != NULL) {
+		AJU_LOCK(sc);
+		aju_intr_readable_enable(sc);
+		AJU_UNLOCK(sc);
+	} else {
+		callout_init(&sc->ajus_io_callout, 1);
+		callout_reset(&sc->ajus_io_callout, AJU_IO_POLLINTERVAL,
+		    aju_io_callout, sc);
+	}
+	callout_init(&sc->ajus_ac_callout, 1);
+	callout_reset(&sc->ajus_ac_callout, AJU_AC_POLLINTERVAL,
+	    aju_ac_callout, sc);
+	return (0);
+}
+
+void
+altera_jtag_uart_detach(struct altera_jtag_uart_softc *sc)
+{
+	struct tty *tp = sc->ajus_ttyp;
+
+	/*
+	 * If we're using interrupts, disable and release the interrupt
+	 * handler now.  Otherwise drain the polling timeout.
+	 */
+	if (sc->ajus_irq_res != NULL) {
+		AJU_LOCK(sc);
+		aju_intr_disable(sc);
+		AJU_UNLOCK(sc);
+		bus_teardown_intr(sc->ajus_dev, sc->ajus_irq_res,
+		    sc->ajus_irq_cookie);
+	} else
+		callout_drain(&sc->ajus_io_callout);
+	callout_drain(&sc->ajus_ac_callout);
+	if (sc->ajus_flags & ALTERA_JTAG_UART_FLAG_CONSOLE)
+		aju_cons_sc = NULL;
+	tty_lock(tp);
+	tty_rel_gone(tp);
+	AJU_LOCK_DESTROY(sc);
+}


Property changes on: trunk/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/sdcard/altera_sdcard.c
===================================================================
--- trunk/sys/dev/altera/sdcard/altera_sdcard.c	                        (rev 0)
+++ trunk/sys/dev/altera/sdcard/altera_sdcard.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,414 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/sdcard/altera_sdcard.c 257445 2013-10-31 13:47:39Z brooks $");
+
+#include "opt_altera_sdcard.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+/*
+ * Device driver for the Altera University Program Secure Data Card IP Core,
+ * as described in the similarly named SOPC Builder IP Core specification.
+ * This soft core is not a full SD host controller interface (SDHCI) but
+ * instead provides a set of memory mapped registers and memory buffer that
+ * mildly abstract the SD Card protocol, but without providing DMA or
+ * interrupts.  However, it does hide the details of voltage and
+ * communications negotiation.  This driver implements disk(9), but due to the
+ * lack of interrupt support, must rely on timer-driven polling to determine
+ * when I/Os have completed.
+ *
+ * TODO:
+ *
+ * 1. Implement DISKFLAG_CANDELETE / SD Card sector erase support.
+ * 2. Implement d_ident from SD Card CID serial number field.
+ * 3. Handle read-only SD Cards.
+ * 4. Tune timeouts based on real-world SD Card speeds.
+ */
+devclass_t	altera_sdcard_devclass;
+
+void
+altera_sdcard_attach(struct altera_sdcard_softc *sc)
+{
+
+	ALTERA_SDCARD_LOCK_INIT(sc);
+	ALTERA_SDCARD_CONDVAR_INIT(sc);
+	sc->as_disk = NULL;
+	bioq_init(&sc->as_bioq);
+	sc->as_currentbio = NULL;
+	sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
+	sc->as_taskqueue = taskqueue_create("altera_sdcardc taskq", M_WAITOK,
+	    taskqueue_thread_enqueue, &sc->as_taskqueue);
+	taskqueue_start_threads(&sc->as_taskqueue, 1, PI_DISK,
+	    "altera_sdcardc%d taskqueue", sc->as_unit);
+	TIMEOUT_TASK_INIT(sc->as_taskqueue, &sc->as_task, 0,
+	    altera_sdcard_task, sc);
+
+	/*
+	 * Kick off timer-driven processing with a manual poll so that we
+	 * synchronously detect an already-inserted SD Card during the boot or
+	 * other driver attach point.
+	 */
+	altera_sdcard_task(sc, 1);
+}
+
+void
+altera_sdcard_detach(struct altera_sdcard_softc *sc)
+{
+
+	KASSERT(sc->as_taskqueue != NULL, ("%s: taskqueue not present",
+	    __func__));
+
+	/*
+	 * Winding down the driver on detach is a bit complex.  Update the
+	 * flags to indicate that a detach has been requested, and then wait
+	 * for in-progress I/O to wind down before continuing.
+	 */
+	ALTERA_SDCARD_LOCK(sc);
+	sc->as_flags |= ALTERA_SDCARD_FLAG_DETACHREQ;
+	while (sc->as_state != ALTERA_SDCARD_STATE_DETACHED)
+		ALTERA_SDCARD_CONDVAR_WAIT(sc);
+	ALTERA_SDCARD_UNLOCK(sc);
+
+	/*
+	 * Now wait for the possibly still executing taskqueue to drain.  In
+	 * principle no more events will be scheduled as we've transitioned to
+	 * a detached state, but there might still be a request in execution.
+	 */
+	while (taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL))
+		taskqueue_drain_timeout(sc->as_taskqueue, &sc->as_task);
+
+	/*
+	 * Simulate a disk removal if one is present to deal with any pending
+	 * or queued I/O.
+	 */
+	if (sc->as_disk != NULL)
+		altera_sdcard_disk_remove(sc);
+	KASSERT(bioq_first(&sc->as_bioq) == NULL,
+	    ("%s: non-empty bioq", __func__));
+
+	/*
+	 * Free any remaining allocated resources.
+	 */
+	taskqueue_free(sc->as_taskqueue);
+	sc->as_taskqueue = NULL;
+	ALTERA_SDCARD_CONDVAR_DESTROY(sc);
+	ALTERA_SDCARD_LOCK_DESTROY(sc);
+}
+
+/*
+ * Set up and start the next I/O.  Transition to the I/O state, but allow the
+ * caller to schedule the next timeout, as this may be called either from an
+ * initial attach context, or from the task queue, which requires different
+ * behaviour.
+ */
+static void
+altera_sdcard_nextio(struct altera_sdcard_softc *sc)
+{
+	struct bio *bp;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+	KASSERT(sc->as_currentbio == NULL,
+	    ("%s: bio already active", __func__));
+
+	bp = bioq_takefirst(&sc->as_bioq);
+	if (bp == NULL)
+		panic("%s: bioq empty", __func__);
+	altera_sdcard_io_start(sc, bp);
+	sc->as_state = ALTERA_SDCARD_STATE_IO;
+}
+
+static void
+altera_sdcard_task_nocard(struct altera_sdcard_softc *sc)
+{
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*
+	 * Handle device driver detach.
+	 */
+	if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
+		sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
+		return;
+	}
+
+	/*
+	 * If there is no card insertion, remain in NOCARD.
+	 */
+	if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT))
+		return;
+
+	/*
+	 * Read the CSD -- it may contain values that the driver can't handle,
+	 * either because of an unsupported version/feature, or because the
+	 * card is misbehaving.  This triggers a transition to
+	 * ALTERA_SDCARD_STATE_BADCARD.  We rely on the CSD read to print a
+	 * banner about how the card is problematic, since it has more
+	 * information.  The bad card state allows us to print that banner
+	 * once rather than each time we notice the card is there, and still
+	 * bad.
+	 */
+	if (altera_sdcard_read_csd(sc) != 0) {
+		sc->as_state = ALTERA_SDCARD_STATE_BADCARD;
+		return;
+	}
+
+	/*
+	 * Process card insertion and upgrade to the IDLE state.
+	 */
+	altera_sdcard_disk_insert(sc);
+	sc->as_state = ALTERA_SDCARD_STATE_IDLE;
+}
+
+static void
+altera_sdcard_task_badcard(struct altera_sdcard_softc *sc)
+{
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*
+	 * Handle device driver detach.
+	 */
+	if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
+		sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
+		return;
+	}
+
+	/*
+	 * Handle safe card removal -- no teardown is required, just a state
+	 * transition.
+	 */
+	if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT))
+		sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
+}
+
+static void
+altera_sdcard_task_idle(struct altera_sdcard_softc *sc)
+{
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*
+	 * Handle device driver detach.
+	 */
+	if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
+		sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
+		return;
+	}
+
+	/*
+	 * Handle safe card removal.
+	 */
+	if (!(altera_sdcard_read_asr(sc) & ALTERA_SDCARD_ASR_CARDPRESENT)) {
+		altera_sdcard_disk_remove(sc);
+		sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
+	}
+}
+
+static void
+altera_sdcard_task_io(struct altera_sdcard_softc *sc)
+{
+	uint16_t asr;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+	KASSERT(sc->as_currentbio != NULL, ("%s: no current I/O", __func__));
+
+#ifdef ALTERA_SDCARD_FAST_SIM
+recheck:
+#endif
+	asr = altera_sdcard_read_asr(sc);
+
+	/*
+	 * Check for unexpected card removal during an I/O.
+	 */
+	if (!(asr & ALTERA_SDCARD_ASR_CARDPRESENT)) {
+		altera_sdcard_disk_remove(sc);
+		if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ)
+			sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
+		else
+			sc->as_state = ALTERA_SDCARD_STATE_NOCARD;
+		return;
+	}
+
+	/*
+	 * If the I/O isn't complete, remain in the IO state without further
+	 * action, even if DETACHREQ is in flight.
+	 */
+	if (asr & ALTERA_SDCARD_ASR_CMDINPROGRESS)
+		return;
+
+	/*
+	 * Handle various forms of I/O completion, successful and otherwise.
+	 * The I/O layer may restart the transaction if an error occurred, in
+	 * which case remain in the IO state and reschedule.
+	 */
+	if (!altera_sdcard_io_complete(sc, asr))
+		return;
+
+	/*
+	 * Now that I/O is complete, process detach requests in preference to
+	 * starting new I/O.
+	 */
+	if (sc->as_flags & ALTERA_SDCARD_FLAG_DETACHREQ) {
+		sc->as_state = ALTERA_SDCARD_STATE_DETACHED;
+		return;
+	}
+
+	/*
+	 * Finally, either start the next I/O or transition to the IDLE state.
+	 */
+	if (bioq_first(&sc->as_bioq) != NULL) {
+		altera_sdcard_nextio(sc);
+#ifdef ALTERA_SDCARD_FAST_SIM
+		goto recheck;
+#endif
+	} else
+		sc->as_state = ALTERA_SDCARD_STATE_IDLE;
+}
+
+static void
+altera_sdcard_task_rechedule(struct altera_sdcard_softc *sc)
+{
+	int interval;
+
+	/*
+	 * Reschedule based on new state.  Or not, if detaching the device
+	 * driver.  Treat a bad card as though it were no card at all.
+	 */
+	switch (sc->as_state) {
+	case ALTERA_SDCARD_STATE_NOCARD:
+	case ALTERA_SDCARD_STATE_BADCARD:
+		interval = ALTERA_SDCARD_TIMEOUT_NOCARD;
+		break;
+
+	case ALTERA_SDCARD_STATE_IDLE:
+		interval = ALTERA_SDCARD_TIMEOUT_IDLE;
+		break;
+
+	case ALTERA_SDCARD_STATE_IO:
+		if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR)
+			interval = ALTERA_SDCARD_TIMEOUT_IOERROR;
+		else
+			interval = ALTERA_SDCARD_TIMEOUT_IO;
+		break;
+
+	default:
+		panic("%s: invalid exit state %d", __func__, sc->as_state);
+	}
+	taskqueue_enqueue_timeout(sc->as_taskqueue, &sc->as_task, interval);
+}
+
+/*
+ * Because the Altera SD Card IP Core doesn't support interrupts, we do all
+ * asynchronous work from a timeout.  Poll at two different rates -- an
+ * infrequent check for card insertion status changes, and a frequent one for
+ * I/O completion.  The task should never start in DETACHED, as that would
+ * imply that a previous instance failed to cancel rather than reschedule.
+ */
+void
+altera_sdcard_task(void *arg, int pending)
+{
+	struct altera_sdcard_softc *sc;
+
+	sc = arg;
+	KASSERT(sc->as_state != ALTERA_SDCARD_STATE_DETACHED,
+	    ("%s: already in detached", __func__));
+
+	ALTERA_SDCARD_LOCK(sc);
+	switch (sc->as_state) {
+	case ALTERA_SDCARD_STATE_NOCARD:
+		altera_sdcard_task_nocard(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_BADCARD:
+		altera_sdcard_task_badcard(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_IDLE:
+		altera_sdcard_task_idle(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_IO:
+		altera_sdcard_task_io(sc);
+		break;
+
+	default:
+		panic("%s: invalid enter state %d", __func__, sc->as_state);
+	}
+
+	/*
+	 * If we have transitioned to DETACHED, signal the detach thread and
+	 * cancel the timeout-driven task.  Otherwise reschedule on an
+	 * appropriate timeout.
+	 */
+	if (sc->as_state == ALTERA_SDCARD_STATE_DETACHED)
+		ALTERA_SDCARD_CONDVAR_SIGNAL(sc);
+	else
+		altera_sdcard_task_rechedule(sc);
+	ALTERA_SDCARD_UNLOCK(sc);
+}
+
+void
+altera_sdcard_start(struct altera_sdcard_softc *sc)
+{
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	KASSERT(sc->as_state == ALTERA_SDCARD_STATE_IDLE,
+	    ("%s: starting when not IDLE", __func__));
+
+	taskqueue_cancel_timeout(sc->as_taskqueue, &sc->as_task, NULL);
+	altera_sdcard_nextio(sc);
+#ifdef ALTERA_SDCARD_FAST_SIM
+	altera_sdcard_task_io(sc);
+#endif
+	altera_sdcard_task_rechedule(sc);
+}


Property changes on: trunk/sys/dev/altera/sdcard/altera_sdcard.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/sdcard/altera_sdcard.h
===================================================================
--- trunk/sys/dev/altera/sdcard/altera_sdcard.h	                        (rev 0)
+++ trunk/sys/dev/altera/sdcard/altera_sdcard.h	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,250 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/10/sys/dev/altera/sdcard/altera_sdcard.h 245819 2013-01-22 18:51:14Z brooks $
+ */
+
+#ifndef _DEV_ALTERA_SDCARD_H_
+#define	_DEV_ALTERA_SDCARD_H_
+
+#define	ALTERA_SDCARD_CSD_SIZE	16
+struct altera_sdcard_csd {
+	uint8_t		 csd_data[ALTERA_SDCARD_CSD_SIZE];
+} __aligned(2);		/* CSD is read in 16-bit chunks, so align to match. */
+
+struct altera_sdcard_softc {
+	device_t		 as_dev;
+	int			 as_unit;
+	struct resource		*as_res;
+	int			 as_rid;
+	struct mtx		 as_lock;
+	struct cv		 as_condvar;
+	int			 as_state;
+	int			 as_flags;
+	struct disk		*as_disk;
+	struct taskqueue	*as_taskqueue;
+	struct timeout_task	 as_task;
+
+	/*
+	 * Fields relating to in-progress and pending I/O, if any.
+	 */
+	struct bio_queue_head	 as_bioq;
+	struct bio		*as_currentbio;
+	u_int			 as_retriesleft;
+
+	/*
+	 * Infrequently changing fields cached from the SD Card IP Core.
+	 */
+	struct altera_sdcard_csd	 as_csd;
+	uint8_t			 as_csd_structure;	/* CSD version. */
+	uint64_t		 as_mediasize;
+};
+
+#define	ALTERA_SDCARD_LOCK(sc)		mtx_lock(&(sc)->as_lock)
+#define	ALTERA_SDCARD_LOCK_ASSERT(sc)	mtx_assert(&(sc)->as_lock, MA_OWNED)
+#define	ALTERA_SDCARD_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->as_lock)
+#define	ALTERA_SDCARD_LOCK_INIT(sc)	mtx_init(&(sc)->as_lock,	\
+					    "altera_sdcard", NULL, MTX_DEF)
+#define	ALTERA_SDCARD_UNLOCK(sc)	mtx_unlock(&(sc)->as_lock)
+
+#define	ALTERA_SDCARD_CONDVAR_DESTROY(sc)	cv_destroy(&(sc)->as_condvar)
+#define	ALTERA_SDCARD_CONDVAR_INIT(sc)		cv_init(&(sc)->as_condvar, \
+						    "altera_sdcard_detach_wait")
+#define	ALTERA_SDCARD_CONDVAR_SIGNAL(dc)	cv_signal(&(sc)->as_condvar)
+#define	ALTERA_SDCARD_CONDVAR_WAIT(sc)		cv_wait(&(sc)->as_condvar, \
+						    &(sc)->as_lock)
+
+/*
+ * States an instance can be in at any given moment.
+ */
+#define	ALTERA_SDCARD_STATE_NOCARD	1	/* No card inserted. */
+#define	ALTERA_SDCARD_STATE_BADCARD	2	/* Card bad/not supported. */
+#define	ALTERA_SDCARD_STATE_IDLE	3	/* Card present but idle. */
+#define	ALTERA_SDCARD_STATE_IO		4	/* Card in I/O currently. */
+#define	ALTERA_SDCARD_STATE_DETACHED	5	/* Driver is detaching. */
+
+/*
+ * Different timeout intervals based on state.  When just looking for a card
+ * status change, check twice a second.  When we're actively waiting on I/O
+ * completion, check every millisecond.
+ */
+#define	ALTERA_SDCARD_TIMEOUT_NOCARD	(hz/2)
+#define	ALTERA_SDCARD_TIMEOUT_IDLE	(hz/2)
+#define	ALTERA_SDCARD_TIMEOUT_IO	(1)
+#define	ALTERA_SDCARD_TIMEOUT_IOERROR	(hz/5)
+
+/*
+ * Maximum number of retries on an I/O.
+ */
+#define	ALTERA_SDCARD_RETRY_LIMIT	10
+
+/*
+ * Driver status flags.
+ */
+#define	ALTERA_SDCARD_FLAG_DETACHREQ	0x00000001	/* Detach requested. */
+#define	ALTERA_SDCARD_FLAG_IOERROR	0x00000002	/* Error in progress. */
+
+/*
+ * Functions for performing low-level register and memory I/O to/from the SD
+ * Card IP Core.  In general, only code in altera_sdcard_io.c is aware of the
+ * hardware interface.
+ */
+uint16_t	altera_sdcard_read_asr(struct altera_sdcard_softc *sc);
+int		altera_sdcard_read_csd(struct altera_sdcard_softc *sc);
+
+int	altera_sdcard_io_complete(struct altera_sdcard_softc *sc,
+	    uint16_t asr);
+void	altera_sdcard_io_start(struct altera_sdcard_softc *sc,
+	    struct bio *bp);
+
+/*
+ * Constants for interpreting the SD Card Card Specific Data (CSD) register.
+ */
+#define	ALTERA_SDCARD_CSD_STRUCTURE_BYTE	15
+#define	ALTERA_SDCARD_CSD_STRUCTURE_MASK	0xc0	/* 2 bits */
+#define	ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT	6
+
+#define	ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE	10
+#define	ALTERA_SDCARD_CSD_READ_BL_LEN_MASK	0x0f	/* 4 bits */
+
+/*
+ * C_SIZE is a 12-bit field helpfully split over three differe bytes of CSD
+ * data.  Software ease of use was not a design consideration.
+ */
+#define	ALTERA_SDCARD_CSD_C_SIZE_BYTE0		7
+#define	ALTERA_SDCARD_CSD_C_SIZE_MASK0		0xc0	/* top 2 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0	6
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_BYTE1		8
+#define	ALTERA_SDCARD_CSD_C_SIZE_MASK1		0xff	/* 8 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1	2
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_BYTE2		9
+#define	ALTERA_SDCARD_CSD_C_SIZE_MASK2		0x03	/* bottom 2 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2	10
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0	5
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0	0x80	/* top 1 bit */
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0	7
+
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1	6
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1	0x03	/* bottom 2 bits */
+#define	ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1	1
+
+/*
+ * I/O register/buffer offsets, from Table 4.1.1 in the Altera University
+ * Program SD Card IP Core specification.
+ */
+#define	ALTERA_SDCARD_OFF_RXTX_BUFFER	0	/* 512-byte I/O buffer */
+#define	ALTERA_SDCARD_OFF_CID		512	/* 16-byte Card ID number */
+#define	ALTERA_SDCARD_OFF_CSD		528	/* 16-byte Card Specific Data */
+#define	ALTERA_SDCARD_OFF_OCR		544	/* Operating Conditions Reg */
+#define	ALTERA_SDCARD_OFF_SR		548	/* SD Card Status Register */
+#define	ALTERA_SDCARD_OFF_RCA		552	/* Relative Card Address Reg */
+#define	ALTERA_SDCARD_OFF_CMD_ARG	556	/* Command Argument Register */
+#define	ALTERA_SDCARD_OFF_CMD		560	/* Command Register */
+#define	ALTERA_SDCARD_OFF_ASR		564	/* Auxiliary Status Register */
+#define	ALTERA_SDCARD_OFF_RR1		568	/* Response R1 */
+
+/*
+ * The Altera IP Core provides a 16-bit "Additional Status Register" (ASR)
+ * beyond those described in the SD Card specification that captures IP Core
+ * transaction state, such as whether the last command is in progress, the
+ * card has been removed, etc.
+ */
+#define	ALTERA_SDCARD_ASR_CMDVALID	0x0001
+#define	ALTERA_SDCARD_ASR_CARDPRESENT	0x0002
+#define	ALTERA_SDCARD_ASR_CMDINPROGRESS	0x0004
+#define	ALTERA_SDCARD_ASR_SRVALID	0x0008
+#define	ALTERA_SDCARD_ASR_CMDTIMEOUT	0x0010
+#define	ALTERA_SDCARD_ASR_CMDDATAERROR	0x0020
+
+/*
+ * The Altera IP Core claims to provide a 16-bit "Response R1" register (RR1)
+ * to provide more detailed error reporting when a read or write fails.
+ *
+ * XXXRW: The specification claims that this field is 16-bit, but then
+ * proceeds to define values as though it is 32-bit.  In practice, 16-bit
+ * seems more likely as the register is not 32-bit aligned.
+ */
+#define	ALTERA_SDCARD_RR1_INITPROCRUNNING	0x0100
+#define	ALTERA_SDCARD_RR1_ERASEINTERRUPTED	0x0200
+#define	ALTERA_SDCARD_RR1_ILLEGALCOMMAND	0x0400
+#define	ALTERA_SDCARD_RR1_COMMANDCRCFAILED	0x0800
+#define	ALTERA_SDCARD_RR1_ADDRESSMISALIGNED	0x1000
+#define	ALTERA_SDCARD_RR1_ADDRBLOCKRANGE	0x2000
+
+/*
+ * Not all RR1 values are "errors" per se -- check only for the ones that are
+ * when performing error handling.
+ */
+#define	ALTERA_SDCARD_RR1_ERRORMASK					      \
+    (ALTERA_SDCARD_RR1_ERASEINTERRUPTED | ALTERA_SDCARD_RR1_ILLEGALCOMMAND |  \
+    ALTERA_SDCARD_RR1_COMMANDCRCFAILED | ALTERA_SDCARD_RR1_ADDRESSMISALIGNED |\
+    ALTERA_SDCARD_RR1_ADDRBLOCKRANGE)
+
+/*
+ * Although SD Cards may have various sector sizes, the Altera IP Core
+ * requires that I/O be done in 512-byte chunks.
+ */
+#define	ALTERA_SDCARD_SECTORSIZE	512
+
+/*
+ * SD Card commands used in this driver.
+ */
+#define	ALTERA_SDCARD_CMD_SEND_RCA	0x03	/* Retrieve card RCA. */
+#define	ALTERA_SDCARD_CMD_SEND_CSD	0x09	/* Retrieve CSD register. */
+#define	ALTERA_SDCARD_CMD_SEND_CID	0x0A	/* Retrieve CID register. */
+#define	ALTERA_SDCARD_CMD_READ_BLOCK	0x11	/* Read block from disk. */
+#define	ALTERA_SDCARD_CMD_WRITE_BLOCK	0x18	/* Write block to disk. */
+
+/*
+ * Functions exposed by the device driver core to newbus(9) bus attachment
+ * implementations.
+ */
+void	altera_sdcard_attach(struct altera_sdcard_softc *sc);
+void	altera_sdcard_detach(struct altera_sdcard_softc *sc);
+void	altera_sdcard_task(void *arg, int pending);
+
+/*
+ * Functions exposed by the device driver core to the disk(9) front-end.
+ */
+void	altera_sdcard_start(struct altera_sdcard_softc *sc);
+
+/*
+ * Functions relating to the implementation of disk(9) KPIs for the SD Card
+ * driver.
+ */
+void	altera_sdcard_disk_insert(struct altera_sdcard_softc *sc);
+void	altera_sdcard_disk_remove(struct altera_sdcard_softc *sc);
+
+extern devclass_t	altera_sdcard_devclass;
+
+#endif	/* _DEV_ALTERA_SDCARD_H_ */


Property changes on: trunk/sys/dev/altera/sdcard/altera_sdcard.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/sdcard/altera_sdcard_disk.c
===================================================================
--- trunk/sys/dev/altera/sdcard/altera_sdcard_disk.c	                        (rev 0)
+++ trunk/sys/dev/altera/sdcard/altera_sdcard_disk.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,186 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/sdcard/altera_sdcard_disk.c 239675 2012-08-25 11:19:20Z rwatson $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+static int
+altera_sdcard_disk_dump(void *arg, void *virtual, vm_offset_t physical,
+    off_t offset, size_t length)
+{
+
+	panic("%s: not yet", __func__);
+}
+
+static int
+altera_sdcard_disk_ioctl(struct disk *disk, u_long cmd, void *data, int fflag,
+    struct thread *td)
+{
+
+	/* XXXRW: more here? */
+	return (EINVAL);
+}
+
+static void
+altera_sdcard_disk_strategy(struct bio *bp)
+{
+	struct altera_sdcard_softc *sc;
+
+	/*
+	 * Although the SD Card doesn't need sorting, we don't want to
+	 * introduce barriers, so use bioq_disksort().
+	 */
+	sc = bp->bio_disk->d_drv1;
+	ALTERA_SDCARD_LOCK(sc);
+	switch (sc->as_state) {
+	case ALTERA_SDCARD_STATE_NOCARD:
+		device_printf(sc->as_dev, "%s: unexpected I/O on NOCARD",
+		    __func__);
+		biofinish(bp, NULL, ENXIO);
+		break;
+
+	case ALTERA_SDCARD_STATE_BADCARD:
+		device_printf(sc->as_dev, "%s: unexpected I/O on BADCARD",
+		    __func__);
+		biofinish(bp, NULL, ENXIO);
+		break;
+
+	case ALTERA_SDCARD_STATE_DETACHED:
+		device_printf(sc->as_dev, "%s: unexpected I/O on DETACHED",
+		    __func__);
+		biofinish(bp, NULL, ENXIO);
+
+	case ALTERA_SDCARD_STATE_IDLE:
+		bioq_disksort(&sc->as_bioq, bp);
+		altera_sdcard_start(sc);
+		break;
+
+	case ALTERA_SDCARD_STATE_IO:
+		bioq_disksort(&sc->as_bioq, bp);
+		break;
+
+	default:
+		panic("%s: invalid state %d", __func__, sc->as_state);
+	}
+	ALTERA_SDCARD_UNLOCK(sc);
+}
+
+void
+altera_sdcard_disk_insert(struct altera_sdcard_softc *sc)
+{
+	struct disk *disk;
+	uint64_t size;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*
+	 * Because the disk insertion routine occupies the driver instance's
+	 * task queue thread, and the disk(9) instance isn't hooked up yet by
+	 * definition, the only other source of events of concern is a thread
+	 * initiating driver detach.  That thread has to issue a detach
+	 * request and await an ACK from the taskqueue thread.  It is
+	 * therefore safe to drop the lock here.
+	 */
+	ALTERA_SDCARD_UNLOCK(sc);
+	disk = disk_alloc();
+	disk->d_drv1 = sc;
+	disk->d_name = "altera_sdcard";
+	disk->d_unit = sc->as_unit;
+	disk->d_strategy = altera_sdcard_disk_strategy;
+	disk->d_dump = altera_sdcard_disk_dump;
+	disk->d_ioctl = altera_sdcard_disk_ioctl;
+	disk->d_sectorsize = ALTERA_SDCARD_SECTORSIZE;
+	disk->d_mediasize = sc->as_mediasize;
+	disk->d_maxsize = ALTERA_SDCARD_SECTORSIZE;
+	sc->as_disk = disk;
+	disk_create(disk, DISK_VERSION);
+	ALTERA_SDCARD_LOCK(sc);
+
+	/*
+	 * Print a pretty-ish card insertion string.  We could stand to
+	 * decorate this further, e.g., with card vendor information.
+	 */
+	size = sc->as_mediasize / (1000 * 1000);
+	device_printf(sc->as_dev, "%juM SD Card inserted\n", (uintmax_t)size);
+}
+
+void
+altera_sdcard_disk_remove(struct altera_sdcard_softc *sc)
+{
+	struct disk *disk;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+	KASSERT(sc->as_disk != NULL, ("%s: as_disk NULL", __func__));
+
+	/*
+	 * sc->as_state will be updated by the caller.
+	 *
+	 * XXXRW: Is it OK to call disk_destroy() under the mutex, or should
+	 * we be deferring that to the calling context once it is released?
+	 */
+	disk = sc->as_disk;
+	disk_gone(disk);
+	disk_destroy(disk);
+	sc->as_disk = NULL;
+
+	/*
+	 * Cancel all outstanding I/O on the SD Card.
+	 */
+	if (sc->as_currentbio != NULL) {
+		device_printf(sc->as_dev, "%s: SD Card removed during I/O",
+		    __func__);
+		biofinish(sc->as_currentbio, NULL, ENXIO);
+		sc->as_currentbio = NULL;
+	}
+	bioq_flush(&sc->as_bioq, NULL, ENXIO);
+	device_printf(sc->as_dev, "SD Card removed\n");
+}


Property changes on: trunk/sys/dev/altera/sdcard/altera_sdcard_disk.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/sdcard/altera_sdcard_fdt.c
===================================================================
--- trunk/sys/dev/altera/sdcard/altera_sdcard_fdt.c	                        (rev 0)
+++ trunk/sys/dev/altera/sdcard/altera_sdcard_fdt.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,124 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/sdcard/altera_sdcard_fdt.c 266152 2014-05-15 16:11:06Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/*
+ * FDT bus attachment for the Altera SD Card IP core.
+ */
+static int
+altera_sdcard_fdt_probe(device_t dev)
+{
+
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_is_compatible(dev, "altera,sdcard_11_2011")) {
+		device_set_desc(dev, "Altera Secure Data Card IP Core");
+		return (BUS_PROBE_DEFAULT);
+	}
+	return (ENXIO);
+}
+
+static int
+altera_sdcard_fdt_attach(device_t dev)
+{
+	struct altera_sdcard_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->as_dev = dev;
+	sc->as_unit = device_get_unit(dev);
+	sc->as_rid = 0;
+	sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->as_rid, RF_ACTIVE);
+	if (sc->as_res == NULL) {
+		device_printf(dev, "couldn't map memory\n");
+		return (ENXIO);
+	}
+	altera_sdcard_attach(sc);
+	return (0);
+}
+
+static int
+altera_sdcard_fdt_detach(device_t dev)
+{
+	struct altera_sdcard_softc *sc;
+
+	sc = device_get_softc(dev);
+	KASSERT(sc->as_res != NULL, ("%s: resources not allocated",
+	    __func__));
+	altera_sdcard_detach(sc);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res);
+	return (0);
+}
+
+static device_method_t altera_sdcard_fdt_methods[] = {
+	DEVMETHOD(device_probe,		altera_sdcard_fdt_probe),
+	DEVMETHOD(device_attach,	altera_sdcard_fdt_attach),
+	DEVMETHOD(device_detach,	altera_sdcard_fdt_detach),
+	{ 0, 0 }
+};
+
+static driver_t altera_sdcard_fdt_driver = {
+	"altera_sdcardc",
+	altera_sdcard_fdt_methods,
+	sizeof(struct altera_sdcard_softc),
+};
+
+DRIVER_MODULE(altera_sdcard, simplebus, altera_sdcard_fdt_driver,
+    altera_sdcard_devclass, 0, 0);


Property changes on: trunk/sys/dev/altera/sdcard/altera_sdcard_fdt.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/sdcard/altera_sdcard_io.c
===================================================================
--- trunk/sys/dev/altera/sdcard/altera_sdcard_io.c	                        (rev 0)
+++ trunk/sys/dev/altera/sdcard/altera_sdcard_io.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,444 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/sdcard/altera_sdcard_io.c 257445 2013-10-31 13:47:39Z brooks $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+int altera_sdcard_ignore_crc_errors = 1;
+int altera_sdcard_verify_rxtx_writes = 1;
+
+/*
+ * Low-level I/O routines for the Altera SD Card University IP Core driver.
+ *
+ * XXXRW: Throughout, it is assumed that the IP Core handles multibyte
+ * registers as little endian, as is the case for other Altera IP cores.
+ * However, the specification makes no reference to endianness, so this
+ * assumption might not always be correct.
+ */
+uint16_t
+altera_sdcard_read_asr(struct altera_sdcard_softc *sc)
+{
+
+	return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_ASR)));
+}
+
+static int
+altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
+{
+	uint64_t c_size, c_size_mult, read_bl_len;
+	uint8_t byte0, byte1, byte2;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*-
+	 * Compute card capacity per SD Card interface description as follows:
+	 *
+	 *   Memory capacity = BLOCKNR * BLOCK_LEN
+	 *
+	 * Where:
+	 *
+	 *   BLOCKNR = (C_SIZE + 1) * MULT
+	 *   MULT = 2^(C_SIZE_MULT+2)
+	 *   BLOCK_LEN = 2^READ_BL_LEN
+	 */
+	read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
+	read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
+
+	byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
+	byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
+	byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
+	byte2 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE2];
+	byte2 &= ALTERA_SDCARD_CSD_C_SIZE_MASK2;
+	c_size = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0) |
+	    (byte1 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1) |
+	    (byte2 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2);
+
+	byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
+	byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
+	byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
+	byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
+	c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
+	    (byte1 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
+
+	/*
+	 * If we're just getting back zero's, mark the card as bad, even
+	 * though it could just mean a Very Small Disk Indeed.
+	 */
+	if (c_size == 0 && c_size_mult == 0 && read_bl_len == 0) {
+		device_printf(sc->as_dev, "Ignored zero-size card\n");
+		return (ENXIO);
+	}
+	sc->as_mediasize = (c_size + 1) * (1 << (c_size_mult + 2)) *
+	    (1 << read_bl_len);
+	return (0);
+}
+
+int
+altera_sdcard_read_csd(struct altera_sdcard_softc *sc)
+{
+	uint8_t csd_structure;
+	int error;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+
+	/*
+	 * XXXRW: Assume for now that when the SD Card IP Core negotiates
+	 * voltage/speed/etc, it must use the CSD register, and therefore
+	 * populates the SD Card IP Core's cache of the register value.  This
+	 * means that we can read it without issuing further SD Card commands.
+	 * If this assumption proves false, we will (a) get back garbage and
+	 * (b) need to add additional states in the driver state machine in
+	 * order to query card properties before I/O can start.
+	 *
+	 * XXXRW: Treating this as an array of bytes, so no byte swapping --
+	 * is that a safe assumption?
+	 */
+	KASSERT(((uintptr_t)&sc->as_csd.csd_data) % 2 == 0,
+	    ("%s: CSD buffer unaligned", __func__));
+	bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_CSD,
+	    (uint16_t *)sc->as_csd.csd_data, sizeof(sc->as_csd) / 2);
+
+	/*
+	 * Interpret the loaded CSD, extracting certain fields and copying
+	 * them into the softc for easy software access.
+	 *
+	 * Currently, we support only CSD Version 1.0.  If we detect a newer
+	 * version, suppress card detection.
+	 */
+	csd_structure = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_STRUCTURE_BYTE];
+	csd_structure &= ALTERA_SDCARD_CSD_STRUCTURE_MASK;
+	csd_structure >>= ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT;
+	sc->as_csd_structure = csd_structure;
+
+	/*
+	 * Interpret the CSD field based on its version.  Extract fields,
+	 * especially mediasize.
+	 *
+	 * XXXRW: Desirable to support further CSD versions here.
+	 */
+	switch (sc->as_csd_structure) {
+	case 0:
+		error = altera_sdcard_process_csd0(sc);
+		if (error)
+			return (error);
+		break;
+
+	default:
+		device_printf(sc->as_dev,
+		    "Ignored disk with unsupported CSD structure (%d)\n",
+		    sc->as_csd_structure);
+		return (ENXIO);
+	}
+	return (0);
+}
+
+/*
+ * XXXRW: The Altera IP Core specification indicates that RR1 is a 16-bit
+ * register, but all bits it identifies are >16 bit.  Most likely, RR1 is a
+ * 32-bit register?
+ */
+static uint16_t
+altera_sdcard_read_rr1(struct altera_sdcard_softc *sc)
+{
+
+	return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_RR1)));
+}
+
+static void
+altera_sdcard_write_cmd_arg(struct altera_sdcard_softc *sc, uint32_t cmd_arg)
+{
+
+	bus_write_4(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole32(cmd_arg));
+}
+
+static void
+altera_sdcard_write_cmd(struct altera_sdcard_softc *sc, uint16_t cmd)
+{
+
+	bus_write_2(sc->as_res, ALTERA_SDCARD_OFF_CMD, htole16(cmd));
+}
+
+static void
+altera_sdcard_read_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
+    size_t len)
+{
+
+	KASSERT((uintptr_t)data % 2 == 0,
+	    ("%s: unaligned data %p", __func__, data));
+	KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
+	    ("%s: invalid length %ju", __func__, len));
+
+	bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
+	    (uint16_t *)data, len / 2);
+}
+
+static void
+altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
+    size_t len)
+{
+	u_int corrections, differences, i, retry_counter;
+	uint16_t d, v;
+
+	KASSERT((uintptr_t)data % 2 == 0,
+	    ("%s: unaligned data %p", __func__, data));
+	KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
+	    ("%s: invalid length %ju", __func__, len));
+
+	retry_counter = 0;
+	do {
+		bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
+		    (uint16_t *)data, len / 2);
+
+		/*
+		 * XXXRW: Due to a possible hardware bug, the above call to
+		 * bus_write_region_2() might not succeed.  If the workaround
+		 * is enabled, verify each write and retry until it succeeds.
+		 *
+		 * XXXRW: Do we want a limit counter for retries here?
+		 */
+recheck:
+		corrections = 0;
+		differences = 0;
+		if (altera_sdcard_verify_rxtx_writes) {
+			for (i = 0; i < ALTERA_SDCARD_SECTORSIZE; i += 2) {
+				v = bus_read_2(sc->as_res,
+				    ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
+				d = *(uint16_t *)((uint8_t *)data + i);
+				if (v != d) {
+					if (retry_counter == 0) {
+						bus_write_2(sc->as_res,
+						    ALTERA_SDCARD_OFF_RXTX_BUFFER + i,
+						    d);
+						v = bus_read_2(sc->as_res,
+						    ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
+						if (v == d) {
+							corrections++;
+							device_printf(sc->as_dev,
+							    "%s: single word rewrite worked"
+							    " at offset %u\n", 
+							    __func__, i);
+							continue;
+						}
+					}
+					differences++;
+					device_printf(sc->as_dev,
+					    "%s: retrying write -- difference"
+					    " %u at offset %u, retry %u\n",
+					    __func__, differences, i,
+					    retry_counter);
+				}
+			}
+			if (differences != 0) {
+				retry_counter++;
+				if (retry_counter == 1 &&
+				    corrections == differences)
+					goto recheck;
+			}
+		}
+	} while (differences != 0);
+	if (retry_counter)
+		device_printf(sc->as_dev, "%s: succeeded after %u retries\n",
+		    __func__, retry_counter);
+}
+
+static void
+altera_sdcard_io_start_internal(struct altera_sdcard_softc *sc, struct bio *bp)
+{
+
+	switch (bp->bio_cmd) {
+	case BIO_READ:
+		altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
+		    ALTERA_SDCARD_SECTORSIZE);
+		altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK);
+		break;
+
+	case BIO_WRITE:
+		altera_sdcard_write_rxtx_buffer(sc, bp->bio_data,
+		    bp->bio_bcount);
+		altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
+		    ALTERA_SDCARD_SECTORSIZE);
+		altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK);
+		break;
+
+	default:
+		panic("%s: unsupported I/O operation %d", __func__,
+		    bp->bio_cmd);
+	}
+}
+
+void
+altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp)
+{
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+	KASSERT(sc->as_currentbio == NULL,
+	    ("%s: bio already started", __func__));
+
+	/*
+	 * We advertise a block size and maximum I/O size up the stack of the
+	 * SD Card IP Core sector size.  Catch any attempts to not follow the
+	 * rules.
+	 */
+	KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE,
+	    ("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE));
+	altera_sdcard_io_start_internal(sc, bp);
+	sc->as_currentbio = bp;
+	sc->as_retriesleft = ALTERA_SDCARD_RETRY_LIMIT;
+}
+
+/*
+ * Handle completed I/O.  ASR is passed in to avoid reading it more than once.
+ * Return 1 if the I/O is actually complete (success, or retry limit
+ * exceeded), or 0 if not.
+ */
+int
+altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr)
+{
+	struct bio *bp;
+	uint16_t rr1, mask;
+	int error;
+
+	ALTERA_SDCARD_LOCK_ASSERT(sc);
+	KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS),
+	    ("%s: still in progress", __func__));
+	KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT,
+	    ("%s: card removed", __func__));
+
+	bp = sc->as_currentbio;
+
+	/*-
+	 * Handle I/O retries if an error is returned by the device.  Various
+	 * quirks handled in the process:
+	 *
+	 * 1. ALTERA_SDCARD_ASR_CMDDATAERROR is ignored for BIO_WRITE.
+	 * 2. ALTERA_SDCARD_RR1_COMMANDCRCFAILED is optionally ignored for
+	 *    BIO_READ.
+	 */
+	error = 0;
+	rr1 = altera_sdcard_read_rr1(sc);
+	switch (bp->bio_cmd) {
+	case BIO_READ:
+		mask = ALTERA_SDCARD_RR1_ERRORMASK;
+		if (altera_sdcard_ignore_crc_errors)
+			mask &= ~ALTERA_SDCARD_RR1_COMMANDCRCFAILED;
+		if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
+			error = EIO;
+		else if ((asr & ALTERA_SDCARD_ASR_CMDDATAERROR) &&
+		    (rr1 & mask))
+			error = EIO;
+		else
+			error = 0;
+		break;
+
+	case BIO_WRITE:
+		if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
+			error = EIO;
+		else
+			error = 0;
+		break;
+
+	default:
+		break;
+	}
+	if (error) {
+		sc->as_retriesleft--;
+		if (sc->as_retriesleft == 0 || bootverbose)
+			device_printf(sc->as_dev, "%s: %s operation block %ju "
+			    "length %ju failed; asr 0x%08x (rr1: 0x%04x)%s\n",
+			    __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
+			    (bp->bio_cmd == BIO_WRITE ? "BIO_WRITE" :
+			    "unknown"),
+			    bp->bio_pblkno, bp->bio_bcount, asr, rr1,
+			    sc->as_retriesleft != 0 ? " retrying" : "");
+		/*
+		 * This attempt experienced an error; possibly retry.
+		 */
+		if (sc->as_retriesleft != 0) {
+			sc->as_flags |= ALTERA_SDCARD_FLAG_IOERROR;
+			altera_sdcard_io_start_internal(sc, bp);
+			return (0);
+		}
+		sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
+	} else {
+		/*
+		 * Successful I/O completion path.
+		 */
+		if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR) {
+			device_printf(sc->as_dev, "%s: %s operation block %ju"
+			    " length %ju succeeded after %d retries\n",
+			    __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
+			    (bp->bio_cmd == BIO_WRITE ? "write" : "unknown"),
+			    bp->bio_pblkno, bp->bio_bcount,
+			    ALTERA_SDCARD_RETRY_LIMIT - sc->as_retriesleft);
+			sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
+		}
+		switch (bp->bio_cmd) {
+		case BIO_READ:
+			altera_sdcard_read_rxtx_buffer(sc, bp->bio_data,
+			    bp->bio_bcount);
+			break;
+
+		case BIO_WRITE:
+			break;
+
+		default:
+			panic("%s: unsupported I/O operation %d", __func__,
+			    bp->bio_cmd);
+		}
+		bp->bio_resid = 0;
+		error = 0;
+	}
+	biofinish(bp, NULL, error);
+	sc->as_currentbio = NULL;
+	return (1);
+}


Property changes on: trunk/sys/dev/altera/sdcard/altera_sdcard_io.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sys/dev/altera/sdcard/altera_sdcard_nexus.c
===================================================================
--- trunk/sys/dev/altera/sdcard/altera_sdcard_nexus.c	                        (rev 0)
+++ trunk/sys/dev/altera/sdcard/altera_sdcard_nexus.c	2018-05-28 00:11:41 UTC (rev 10115)
@@ -0,0 +1,115 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2012 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sys/dev/altera/sdcard/altera_sdcard_nexus.c 265999 2014-05-14 01:35:43Z ian $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/conf.h>
+#include <sys/bio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <geom/geom_disk.h>
+
+#include <dev/altera/sdcard/altera_sdcard.h>
+
+/*
+ * Nexus bus attachment for the Altera SD Card IP core.  Appropriate for most
+ * Altera FPGA SoC-style configurations in which the IP core will be exposed
+ * to the processor via a memory-mapped Avalon bus.
+ */
+static int
+altera_sdcard_nexus_probe(device_t dev)
+{
+
+	device_set_desc(dev, "Altera Secure Data Card IP Core");
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+altera_sdcard_nexus_attach(device_t dev)
+{
+	struct altera_sdcard_softc *sc;
+
+	sc = device_get_softc(dev);
+	sc->as_dev = dev;
+	sc->as_unit = device_get_unit(dev);
+	sc->as_rid = 0;
+	sc->as_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->as_rid, RF_ACTIVE);
+	if (sc->as_res == NULL) {
+		device_printf(dev, "couldn't map memory\n");
+		return (ENXIO);
+	}
+	altera_sdcard_attach(sc);
+	return (0);
+}
+
+static int
+altera_sdcard_nexus_detach(device_t dev)
+{
+	struct altera_sdcard_softc *sc;
+
+	sc = device_get_softc(dev);
+	KASSERT(sc->as_res != NULL, ("%s: resources not allocated",
+	    __func__));
+	altera_sdcard_detach(sc);
+	bus_release_resource(dev, SYS_RES_MEMORY, sc->as_rid, sc->as_res);
+	return (0);
+}
+
+static device_method_t altera_sdcard_nexus_methods[] = {
+	DEVMETHOD(device_probe,		altera_sdcard_nexus_probe),
+	DEVMETHOD(device_attach,	altera_sdcard_nexus_attach),
+	DEVMETHOD(device_detach,	altera_sdcard_nexus_detach),
+	{ 0, 0 }
+};
+
+static driver_t altera_sdcard_nexus_driver = {
+	"altera_sdcardc",
+	altera_sdcard_nexus_methods,
+	sizeof(struct altera_sdcard_softc),
+};
+
+DRIVER_MODULE(altera_sdcard, nexus, altera_sdcard_nexus_driver,
+    altera_sdcard_devclass, 0, 0);


Property changes on: trunk/sys/dev/altera/sdcard/altera_sdcard_nexus.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list