diff options
Diffstat (limited to 'sys/dev/altera')
26 files changed, 0 insertions, 8290 deletions
diff --git a/sys/dev/altera/atse/if_atse.c b/sys/dev/altera/atse/if_atse.c deleted file mode 100644 index 923292484207..000000000000 --- a/sys/dev/altera/atse/if_atse.c +++ /dev/null @@ -1,1597 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2012, 2013 Bjoern A. Zeeb - * Copyright (c) 2014 Robert N. M. Watson - * Copyright (c) 2016-2017 Ruslan Bukin <br@bsdpad.com> - * 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> -#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/xdma/xdma.h> - -#define RX_QUEUE_SIZE 4096 -#define TX_QUEUE_SIZE 4096 -#define NUM_RX_MBUF 512 -#define BUFRING_SIZE 8192 - -#include <machine/cache.h> - -/* 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]; - -/* - * 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_DEBUG -#undef ATSE_DEBUG - -#ifdef ATSE_DEBUG -#define DPRINTF(format, ...) printf(format, __VA_ARGS__) -#else -#define DPRINTF(format, ...) -#endif - -/* - * 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); - -static int -atse_rx_enqueue(struct atse_softc *sc, uint32_t n) -{ - struct mbuf *m; - int i; - - for (i = 0; i < n; i++) { - m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - device_printf(sc->dev, - "%s: Can't alloc rx mbuf\n", __func__); - return (-1); - } - - m->m_pkthdr.len = m->m_len = m->m_ext.ext_size; - xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM); - } - - return (0); -} - -static int -atse_xdma_tx_intr(void *arg, xdma_transfer_status_t *status) -{ - xdma_transfer_status_t st; - struct atse_softc *sc; - if_t ifp; - struct mbuf *m; - int err; - - sc = arg; - - ATSE_LOCK(sc); - - ifp = sc->atse_ifp; - - for (;;) { - err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st); - if (err != 0) { - break; - } - - if (st.error != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } - - m_freem(m); - sc->txcount--; - } - - if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); - - ATSE_UNLOCK(sc); - - return (0); -} - -static int -atse_xdma_rx_intr(void *arg, xdma_transfer_status_t *status) -{ - xdma_transfer_status_t st; - struct atse_softc *sc; - if_t ifp; - struct mbuf *m; - int err; - uint32_t cnt_processed; - - sc = arg; - - ATSE_LOCK(sc); - - ifp = sc->atse_ifp; - - cnt_processed = 0; - for (;;) { - err = xdma_dequeue_mbuf(sc->xchan_rx, &m, &st); - if (err != 0) { - break; - } - cnt_processed++; - - if (st.error != 0) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - m_freem(m); - continue; - } - - m->m_pkthdr.len = m->m_len = st.transferred; - m->m_pkthdr.rcvif = ifp; - m_adj(m, ETHER_ALIGN); - ATSE_UNLOCK(sc); - if_input(ifp, m); - ATSE_LOCK(sc); - } - - atse_rx_enqueue(sc, cnt_processed); - - ATSE_UNLOCK(sc); - - return (0); -} - -static int -atse_transmit_locked(if_t ifp) -{ - struct atse_softc *sc; - struct mbuf *m; - struct buf_ring *br; - int error; - int enq; - - sc = if_getsoftc(ifp); - br = sc->br; - - enq = 0; - - while ((m = drbr_peek(ifp, br)) != NULL) { - error = xdma_enqueue_mbuf(sc->xchan_tx, &m, 0, 4, 4, XDMA_MEM_TO_DEV); - if (error != 0) { - /* No space in request queue available yet. */ - drbr_putback(ifp, br, m); - break; - } - - drbr_advance(ifp, br); - - sc->txcount++; - enq++; - - /* If anyone is interested give them a copy. */ - ETHER_BPF_MTAP(ifp, m); - } - - if (enq > 0) - xdma_queue_submit(sc->xchan_tx); - - return (0); -} - -static int -atse_transmit(if_t ifp, struct mbuf *m) -{ - struct atse_softc *sc; - struct buf_ring *br; - int error; - - sc = if_getsoftc(ifp); - br = sc->br; - - ATSE_LOCK(sc); - - mtx_lock(&sc->br_mtx); - - if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) { - error = drbr_enqueue(ifp, sc->br, m); - mtx_unlock(&sc->br_mtx); - ATSE_UNLOCK(sc); - return (error); - } - - if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) { - error = drbr_enqueue(ifp, sc->br, m); - mtx_unlock(&sc->br_mtx); - ATSE_UNLOCK(sc); - return (error); - } - - error = drbr_enqueue(ifp, br, m); - if (error) { - mtx_unlock(&sc->br_mtx); - ATSE_UNLOCK(sc); - return (error); - } - error = atse_transmit_locked(ifp); - - mtx_unlock(&sc->br_mtx); - ATSE_UNLOCK(sc); - - return (error); -} - -static void -atse_qflush(if_t ifp) -{ - struct atse_softc *sc; - - sc = if_getsoftc(ifp); - - printf("%s\n", __func__); -} - -static int -atse_stop_locked(struct atse_softc *sc) -{ - uint32_t mask, val4; - if_t ifp; - int i; - - ATSE_LOCK_ASSERT(sc); - - callout_stop(&sc->atse_tick); - - ifp = sc->atse_ifp; - if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); - - /* 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; - - return (0); -} - -static u_int -atse_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) -{ - uint64_t *h = arg; - uint8_t *addr, x, y; - int i, j; - - addr = LLADDR(sdl); - 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); - } - *h |= (1 << x); - - return (1); -} - -static int -atse_rxfilter_locked(struct atse_softc *sc) -{ - if_t ifp; - 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 (if_getflags(ifp) & 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 (if_getflags(ifp) & 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; - - /* - * 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. - */ - h = 0; - (void)if_foreach_llmaddr(ifp, atse_hash_maddr, &h); - 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 address: 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) -{ - uint32_t val4, mask; - uint16_t val; - int i; - - /* 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; - 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) -{ - if_t ifp; - struct mii_data *mii; - uint8_t *eaddr; - - ATSE_LOCK_ASSERT(sc); - ifp = sc->atse_ifp; - - if ((if_getdrvflags(ifp) & 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_getlladdr(sc->atse_ifp); - bcopy(eaddr, &sc->atse_eth_addr, ETHER_ADDR_LEN); - - /* Make things frind to halt, cleanup, ... */ - atse_stop_locked(sc); - - atse_reset(sc); - - /* ... and fire up the engine again. */ - atse_rxfilter_locked(sc); - - sc->atse_flags &= ATSE_FLAGS_LINK; /* Preserve. */ - - mii = device_get_softc(sc->atse_miibus); - - sc->atse_flags &= ~ATSE_FLAGS_LINK; - mii_mediachg(mii); - - if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); - if_setdrvflagbits(ifp, 0, 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(if_t ifp, u_long command, caddr_t data) -{ - struct atse_softc *sc; - struct ifreq *ifr; - int error, mask; - - error = 0; - sc = if_getsoftc(ifp); - ifr = (struct ifreq *)data; - - switch (command) { - case SIOCSIFFLAGS: - ATSE_LOCK(sc); - if (if_getflags(ifp) & IFF_UP) { - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0 && - ((if_getflags(ifp) ^ sc->atse_if_flags) & - (IFF_PROMISC | IFF_ALLMULTI)) != 0) - atse_rxfilter_locked(sc); - else - atse_init_locked(sc); - } else if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) - atse_stop_locked(sc); - sc->atse_if_flags = if_getflags(ifp); - ATSE_UNLOCK(sc); - break; - case SIOCSIFCAP: - ATSE_LOCK(sc); - mask = ifr->ifr_reqcap ^ if_getcapenable(ifp); - 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_tick(void *xsc) -{ - struct atse_softc *sc; - struct mii_data *mii; - if_t ifp; - - sc = (struct atse_softc *)xsc; - ATSE_LOCK_ASSERT(sc); - ifp = sc->atse_ifp; - - mii = device_get_softc(sc->atse_miibus); - mii_tick(mii); - 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(if_t ifp) -{ - struct atse_softc *sc; - struct mii_data *mii; - struct mii_softc *miisc; - int error; - - sc = if_getsoftc(ifp); - - 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); -} - -/* - * Report current media status. - */ -static void -atse_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) -{ - struct atse_softc *sc; - struct mii_data *mii; - - sc = if_getsoftc(ifp); - - 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 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 < nitems(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 | CTLFLAG_NEEDGIANT, - 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 | CTLFLAG_NEEDGIANT, - 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; - if_t ifp; - uint32_t caps; - int error; - - sc = device_get_softc(dev); - sc->dev = dev; - - /* Get xDMA controller */ - sc->xdma_tx = xdma_ofw_get(sc->dev, "tx"); - if (sc->xdma_tx == NULL) { - device_printf(dev, "Can't find DMA controller.\n"); - return (ENXIO); - } - - /* - * Only final (EOP) write can be less than "symbols per beat" value - * so we have to defrag mbuf chain. - * Chapter 15. On-Chip FIFO Memory Core. - * Embedded Peripherals IP User Guide. - */ - caps = XCHAN_CAP_NOSEG; - - /* Alloc xDMA virtual channel. */ - sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, caps); - if (sc->xchan_tx == NULL) { - device_printf(dev, "Can't alloc virtual DMA channel.\n"); - return (ENXIO); - } - - /* Setup interrupt handler. */ - error = xdma_setup_intr(sc->xchan_tx, 0, - atse_xdma_tx_intr, sc, &sc->ih_tx); - if (error) { - device_printf(sc->dev, - "Can't setup xDMA interrupt handler.\n"); - return (ENXIO); - } - - xdma_prep_sg(sc->xchan_tx, - TX_QUEUE_SIZE, /* xchan requests queue size */ - MCLBYTES, /* maxsegsize */ - 8, /* maxnsegs */ - 16, /* alignment */ - 0, /* boundary */ - BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR); - - /* Get RX xDMA controller */ - sc->xdma_rx = xdma_ofw_get(sc->dev, "rx"); - if (sc->xdma_rx == NULL) { - device_printf(dev, "Can't find DMA controller.\n"); - return (ENXIO); - } - - /* Alloc xDMA virtual channel. */ - sc->xchan_rx = xdma_channel_alloc(sc->xdma_rx, caps); - if (sc->xchan_rx == NULL) { - device_printf(dev, "Can't alloc virtual DMA channel.\n"); - return (ENXIO); - } - - /* Setup interrupt handler. */ - error = xdma_setup_intr(sc->xchan_rx, XDMA_INTR_NET, - atse_xdma_rx_intr, sc, &sc->ih_rx); - if (error) { - device_printf(sc->dev, - "Can't setup xDMA interrupt handler.\n"); - return (ENXIO); - } - - xdma_prep_sg(sc->xchan_rx, - RX_QUEUE_SIZE, /* xchan requests queue size */ - MCLBYTES, /* maxsegsize */ - 1, /* maxnsegs */ - 16, /* alignment */ - 0, /* boundary */ - BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR); - - mtx_init(&sc->br_mtx, "buf ring mtx", NULL, MTX_DEF); - sc->br = buf_ring_alloc(BUFRING_SIZE, M_DEVBUF, - M_NOWAIT, &sc->br_mtx); - if (sc->br == NULL) { - return (ENOMEM); - } - - 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); - - /* - * 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; - } - if_setsoftc(ifp, sc); - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); - if_setioctlfn(ifp, atse_ioctl); - if_settransmitfn(ifp, atse_transmit); - if_setqflushfn(ifp, atse_qflush); - if_setinitfn(ifp, atse_init); - if_setsendqlen(ifp, ATSE_TX_LIST_CNT - 1); - if_setsendqready(ifp); - - /* 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. */ - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); - if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0); - if_setcapenable(ifp, if_getcapabilities(ifp)); - -err: - if (error != 0) { - atse_detach(dev); - } - - if (error == 0) { - atse_sysctl_stats_attach(dev); - } - - atse_rx_enqueue(sc, NUM_RX_MBUF); - xdma_queue_submit(sc->xchan_rx); - - return (error); -} - -static int -atse_detach(device_t dev) -{ - struct atse_softc *sc; - if_t ifp; - - sc = device_get_softc(dev); - KASSERT(mtx_initialized(&sc->atse_mtx), ("%s: mutex not initialized", - device_get_nameunit(dev))); - ifp = sc->atse_ifp; - - /* 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 (ifp != NULL) { - if_free(ifp); - } - - mtx_destroy(&sc->atse_mtx); - - xdma_channel_free(sc->xchan_tx); - xdma_channel_free(sc->xchan_rx); - xdma_put(sc->xdma_tx); - xdma_put(sc->xdma_rx); - - 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_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; - int val; - - 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); - } - - val = PHY_READ_2(sc, reg); - - return (val); -} - -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; - if_t 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 || - (if_getdrvflags(ifp) & 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) { - /* 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; - } - - /* 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); -} - -MODULE_DEPEND(atse, ether, 1, 1, 1); -MODULE_DEPEND(atse, miibus, 1, 1, 1); diff --git a/sys/dev/altera/atse/if_atse_fdt.c b/sys/dev/altera/atse/if_atse_fdt.c deleted file mode 100644 index 77fa930ee945..000000000000 --- a/sys/dev/altera/atse/if_atse_fdt.c +++ /dev/null @@ -1,144 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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 <net/if_var.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")) { - return (ENXIO); - } - - device_set_desc(dev, "Altera Triple-Speed Ethernet MegaCore"); - - return (BUS_PROBE_DEFAULT); -} - -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"); - /* Cleanup. */ - atse_detach_resources(dev); - - return (ENXIO); - } - 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))); - - error = atse_attach(dev); - if (error) { - /* Cleanup. */ - atse_detach_resources(dev); - - return (error); - } - - return (0); -} - -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, 0, 0); -DRIVER_MODULE(miibus, atse, miibus_driver, 0, 0); diff --git a/sys/dev/altera/atse/if_atse_nexus.c b/sys/dev/altera/atse/if_atse_nexus.c deleted file mode 100644 index 22a66dd305d4..000000000000 --- a/sys/dev/altera/atse/if_atse_nexus.c +++ /dev/null @@ -1,158 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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> -#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 <net/if_var.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 __unused -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 __unused -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) -{ - - 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); - - /* 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); - } - - error = atse_attach(dev); - if (error) { - /* Cleanup. */ - atse_detach_resources(dev); - return (error); - } - - return (0); -} - -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, 0, 0); -DRIVER_MODULE(miibus, atse, miibus_driver, 0, 0); diff --git a/sys/dev/altera/atse/if_atsereg.h b/sys/dev/altera/atse/if_atsereg.h deleted file mode 100644 index 2f7643f27094..000000000000 --- a/sys/dev/altera/atse/if_atsereg.h +++ /dev/null @@ -1,464 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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. - */ - -#ifndef _DEV_IF_ATSEREG_H -#define _DEV_IF_ATSEREG_H - -#include <dev/xdma/xdma.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 { - if_t atse_ifp; - struct resource *atse_mem_res; - device_t atse_miibus; - device_t atse_dev; - int atse_unit; - int atse_mem_rid; - int atse_phy_addr; - int atse_if_flags; - 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 - 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; - device_t dev; - - /* xDMA */ - xdma_controller_t *xdma_tx; - xdma_channel_t *xchan_tx; - void *ih_tx; - int txcount; - - xdma_controller_t *xdma_rx; - xdma_channel_t *xchan_rx; - void *ih_rx; - - struct buf_ring *br; - struct mtx br_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); - -#endif /* _DEV_IF_ATSEREG_H */ diff --git a/sys/dev/altera/avgen/altera_avgen.c b/sys/dev/altera/avgen/altera_avgen.c deleted file mode 100644 index 846167c649f8..000000000000 --- a/sys/dev/altera/avgen/altera_avgen.c +++ /dev/null @@ -1,551 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2012-2013, 2016 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/param.h> -#include <sys/bio.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 <geom/geom_disk.h> - -#include <machine/bus.h> -#include <machine/resource.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. - */ - -static d_mmap_t altera_avgen_mmap; -static d_read_t altera_avgen_read; -static d_write_t altera_avgen_write; - -#define ALTERA_AVGEN_DEVNAME "altera_avgen" -#define ALTERA_AVGEN_DEVNAME_FMT (ALTERA_AVGEN_DEVNAME "%d") - -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_DEVNAME, -}; - -#define ALTERA_AVGEN_SECTORSIZE 512 /* Not configurable at this time. */ - -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 && - offset + PAGE_SIZE > 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); -} - -/* - * NB: We serialise block reads and writes in case the OS is generating - * concurrent I/O against the same block, in which case we want one I/O (or - * another) to win. This is not sufficient to provide atomicity for the - * sector in the presence of a fail stop -- however, we're just writing this - * to non-persistent DRAM .. right? - */ -static void -altera_avgen_disk_strategy(struct bio *bp) -{ - struct altera_avgen_softc *sc; - void *data; - long bcount; - daddr_t pblkno; - int error; - - sc = bp->bio_disk->d_drv1; - data = bp->bio_data; - bcount = bp->bio_bcount; - pblkno = bp->bio_pblkno; - error = 0; - - /* - * Serialize block reads / writes. - */ - mtx_lock(&sc->avg_disk_mtx); - switch (bp->bio_cmd) { - case BIO_READ: - if (!(sc->avg_flags & ALTERA_AVALON_FLAG_GEOM_READ)) { - error = EROFS; - break; - } - switch (sc->avg_width) { - case 1: - bus_read_region_1(sc->avg_res, - bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE, - (uint8_t *)data, bcount); - break; - - case 2: - bus_read_region_2(sc->avg_res, - bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE, - (uint16_t *)data, bcount / 2); - break; - - case 4: - bus_read_region_4(sc->avg_res, - bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE, - (uint32_t *)data, bcount / 4); - break; - - default: - panic("%s: unexpected width %u", __func__, - sc->avg_width); - } - break; - - case BIO_WRITE: - if (!(sc->avg_flags & ALTERA_AVALON_FLAG_GEOM_WRITE)) { - biofinish(bp, NULL, EROFS); - break; - } - switch (sc->avg_width) { - case 1: - bus_write_region_1(sc->avg_res, - bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE, - (uint8_t *)data, bcount); - break; - - case 2: - bus_write_region_2(sc->avg_res, - bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE, - (uint16_t *)data, bcount / 2); - break; - - case 4: - bus_write_region_4(sc->avg_res, - bp->bio_pblkno * ALTERA_AVGEN_SECTORSIZE, - (uint32_t *)data, bcount / 4); - break; - - default: - panic("%s: unexpected width %u", __func__, - sc->avg_width); - } - break; - - default: - error = EOPNOTSUPP; - break; - } - mtx_unlock(&sc->avg_disk_mtx); - biofinish(bp, NULL, error); -} - -static int -altera_avgen_process_options(struct altera_avgen_softc *sc, - const char *str_fileio, const char *str_geomio, 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_geomio == NULL && str_mmapio == NULL) { - device_printf(dev, - "at least one of %s, %s, or %s must be specified\n", - ALTERA_AVALON_STR_FILEIO, ALTERA_AVALON_STR_GEOMIO, - ALTERA_AVALON_STR_MMAPIO); - return (ENXIO); - } - - /* - * Validity check: a device can either be a GEOM device (in which case - * we use GEOM to register the device node), or a special device -- - * but not both as that causes a collision in /dev. - */ - if (str_geomio != NULL && (str_fileio != NULL || str_mmapio != NULL)) { - device_printf(dev, - "at most one of %s and (%s or %s) may be specified\n", - ALTERA_AVALON_STR_GEOMIO, ALTERA_AVALON_STR_FILEIO, - ALTERA_AVALON_STR_MMAPIO); - return (ENXIO); - } - - /* - * Ensure that a unit is specified if a name is also specified. - */ - 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_geomio != NULL) { - for (cp = str_geomio; *cp != '\0'; cp++){ - switch (*cp) { - case ALTERA_AVALON_CHAR_READ: - sc->avg_flags |= ALTERA_AVALON_FLAG_GEOM_READ; - break; - - case ALTERA_AVALON_CHAR_WRITE: - sc->avg_flags |= ALTERA_AVALON_FLAG_GEOM_WRITE; - break; - - default: - device_printf(dev, - "invalid %s character %c\n", - ALTERA_AVALON_STR_GEOMIO, *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_geomio, 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_geomio, - 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); - } - } - - /* - * If a GEOM permission is requested, then create the device via GEOM. - * Otherwise, create a special device. We checked during options - * processing that both weren't requested a once. - */ - if (str_devname != NULL) { - sc->avg_name = strdup(str_devname, M_TEMP); - devunit = sc->avg_unit; - } else - sc->avg_name = strdup(ALTERA_AVGEN_DEVNAME, M_TEMP); - if (sc->avg_flags & (ALTERA_AVALON_FLAG_GEOM_READ | - ALTERA_AVALON_FLAG_GEOM_WRITE)) { - mtx_init(&sc->avg_disk_mtx, "altera_avgen_disk", NULL, - MTX_DEF); - sc->avg_disk = disk_alloc(); - sc->avg_disk->d_drv1 = sc; - sc->avg_disk->d_strategy = altera_avgen_disk_strategy; - if (devunit == -1) - devunit = 0; - sc->avg_disk->d_name = sc->avg_name; - sc->avg_disk->d_unit = devunit; - - /* - * NB: As avg_res is a multiple of PAGE_SIZE, it is also a - * multiple of ALTERA_AVGEN_SECTORSIZE. - */ - sc->avg_disk->d_sectorsize = ALTERA_AVGEN_SECTORSIZE; - sc->avg_disk->d_mediasize = rman_get_size(sc->avg_res); - sc->avg_disk->d_maxsize = ALTERA_AVGEN_SECTORSIZE; - disk_create(sc->avg_disk, DISK_VERSION); - } else { - /* Device node allocation. */ - if (str_devname == NULL) { - str_devname = ALTERA_AVGEN_DEVNAME_FMT; - 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, "%s%d", - str_devname, devunit); - else - sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit, - UID_ROOT, GID_WHEEL, S_IRUSR | S_IWUSR, - "%s", 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) -{ - - KASSERT((sc->avg_disk != NULL) || (sc->avg_cdev != NULL), - ("%s: neither GEOM nor special device", __func__)); - - if (sc->avg_disk != NULL) { - disk_gone(sc->avg_disk); - disk_destroy(sc->avg_disk); - free(sc->avg_name, M_TEMP); - mtx_destroy(&sc->avg_disk_mtx); - } else { - destroy_dev(sc->avg_cdev); - } -} diff --git a/sys/dev/altera/avgen/altera_avgen.h b/sys/dev/altera/avgen/altera_avgen.h deleted file mode 100644 index ffa813b8ec65..000000000000 --- a/sys/dev/altera/avgen/altera_avgen.h +++ /dev/null @@ -1,96 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2012, 2016 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. - */ - -#ifndef _DEV_ALTERA_AVALON_H_ -#define _DEV_ALTERA_AVALON_H_ - -struct altera_avgen_softc { - /* - * Bus-related fields. - */ - device_t avg_dev; - int avg_unit; - char *avg_name; - - /* - * 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; - u_int avg_sectorsize; - - /* - * disk(9) state, if required for this device. - */ - struct disk *avg_disk; - struct mtx avg_disk_mtx; -}; - -/* - * 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_FLAG_GEOM_READ 0x20 -#define ALTERA_AVALON_FLAG_GEOM_WRITE 0x40 - -#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_GEOMIO "geomio" -#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_geomio, - const char *str_mmapio, const char *str_devname, int devunit); -void altera_avgen_detach(struct altera_avgen_softc *sc); - -#endif /* _DEV_ALTERA_AVALON_H_ */ diff --git a/sys/dev/altera/avgen/altera_avgen_fdt.c b/sys/dev/altera/avgen/altera_avgen_fdt.c deleted file mode 100644 index ad12fc9df265..000000000000 --- a/sys/dev/altera/avgen/altera_avgen_fdt.c +++ /dev/null @@ -1,159 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2012-2013, 2016 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/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 <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_geomio, *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_geomio = 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", - (void **)&str_fileio); - (void)OF_getprop_alloc(node, "sri-cambridge,geomio", - (void **)&str_geomio); - (void)OF_getprop_alloc(node, "sri-cambridge,mmapio", - (void **)&str_mmapio); - (void)OF_getprop_alloc(node, "sri-cambridge,devname", - (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_geomio, 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) - OF_prop_free(str_fileio); - if (str_geomio != NULL) - OF_prop_free(str_geomio); - if (str_mmapio != NULL) - OF_prop_free(str_mmapio); - if (str_devname != NULL) - OF_prop_free(str_devname); - 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, 0, 0); diff --git a/sys/dev/altera/avgen/altera_avgen_nexus.c b/sys/dev/altera/avgen/altera_avgen_nexus.c deleted file mode 100644 index 67448bc83f9c..000000000000 --- a/sys/dev/altera/avgen/altera_avgen_nexus.c +++ /dev/null @@ -1,141 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2012-2013, 2016 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/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 <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_geomio, *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_geomio = 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_GEOMIO, &str_geomio); - (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_geomio, 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, 0, 0); diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart.h b/sys/dev/altera/jtag_uart/altera_jtag_uart.h deleted file mode 100644 index 1f64184f963f..000000000000 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart.h +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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. - */ - -#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); - -#endif /* _DEV_ALTERA_JTAG_UART_H_ */ diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c deleted file mode 100644 index dd708bd68f22..000000000000 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart_cons.c +++ /dev/null @@ -1,331 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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/sysctl.h> -#include <sys/systm.h> -#include <sys/tty.h> - -#include <ddb/ddb.h> - -#include <dev/altera/jtag_uart/altera_jtag_uart.h> - -static SYSCTL_NODE(_hw, OID_AUTO, altera_jtag_uart, - CTLFLAG_RW | CTLFLAG_MPSAFE, 0, - "Altera JTAG UART configuration knobs"); - -/* - * 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 -static u_int altera_jtag_uart_ac_poll_delay = - ALTERA_JTAG_UART_AC_POLL_DELAY; -SYSCTL_UINT(_hw_altera_jtag_uart, OID_AUTO, ac_poll_delay, - CTLFLAG_RW, &altera_jtag_uart_ac_poll_delay, 0, - "Maximum delay waiting for JTAG present flag when buffer is full"); - -/* - * 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: Notice the inherent race with hardware: in clearing the - * bit, we may race with hardware setting the same bit. This can - * cause real-world reliability problems due to lost output on the - * console. - */ - 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); diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c deleted file mode 100644 index 6290238d784b..000000000000 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart_fdt.c +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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, 0, 0); diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c deleted file mode 100644 index 141518e85cb5..000000000000 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart_nexus.c +++ /dev/null @@ -1,139 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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, 0, 0); diff --git a/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c b/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c deleted file mode 100644 index 3a299d80caa1..000000000000 --- a/sys/dev/altera/jtag_uart/altera_jtag_uart_tty.c +++ /dev/null @@ -1,561 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2011-2012, 2016 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/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/sysctl.h> -#include <sys/tty.h> - -#include <ddb/ddb.h> - -#include <machine/atomic.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, four seconds. - */ -#define AJU_JTAG_MAXMISS 20 - -/* - * Polling intervals for input/output and JTAG connection events. - */ -#define AJU_IO_POLLINTERVAL (hz/100) -#define AJU_AC_POLLINTERVAL (hz/5) - -/* - * Statistics on JTAG removal events when sending, for debugging purposes - * only. - */ -static u_int aju_jtag_vanished; -SYSCTL_UINT(_debug, OID_AUTO, aju_jtag_vanished, CTLFLAG_RW, - &aju_jtag_vanished, 0, "Number of times JTAG has vanished"); - -static u_int aju_jtag_appeared; -SYSCTL_UINT(_debug, OID_AUTO, aju_jtag_appeared, CTLFLAG_RW, - &aju_jtag_appeared, 0, "Number of times JTAG has appeared"); - -SYSCTL_INT(_debug, OID_AUTO, aju_cons_jtag_present, CTLFLAG_RW, - &aju_cons_jtag_present, 0, "JTAG console present flag"); - -SYSCTL_UINT(_debug, OID_AUTO, aju_cons_jtag_missed, CTLFLAG_RW, - &aju_cons_jtag_missed, 0, "JTAG console missed counter"); - -/* - * Interrupt-related statistics. - */ -static u_int aju_intr_readable_enabled; -SYSCTL_UINT(_debug, OID_AUTO, aju_intr_readable_enabled, CTLFLAG_RW, - &aju_intr_readable_enabled, 0, "Number of times read interrupt enabled"); - -static u_int aju_intr_writable_disabled; -SYSCTL_UINT(_debug, OID_AUTO, aju_intr_writable_disabled, CTLFLAG_RW, - &aju_intr_writable_disabled, 0, - "Number of times write interrupt disabled"); - -static u_int aju_intr_writable_enabled; -SYSCTL_UINT(_debug, OID_AUTO, aju_intr_writable_enabled, CTLFLAG_RW, - &aju_intr_writable_enabled, 0, - "Number of times write interrupt enabled"); - -static u_int aju_intr_disabled; -SYSCTL_UINT(_debug, OID_AUTO, aju_intr_disabled, CTLFLAG_RW, - &aju_intr_disabled, 0, "Number of times write interrupt disabled"); - -static u_int aju_intr_read_count; -SYSCTL_UINT(_debug, OID_AUTO, aju_intr_read_count, CTLFLAG_RW, - &aju_intr_read_count, 0, "Number of times read interrupt fired"); - -static u_int aju_intr_write_count; -SYSCTL_UINT(_debug, OID_AUTO, aju_intr_write_count, CTLFLAG_RW, - &aju_intr_write_count, 0, "Number of times write interrupt fired"); - -/* - * 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); - - atomic_add_int(&aju_intr_readable_enabled, 1); - 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); - - atomic_add_int(&aju_intr_writable_enabled, 1); - 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); - - atomic_add_int(&aju_intr_writable_disabled, 1); - 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); - - atomic_add_int(&aju_intr_disabled, 1); - 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_assert_locked(tp); - 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_assert_locked(tp); - AJU_LOCK_ASSERT(sc); - - AJU_UNLOCK(sc); - while (ttydisc_getc_poll(tp) != 0) { - AJU_LOCK(sc); - if (*sc->ajus_jtag_presentp == 0) { - /* - * 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. - */ - AJU_UNLOCK(sc); - if (ttydisc_getc(tp, &ch, sizeof(ch)) != - sizeof(ch)) - panic("%s: ttydisc_getc", __func__); - continue; - } - v = aju_control_read(sc); - if ((v & ALTERA_JTAG_UART_CONTROL_WSPACE) == 0) { - if (sc->ajus_irq_res != NULL && - (v & ALTERA_JTAG_UART_CONTROL_WE) == 0) - aju_intr_writable_enable(sc); - return; - } - AJU_UNLOCK(sc); - if (ttydisc_getc(tp, &ch, sizeof(ch)) != sizeof(ch)) - panic("%s: ttydisc_getc 2", __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); - AJU_UNLOCK(sc); - } - AJU_LOCK(sc); - - /* - * If interrupts are configured, and there's no data to write, but we - * had previously enabled write interrupts, disable them now. - */ - v = aju_control_read(sc); - if (sc->ajus_irq_res != NULL && (v & ALTERA_JTAG_UART_CONTROL_WE) != 0) - aju_intr_writable_disable(sc); -} - -static void -aju_outwakeup(struct tty *tp) -{ - struct altera_jtag_uart_softc *sc = tty_softc(tp); - - tty_assert_locked(tp); - - 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_presentp = 1; - atomic_add_int(&aju_jtag_appeared, 1); - aju_handle_output(sc, tp); - } - - /* Any hit eliminates all recent misses. */ - *sc->ajus_jtag_missedp = 0; - } else if (*sc->ajus_jtag_presentp != 0) { - /* - * If we've exceeded our tolerance for misses, mark JTAG as - * disconnected and drain output. Otherwise, bump the miss - * counter. - */ - if (*sc->ajus_jtag_missedp > AJU_JTAG_MAXMISS) { - *sc->ajus_jtag_presentp = 0; - atomic_add_int(&aju_jtag_vanished, 1); - aju_handle_output(sc, tp); - } else - (*sc->ajus_jtag_missedp)++; - } - 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) { - atomic_add_int(&aju_intr_read_count, 1); - aju_handle_input(sc, tp); - } - if (v & ALTERA_JTAG_UART_CONTROL_WI) { - atomic_add_int(&aju_intr_write_count, 1); - 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); -} diff --git a/sys/dev/altera/msgdma/msgdma.c b/sys/dev/altera/msgdma/msgdma.c deleted file mode 100644 index bb35d7315b6c..000000000000 --- a/sys/dev/altera/msgdma/msgdma.c +++ /dev/null @@ -1,642 +0,0 @@ -/*- - * Copyright (c) 2016-2018 Ruslan Bukin <br@bsdpad.com> - * 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. - */ - -/* Altera mSGDMA driver. */ - -#include <sys/cdefs.h> -#include "opt_platform.h" -#include <sys/param.h> -#include <sys/endian.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/sglist.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/resource.h> -#include <sys/rman.h> - -#include <machine/bus.h> -#include <machine/fdt.h> -#include <machine/cache.h> - -#ifdef FDT -#include <dev/fdt/fdt_common.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> -#endif - -#include <dev/xdma/xdma.h> -#include "xdma_if.h" -#include "opt_altera_msgdma.h" - -#include <dev/altera/msgdma/msgdma.h> - -#define MSGDMA_DEBUG -#undef MSGDMA_DEBUG - -#ifdef MSGDMA_DEBUG -#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define dprintf(fmt, ...) -#endif - -#define MSGDMA_NCHANNELS 1 - -struct msgdma_channel { - struct msgdma_softc *sc; - struct mtx mtx; - xdma_channel_t *xchan; - struct proc *p; - int used; - int index; - int idx_head; - int idx_tail; - - struct msgdma_desc **descs; - bus_dma_segment_t *descs_phys; - uint32_t descs_num; - bus_dma_tag_t dma_tag; - bus_dmamap_t *dma_map; - uint32_t map_descr; - uint8_t map_err; - uint32_t descs_used_count; -}; - -struct msgdma_softc { - device_t dev; - struct resource *res[3]; - bus_space_tag_t bst; - bus_space_handle_t bsh; - bus_space_tag_t bst_d; - bus_space_handle_t bsh_d; - void *ih; - struct msgdma_desc desc; - struct msgdma_channel channels[MSGDMA_NCHANNELS]; -}; - -static struct resource_spec msgdma_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_MEMORY, 1, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -#define HWTYPE_NONE 0 -#define HWTYPE_STD 1 - -static struct ofw_compat_data compat_data[] = { - { "altr,msgdma-16.0", HWTYPE_STD }, - { "altr,msgdma-1.0", HWTYPE_STD }, - { NULL, HWTYPE_NONE }, -}; - -static int msgdma_probe(device_t dev); -static int msgdma_attach(device_t dev); -static int msgdma_detach(device_t dev); - -static inline uint32_t -msgdma_next_desc(struct msgdma_channel *chan, uint32_t curidx) -{ - - return ((curidx + 1) % chan->descs_num); -} - -static void -msgdma_intr(void *arg) -{ - xdma_transfer_status_t status; - struct xdma_transfer_status st; - struct msgdma_desc *desc; - struct msgdma_channel *chan; - struct xdma_channel *xchan; - struct msgdma_softc *sc; - uint32_t tot_copied; - - sc = arg; - chan = &sc->channels[0]; - xchan = chan->xchan; - - dprintf("%s(%d): status 0x%08x next_descr 0x%08x, control 0x%08x\n", - __func__, device_get_unit(sc->dev), - READ4_DESC(sc, PF_STATUS), - READ4_DESC(sc, PF_NEXT_LO), - READ4_DESC(sc, PF_CONTROL)); - - tot_copied = 0; - - while (chan->idx_tail != chan->idx_head) { - dprintf("%s: idx_tail %d idx_head %d\n", __func__, - chan->idx_tail, chan->idx_head); - bus_dmamap_sync(chan->dma_tag, chan->dma_map[chan->idx_tail], - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - - desc = chan->descs[chan->idx_tail]; - if ((le32toh(desc->control) & CONTROL_OWN) != 0) { - break; - } - - tot_copied += le32toh(desc->transferred); - st.error = 0; - st.transferred = le32toh(desc->transferred); - xchan_seg_done(xchan, &st); - - chan->idx_tail = msgdma_next_desc(chan, chan->idx_tail); - atomic_subtract_int(&chan->descs_used_count, 1); - } - - WRITE4_DESC(sc, PF_STATUS, PF_STATUS_IRQ); - - /* Finish operation */ - status.error = 0; - status.transferred = tot_copied; - xdma_callback(chan->xchan, &status); -} - -static int -msgdma_reset(struct msgdma_softc *sc) -{ - int timeout; - - dprintf("%s: read status: %x\n", __func__, READ4(sc, 0x00)); - dprintf("%s: read control: %x\n", __func__, READ4(sc, 0x04)); - dprintf("%s: read 1: %x\n", __func__, READ4(sc, 0x08)); - dprintf("%s: read 2: %x\n", __func__, READ4(sc, 0x0C)); - - WRITE4(sc, DMA_CONTROL, CONTROL_RESET); - - timeout = 100; - do { - if ((READ4(sc, DMA_STATUS) & STATUS_RESETTING) == 0) - break; - } while (timeout--); - - dprintf("timeout %d\n", timeout); - - if (timeout == 0) - return (-1); - - dprintf("%s: read control after reset: %x\n", - __func__, READ4(sc, DMA_CONTROL)); - - return (0); -} - -static int -msgdma_probe(device_t dev) -{ - int hwtype; - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data; - if (hwtype == HWTYPE_NONE) - return (ENXIO); - - device_set_desc(dev, "Altera mSGDMA"); - - return (BUS_PROBE_DEFAULT); -} - -static int -msgdma_attach(device_t dev) -{ - struct msgdma_softc *sc; - phandle_t xref, node; - int err; - - sc = device_get_softc(dev); - sc->dev = dev; - - if (bus_alloc_resources(dev, msgdma_spec, sc->res)) { - device_printf(dev, "could not allocate resources for device\n"); - return (ENXIO); - } - - /* CSR memory interface */ - sc->bst = rman_get_bustag(sc->res[0]); - sc->bsh = rman_get_bushandle(sc->res[0]); - - /* Descriptor memory interface */ - sc->bst_d = rman_get_bustag(sc->res[1]); - sc->bsh_d = rman_get_bushandle(sc->res[1]); - - /* Setup interrupt handler */ - err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE, - NULL, msgdma_intr, sc, &sc->ih); - if (err) { - device_printf(dev, "Unable to alloc interrupt resource.\n"); - return (ENXIO); - } - - node = ofw_bus_get_node(dev); - xref = OF_xref_from_node(node); - OF_device_register_xref(xref, dev); - - if (msgdma_reset(sc) != 0) - return (-1); - - WRITE4(sc, DMA_CONTROL, CONTROL_GIEM); - - return (0); -} - -static int -msgdma_detach(device_t dev) -{ - struct msgdma_softc *sc; - - sc = device_get_softc(dev); - - return (0); -} - -static void -msgdma_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) -{ - struct msgdma_channel *chan; - - chan = (struct msgdma_channel *)arg; - KASSERT(chan != NULL, ("xchan is NULL")); - - if (err) { - chan->map_err = 1; - return; - } - - chan->descs_phys[chan->map_descr].ds_addr = segs[0].ds_addr; - chan->descs_phys[chan->map_descr].ds_len = segs[0].ds_len; - - dprintf("map desc %d: descs phys %lx len %ld\n", - chan->map_descr, segs[0].ds_addr, segs[0].ds_len); -} - -static int -msgdma_desc_free(struct msgdma_softc *sc, struct msgdma_channel *chan) -{ - struct msgdma_desc *desc; - int nsegments; - int i; - - nsegments = chan->descs_num; - - for (i = 0; i < nsegments; i++) { - desc = chan->descs[i]; - bus_dmamap_unload(chan->dma_tag, chan->dma_map[i]); - bus_dmamem_free(chan->dma_tag, desc, chan->dma_map[i]); - } - - bus_dma_tag_destroy(chan->dma_tag); - free(chan->descs, M_DEVBUF); - free(chan->dma_map, M_DEVBUF); - free(chan->descs_phys, M_DEVBUF); - - return (0); -} - -static int -msgdma_desc_alloc(struct msgdma_softc *sc, struct msgdma_channel *chan, - uint32_t desc_size, uint32_t align) -{ - int nsegments; - int err; - int i; - - nsegments = chan->descs_num; - - dprintf("%s: nseg %d\n", __func__, nsegments); - - err = bus_dma_tag_create( - bus_get_dma_tag(sc->dev), - align, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - desc_size, 1, /* maxsize, nsegments*/ - desc_size, 0, /* maxsegsize, flags */ - NULL, NULL, /* lockfunc, lockarg */ - &chan->dma_tag); - if (err) { - device_printf(sc->dev, - "%s: Can't create bus_dma tag.\n", __func__); - return (-1); - } - - /* Descriptors. */ - chan->descs = malloc(nsegments * sizeof(struct msgdma_desc *), - M_DEVBUF, (M_WAITOK | M_ZERO)); - if (chan->descs == NULL) { - device_printf(sc->dev, - "%s: Can't allocate memory.\n", __func__); - return (-1); - } - chan->dma_map = malloc(nsegments * sizeof(bus_dmamap_t), - M_DEVBUF, (M_WAITOK | M_ZERO)); - chan->descs_phys = malloc(nsegments * sizeof(bus_dma_segment_t), - M_DEVBUF, (M_WAITOK | M_ZERO)); - - /* Allocate bus_dma memory for each descriptor. */ - for (i = 0; i < nsegments; i++) { - err = bus_dmamem_alloc(chan->dma_tag, (void **)&chan->descs[i], - BUS_DMA_WAITOK | BUS_DMA_ZERO, &chan->dma_map[i]); - if (err) { - device_printf(sc->dev, - "%s: Can't allocate memory for descriptors.\n", - __func__); - return (-1); - } - - chan->map_err = 0; - chan->map_descr = i; - err = bus_dmamap_load(chan->dma_tag, chan->dma_map[i], chan->descs[i], - desc_size, msgdma_dmamap_cb, chan, BUS_DMA_WAITOK); - if (err) { - device_printf(sc->dev, - "%s: Can't load DMA map.\n", __func__); - return (-1); - } - - if (chan->map_err != 0) { - device_printf(sc->dev, - "%s: Can't load DMA map.\n", __func__); - return (-1); - } - } - - return (0); -} - -static int -msgdma_channel_alloc(device_t dev, struct xdma_channel *xchan) -{ - struct msgdma_channel *chan; - struct msgdma_softc *sc; - int i; - - sc = device_get_softc(dev); - - for (i = 0; i < MSGDMA_NCHANNELS; i++) { - chan = &sc->channels[i]; - if (chan->used == 0) { - chan->xchan = xchan; - xchan->chan = (void *)chan; - if ((xchan->caps & XCHAN_CAP_IOMMU) == 0) - xchan->caps |= XCHAN_CAP_BUSDMA; - chan->index = i; - chan->sc = sc; - chan->used = 1; - chan->idx_head = 0; - chan->idx_tail = 0; - chan->descs_used_count = 0; - chan->descs_num = 1024; - - return (0); - } - } - - return (-1); -} - -static int -msgdma_channel_free(device_t dev, struct xdma_channel *xchan) -{ - struct msgdma_channel *chan; - struct msgdma_softc *sc; - - sc = device_get_softc(dev); - - chan = (struct msgdma_channel *)xchan->chan; - - msgdma_desc_free(sc, chan); - - chan->used = 0; - - return (0); -} - -static int -msgdma_channel_capacity(device_t dev, xdma_channel_t *xchan, - uint32_t *capacity) -{ - struct msgdma_channel *chan; - uint32_t c; - - chan = (struct msgdma_channel *)xchan->chan; - - /* At least one descriptor must be left empty. */ - c = (chan->descs_num - chan->descs_used_count - 1); - - *capacity = c; - - return (0); -} - -static int -msgdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, - struct xdma_sglist *sg, uint32_t sg_n) -{ - struct msgdma_channel *chan; - struct msgdma_desc *desc; - struct msgdma_softc *sc; - bus_addr_t src_addr_lo; - bus_addr_t dst_addr_lo; - uint32_t len; - uint32_t tmp; - int i; - - sc = device_get_softc(dev); - - chan = (struct msgdma_channel *)xchan->chan; - - for (i = 0; i < sg_n; i++) { - src_addr_lo = sg[i].src_addr; - dst_addr_lo = sg[i].dst_addr; - len = (uint32_t)sg[i].len; - - dprintf("%s: src %x dst %x len %d\n", __func__, - src_addr_lo, dst_addr_lo, len); - - desc = chan->descs[chan->idx_head]; -#if defined(ALTERA_MSGDMA_DESC_EXT) || defined(ALTERA_MSGDMA_DESC_PF_EXT) - desc->read_hi = htole32(src_addr_lo >> 32); - desc->write_hi = htole32(dst_addr_lo >> 32); -#endif - desc->read_lo = htole32(src_addr_lo); - desc->write_lo = htole32(dst_addr_lo); - desc->length = htole32(len); - desc->transferred = 0; - desc->status = 0; - desc->reserved = 0; - desc->control = 0; - - if (sg[i].direction == XDMA_MEM_TO_DEV) { - if (sg[i].first == 1) { - desc->control |= htole32(CONTROL_GEN_SOP); - } - - if (sg[i].last == 1) { - desc->control |= htole32(CONTROL_GEN_EOP); - desc->control |= htole32(CONTROL_TC_IRQ_EN | - CONTROL_ET_IRQ_EN | CONTROL_ERR_M); - } - } else { - desc->control |= htole32(CONTROL_END_ON_EOP | (1 << 13)); - desc->control |= htole32(CONTROL_TC_IRQ_EN | - CONTROL_ET_IRQ_EN | CONTROL_ERR_M); - } - - tmp = chan->idx_head; - - atomic_add_int(&chan->descs_used_count, 1); - chan->idx_head = msgdma_next_desc(chan, chan->idx_head); - - desc->control |= htole32(CONTROL_OWN | CONTROL_GO); - - bus_dmamap_sync(chan->dma_tag, chan->dma_map[tmp], - BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - } - - return (0); -} - -static int -msgdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) -{ - struct msgdma_channel *chan; - struct msgdma_desc *desc; - struct msgdma_softc *sc; - uint32_t addr; - uint32_t reg; - int ret; - int i; - - sc = device_get_softc(dev); - - dprintf("%s(%d)\n", __func__, device_get_unit(dev)); - - chan = (struct msgdma_channel *)xchan->chan; - - ret = msgdma_desc_alloc(sc, chan, sizeof(struct msgdma_desc), 16); - if (ret != 0) { - device_printf(sc->dev, - "%s: Can't allocate descriptors.\n", __func__); - return (-1); - } - - for (i = 0; i < chan->descs_num; i++) { - desc = chan->descs[i]; - - if (i == (chan->descs_num - 1)) { - desc->next = htole32(chan->descs_phys[0].ds_addr); - } else { - desc->next = htole32(chan->descs_phys[i+1].ds_addr); - } - - dprintf("%s(%d): desc %d vaddr %lx next paddr %x\n", __func__, - device_get_unit(dev), i, (uint64_t)desc, le32toh(desc->next)); - } - - addr = chan->descs_phys[0].ds_addr; - WRITE4_DESC(sc, PF_NEXT_LO, addr); - WRITE4_DESC(sc, PF_NEXT_HI, 0); - WRITE4_DESC(sc, PF_POLL_FREQ, 1000); - - reg = (PF_CONTROL_GIEM | PF_CONTROL_DESC_POLL_EN); - reg |= PF_CONTROL_RUN; - WRITE4_DESC(sc, PF_CONTROL, reg); - - return (0); -} - -static int -msgdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) -{ - struct msgdma_channel *chan; - struct msgdma_softc *sc; - - sc = device_get_softc(dev); - - chan = (struct msgdma_channel *)xchan->chan; - - switch (cmd) { - case XDMA_CMD_BEGIN: - case XDMA_CMD_TERMINATE: - case XDMA_CMD_PAUSE: - /* TODO: implement me */ - return (-1); - } - - return (0); -} - -#ifdef FDT -static int -msgdma_ofw_md_data(device_t dev, pcell_t *cells, int ncells, void **ptr) -{ - - return (0); -} -#endif - -static device_method_t msgdma_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, msgdma_probe), - DEVMETHOD(device_attach, msgdma_attach), - DEVMETHOD(device_detach, msgdma_detach), - - /* xDMA Interface */ - DEVMETHOD(xdma_channel_alloc, msgdma_channel_alloc), - DEVMETHOD(xdma_channel_free, msgdma_channel_free), - DEVMETHOD(xdma_channel_control, msgdma_channel_control), - - /* xDMA SG Interface */ - DEVMETHOD(xdma_channel_capacity, msgdma_channel_capacity), - DEVMETHOD(xdma_channel_prep_sg, msgdma_channel_prep_sg), - DEVMETHOD(xdma_channel_submit_sg, msgdma_channel_submit_sg), - -#ifdef FDT - DEVMETHOD(xdma_ofw_md_data, msgdma_ofw_md_data), -#endif - - DEVMETHOD_END -}; - -static driver_t msgdma_driver = { - "msgdma", - msgdma_methods, - sizeof(struct msgdma_softc), -}; - -EARLY_DRIVER_MODULE(msgdma, simplebus, msgdma_driver, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); diff --git a/sys/dev/altera/msgdma/msgdma.h b/sys/dev/altera/msgdma/msgdma.h deleted file mode 100644 index 1e72d26b7c6e..000000000000 --- a/sys/dev/altera/msgdma/msgdma.h +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * Copyright (c) 2017-2018 Ruslan Bukin <br@bsdpad.com> - * 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 "opt_altera_msgdma.h" - -/* Altera mSGDMA registers. */ -#define DMA_STATUS 0x00 -#define STATUS_RESETTING (1 << 6) -#define DMA_CONTROL 0x04 -#define CONTROL_GIEM (1 << 4) /* Global Interrupt Enable Mask */ -#define CONTROL_RESET (1 << 1) /* Reset Dispatcher */ - -/* Descriptor fields. */ -#define CONTROL_GO (1 << 31) /* Commit all the descriptor info */ -#define CONTROL_OWN (1 << 30) /* Owned by hardware (prefetcher-enabled only) */ -#define CONTROL_EDE (1 << 24) /* Early done enable */ -#define CONTROL_ERR_S 16 /* Transmit Error, Error IRQ Enable */ -#define CONTROL_ERR_M (0xff << CONTROL_ERR_S) -#define CONTROL_ET_IRQ_EN (1 << 15) /* Early Termination IRQ Enable */ -#define CONTROL_TC_IRQ_EN (1 << 14) /* Transfer Complete IRQ Enable */ -#define CONTROL_END_ON_EOP (1 << 12) /* End on EOP */ -#define CONTROL_PARK_WR (1 << 11) /* Park Writes */ -#define CONTROL_PARK_RD (1 << 10) /* Park Reads */ -#define CONTROL_GEN_EOP (1 << 9) /* Generate EOP */ -#define CONTROL_GEN_SOP (1 << 8) /* Generate SOP */ -#define CONTROL_TX_CHANNEL_S 0 /* Transmit Channel */ -#define CONTROL_TX_CHANNEL_M (0xff << CONTROL_TRANSMIT_CH_S) - -/* Prefetcher */ -#define PF_CONTROL 0x00 -#define PF_CONTROL_GIEM (1 << 3) -#define PF_CONTROL_RESET (1 << 2) -#define PF_CONTROL_DESC_POLL_EN (1 << 1) -#define PF_CONTROL_RUN (1 << 0) -#define PF_NEXT_LO 0x04 -#define PF_NEXT_HI 0x08 -#define PF_POLL_FREQ 0x0C -#define PF_STATUS 0x10 -#define PF_STATUS_IRQ (1 << 0) - -#define READ4(_sc, _reg) \ - le32toh(bus_space_read_4(_sc->bst, _sc->bsh, _reg)) -#define WRITE4(_sc, _reg, _val) \ - bus_space_write_4(_sc->bst, _sc->bsh, _reg, htole32(_val)) - -#define READ4_DESC(_sc, _reg) \ - le32toh(bus_space_read_4(_sc->bst_d, _sc->bsh_d, _reg)) -#define WRITE4_DESC(_sc, _reg, _val) \ - bus_space_write_4(_sc->bst_d, _sc->bsh_d, _reg, htole32(_val)) - -#if defined(ALTERA_MSGDMA_DESC_STD) - -/* Standard descriptor format with prefetcher disabled. */ -struct msgdma_desc { - uint32_t read_lo; - uint32_t write_lo; - uint32_t length; - uint32_t control; -}; - -#elif defined(ALTERA_MSGDMA_DESC_EXT) - -/* Extended descriptor format with prefetcher disabled. */ -struct msgdma_desc { - uint32_t read_lo; - uint32_t write_lo; - uint32_t length; - uint8_t write_burst; - uint8_t read_burst; - uint16_t seq_num; - uint16_t write_stride; - uint16_t read_stride; - uint32_t read_hi; - uint32_t write_hi; - uint32_t control; -}; - -#elif defined(ALTERA_MSGDMA_DESC_PF_STD) - -/* Standard descriptor format with prefetcher enabled. */ -struct msgdma_desc { - uint32_t read_lo; - uint32_t write_lo; - uint32_t length; - uint32_t next; - uint32_t transferred; - uint32_t status; - uint32_t reserved; - uint32_t control; -}; - -#elif defined(ALTERA_MSGDMA_DESC_PF_EXT) - -/* Extended descriptor format with prefetcher enabled. */ -struct msgdma_desc { - uint32_t read_lo; - uint32_t write_lo; - uint32_t length; - uint32_t next; - uint32_t transferred; - uint32_t status; - uint32_t reserved; - uint8_t write_burst; - uint8_t read_burst; - uint16_t seq_num; - uint16_t write_stride; - uint16_t read_stride; - uint32_t read_hi; - uint32_t write_hi; - uint32_t next_hi; - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; - uint32_t control; -}; - -#else - -#error "mSGDMA descriptor format (kernel option) is not set." - -#endif diff --git a/sys/dev/altera/pio/pio.c b/sys/dev/altera/pio/pio.c deleted file mode 100644 index e002fc347f28..000000000000 --- a/sys/dev/altera/pio/pio.c +++ /dev/null @@ -1,208 +0,0 @@ -/*- - * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> - * 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. - */ - -/* - * Altera PIO (Parallel IO) device driver - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/rman.h> -#include <sys/timeet.h> -#include <sys/timetc.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 <machine/bus.h> -#include <machine/fdt.h> -#include <machine/cpu.h> - -#include <dev/altera/pio/pio.h> -#include "pio_if.h" - -#define READ4(_sc, _reg) bus_read_4((_sc)->res[0], _reg) -#define READ2(_sc, _reg) bus_read_2((_sc)->res[0], _reg) -#define READ1(_sc, _reg) bus_read_1((_sc)->res[0], _reg) -#define WRITE4(_sc, _reg, _val) bus_write_4((_sc)->res[0], _reg, _val) -#define WRITE2(_sc, _reg, _val) bus_write_2((_sc)->res[0], _reg, _val) -#define WRITE1(_sc, _reg, _val) bus_write_1((_sc)->res[0], _reg, _val) - -struct pio_softc { - struct resource *res[2]; - bus_space_tag_t bst; - bus_space_handle_t bsh; - device_t dev; - void *ih; -}; - -static struct resource_spec pio_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -static int -pio_setup_irq(device_t dev, void *intr_handler, void *ih_user) -{ - struct pio_softc *sc; - - sc = device_get_softc(dev); - - /* Setup interrupt handlers */ - if (bus_setup_intr(sc->dev, sc->res[1], INTR_TYPE_BIO | INTR_MPSAFE, - NULL, intr_handler, ih_user, &sc->ih)) { - device_printf(sc->dev, "Unable to setup intr\n"); - return (1); - } - - return (0); -} - -static int -pio_teardown_irq(device_t dev) -{ - struct pio_softc *sc; - - sc = device_get_softc(dev); - - bus_teardown_intr(sc->dev, sc->res[1], sc->ih); - - return (0); -} - -static int -pio_read(device_t dev) -{ - struct pio_softc *sc; - - sc = device_get_softc(dev); - - return (READ4(sc, PIO_DATA)); -} - -static int -pio_set(device_t dev, int bit, int enable) -{ - struct pio_softc *sc; - - sc = device_get_softc(dev); - - if (enable) - WRITE4(sc, PIO_OUTSET, bit); - else - WRITE4(sc, PIO_OUTCLR, bit); - - return (0); -} - -static int -pio_configure(device_t dev, int dir, int mask) -{ - struct pio_softc *sc; - - sc = device_get_softc(dev); - - WRITE4(sc, PIO_INT_MASK, mask); - WRITE4(sc, PIO_DIR, dir); - - return (0); -} - -static int -pio_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "altr,pio")) - return (ENXIO); - - device_set_desc(dev, "Altera PIO"); - return (BUS_PROBE_DEFAULT); -} - -static int -pio_attach(device_t dev) -{ - struct pio_softc *sc; - struct fdt_ic *fic; - phandle_t node; - - sc = device_get_softc(dev); - sc->dev = dev; - - if (bus_alloc_resources(dev, pio_spec, sc->res)) { - device_printf(dev, "could not allocate resources\n"); - return (ENXIO); - } - - /* Memory interface */ - sc->bst = rman_get_bustag(sc->res[0]); - sc->bsh = rman_get_bushandle(sc->res[0]); - - if ((node = ofw_bus_get_node(sc->dev)) == -1) - return (ENXIO); - - fic = malloc(sizeof(*fic), M_DEVBUF, M_WAITOK|M_ZERO); - fic->iph = node; - fic->dev = dev; - SLIST_INSERT_HEAD(&fdt_ic_list_head, fic, fdt_ics); - - return (0); -} - -static device_method_t pio_methods[] = { - DEVMETHOD(device_probe, pio_probe), - DEVMETHOD(device_attach, pio_attach), - - /* pio_if.m */ - DEVMETHOD(pio_read, pio_read), - DEVMETHOD(pio_configure, pio_configure), - DEVMETHOD(pio_set, pio_set), - DEVMETHOD(pio_setup_irq, pio_setup_irq), - DEVMETHOD(pio_teardown_irq, pio_teardown_irq), - DEVMETHOD_END -}; - -static driver_t pio_driver = { - "altera_pio", - pio_methods, - sizeof(struct pio_softc), -}; - -DRIVER_MODULE(altera_pio, simplebus, pio_driver, 0, 0); diff --git a/sys/dev/altera/pio/pio.h b/sys/dev/altera/pio/pio.h deleted file mode 100644 index b1244d721209..000000000000 --- a/sys/dev/altera/pio/pio.h +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> - * 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. - */ - -#define PIO_DATA 0x00 -#define PIO_DIR 0x04 -#define PIO_OUT(n) (1 << n) -#define PIO_OUT_ALL 0xffffffff -#define PIO_INT_MASK 0x08 -#define PIO_UNMASK(n) (1 << n) -#define PIO_UNMASK_ALL 0xffffffff -#define PIO_EDGECAPT 0x0c -#define PIO_OUTSET 0x10 -#define PIO_OUTCLR 0x14 diff --git a/sys/dev/altera/pio/pio_if.m b/sys/dev/altera/pio/pio_if.m deleted file mode 100644 index 068963816cc5..000000000000 --- a/sys/dev/altera/pio/pio_if.m +++ /dev/null @@ -1,64 +0,0 @@ -#- -# Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> -# 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/types.h> - -INTERFACE pio; - -# -# PIO device methods -# - -METHOD int read { - device_t dev; -}; - -METHOD int setup_irq { - device_t dev; - void *handler; - void *ih_user; -}; - -METHOD int teardown_irq { - device_t dev; -}; - -METHOD int set { - device_t dev; - int bit; - int enable; -}; - -METHOD int configure { - device_t dev; - int dir; - int mask; -} diff --git a/sys/dev/altera/sdcard/altera_sdcard.c b/sys/dev/altera/sdcard/altera_sdcard.c deleted file mode 100644 index 05caeead0b58..000000000000 --- a/sys/dev/altera/sdcard/altera_sdcard.c +++ /dev/null @@ -1,412 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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> -#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. - */ - -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); -} diff --git a/sys/dev/altera/sdcard/altera_sdcard.h b/sys/dev/altera/sdcard/altera_sdcard.h deleted file mode 100644 index 15a8cdad0be2..000000000000 --- a/sys/dev/altera/sdcard/altera_sdcard.h +++ /dev/null @@ -1,247 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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. - */ - -#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); - -#endif /* _DEV_ALTERA_SDCARD_H_ */ diff --git a/sys/dev/altera/sdcard/altera_sdcard_disk.c b/sys/dev/altera/sdcard/altera_sdcard_disk.c deleted file mode 100644 index 87fdfb2a6475..000000000000 --- a/sys/dev/altera/sdcard/altera_sdcard_disk.c +++ /dev/null @@ -1,184 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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"); -} diff --git a/sys/dev/altera/sdcard/altera_sdcard_fdt.c b/sys/dev/altera/sdcard/altera_sdcard_fdt.c deleted file mode 100644 index c62b480eecc3..000000000000 --- a/sys/dev/altera/sdcard/altera_sdcard_fdt.c +++ /dev/null @@ -1,121 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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, 0, 0); diff --git a/sys/dev/altera/sdcard/altera_sdcard_io.c b/sys/dev/altera/sdcard/altera_sdcard_io.c deleted file mode 100644 index 5c3347960c75..000000000000 --- a/sys/dev/altera/sdcard/altera_sdcard_io.c +++ /dev/null @@ -1,446 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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 **bpp) -{ - struct bio *bp; - - bp = *bpp; - - 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: - biofinish(bp, NULL, EOPNOTSUPP); - *bpp = NULL; - } -} - -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); -} diff --git a/sys/dev/altera/sdcard/altera_sdcard_nexus.c b/sys/dev/altera/sdcard/altera_sdcard_nexus.c deleted file mode 100644 index 9e42f0b01ba2..000000000000 --- a/sys/dev/altera/sdcard/altera_sdcard_nexus.c +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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/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, 0, 0); diff --git a/sys/dev/altera/softdma/a_api.h b/sys/dev/altera/softdma/a_api.h deleted file mode 100644 index 524d1bf2898a..000000000000 --- a/sys/dev/altera/softdma/a_api.h +++ /dev/null @@ -1,98 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * 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. - */ -/* - * 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 */ diff --git a/sys/dev/altera/softdma/softdma.c b/sys/dev/altera/softdma/softdma.c deleted file mode 100644 index 4bea1315ce42..000000000000 --- a/sys/dev/altera/softdma/softdma.c +++ /dev/null @@ -1,882 +0,0 @@ -/*- - * Copyright (c) 2017-2018 Ruslan Bukin <br@bsdpad.com> - * 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. - */ - -/* This is driver for SoftDMA device built using Altera FIFO component. */ - -#include <sys/cdefs.h> -#include "opt_platform.h" -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/conf.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/kernel.h> -#include <sys/kthread.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/resource.h> -#include <sys/rman.h> - -#include <machine/bus.h> - -#ifdef FDT -#include <dev/fdt/fdt_common.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> -#endif - -#include <dev/altera/softdma/a_api.h> - -#include <dev/xdma/xdma.h> -#include "xdma_if.h" - -#define SOFTDMA_DEBUG -#undef SOFTDMA_DEBUG - -#ifdef SOFTDMA_DEBUG -#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define dprintf(fmt, ...) -#endif - -#define AVALON_FIFO_TX_BASIC_OPTS_DEPTH 16 -#define SOFTDMA_NCHANNELS 1 -#define CONTROL_GEN_SOP (1 << 0) -#define CONTROL_GEN_EOP (1 << 1) -#define CONTROL_OWN (1 << 31) - -#define SOFTDMA_RX_EVENTS \ - (A_ONCHIP_FIFO_MEM_CORE_INTR_FULL | \ - A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \ - A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW) -#define SOFTDMA_TX_EVENTS \ - (A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY | \ - A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \ - A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW) - -struct softdma_channel { - struct softdma_softc *sc; - struct mtx mtx; - xdma_channel_t *xchan; - struct proc *p; - int used; - int index; - int run; - uint32_t idx_tail; - uint32_t idx_head; - struct softdma_desc *descs; - - uint32_t descs_num; - uint32_t descs_used_count; -}; - -struct softdma_desc { - uint64_t src_addr; - uint64_t dst_addr; - uint32_t len; - uint32_t access_width; - uint32_t count; - uint16_t src_incr; - uint16_t dst_incr; - uint32_t direction; - struct softdma_desc *next; - uint32_t transfered; - uint32_t status; - uint32_t reserved; - uint32_t control; -}; - -struct softdma_softc { - device_t dev; - struct resource *res[3]; - bus_space_tag_t bst; - bus_space_handle_t bsh; - bus_space_tag_t bst_c; - bus_space_handle_t bsh_c; - void *ih; - struct softdma_channel channels[SOFTDMA_NCHANNELS]; -}; - -static struct resource_spec softdma_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* fifo */ - { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* core */ - { SYS_RES_IRQ, 0, RF_ACTIVE }, - { -1, 0 } -}; - -static int softdma_probe(device_t dev); -static int softdma_attach(device_t dev); -static int softdma_detach(device_t dev); - -static inline uint32_t -softdma_next_desc(struct softdma_channel *chan, uint32_t curidx) -{ - - return ((curidx + 1) % chan->descs_num); -} - -static void -softdma_mem_write(struct softdma_softc *sc, uint32_t reg, uint32_t val) -{ - - bus_write_4(sc->res[0], reg, htole32(val)); -} - -static uint32_t -softdma_mem_read(struct softdma_softc *sc, uint32_t reg) -{ - uint32_t val; - - val = bus_read_4(sc->res[0], reg); - - return (le32toh(val)); -} - -static void -softdma_memc_write(struct softdma_softc *sc, uint32_t reg, uint32_t val) -{ - - bus_write_4(sc->res[1], reg, htole32(val)); -} - -static uint32_t -softdma_memc_read(struct softdma_softc *sc, uint32_t reg) -{ - uint32_t val; - - val = bus_read_4(sc->res[1], reg); - - return (le32toh(val)); -} - -static uint32_t -softdma_fill_level(struct softdma_softc *sc) -{ - uint32_t val; - - val = softdma_memc_read(sc, - A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL); - - return (val); -} - -static uint32_t -fifo_fill_level_wait(struct softdma_softc *sc) -{ - uint32_t val; - - do - val = softdma_fill_level(sc); - while (val == AVALON_FIFO_TX_BASIC_OPTS_DEPTH); - - return (val); -} - -static void -softdma_intr(void *arg) -{ - struct softdma_channel *chan; - struct softdma_softc *sc; - int reg; - int err; - - sc = arg; - - chan = &sc->channels[0]; - - reg = softdma_memc_read(sc, A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT); - - if (reg & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW | - A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) { - /* Errors */ - err = (((reg & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >> \ - A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff); - } - - if (reg != 0) { - softdma_memc_write(sc, - A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, reg); - chan->run = 1; - wakeup(chan); - } -} - -static int -softdma_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "altr,softdma")) - return (ENXIO); - - device_set_desc(dev, "SoftDMA"); - - return (BUS_PROBE_DEFAULT); -} - -static int -softdma_attach(device_t dev) -{ - struct softdma_softc *sc; - phandle_t xref, node; - int err; - - sc = device_get_softc(dev); - sc->dev = dev; - - if (bus_alloc_resources(dev, softdma_spec, sc->res)) { - device_printf(dev, - "could not allocate resources for device\n"); - return (ENXIO); - } - - /* FIFO memory interface */ - sc->bst = rman_get_bustag(sc->res[0]); - sc->bsh = rman_get_bushandle(sc->res[0]); - - /* FIFO control memory interface */ - sc->bst_c = rman_get_bustag(sc->res[1]); - sc->bsh_c = rman_get_bushandle(sc->res[1]); - - /* Setup interrupt handler */ - err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE, - NULL, softdma_intr, sc, &sc->ih); - if (err) { - device_printf(dev, "Unable to alloc interrupt resource.\n"); - return (ENXIO); - } - - node = ofw_bus_get_node(dev); - xref = OF_xref_from_node(node); - OF_device_register_xref(xref, dev); - - return (0); -} - -static int -softdma_detach(device_t dev) -{ - struct softdma_softc *sc; - - sc = device_get_softc(dev); - - return (0); -} - -static int -softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc) -{ - struct softdma_softc *sc; - uint64_t addr; - uint64_t buf; - uint32_t word; - uint32_t missing; - uint32_t reg; - int got_bits; - int len; - - sc = chan->sc; - - fifo_fill_level_wait(sc); - - /* Set start of packet. */ - if (desc->control & CONTROL_GEN_SOP) - softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, - A_ONCHIP_FIFO_MEM_CORE_SOP); - - got_bits = 0; - buf = 0; - - addr = desc->src_addr; - len = desc->len; - - if (addr & 1) { - buf = (buf << 8) | *(uint8_t *)addr; - got_bits += 8; - addr += 1; - len -= 1; - } - - if (len >= 2 && addr & 2) { - buf = (buf << 16) | *(uint16_t *)addr; - got_bits += 16; - addr += 2; - len -= 2; - } - - while (len >= 4) { - buf = (buf << 32) | (uint64_t)*(uint32_t *)addr; - addr += 4; - len -= 4; - word = (uint32_t)((buf >> got_bits) & 0xffffffff); - - fifo_fill_level_wait(sc); - if (len == 0 && got_bits == 0 && - (desc->control & CONTROL_GEN_EOP) != 0) - softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, - A_ONCHIP_FIFO_MEM_CORE_EOP); - bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word); - } - - if (len & 2) { - buf = (buf << 16) | *(uint16_t *)addr; - got_bits += 16; - addr += 2; - len -= 2; - } - - if (len & 1) { - buf = (buf << 8) | *(uint8_t *)addr; - got_bits += 8; - addr += 1; - len -= 1; - } - - if (got_bits >= 32) { - got_bits -= 32; - word = (uint32_t)((buf >> got_bits) & 0xffffffff); - - fifo_fill_level_wait(sc); - if (len == 0 && got_bits == 0 && - (desc->control & CONTROL_GEN_EOP) != 0) - softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, - A_ONCHIP_FIFO_MEM_CORE_EOP); - bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word); - } - - if (got_bits) { - missing = 32 - got_bits; - got_bits /= 8; - - fifo_fill_level_wait(sc); - reg = A_ONCHIP_FIFO_MEM_CORE_EOP | - ((4 - got_bits) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT); - softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg); - word = (uint32_t)((buf << missing) & 0xffffffff); - bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word); - } - - return (desc->len); -} - -static int -softdma_process_rx(struct softdma_channel *chan, struct softdma_desc *desc) -{ - uint32_t src_offs, dst_offs; - struct softdma_softc *sc; - uint32_t fill_level; - uint32_t empty; - uint32_t meta; - uint32_t data; - int sop_rcvd; - int timeout; - size_t len; - int error; - - sc = chan->sc; - empty = 0; - src_offs = dst_offs = 0; - error = 0; - - fill_level = softdma_fill_level(sc); - if (fill_level == 0) { - /* Nothing to receive. */ - return (0); - } - - len = desc->len; - - sop_rcvd = 0; - while (fill_level) { - empty = 0; - data = bus_read_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA); - meta = softdma_mem_read(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA); - - if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) { - error = 1; - break; - } - - if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0) { - error = 1; - break; - } - - if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) { - sop_rcvd = 1; - } - - if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) { - empty = (meta & A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >> - A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT; - } - - if (sop_rcvd == 0) { - error = 1; - break; - } - - if (empty == 0) { - *(uint32_t *)(desc->dst_addr + dst_offs) = data; - dst_offs += 4; - } else if (empty == 1) { - *(uint16_t *)(desc->dst_addr + dst_offs) = - ((data >> 16) & 0xffff); - dst_offs += 2; - - *(uint8_t *)(desc->dst_addr + dst_offs) = - ((data >> 8) & 0xff); - dst_offs += 1; - } else { - panic("empty %d\n", empty); - } - - if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) - break; - - fill_level = softdma_fill_level(sc); - timeout = 100; - while (fill_level == 0 && timeout--) - fill_level = softdma_fill_level(sc); - if (timeout == 0) { - /* No EOP received. Broken packet. */ - error = 1; - break; - } - } - - if (error) { - return (-1); - } - - return (dst_offs); -} - -static uint32_t -softdma_process_descriptors(struct softdma_channel *chan, - xdma_transfer_status_t *status) -{ - struct xdma_channel *xchan; - struct softdma_desc *desc; - struct softdma_softc *sc; - xdma_transfer_status_t st; - int ret; - - sc = chan->sc; - - xchan = chan->xchan; - - desc = &chan->descs[chan->idx_tail]; - - while (desc != NULL) { - if ((desc->control & CONTROL_OWN) == 0) { - break; - } - - if (desc->direction == XDMA_MEM_TO_DEV) { - ret = softdma_process_tx(chan, desc); - } else { - ret = softdma_process_rx(chan, desc); - if (ret == 0) { - /* No new data available. */ - break; - } - } - - /* Descriptor processed. */ - desc->control = 0; - - if (ret >= 0) { - st.error = 0; - st.transferred = ret; - } else { - st.error = ret; - st.transferred = 0; - } - - xchan_seg_done(xchan, &st); - atomic_subtract_int(&chan->descs_used_count, 1); - - if (ret >= 0) { - status->transferred += ret; - } else { - status->error = 1; - break; - } - - chan->idx_tail = softdma_next_desc(chan, chan->idx_tail); - - /* Process next descriptor, if any. */ - desc = desc->next; - } - - return (0); -} - -static void -softdma_worker(void *arg) -{ - xdma_transfer_status_t status; - struct softdma_channel *chan; - struct softdma_softc *sc; - - chan = arg; - - sc = chan->sc; - - while (1) { - mtx_lock(&chan->mtx); - - do { - mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2); - } while (chan->run == 0); - - status.error = 0; - status.transferred = 0; - - softdma_process_descriptors(chan, &status); - - /* Finish operation */ - chan->run = 0; - xdma_callback(chan->xchan, &status); - - mtx_unlock(&chan->mtx); - } - -} - -static int -softdma_proc_create(struct softdma_channel *chan) -{ - struct softdma_softc *sc; - - sc = chan->sc; - - if (chan->p != NULL) { - /* Already created */ - return (0); - } - - mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF); - - if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0, - "softdma_worker") != 0) { - device_printf(sc->dev, - "%s: Failed to create worker thread.\n", __func__); - return (-1); - } - - return (0); -} - -static int -softdma_channel_alloc(device_t dev, struct xdma_channel *xchan) -{ - struct softdma_channel *chan; - struct softdma_softc *sc; - int i; - - sc = device_get_softc(dev); - - for (i = 0; i < SOFTDMA_NCHANNELS; i++) { - chan = &sc->channels[i]; - if (chan->used == 0) { - chan->xchan = xchan; - xchan->chan = (void *)chan; - xchan->caps |= XCHAN_CAP_NOSEG; - chan->index = i; - chan->idx_head = 0; - chan->idx_tail = 0; - chan->descs_used_count = 0; - chan->descs_num = 1024; - chan->sc = sc; - - if (softdma_proc_create(chan) != 0) { - return (-1); - } - - chan->used = 1; - - return (0); - } - } - - return (-1); -} - -static int -softdma_channel_free(device_t dev, struct xdma_channel *xchan) -{ - struct softdma_channel *chan; - struct softdma_softc *sc; - - sc = device_get_softc(dev); - - chan = (struct softdma_channel *)xchan->chan; - - if (chan->descs != NULL) { - free(chan->descs, M_DEVBUF); - } - - chan->used = 0; - - return (0); -} - -static int -softdma_desc_alloc(struct xdma_channel *xchan) -{ - struct softdma_channel *chan; - uint32_t nsegments; - - chan = (struct softdma_channel *)xchan->chan; - - nsegments = chan->descs_num; - - chan->descs = malloc(nsegments * sizeof(struct softdma_desc), - M_DEVBUF, (M_WAITOK | M_ZERO)); - - return (0); -} - -static int -softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) -{ - struct softdma_channel *chan; - struct softdma_desc *desc; - struct softdma_softc *sc; - int ret; - int i; - - sc = device_get_softc(dev); - - chan = (struct softdma_channel *)xchan->chan; - - ret = softdma_desc_alloc(xchan); - if (ret != 0) { - device_printf(sc->dev, - "%s: Can't allocate descriptors.\n", __func__); - return (-1); - } - - for (i = 0; i < chan->descs_num; i++) { - desc = &chan->descs[i]; - - if (i == (chan->descs_num - 1)) { - desc->next = &chan->descs[0]; - } else { - desc->next = &chan->descs[i+1]; - } - } - - return (0); -} - -static int -softdma_channel_capacity(device_t dev, xdma_channel_t *xchan, - uint32_t *capacity) -{ - struct softdma_channel *chan; - uint32_t c; - - chan = (struct softdma_channel *)xchan->chan; - - /* At least one descriptor must be left empty. */ - c = (chan->descs_num - chan->descs_used_count - 1); - - *capacity = c; - - return (0); -} - -static int -softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, - struct xdma_sglist *sg, uint32_t sg_n) -{ - struct softdma_channel *chan; - struct softdma_desc *desc; - struct softdma_softc *sc; - uint32_t enqueued; - uint32_t saved_dir; - uint32_t tmp; - uint32_t len; - int i; - - sc = device_get_softc(dev); - - chan = (struct softdma_channel *)xchan->chan; - - enqueued = 0; - - for (i = 0; i < sg_n; i++) { - len = (uint32_t)sg[i].len; - - desc = &chan->descs[chan->idx_head]; - desc->src_addr = sg[i].src_addr; - desc->dst_addr = sg[i].dst_addr; - if (sg[i].direction == XDMA_MEM_TO_DEV) { - desc->src_incr = 1; - desc->dst_incr = 0; - } else { - desc->src_incr = 0; - desc->dst_incr = 1; - } - desc->direction = sg[i].direction; - saved_dir = sg[i].direction; - desc->len = len; - desc->transfered = 0; - desc->status = 0; - desc->reserved = 0; - desc->control = 0; - - if (sg[i].first == 1) - desc->control |= CONTROL_GEN_SOP; - if (sg[i].last == 1) - desc->control |= CONTROL_GEN_EOP; - - tmp = chan->idx_head; - chan->idx_head = softdma_next_desc(chan, chan->idx_head); - atomic_add_int(&chan->descs_used_count, 1); - desc->control |= CONTROL_OWN; - enqueued += 1; - } - - if (enqueued == 0) - return (0); - - if (saved_dir == XDMA_MEM_TO_DEV) { - chan->run = 1; - wakeup(chan); - } else - softdma_memc_write(sc, - A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, - SOFTDMA_RX_EVENTS); - - return (0); -} - -static int -softdma_channel_request(device_t dev, struct xdma_channel *xchan, - struct xdma_request *req) -{ - struct softdma_channel *chan; - struct softdma_desc *desc; - struct softdma_softc *sc; - int ret; - - sc = device_get_softc(dev); - - chan = (struct softdma_channel *)xchan->chan; - - ret = softdma_desc_alloc(xchan); - if (ret != 0) { - device_printf(sc->dev, - "%s: Can't allocate descriptors.\n", __func__); - return (-1); - } - - desc = &chan->descs[0]; - - desc->src_addr = req->src_addr; - desc->dst_addr = req->dst_addr; - desc->len = req->block_len; - desc->src_incr = 1; - desc->dst_incr = 1; - desc->next = NULL; - - return (0); -} - -static int -softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) -{ - struct softdma_channel *chan; - struct softdma_softc *sc; - - sc = device_get_softc(dev); - - chan = (struct softdma_channel *)xchan->chan; - - switch (cmd) { - case XDMA_CMD_BEGIN: - case XDMA_CMD_TERMINATE: - case XDMA_CMD_PAUSE: - /* TODO: implement me */ - return (-1); - } - - return (0); -} - -#ifdef FDT -static int -softdma_ofw_md_data(device_t dev, pcell_t *cells, - int ncells, void **ptr) -{ - - return (0); -} -#endif - -static device_method_t softdma_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, softdma_probe), - DEVMETHOD(device_attach, softdma_attach), - DEVMETHOD(device_detach, softdma_detach), - - /* xDMA Interface */ - DEVMETHOD(xdma_channel_alloc, softdma_channel_alloc), - DEVMETHOD(xdma_channel_free, softdma_channel_free), - DEVMETHOD(xdma_channel_request, softdma_channel_request), - DEVMETHOD(xdma_channel_control, softdma_channel_control), - - /* xDMA SG Interface */ - DEVMETHOD(xdma_channel_prep_sg, softdma_channel_prep_sg), - DEVMETHOD(xdma_channel_submit_sg, softdma_channel_submit_sg), - DEVMETHOD(xdma_channel_capacity, softdma_channel_capacity), - -#ifdef FDT - DEVMETHOD(xdma_ofw_md_data, softdma_ofw_md_data), -#endif - - DEVMETHOD_END -}; - -static driver_t softdma_driver = { - "softdma", - softdma_methods, - sizeof(struct softdma_softc), -}; - -EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, 0, 0, - BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); |