[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