diff options
author | Vijay Kumar Banerjee <vijay@rtems.org> | 2021-02-24 19:09:56 -0700 |
---|---|---|
committer | Vijay Kumar Banerjee <vijay@rtems.org> | 2021-04-07 16:15:38 -0600 |
commit | c90fa83041f1467ac9795c489b7151db3a041ab5 (patch) | |
tree | ee3ebcd4af33202b34f89133a301d268609e355c /bsps/arm | |
parent | cpukit/libfs: Remove nfsclient (diff) | |
download | rtems-c90fa83041f1467ac9795c489b7151db3a041ab5.tar.bz2 |
bsps: Remove networking drivers
Update #3850
Diffstat (limited to 'bsps/arm')
-rw-r--r-- | bsps/arm/atsam/net/if_atsam.c | 1255 | ||||
-rw-r--r-- | bsps/arm/csb336/net/lan91c11x.c | 261 | ||||
-rw-r--r-- | bsps/arm/csb336/net/lan91c11x.h | 229 | ||||
-rw-r--r-- | bsps/arm/csb336/net/network.c | 708 | ||||
-rw-r--r-- | bsps/arm/csb337/net/network.c | 864 | ||||
-rw-r--r-- | bsps/arm/edb7312/net/network.c | 126 | ||||
-rw-r--r-- | bsps/arm/gumstix/net/rtl8019.c | 1197 | ||||
-rw-r--r-- | bsps/arm/gumstix/net/wd80x3.h | 303 | ||||
-rw-r--r-- | bsps/arm/rtl22xx/net/network.c | 126 | ||||
-rw-r--r-- | bsps/arm/shared/net/lpc-ethernet.c | 1839 |
10 files changed, 0 insertions, 6908 deletions
diff --git a/bsps/arm/atsam/net/if_atsam.c b/bsps/arm/atsam/net/if_atsam.c deleted file mode 100644 index 9665aa1bcb..0000000000 --- a/bsps/arm/atsam/net/if_atsam.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Copyright (c) 2016 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * <info@embedded-brains.de> - * - * 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 COPYRIGHT HOLDERS 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 COPYRIGHT - * OWNER 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 <libchip/chip.h> -#include <libchip/include/gmacd.h> -#include <libchip/include/pio.h> - -#include <machine/rtems-bsd-kernel-space.h> - -#include <bsp.h> -#include <bsp/irq.h> - -#include <stdio.h> - -#include <rtems/error.h> -#include <rtems/rtems_bsdnet.h> -#include <rtems/rtems_mii_ioctl.h> - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_types.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <dev/mii/mii.h> - -/* - * Number of interfaces supported by the driver - */ -#define NIFACES 1 - -/** Enable/Disable CopyAllFrame */ -#define GMAC_CAF_DISABLE 0 -#define GMAC_CAF_ENABLE 1 - -/** Enable/Disable NoBroadCast */ -#define GMAC_NBC_DISABLE 0 -#define GMAC_NBC_ENABLE 1 - -/** The PIN list of PIO for GMAC */ -#define BOARD_GMAC_PINS \ - { (PIO_PD0A_GTXCK | PIO_PD1A_GTXEN | PIO_PD2A_GTX0 | PIO_PD3A_GTX1 \ - | PIO_PD4A_GRXDV | PIO_PD5A_GRX0 | PIO_PD6A_GRX1 \ - | PIO_PD7A_GRXER \ - | PIO_PD8A_GMDC | PIO_PD9A_GMDIO), PIOD, ID_PIOD, PIO_PERIPH_A, \ - PIO_DEFAULT } -/** The runtime pin configure list for GMAC */ -#define BOARD_GMAC_RUN_PINS BOARD_GMAC_PINS - -/** The PIN list of PIO for GMAC */ -#define BOARD_GMAC_RESET_PIN \ - { PIO_PC10, PIOC, ID_PIOC, \ - PIO_OUTPUT_1, \ - PIO_PULLUP } - -/** Multicast Enable */ -#define GMAC_MC_ENABLE (1u << 6) -#define HASH_INDEX_AMOUNT 6 -#define HASH_ELEMENTS_PER_INDEX 8 -#define MAC_ADDR_MASK 0x0000FFFFFFFFFFFF -#define MAC_IDX_MASK (1u << 0) - -/** Promiscuous Mode Enable */ -#define GMAC_PROM_ENABLE (1u << 4) - -/** RX Defines */ -#define GMAC_RX_BUFFER_SIZE 1536 -#define GMAC_RX_BUF_DESC_ADDR_MASK 0xFFFFFFFC -#define GMAC_RX_SET_OFFSET (1u << 15) -#define GMAC_RX_SET_USED_WRAP ((1u << 1) | (1u << 0)) -#define GMAC_RX_SET_WRAP (1u << 1) -#define GMAC_RX_SET_USED (1u << 0) -/** TX Defines */ -#define GMAC_TX_SET_EOF (1u << 15) -#define GMAC_TX_SET_WRAP (1u << 30) -#define GMAC_TX_SET_USED (1u << 31) - -#define GMAC_DESCRIPTOR_ALIGNMENT 8 - -/** Events */ -#define ATSAMV7_ETH_RX_EVENT_INTERRUPT RTEMS_EVENT_1 -#define ATSAMV7_ETH_TX_EVENT_INTERRUPT RTEMS_EVENT_2 -#define ATSAMV7_ETH_START_TRANSMIT_EVENT RTEMS_EVENT_3 - -#define ATSAMV7_ETH_RX_DATA_OFFSET 2 - -#define WATCHDOG_TIMEOUT 5 - -/** The PINs for GMAC */ -static const Pin gmacPins[] = { BOARD_GMAC_RUN_PINS }; - -static const Pin gmacResetPin = BOARD_GMAC_RESET_PIN; - -typedef struct if_atsam_gmac { - /** The GMAC driver instance */ - sGmacd gGmacd; - uint32_t retries; - uint8_t phy_address; -} if_atsam_gmac; - -typedef struct ring_buffer { - unsigned tx_bd_used; - unsigned tx_bd_free; - size_t length; -} ring_buffer; - -/* - * Per-device data - */ -typedef struct if_atsam_softc { - /* - * Data - */ - struct arpcom arpcom; - if_atsam_gmac Gmac_inst; - struct rtems_mdio_info mdio; - uint8_t GMacAddress[6]; - rtems_id rx_daemon_tid; - rtems_id tx_daemon_tid; - rtems_vector_number interrupt_number; - struct mbuf **rx_mbuf; - struct mbuf **tx_mbuf; - volatile sGmacTxDescriptor *tx_bd_base; - uint32_t anlpar; - size_t rx_bd_fill_idx; - size_t amount_rx_buf; - size_t amount_tx_buf; - ring_buffer tx_ring; - - /* - * Statistics - */ - unsigned rx_overrun_errors; - unsigned rx_interrupts; - unsigned tx_complete_int; - unsigned tx_tur_errors; - unsigned tx_rlex_errors; - unsigned tx_tfc_errors; - unsigned tx_hresp_errors; - unsigned tx_interrupts; -} if_atsam_softc; - -static struct if_atsam_softc if_atsam_softc_inst; - -static struct mbuf *if_atsam_new_mbuf(struct ifnet *ifp) -{ - struct mbuf *m; - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m != NULL) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) != 0) { - m->m_pkthdr.rcvif = ifp; - m->m_data = mtod(m, char *); - rtems_cache_invalidate_multiple_data_lines(mtod(m, void *), - GMAC_RX_BUFFER_SIZE); - } else { - m_free(m); - m = NULL; - } - } - return (m); -} - - -static uint8_t if_atsam_wait_phy(Gmac *pHw, uint32_t retry) -{ - volatile uint32_t retry_count = 0; - - while (!GMAC_IsIdle(pHw)) { - if (retry == 0) { - continue; - } - retry_count++; - - if (retry_count >= retry) { - return (1); - } - rtems_task_wake_after(1); - } - - return (0); -} - - -static uint8_t -if_atsam_write_phy(Gmac *pHw, uint8_t PhyAddress, uint8_t Address, - uint32_t Value, uint32_t retry) -{ - GMAC_PHYMaintain(pHw, PhyAddress, Address, 0, (uint16_t)Value); - if (if_atsam_wait_phy(pHw, retry) == 1) { - return (1); - } - return (0); -} - - -static uint8_t -if_atsam_read_phy(Gmac *pHw, - uint8_t PhyAddress, uint8_t Address, uint32_t *pvalue, uint32_t retry) -{ - GMAC_PHYMaintain(pHw, PhyAddress, Address, 1, 0); - if (if_atsam_wait_phy(pHw, retry) == 1) { - return (1); - } - *pvalue = GMAC_PHYData(pHw); - return (0); -} - - -static void atsamv7_find_valid_phy(if_atsam_gmac *gmac_inst) -{ - Gmac *pHw = gmac_inst->gGmacd.pHw; - uint32_t value = 0; - uint8_t phy_address; - int i; - - if (gmac_inst->phy_address != 0xFF) { - return; - } - - /* Find another one */ - phy_address = 0xFF; - - for (i = 31; i >= 0; --i) { - int rv; - - rv = if_atsam_read_phy(pHw, (uint8_t)i, MII_PHYIDR1, - &value, gmac_inst->retries); - if (rv == 0 && value != 0 && value < 0xffff) { - phy_address = (uint8_t)i; - break; - } - } - - if (phy_address != 0xFF) { - if_atsam_read_phy(pHw, phy_address, MII_PHYIDR1, &value, - gmac_inst->retries); - if_atsam_read_phy(pHw, phy_address, MII_PHYIDR2, &value, - gmac_inst->retries); - gmac_inst->phy_address = phy_address; - } -} - - -static uint8_t if_atsam_reset_phy(if_atsam_gmac *gmac_inst) -{ - uint32_t retry_max; - uint32_t bmcr; - uint8_t phy_address; - uint32_t timeout = 10; - uint8_t ret = 0; - - Gmac *pHw = gmac_inst->gGmacd.pHw; - - phy_address = gmac_inst->phy_address; - retry_max = gmac_inst->retries; - - bmcr = BMCR_RESET; - if_atsam_write_phy(pHw, phy_address, MII_BMCR, bmcr, retry_max); - do { - if_atsam_read_phy(pHw, phy_address, MII_BMCR, &bmcr, - retry_max); - timeout--; - } while ((bmcr & BMCR_RESET) && timeout); - - if (!timeout) { - ret = 1; - } - return (ret); -} - - -static uint8_t -if_atsam_init_phy(if_atsam_gmac *gmac_inst, uint32_t mck, - const Pin *pResetPins, uint32_t nbResetPins, const Pin *pGmacPins, - uint32_t nbGmacPins) -{ - uint8_t rc = 1; - Gmac *pHw = gmac_inst->gGmacd.pHw; - - /* Perform RESET */ - if (pResetPins) { - /* Configure PINS */ - PIO_Configure(pResetPins, nbResetPins); - PIO_Clear(pResetPins); - rtems_task_wake_after(1); - PIO_Set(pResetPins); - } - /* Configure GMAC runtime pins */ - if (rc) { - PIO_Configure(pGmacPins, nbGmacPins); - rc = GMAC_SetMdcClock(pHw, mck); - - if (!rc) { - return (0); - } - if_atsam_reset_phy(gmac_inst); - } - return (rc); -} - -static bool if_atsam_is_valid_phy(int phy) -{ - return phy >= 0 && phy <= 31; -} - -static int if_atsam_mdio_read(int phy, void *arg, unsigned reg, uint32_t *pval) -{ - if_atsam_softc *sc = (if_atsam_softc *)arg; - - if (!if_atsam_is_valid_phy(phy)) { - return (EINVAL); - } - - return (if_atsam_read_phy(sc->Gmac_inst.gGmacd.pHw, - (uint8_t)phy, (uint8_t)reg, pval, sc->Gmac_inst.retries)); -} - - -static int if_atsam_mdio_write(int phy, void *arg, unsigned reg, uint32_t pval) -{ - if_atsam_softc *sc = (if_atsam_softc *)arg; - - if (!if_atsam_is_valid_phy(phy)) { - return (EINVAL); - } - - return if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw, - (uint8_t)phy, (uint8_t)reg, pval, sc->Gmac_inst.retries); -} - - -/* - * Interrupt Handler for the network driver - */ -static void if_atsam_interrupt_handler(void *arg) -{ - if_atsam_softc *sc = (if_atsam_softc *)arg; - uint32_t irq_status_val; - rtems_event_set rx_event = 0; - rtems_event_set tx_event = 0; - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - - /* Get interrupt status */ - irq_status_val = GMAC_GetItStatus(pHw, 0); - - /* Check receive interrupts */ - if ((irq_status_val & GMAC_IER_ROVR) != 0) { - ++sc->rx_overrun_errors; - rx_event = ATSAMV7_ETH_RX_EVENT_INTERRUPT; - } - if ((irq_status_val & GMAC_IER_RCOMP) != 0) { - rx_event = ATSAMV7_ETH_RX_EVENT_INTERRUPT; - } - /* Send events to receive task and switch off rx interrupts */ - if (rx_event != 0) { - ++sc->rx_interrupts; - /* Erase the interrupts for RX completion and errors */ - GMAC_DisableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0); - (void)rtems_bsdnet_event_send(sc->rx_daemon_tid, rx_event); - } - if ((irq_status_val & GMAC_IER_TUR) != 0) { - ++sc->tx_tur_errors; - tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT; - } - if ((irq_status_val & GMAC_IER_RLEX) != 0) { - ++sc->tx_rlex_errors; - tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT; - } - if ((irq_status_val & GMAC_IER_TFC) != 0) { - ++sc->tx_tfc_errors; - tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT; - } - if ((irq_status_val & GMAC_IER_HRESP) != 0) { - ++sc->tx_hresp_errors; - tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT; - } - if ((irq_status_val & GMAC_IER_TCOMP) != 0) { - ++sc->tx_complete_int; - tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT; - } - /* Send events to transmit task and switch off tx interrupts */ - if (tx_event != 0) { - ++sc->tx_interrupts; - /* Erase the interrupts for TX completion and errors */ - GMAC_DisableIt(pHw, GMAC_INT_TX_BITS, 0); - (void)rtems_bsdnet_event_send(sc->tx_daemon_tid, tx_event); - } -} -/* - * Receive daemon - */ -static void if_atsam_rx_daemon(void *arg) -{ - if_atsam_softc *sc = (if_atsam_softc *)arg; - rtems_event_set events = 0; - void *rx_bd_base; - struct mbuf *m; - struct mbuf *n; - volatile sGmacRxDescriptor *buffer_desc; - int frame_len; - struct ether_header *eh; - uint32_t tmp_rx_bd_address; - - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - - /* Allocate memory space for priority queue descriptor list */ - rx_bd_base = rtems_cache_coherent_allocate(sizeof(sGmacRxDescriptor), - GMAC_DESCRIPTOR_ALIGNMENT, 0); - assert(rx_bd_base != NULL); - - buffer_desc = (sGmacRxDescriptor *)rx_bd_base; - buffer_desc->addr.val = GMAC_RX_SET_USED_WRAP; - buffer_desc->status.val = 0; - - GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 1); - GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 2); - - /* Allocate memory space for buffer descriptor list */ - rx_bd_base = rtems_cache_coherent_allocate( - sc->amount_rx_buf * sizeof(sGmacRxDescriptor), - GMAC_DESCRIPTOR_ALIGNMENT, 0); - assert(rx_bd_base != NULL); - buffer_desc = (sGmacRxDescriptor *)rx_bd_base; - - /* Create descriptor list and mark as empty */ - for (sc->rx_bd_fill_idx = 0; sc->rx_bd_fill_idx < sc->amount_rx_buf; - ++sc->rx_bd_fill_idx) { - m = if_atsam_new_mbuf(&sc->arpcom.ac_if); - assert(m != NULL); - sc->rx_mbuf[sc->rx_bd_fill_idx] = m; - buffer_desc->addr.val = ((uint32_t)m->m_data) & - GMAC_RX_BUF_DESC_ADDR_MASK; - buffer_desc->status.val = 0; - if (sc->rx_bd_fill_idx == (sc->amount_rx_buf - 1)) { - buffer_desc->addr.bm.bWrap = 1; - } else { - buffer_desc++; - } - } - buffer_desc = (sGmacRxDescriptor *)rx_bd_base; - - /* Set 2 Byte Receive Buffer Offset */ - pHw->GMAC_NCFGR |= GMAC_RX_SET_OFFSET; - - /* Write Buffer Queue Base Address Register */ - GMAC_ReceiveEnable(pHw, 0); - GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 0); - - /* Set address for address matching */ - GMAC_SetAddress(pHw, 0, sc->GMacAddress); - - /* Enable Receiving of data */ - GMAC_ReceiveEnable(pHw, 1); - - /* Setup the interrupts for RX completion and errors */ - GMAC_EnableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0); - - sc->rx_bd_fill_idx = 0; - - while (true) { - /* Wait for events */ - rtems_bsdnet_event_receive(ATSAMV7_ETH_RX_EVENT_INTERRUPT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); - - /* - * Check for all packets with a set ownership bit - */ - while (buffer_desc->addr.bm.bOwnership == 1) { - if (buffer_desc->status.bm.bEof == 1) { - m = sc->rx_mbuf[sc->rx_bd_fill_idx]; - - /* New mbuf for desc */ - n = if_atsam_new_mbuf(&sc->arpcom.ac_if); - if (n != NULL) { - frame_len = (int) - (buffer_desc->status.bm.len); - - /* Discard Ethernet header */ - int sz = frame_len - ETHER_HDR_LEN; - - /* Update mbuf */ - eh = (struct ether_header *) - (mtod(m, char *) + 2); - m->m_len = sz; - m->m_pkthdr.len = sz; - m->m_data = (void *)(eh + 1); - ether_input(&sc->arpcom.ac_if, eh, m); - m = n; - } else { - (void)rtems_bsdnet_event_send( - sc->tx_daemon_tid, ATSAMV7_ETH_START_TRANSMIT_EVENT); - } - sc->rx_mbuf[sc->rx_bd_fill_idx] = m; - tmp_rx_bd_address = (uint32_t)m->m_data & - GMAC_RX_BUF_DESC_ADDR_MASK; - - /* Switch pointer to next buffer descriptor */ - if (sc->rx_bd_fill_idx == - (sc->amount_rx_buf - 1)) { - tmp_rx_bd_address |= GMAC_RX_SET_WRAP; - sc->rx_bd_fill_idx = 0; - } else { - ++sc->rx_bd_fill_idx; - } - - /* - * Give ownership to GMAC for further processing - */ - tmp_rx_bd_address &= ~GMAC_RX_SET_USED; - _ARM_Data_synchronization_barrier(); - buffer_desc->addr.val = tmp_rx_bd_address; - - buffer_desc = (sGmacRxDescriptor *)rx_bd_base - + sc->rx_bd_fill_idx; - } - } - /* Setup the interrupts for RX completion and errors */ - GMAC_EnableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0); - } -} - -/* - * Update of current transmit buffer position. - */ -static void if_atsam_tx_bd_pos_update(size_t *pos, size_t amount_tx_buf) -{ - *pos = (*pos + 1) % amount_tx_buf; -} - -/* - * Is RingBuffer empty - */ -static bool if_atsam_ring_buffer_empty(ring_buffer *ring_buffer) -{ - return (ring_buffer->tx_bd_used == ring_buffer->tx_bd_free); -} - -/* - * Is RingBuffer full - */ -static bool if_atsam_ring_buffer_full(ring_buffer *ring_buffer) -{ - size_t tx_bd_used_next = ring_buffer->tx_bd_used; - - if_atsam_tx_bd_pos_update(&tx_bd_used_next, ring_buffer->length); - return (tx_bd_used_next == ring_buffer->tx_bd_free); -} - -/* - * Cleanup transmit file descriptors by freeing mbufs which are not needed any - * longer due to correct transmission. - */ -static void if_atsam_tx_bd_cleanup(if_atsam_softc *sc) -{ - struct mbuf *m; - volatile sGmacTxDescriptor *cur; - bool eof_needed = false; - - while (!if_atsam_ring_buffer_empty(&sc->tx_ring)){ - cur = sc->tx_bd_base + sc->tx_ring.tx_bd_free; - if (((cur->status.bm.bUsed == 1) && !eof_needed) || eof_needed) { - eof_needed = true; - cur->status.val |= GMAC_TX_SET_USED; - m = sc->tx_mbuf[sc->tx_ring.tx_bd_free]; - m_free(m); - sc->tx_mbuf[sc->tx_ring.tx_bd_free] = 0; - if_atsam_tx_bd_pos_update(&sc->tx_ring.tx_bd_free, - sc->tx_ring.length); - if (cur->status.bm.bLastBuffer) { - eof_needed = false; - } - } else { - break; - } - } -} - -/* - * Prepare Ethernet frame to start transmission. - */ -static bool if_atsam_send_packet(if_atsam_softc *sc, struct mbuf *m) -{ - volatile sGmacTxDescriptor *cur; - volatile sGmacTxDescriptor *start_packet_tx_bd = 0; - int pos = 0; - uint32_t tmp_val = 0; - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - bool success; - - if_atsam_tx_bd_cleanup(sc); - /* Wait for interrupt in case no buffer descriptors are available */ - /* Wait for events */ - while (true) { - if (if_atsam_ring_buffer_full(&sc->tx_ring)) { - /* Setup the interrupts for TX completion and errors */ - GMAC_EnableIt(pHw, GMAC_INT_TX_BITS, 0); - success = false; - break; - } - - /* - * Get current mbuf for data fill - */ - cur = &sc->tx_bd_base[sc->tx_ring.tx_bd_used]; - /* Set the transfer data */ - if (m->m_len) { - uintptr_t cache_adjustment = mtod(m, uintptr_t) % 32; - - rtems_cache_flush_multiple_data_lines( - mtod(m, const char *) - cache_adjustment, - (size_t)(m->m_len + cache_adjustment)); - - cur->addr = mtod(m, uint32_t); - tmp_val = (uint32_t)m->m_len | GMAC_TX_SET_USED; - if (sc->tx_ring.tx_bd_used == (sc->tx_ring.length - 1)) { - tmp_val |= GMAC_TX_SET_WRAP; - } - if (pos == 0) { - start_packet_tx_bd = cur; - } - sc->tx_mbuf[sc->tx_ring.tx_bd_used] = m; - m = m->m_next; - if_atsam_tx_bd_pos_update(&sc->tx_ring.tx_bd_used, - sc->tx_ring.length); - } else { - /* Discard empty mbufs */ - m = m_free(m); - } - - /* - * Send out the buffer once the complete mbuf_chain has been - * processed - */ - if (m == NULL) { - tmp_val |= GMAC_TX_SET_EOF; - tmp_val &= ~GMAC_TX_SET_USED; - _ARM_Data_synchronization_barrier(); - cur->status.val = tmp_val; - start_packet_tx_bd->status.val &= ~GMAC_TX_SET_USED; - _ARM_Data_synchronization_barrier(); - GMAC_TransmissionStart(pHw); - success = true; - break; - } else { - if (pos > 0) { - tmp_val &= ~GMAC_TX_SET_USED; - } - pos++; - cur->status.val = tmp_val; - } - } - return success; -} - - -/* - * Transmit daemon - */ -static void if_atsam_tx_daemon(void *arg) -{ - if_atsam_softc *sc = (if_atsam_softc *)arg; - rtems_event_set events = 0; - sGmacTxDescriptor *buffer_desc; - int bd_number; - void *tx_bd_base; - struct mbuf *m; - bool success; - - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - struct ifnet *ifp = &sc->arpcom.ac_if; - - GMAC_TransmitEnable(pHw, 0); - - /* Allocate memory space for priority queue descriptor list */ - tx_bd_base = rtems_cache_coherent_allocate(sizeof(sGmacTxDescriptor), - GMAC_DESCRIPTOR_ALIGNMENT, 0); - assert(tx_bd_base != NULL); - - buffer_desc = (sGmacTxDescriptor *)tx_bd_base; - buffer_desc->addr = 0; - buffer_desc->status.val = GMAC_TX_SET_USED | GMAC_TX_SET_WRAP; - - GMAC_SetTxQueue(pHw, (uint32_t)buffer_desc, 1); - GMAC_SetTxQueue(pHw, (uint32_t)buffer_desc, 2); - - /* Allocate memory space for buffer descriptor list */ - tx_bd_base = rtems_cache_coherent_allocate( - sc->amount_tx_buf * sizeof(sGmacTxDescriptor), - GMAC_DESCRIPTOR_ALIGNMENT, 0); - assert(tx_bd_base != NULL); - buffer_desc = (sGmacTxDescriptor *)tx_bd_base; - - /* Create descriptor list and mark as empty */ - for (bd_number = 0; bd_number < sc->amount_tx_buf; bd_number++) { - buffer_desc->addr = 0; - buffer_desc->status.val = GMAC_TX_SET_USED; - if (bd_number == (sc->amount_tx_buf - 1)) { - buffer_desc->status.bm.bWrap = 1; - } else { - buffer_desc++; - } - } - buffer_desc = (sGmacTxDescriptor *)tx_bd_base; - - /* Write Buffer Queue Base Address Register */ - GMAC_SetTxQueue(pHw, (uint32_t)buffer_desc, 0); - - /* Enable Transmission of data */ - GMAC_TransmitEnable(pHw, 1); - - /* Set variables in context */ - sc->tx_bd_base = tx_bd_base; - - while (true) { - /* Wait for events */ - rtems_bsdnet_event_receive(ATSAMV7_ETH_START_TRANSMIT_EVENT | ATSAMV7_ETH_TX_EVENT_INTERRUPT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); - //printf("TX Transmit Event received\n"); - - /* - * Send packets till queue is empty - */ - while (true) { - /* - * Get the mbuf chain to transmit - */ - if_atsam_tx_bd_cleanup(sc); - IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m); - if (!m) { - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - success = if_atsam_send_packet(sc, m); - if (!success){ - break; - } - } - } -} - - -/* - * Send packet (caller provides header). - */ -static void if_atsam_enet_start(struct ifnet *ifp) -{ - if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc; - - ifp->if_flags |= IFF_OACTIVE; - rtems_bsdnet_event_send(sc->tx_daemon_tid, - ATSAMV7_ETH_START_TRANSMIT_EVENT); -} - - -/* - * Attach a watchdog for autonegotiation to the system - */ -static void if_atsam_interface_watchdog(struct ifnet *ifp) -{ - uint32_t anlpar; - uint8_t speed = GMAC_SPEED_100M; - uint8_t full_duplex = GMAC_DUPLEX_FULL; - - if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc; - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - uint8_t phy = sc->Gmac_inst.phy_address; - uint32_t retries = sc->Gmac_inst.retries; - - if (if_atsam_read_phy(pHw, phy, MII_ANLPAR, &anlpar, retries)) { - anlpar = 0; - } - if (sc->anlpar != anlpar) { - /* Set up the GMAC link speed */ - if (anlpar & ANLPAR_TX_FD) { - /* Set MII for 100BaseTx and Full Duplex */ - speed = GMAC_SPEED_100M; - full_duplex = GMAC_DUPLEX_FULL; - } else if (anlpar & ANLPAR_10_FD) { - /* Set MII for 10BaseTx and Full Duplex */ - speed = GMAC_SPEED_10M; - full_duplex = GMAC_DUPLEX_FULL; - } else if (anlpar & ANLPAR_TX) { - /* Set MII for 100BaseTx and half Duplex */ - speed = GMAC_SPEED_100M; - full_duplex = GMAC_DUPLEX_HALF; - } else if (anlpar & ANLPAR_10) { - /* Set MII for 10BaseTx and half Duplex */ - speed = GMAC_SPEED_10M; - full_duplex = GMAC_DUPLEX_HALF; - } else { - /* Set MII for 100BaseTx and Full Duplex */ - speed = GMAC_SPEED_100M; - full_duplex = GMAC_DUPLEX_FULL; - } - GMAC_SetLinkSpeed(pHw, speed, full_duplex); - sc->anlpar = anlpar; - } - ifp->if_timer = WATCHDOG_TIMEOUT; -} - - -/* - * Sets up the hardware and chooses the interface to be used - */ -static void if_atsam_init(void *arg) -{ - rtems_status_code status; - - if_atsam_softc *sc = (if_atsam_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - uint32_t dmac_cfg = 0; - uint32_t gmii_val = 0; - - if (sc->arpcom.ac_if.if_flags & IFF_RUNNING) { - return; - } - sc->arpcom.ac_if.if_flags |= IFF_RUNNING; - sc->interrupt_number = GMAC_IRQn; - - /* Enable Peripheral Clock */ - if ((PMC->PMC_PCSR1 & (1u << 7)) != (1u << 7)) { - PMC->PMC_PCER1 = 1 << 7; - } - /* Setup interrupts */ - NVIC_ClearPendingIRQ(GMAC_IRQn); - NVIC_EnableIRQ(GMAC_IRQn); - - GMACD_Init(&sc->Gmac_inst.gGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE, - GMAC_NBC_DISABLE); - - /* Enable MDIO interface */ - GMAC_EnableMdio(sc->Gmac_inst.gGmacd.pHw); - - /* PHY initialize */ - if_atsam_init_phy(&sc->Gmac_inst, BOARD_MCK, &gmacResetPin, 1, - gmacPins, PIO_LISTSIZE(gmacPins)); - /* Find valid Phy */ - atsamv7_find_valid_phy(&sc->Gmac_inst); - - /* Set Link Speed */ - sc->anlpar = 0xFFFFFFFF; - if_atsam_interface_watchdog(ifp); - - /* Enable autonegotation */ - if_atsam_read_phy(sc->Gmac_inst.gGmacd.pHw, sc->Gmac_inst.phy_address, - MII_BMCR, &gmii_val, sc->Gmac_inst.retries); - if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw, sc->Gmac_inst.phy_address, - MII_BMCR, (gmii_val | BMCR_AUTOEN), sc->Gmac_inst.retries); - - /* Configuration of DMAC */ - dmac_cfg = (GMAC_DCFGR_DRBS(GMAC_RX_BUFFER_SIZE >> 6)) | - GMAC_DCFGR_RXBMS(3) | GMAC_DCFGR_TXPBMS | GMAC_DCFGR_FBLDO_INCR16; - GMAC_SetDMAConfig(sc->Gmac_inst.gGmacd.pHw, dmac_cfg, 0); - - /* Shut down Transmit and Receive */ - GMAC_ReceiveEnable(sc->Gmac_inst.gGmacd.pHw, 0); - GMAC_TransmitEnable(sc->Gmac_inst.gGmacd.pHw, 0); - - GMAC_StatisticsWriteEnable(sc->Gmac_inst.gGmacd.pHw, 1); - - /* - * Allocate mbuf pointers - */ - sc->rx_mbuf = malloc(sc->amount_rx_buf * sizeof *sc->rx_mbuf, - M_MBUF, M_NOWAIT); - sc->tx_mbuf = malloc(sc->amount_tx_buf * sizeof *sc->tx_mbuf, - M_MBUF, M_NOWAIT); - - /* Install interrupt handler */ - status = rtems_interrupt_handler_install(sc->interrupt_number, - "Ethernet", - RTEMS_INTERRUPT_UNIQUE, - if_atsam_interrupt_handler, - sc); - assert(status == RTEMS_SUCCESSFUL); - - /* - * Start driver tasks - */ - sc->rx_daemon_tid = rtems_bsdnet_newproc("SCrx", 4096, - if_atsam_rx_daemon, sc); - sc->tx_daemon_tid = rtems_bsdnet_newproc("SCtx", 4096, - if_atsam_tx_daemon, sc); - - /* Start Watchdog Timer */ - ifp->if_timer = 1; -} - - -/* - * Stop the device - */ -static void if_atsam_stop(struct if_atsam_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - - ifp->if_flags &= ~IFF_RUNNING; - - /* Disable MDIO interface and TX/RX */ - pHw->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN); - pHw->GMAC_NCR &= ~GMAC_NCR_MPE; -} - - -/* - * Show interface statistics - */ -static void if_atsam_stats(struct if_atsam_softc *sc) -{ - int eno = EIO; - int media = 0; - Gmac *pHw; - - media = (int)IFM_MAKEWORD(0, 0, 0, sc->Gmac_inst.phy_address); - eno = rtems_mii_ioctl(&sc->mdio, sc, SIOCGIFMEDIA, &media); - - rtems_bsdnet_semaphore_release(); - - if (eno == 0) { - rtems_ifmedia2str(media, NULL, 0); - printf("\n"); - } - pHw = sc->Gmac_inst.gGmacd.pHw; - - printf("\n** Context Statistics **\n"); - printf("Rx interrupts: %u\n", sc->rx_interrupts); - printf("Tx interrupts: %u\n", sc->tx_interrupts); - printf("Error Tur Tx interrupts: %u\n\n", sc->tx_tur_errors); - printf("Error Rlex Tx interrupts: %u\n\n", sc->tx_rlex_errors); - printf("Error Tfc Tx interrupts: %u\n\n", sc->tx_tfc_errors); - printf("Error Hresp Tx interrupts: %u\n\n", sc->tx_hresp_errors); - printf("Tx complete interrupts: %u\n\n", sc->tx_complete_int); - printf("\n** Statistics **\n"); - printf("Octets Transmitted Low: %lu\n", pHw->GMAC_OTLO); - printf("Octets Transmitted High: %lu\n", pHw->GMAC_OTHI); - printf("Frames Transmitted: %lu\n", pHw->GMAC_FT); - printf("Broadcast Frames Transmitted: %lu\n", pHw->GMAC_BCFT); - printf("Multicast Frames Transmitted: %lu\n", pHw->GMAC_MFT); - printf("Pause Frames Transmitted: %lu\n", pHw->GMAC_PFT); - printf("64 Byte Frames Transmitted: %lu\n", pHw->GMAC_BFT64); - printf("65 to 127 Byte Frames Transmitted: %lu\n", pHw->GMAC_TBFT127); - printf("128 to 255 Byte Frames Transmitted: %lu\n", pHw->GMAC_TBFR255); - printf("256 to 511 Byte Frames Transmitted: %lu\n", pHw->GMAC_TBFT511); - printf("512 to 1023 Byte Frames Transmitted: %lu\n", - pHw->GMAC_TBFT1023); - printf("1024 to 1518 Byte Frames Transmitted: %lu\n", - pHw->GMAC_TBFT1518); - printf("Greater Than 1518 Byte Frames Transmitted: %lu\n", - pHw->GMAC_GTBFT1518); - printf("Transmit Underruns: %lu\n", pHw->GMAC_TUR); - printf("Single Collision Frames: %lu\n", pHw->GMAC_SCF); - printf("Multiple Collision Frames: %lu\n", pHw->GMAC_MCF); - printf("Excessive Collisions: %lu\n", pHw->GMAC_EC); - printf("Late Collisions: %lu\n", pHw->GMAC_LC); - printf("Deferred Transmission Frames: %lu\n", pHw->GMAC_DTF); - printf("Carrier Sense Errors: %lu\n", pHw->GMAC_CSE); - printf("Octets Received Low: %lu\n", pHw->GMAC_ORLO); - printf("Octets Received High: %lu\n", pHw->GMAC_ORHI); - printf("Frames Received: %lu\n", pHw->GMAC_FR); - printf("Broadcast Frames Received: %lu\n", pHw->GMAC_BCFR); - printf("Multicast Frames Received: %lu\n", pHw->GMAC_MFR); - printf("Pause Frames Received: %lu\n", pHw->GMAC_PFR); - printf("64 Byte Frames Received: %lu\n", pHw->GMAC_BFR64); - printf("65 to 127 Byte Frames Received: %lu\n", pHw->GMAC_TBFR127); - printf("128 to 255 Byte Frames Received: %lu\n", pHw->GMAC_TBFR255); - printf("256 to 511 Byte Frames Received: %lu\n", pHw->GMAC_TBFR511); - printf("512 to 1023 Byte Frames Received: %lu\n", pHw->GMAC_TBFR1023); - printf("1024 to 1518 Byte Frames Received: %lu\n", pHw->GMAC_TBFR1518); - printf("1519 to Maximum Byte Frames Received: %lu\n", - pHw->GMAC_TBFR1518); - printf("Undersize Frames Received: %lu\n", pHw->GMAC_UFR); - printf("Oversize Frames Received: %lu\n", pHw->GMAC_OFR); - printf("Jabbers Received: %lu\n", pHw->GMAC_JR); - printf("Frame Check Sequence Errors: %lu\n", pHw->GMAC_FCSE); - printf("Length Field Frame Errors: %lu\n", pHw->GMAC_LFFE); - printf("Receive Symbol Errors: %lu\n", pHw->GMAC_RSE); - printf("Alignment Errors: %lu\n", pHw->GMAC_AE); - printf("Receive Resource Errors: %lu\n", pHw->GMAC_RRE); - printf("Receive Overrun: %lu\n", pHw->GMAC_ROE); - printf("IP Header Checksum Errors: %lu\n", pHw->GMAC_IHCE); - printf("TCP Checksum Errors: %lu\n", pHw->GMAC_TCE); - printf("UDP Checksum Errors: %lu\n", pHw->GMAC_UCE); - - rtems_bsdnet_semaphore_obtain(); -} - - -/* - * Calculates the index that is to be sent into the hash registers - */ -static void if_atsam_get_hash_index(uint64_t addr, uint32_t *val) -{ - uint64_t tmp_val; - uint8_t i, j; - uint64_t idx; - int offset = 0; - - addr &= MAC_ADDR_MASK; - - for (i = 0; i < HASH_INDEX_AMOUNT; ++i) { - tmp_val = 0; - offset = 0; - for (j = 0; j < HASH_ELEMENTS_PER_INDEX; j++) { - idx = (addr >> (offset + i)) & MAC_IDX_MASK; - tmp_val ^= idx; - offset += HASH_INDEX_AMOUNT; - } - if (tmp_val > 0) { - *val |= (1u << i); - } - } -} - - -/* - * Dis/Enable promiscuous Mode - */ -static void if_atsam_promiscuous_mode(if_atsam_softc *sc, bool enable) -{ - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - - if (enable) { - pHw->GMAC_NCFGR |= GMAC_PROM_ENABLE; - } else { - pHw->GMAC_NCFGR &= ~GMAC_PROM_ENABLE; - } -} - - -/* - * Multicast handler - */ -static int -if_atsam_multicast_control(bool add, struct ifreq *ifr, if_atsam_softc *sc) -{ - int eno = 0; - struct arpcom *ac = &sc->arpcom; - Gmac *pHw = sc->Gmac_inst.gGmacd.pHw; - - /* Switch off Multicast Hashing */ - pHw->GMAC_NCFGR &= ~GMAC_MC_ENABLE; - - if (add) { - eno = ether_addmulti(ifr, ac); - } else { - eno = ether_delmulti(ifr, ac); - } - - if (eno == ENETRESET) { - struct ether_multistep step; - struct ether_multi *enm; - - eno = 0; - - pHw->GMAC_HRB = 0; - pHw->GMAC_HRT = 0; - - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - uint64_t addrlo = 0; - uint64_t addrhi = 0; - uint32_t val = 0; - - memcpy(&addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); - memcpy(&addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); - while (addrlo <= addrhi) { - if_atsam_get_hash_index(addrlo, &val); - if (val < 32) { - pHw->GMAC_HRB |= (1u << val); - } else { - pHw->GMAC_HRT |= (1u << (val - 32)); - } - ++addrlo; - } - ETHER_NEXT_MULTI(step, enm); - } - } - /* Switch on Multicast Hashing */ - pHw->GMAC_NCFGR |= GMAC_MC_ENABLE; - return (eno); -} - - -/* - * Driver ioctl handler - */ -static int -if_atsam_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc; - struct ifreq *ifr = (struct ifreq *)data; - int rv = 0; - bool prom_enable; - - switch (command) { - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - rtems_mii_ioctl(&sc->mdio, sc, command, &ifr->ifr_media); - break; - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl(ifp, command, data); - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING) { - /* Don't do anything */ - } else { - if_atsam_init(sc); - } - prom_enable = ((ifp->if_flags & IFF_PROMISC) != 0); - if_atsam_promiscuous_mode(sc, prom_enable); - } else { - if (ifp->if_flags & IFF_RUNNING) { - if_atsam_stop(sc); - } - } - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - if_atsam_multicast_control(command == SIOCADDMULTI, ifr, sc); - break; - case SIO_RTEMS_SHOW_STATS: - if_atsam_stats(sc); - break; - default: - rv = EINVAL; - break; - } - return (rv); -} - - -/* - * Attach an SAMV71 driver to the system - */ -static int if_atsam_driver_attach(struct rtems_bsdnet_ifconfig *config) -{ - if_atsam_softc *sc = &if_atsam_softc_inst; - struct ifnet *ifp = &sc->arpcom.ac_if; - const if_atsam_config *conf = config->drv_ctrl; - int unitNumber; - char *unitName; - - if (conf != NULL) { - sc->Gmac_inst.retries = conf->mdio_retries; - sc->Gmac_inst.phy_address = conf->phy_addr; - } else { - sc->Gmac_inst.retries = 10; - sc->Gmac_inst.phy_address = 0xFF; - } - - /* The MAC address used */ - memcpy(sc->GMacAddress, config->hardware_address, ETHER_ADDR_LEN); - memcpy(sc->arpcom.ac_enaddr, sc->GMacAddress, ETHER_ADDR_LEN); - - /* - * Parse driver name - */ - unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName); - assert(unitNumber == 0); - - assert(ifp->if_softc == NULL); - - /* MDIO */ - sc->mdio.mdio_r = if_atsam_mdio_read; - sc->mdio.mdio_w = if_atsam_mdio_write; - sc->mdio.has_gmii = 1; - - if (config->rbuf_count > 0) { - sc->amount_rx_buf = config->rbuf_count; - } else { - sc->amount_rx_buf = 8; - } - - if (config->xbuf_count > 0) { - sc->amount_tx_buf = config->xbuf_count; - } else { - sc->amount_tx_buf = 64; - } - - sc->tx_ring.tx_bd_used = 0; - sc->tx_ring.tx_bd_free = 0; - sc->tx_ring.length = sc->amount_tx_buf; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = (short int)unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = ETHERMTU; - ifp->if_init = if_atsam_init; - ifp->if_ioctl = if_atsam_ioctl; - ifp->if_start = if_atsam_enet_start; - ifp->if_output = ether_output; - ifp->if_watchdog = if_atsam_interface_watchdog; - ifp->if_flags = IFF_MULTICAST | IFF_BROADCAST | IFF_SIMPLEX; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_timer = 0; - - /* - * Attach the interface - */ - if_attach(ifp); - ether_ifattach(ifp); - return (1); -} - - -int if_atsam_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - (void)attaching; - return (if_atsam_driver_attach(config)); -} diff --git a/bsps/arm/csb336/net/lan91c11x.c b/bsps/arm/csb336/net/lan91c11x.c deleted file mode 100644 index 779fbdc039..0000000000 --- a/bsps/arm/csb336/net/lan91c11x.c +++ /dev/null @@ -1,261 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSBSPsARMCSB336 - * - * @brief Helper functions for SMSC LAN91C11x - */ - -/* - * Helper functions for SMSC LAN91C11x - * - * Copyright (c) 2004 by Cogent Computer Systems - * Written by Jay Monkman <jtm@lopingdog.com> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <sys/types.h> -#include <rtems.h> -#include "lan91c11x.h" - -uint16_t lan91c11x_read_reg(int reg) -{ - volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR; - uint16_t old_bank; - uint16_t val; - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - - /* save the bank register */ - old_bank = ptr[7] & 0x7; - - /* set the bank register */ - ptr[7] = (reg >> 4) & 0x7; - - val = ptr[((reg & 0xf) >> 1)]; - - /* restore the bank register */ - ptr[7] = old_bank; - - rtems_interrupt_enable(level); - return val; -} - -void lan91c11x_write_reg(int reg, uint16_t value) -{ - volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR; - uint16_t old_bank; - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - - /* save the bank register */ - old_bank = ptr[7] & 0x7; - - /* set the bank register */ - ptr[7] = (reg >> 4) & 0x7; - - ptr[((reg & 0xf) >> 1)] = value; - - /* restore the bank register */ - ptr[7] = old_bank; - - rtems_interrupt_enable(level); -} - -uint16_t lan91c11x_read_reg_fast(int reg) -{ - volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR; - uint16_t val; - - val = ptr[((reg & 0xf) >> 1)]; - - return val; -} - -void lan91c11x_write_reg_fast(int reg, uint16_t value) -{ - volatile uint16_t *ptr = (uint16_t *)LAN91C11X_BASE_ADDR; - - ptr[((reg & 0xf) >> 1)] = value; -} - - -uint16_t lan91c11x_read_phy_reg(int reg) -{ - int i; - uint16_t mask; - uint16_t bits[64]; - int clk_idx = 0; - int input_idx = 0; - uint16_t phydata; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; ++i) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - } - - /* Start code <01> */ - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - - /* Read command <10> */ - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - - /* Output the PHY address, msb first - Internal PHY is address 0 */ - for (i = 0; i < 5; ++i) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - } - - /* Output the phy register number, msb first */ - mask = 0x10; - for (i = 0; i < 5; ++i) { - if (reg & mask) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - } else { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - } - - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* 1 bit time for turnaround */ - bits[clk_idx++] = 0; - - /* Input starts at this bit time */ - input_idx = clk_idx; - - /* Will input 16 bits */ - for (i = 0; i < 16; ++i) { - bits[clk_idx++] = 0; - } - - /* Final clock bit */ - bits[clk_idx++] = 0; - - /* Turn off all MII Interface bits */ - lan91c11x_write_reg(LAN91C11X_MGMT, - lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0); - - /* Clock all 64 cycles */ - for (i = 0; i < sizeof bits; ++i) { - /* Clock Low - output data */ - lan91c11x_write_reg(LAN91C11X_MGMT, bits[i]); - rtems_task_wake_after(1); - - /* Clock Hi - input data */ - lan91c11x_write_reg(LAN91C11X_MGMT, bits[i] | LAN91C11X_MGMT_MCLK); - rtems_task_wake_after(1); - bits[i] |= lan91c11x_read_reg(LAN91C11X_MGMT) & LAN91C11X_MGMT_MDI; - } - - /* Return to idle state */ - /* Set clock to low, data to low, and output tristated */ - lan91c11x_write_reg(LAN91C11X_MGMT, lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0); - rtems_task_wake_after(1); - - /* Recover input data */ - phydata = 0; - for (i = 0; i < 16; ++i) { - phydata <<= 1; - - if (bits[input_idx++] & LAN91C11X_MGMT_MDI) { - phydata |= 0x0001; - } - } - - return phydata; -} - - - -void lan91c11x_write_phy_reg(int reg, uint16_t phydata) -{ - int i; - ushort mask; - ushort bits[64]; - int clk_idx = 0; - - /* 32 consecutive ones on MDO to establish sync */ - for (i = 0; i < 32; ++i) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - } - - /* Start code <01> */ - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - - /* Write command <01> */ - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - - /* Output the PHY address, msb first - Internal PHY is address 0 */ - for (i = 0; i < 5; ++i) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - } - - /* Output the phy register number, msb first */ - mask = 0x10; - for (i = 0; i < 5; ++i) { - if (reg & mask) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - } else { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - } - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* 2 extra bit times for turnaround */ - bits[clk_idx++] = 0; - bits[clk_idx++] = 0; - - /* Write out 16 bits of data, msb first */ - mask = 0x8000; - for (i = 0; i < 16; ++i) { - if (phydata & mask) { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE | LAN91C11X_MGMT_MDO; - } else { - bits[clk_idx++] = LAN91C11X_MGMT_MDOE; - } - - /* Shift to next lowest bit */ - mask >>= 1; - } - - /* Turn off all MII Interface bits */ - lan91c11x_write_reg(LAN91C11X_MGMT, - lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0); - - /* Clock all 64 cycles */ - for (i = 0; i < sizeof bits; ++i) { - /* Clock Low - output data */ - lan91c11x_write_reg(LAN91C11X_MGMT, bits[i]); - rtems_task_wake_after(1); - - /* Clock Hi - input data */ - lan91c11x_write_reg(LAN91C11X_MGMT, bits[i] | LAN91C11X_MGMT_MCLK); - rtems_task_wake_after(1); - bits[i] |= lan91c11x_read_reg(LAN91C11X_MGMT) & LAN91C11X_MGMT_MDI; - } - - /* Return to idle state */ - /* Set clock to low, data to low, and output tristated */ - lan91c11x_write_reg(LAN91C11X_MGMT, - lan91c11x_read_reg(LAN91C11X_MGMT) & 0xfff0); - rtems_task_wake_after(1); - -} - - - diff --git a/bsps/arm/csb336/net/lan91c11x.h b/bsps/arm/csb336/net/lan91c11x.h deleted file mode 100644 index c1181bda69..0000000000 --- a/bsps/arm/csb336/net/lan91c11x.h +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @file - * - * @ingroup RTEMSBSPsARMCSB336 - * - * @brief SMSC LAN91C11x ethernet devices definitions. - */ - -/** - * @defgroup arm_csb336_lan91c11x SMSC LAN91C11x - * - * @ingroup RTEMSBSPsARMCSB336 - * - * @brief SMSC LAN91C11x ethernet devices definitions. - */ - -/* - * Header file for SMSC LAN91C11x ethernet devices - * - * Copyright (c) 2004 by Cogent Computer Systems - * Written by Jay Monkman <jtm@lopingdog.com> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ -#ifndef __LAN91C11X_H__ -#define __LAN91C11X_H__ - -#include <rtems.h> -#include <bsp.h> - -uint16_t lan91c11x_read_reg(int); -void lan91c11x_write_reg(int, uint16_t); -uint16_t lan91c11x_read_reg_fast(int); -void lan91c11x_write_reg_fast(int, uint16_t); -void lan91c11x_write_phy_reg(int , uint16_t); -uint16_t lan91c11x_read_phy_reg(int); -void lan91c11x_unlock(void); -void lan91c11x_lock(void); - -#define LAN91C11X_BASE_ADDR 0x12000000 - -#define LAN91C11X_REG(_b_, _r_) ((((_b_) & 0xf) << 4) | ((_r_) & 0xf)) - - -#define LAN91C11X_TCR (LAN91C11X_REG(0, 0x0)) -#define LAN91C11X_EPHSTAT (LAN91C11X_REG(0, 0x2)) -#define LAN91C11X_RCR (LAN91C11X_REG(0, 0x4)) -#define LAN91C11X_CNTR (LAN91C11X_REG(0, 0x6)) -#define LAN91C11X_MIR (LAN91C11X_REG(0, 0x8)) -#define LAN91C11X_RPCR (LAN91C11X_REG(0, 0xa)) -#define LAN91C11X_BANK (LAN91C11X_REG(0, 0xe)) -#define LAN91C11X_CONFIG (LAN91C11X_REG(1, 0x0)) -#define LAN91C11X_BASE (LAN91C11X_REG(1, 0x2)) -#define LAN91C11X_IA0 (LAN91C11X_REG(1, 0x4)) -#define LAN91C11X_IA2 (LAN91C11X_REG(1, 0x6)) -#define LAN91C11X_IA4 (LAN91C11X_REG(1, 0x8)) -#define LAN91C11X_GNRL (LAN91C11X_REG(1, 0xa)) -#define LAN91C11X_CTRL (LAN91C11X_REG(1, 0xc)) -#define LAN91C11X_MMUCMD (LAN91C11X_REG(2, 0x0)) -#define LAN91C11X_PNR (LAN91C11X_REG(2, 0x2)) -#define LAN91C11X_FIFO (LAN91C11X_REG(2, 0x4)) -#define LAN91C11X_PTR (LAN91C11X_REG(2, 0x6)) -#define LAN91C11X_DATA (LAN91C11X_REG(2, 0x8)) -#define LAN91C11X_INT (LAN91C11X_REG(2, 0xc)) -#define LAN91C11X_MT0 (LAN91C11X_REG(3, 0x0)) -#define LAN91C11X_MT2 (LAN91C11X_REG(3, 0x2)) -#define LAN91C11X_MT4 (LAN91C11X_REG(3, 0x4)) -#define LAN91C11X_MT6 (LAN91C11X_REG(3, 0x6)) -#define LAN91C11X_MGMT (LAN91C11X_REG(3, 0x8)) -#define LAN91C11X_REV (LAN91C11X_REG(3, 0xa)) -#define LAN91C11X_ERCV (LAN91C11X_REG(3, 0xc)) - - -#define LAN91C11X_TCR_TXENA (bit(0)) -#define LAN91C11X_TCR_LOOP (bit(1)) -#define LAN91C11X_TCR_FORCOL (bit(2)) -#define LAN91C11X_TCR_PADEN (bit(7)) -#define LAN91C11X_TCR_NOCRC (bit(8)) -#define LAN91C11X_TCR_MONCSN (bit(10)) -#define LAN91C11X_TCR_FDUPLX (bit(11)) -#define LAN91C11X_TCR_STPSQET (bit(12)) -#define LAN91C11X_TCR_EPHLOOP (bit(13)) -#define LAN91C11X_TCR_SWFDUP (bit(15)) - -#define LAN91C11X_EPHSTAT_TXSUC (bit(0)) -#define LAN91C11X_EPHSTAT_SNGLCOL (bit(1)) -#define LAN91C11X_EPHSTAT_MULCOL (bit(2)) -#define LAN91C11X_EPHSTAT_LTXMUL (bit(3)) -#define LAN91C11X_EPHSTAT_16COL (bit(4)) -#define LAN91C11X_EPHSTAT_SQET (bit(5)) -#define LAN91C11X_EPHSTAT_LTXBRD (bit(6)) -#define LAN91C11X_EPHSTAT_TXDFR (bit(7)) -#define LAN91C11X_EPHSTAT_LATCOL (bit(9)) -#define LAN91C11X_EPHSTAT_LOST (bit(10)) -#define LAN91C11X_EPHSTAT_EXCDEF (bit(11)) -#define LAN91C11X_EPHSTAT_CTRROL (bit(12)) -#define LAN91C11X_EPHSTAT_LINK (bit(14)) -#define LAN91C11X_EPHSTAT_TXUNRN (bit(15)) - -#define LAN91C11X_RCR_RXABT (bit(0)) -#define LAN91C11X_RCR_PRMS (bit(1)) -#define LAN91C11X_RCR_ALMUL (bit(2)) -#define LAN91C11X_RCR_RXEN (bit(8)) -#define LAN91C11X_RCR_STRIP (bit(9)) -#define LAN91C11X_RCR_ABTENB (bit(13)) -#define LAN91C11X_RCR_FILT (bit(14)) -#define LAN91C11X_RCR_RST (bit(15)) - -#define LAN91C11X_RPCR_LS0B (bit(2)) -#define LAN91C11X_RPCR_LS1B (bit(3)) -#define LAN91C11X_RPCR_LS2B (bit(4)) -#define LAN91C11X_RPCR_LS0A (bit(5)) -#define LAN91C11X_RPCR_LS1A (bit(6)) -#define LAN91C11X_RPCR_LS2A (bit(7)) -#define LAN91C11X_RPCR_ANEG (bit(11)) -#define LAN91C11X_RPCR_DPLX (bit(12)) -#define LAN91C11X_RPCR_SPEED (bit(13)) - -#define LAN91C11X_CONFIG_EXTPHY (bit(9)) -#define LAN91C11X_CONFIG_GPCTRL (bit(10)) -#define LAN91C11X_CONFIG_NOWAIT (bit(12)) -#define LAN91C11X_CONFIG_PWR (bit(15)) - -#define LAN91C11X_CTRL_STORE (bit(0)) -#define LAN91C11X_CTRL_RELOAD (bit(1)) -#define LAN91C11X_CTRL_EEPROM (bit(2)) -#define LAN91C11X_CTRL_TEEN (bit(5)) -#define LAN91C11X_CTRL_CREN (bit(6)) -#define LAN91C11X_CTRL_LEEN (bit(7)) -#define LAN91C11X_CTRL_AUTO (bit(11)) -#define LAN91C11X_CTRL_RCVBAD (bit(14)) - -#define LAN91C11X_MMUCMD_BUSY (bit(0)) -#define LAN91C11X_MMUCMD_NOOP (0 << 5) -#define LAN91C11X_MMUCMD_ALLOCTX (1 << 5) -#define LAN91C11X_MMUCMD_RESETMMU (2 << 5) -#define LAN91C11X_MMUCMD_REMFRM (3 << 5) -#define LAN91C11X_MMUCMD_REMTOP (4 << 5) -#define LAN91C11X_MMUCMD_RELEASE (5 << 5) -#define LAN91C11X_MMUCMD_ENQUEUE (6 << 5) -#define LAN91C11X_MMUCMD_RESETTX (7 << 5) - -#define LAN91C11X_PTR_MASK (0x7ff) -#define LAN91C11X_PTR_NE (bit(11)) -#define LAN91C11X_PTR_ETEN (bit(12)) -#define LAN91C11X_PTR_READ (bit(13)) -#define LAN91C11X_PTR_AUTOINC (bit(14)) -#define LAN91C11X_PTR_RCV (bit(15)) - -#define LAN91C11X_INT_RX (bit(0)) -#define LAN91C11X_INT_TX (bit(1)) -#define LAN91C11X_INT_TXE (bit(2)) -#define LAN91C11X_INT_ALLOC (bit(3)) -#define LAN91C11X_INT_RXOV (bit(4)) -#define LAN91C11X_INT_EPH (bit(5)) -#define LAN91C11X_INT_ERX (bit(6)) -#define LAN91C11X_INT_MD (bit(7)) -#define LAN91C11X_INT_RXMASK (bit(8)) -#define LAN91C11X_INT_TXMASK (bit(9)) -#define LAN91C11X_INT_TXEMASK (bit(10)) -#define LAN91C11X_INT_ALLOCMASK (bit(11)) -#define LAN91C11X_INT_RXOVMASK (bit(12)) -#define LAN91C11X_INT_EPHMASK (bit(13)) -#define LAN91C11X_INT_ERXMASK (bit(14)) -#define LAN91C11X_INT_MDMASK (bit(15)) - -#define LAN91C11X_MGMT_MDO (bit(0)) -#define LAN91C11X_MGMT_MDI (bit(1)) -#define LAN91C11X_MGMT_MCLK (bit(2)) -#define LAN91C11X_MGMT_MDOE (bit(3)) -#define LAN91C11X_MGMT_MSKCRS100 (bit(14)) - - -#define LAN91C11X_PKT_CTRL_CRC (bit(4)) -#define LAN91C11X_PKT_CTRL_ODD (bit(5)) - - -/* PHY Registers */ -#define PHY_CTRL 0x00 /* PHY Control */ -#define PHY_STAT 0x01 /* PHY Status */ -#define PHY_ID1 0x02 /* PHY Identifier 1 */ -#define PHY_ID2 0x03 /* PHY Identifier 2 */ -#define PHY_AD 0x04 /* PHY Auto-negotiate Control */ -#define PHY_RMT 0x05 /* PHY Auto-neg Remote End Cap Register */ -#define PHY_CFG1 0x10 /* PHY Configuration 1 */ -#define PHY_CFG2 0x11 /* PHY Configuration 2 */ -#define PHY_INT 0x12 /* Status Output (Interrupt Status) */ -#define PHY_MASK 0x13 /* Interrupt Mask */ - -/* PHY Control Register Bit Defines */ -#define PHY_CTRL_RST 0x8000 /* PHY Reset */ -#define PHY_CTRL_LPBK 0x4000 /* PHY Loopback */ -#define PHY_CTRL_SPEED 0x2000 /* 100Mbps, 0=10Mpbs */ -#define PHY_CTRL_ANEGEN 0x1000 /* Enable Auto negotiation */ -#define PHY_CTRL_PDN 0x0800 /* PHY Power Down mode */ -#define PHY_CTRL_MIIDIS 0x0400 /* MII 4 bit interface disabled */ -#define PHY_CTRL_ANEGRST 0x0200 /* Reset Auto negotiate */ -#define PHY_CTRL_DPLX 0x0100 /* Full Duplex, 0=Half Duplex */ -#define PHY_CTRL_COLTST 0x0080 /* MII Colision Test */ - -#define PHY_STAT_CAPT4 0x8000 -#define PHY_STAT_CAPTXF 0x4000 -#define PHY_STAT_CAPTXH 0x2000 -#define PHY_STAT_CAPTF 0x1000 -#define PHY_STAT_CAPTH 0x0800 -#define PHY_STAT_CAPSUPR 0x0040 -#define PHY_STAT_ANEGACK 0x0020 -#define PHY_STAT_REMFLT 0x0010 -#define PHY_STAT_CAPANEG 0x0008 -#define PHY_STAT_LINK 0x0004 -#define PHY_STAT_JAB 0x0002 -#define PHY_STAT_EXREG 0x0001 - -#define PHY_ADV_NP 0x8000 -#define PHY_ADV_ACK 0x4000 -#define PHY_ADV_RF 0x2000 -#define PHY_ADV_T4 0x0200 -#define PHY_ADV_TXFDX 0x0100 -#define PHY_ADV_TXHDX 0x0080 -#define PHY_ADV_10FDX 0x0040 -#define PHY_ADV_10HDX 0x0020 -#define PHY_ADV_CSMA 0x0001 - - - - -#endif /* __LAN91C11X_H__ */ diff --git a/bsps/arm/csb336/net/network.c b/bsps/arm/csb336/net/network.c deleted file mode 100644 index ddc671a4cd..0000000000 --- a/bsps/arm/csb336/net/network.c +++ /dev/null @@ -1,708 +0,0 @@ -/* - * MC9323MXL Ethernet driver - * - * Copyright (c) 2004 by Cogent Computer Systems - * Written by Jay Monkman <jtm@lopingdog.com> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <rtems.h> -#include <rtems/rtems_bsdnet.h> -#include <mc9328mxl.h> -#include "lan91c11x.h" - -#include <stdio.h> -#include <string.h> - -#include <errno.h> -#include <rtems/error.h> -#include <rtems/bspIo.h> -#include <assert.h> - -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/if.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <bsp/irq.h> - -/* RTEMS event used by interrupt handler to start receive daemon. */ -#define START_RECEIVE_EVENT RTEMS_EVENT_1 - -/* RTEMS event used to start transmit daemon. */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -static void enet_isr(void *); -static void enet_isr_on(void); - -typedef struct { - unsigned long rx_packets; /* total packets received */ - unsigned long tx_packets; /* total packets transmitted */ - unsigned long rx_bytes; /* total bytes received */ - unsigned long tx_bytes; /* total bytes transmitted */ - unsigned long interrupts; /* total number of interrupts */ - unsigned long rx_interrupts; /* total number of rx interrupts */ - unsigned long tx_interrupts; /* total number of tx interrupts */ - unsigned long txerr_interrupts; /* total number of tx error interrupts */ - -} eth_stats_t; - -/* - * Hardware-specific storage - */ -typedef struct -{ - /* - * Connection to networking code - * This entry *must* be the first in the sonic_softc structure. - */ - struct arpcom arpcom; - - int accept_bcast; - - /* Tasks waiting for interrupts */ - rtems_id rx_task; - rtems_id tx_task; - - eth_stats_t stats; - -} mc9328mxl_enet_softc_t; - -static mc9328mxl_enet_softc_t softc; - - -/* function prototypes */ -int rtems_mc9328mxl_enet_attach(struct rtems_bsdnet_ifconfig *config, - void *chip); -void mc9328mxl_enet_init(void *arg); -void mc9328mxl_enet_init_hw(mc9328mxl_enet_softc_t *sc); -void mc9328mxl_enet_start(struct ifnet *ifp); -void mc9328mxl_enet_stop (mc9328mxl_enet_softc_t *sc); -void mc9328mxl_enet_tx_task (void *arg); -void mc9328mxl_enet_sendpacket (struct ifnet *ifp, struct mbuf *m); -void mc9328mxl_enet_rx_task(void *arg); -void mc9328mxl_enet_stats(mc9328mxl_enet_softc_t *sc); -static int mc9328mxl_enet_ioctl(struct ifnet *ifp, - ioctl_command_t command, caddr_t data); - - -int rtems_mc9328mxl_enet_attach ( - struct rtems_bsdnet_ifconfig *config, - void *chip /* only one ethernet, so no chip number */ - ) -{ - struct ifnet *ifp; - int mtu; - int unitnumber; - char *unitname; - int tmp; - - /* - * Parse driver name - */ - unitnumber = rtems_bsdnet_parse_driver_name(config, &unitname); - if (unitnumber < 0) { - return 0; - } - - /* - * Is driver free? - */ - if (unitnumber != 0) { - printf ("Bad MC9328MXL unit number.\n"); - return 0; - } - - ifp = &softc.arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf ("Driver already in use.\n"); - return 0; - } - - /* zero out the control structure */ - memset( &softc, 0, sizeof(softc) ); - - - /* set the MAC address */ - tmp = lan91c11x_read_reg(LAN91C11X_IA0); - softc.arpcom.ac_enaddr[0] = tmp & 0xff; - softc.arpcom.ac_enaddr[1] = (tmp >> 8) & 0xff; - - tmp = lan91c11x_read_reg(LAN91C11X_IA2); - softc.arpcom.ac_enaddr[2] = tmp & 0xff; - softc.arpcom.ac_enaddr[3] = (tmp >> 8) & 0xff; - - tmp = lan91c11x_read_reg(LAN91C11X_IA4); - softc.arpcom.ac_enaddr[4] = tmp & 0xff; - softc.arpcom.ac_enaddr[5] = (tmp >> 8) & 0xff; - - if (config->mtu) { - mtu = config->mtu; - } else { - mtu = ETHERMTU; - } - - softc.accept_bcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = &softc; - ifp->if_unit = unitnumber; - ifp->if_name = unitname; - ifp->if_mtu = mtu; - ifp->if_init = mc9328mxl_enet_init; - ifp->if_ioctl = mc9328mxl_enet_ioctl; - ifp->if_start = mc9328mxl_enet_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST; - if (ifp->if_snd.ifq_maxlen == 0) { - ifp->if_snd.ifq_maxlen = ifqmaxlen; - } - - /* Attach the interface */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -} - -void mc9328mxl_enet_init(void *arg) -{ - mc9328mxl_enet_softc_t *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - /* - *This is for stuff that only gets done once (mc9328mxl_enet_init() - * gets called multiple times - */ - if (sc->tx_task == 0) - { - /* Set up ENET hardware */ - mc9328mxl_enet_init_hw(sc); - - /* Start driver tasks */ - sc->rx_task = rtems_bsdnet_newproc("ENrx", - 4096, - mc9328mxl_enet_rx_task, - sc); - sc->tx_task = rtems_bsdnet_newproc("ENtx", - 4096, - mc9328mxl_enet_tx_task, - sc); - } /* if tx_task */ - - - /* Configure for promiscuous if needed */ - if (ifp->if_flags & IFF_PROMISC) { - lan91c11x_write_reg(LAN91C11X_RCR, - (lan91c11x_read_reg(LAN91C11X_RCR) | - LAN91C11X_RCR_PRMS)); - } - - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* Enable TX/RX */ - lan91c11x_write_reg(LAN91C11X_TCR, - (lan91c11x_read_reg(LAN91C11X_TCR) | - LAN91C11X_TCR_TXENA)); - - lan91c11x_write_reg(LAN91C11X_RCR, - (lan91c11x_read_reg(LAN91C11X_RCR) | - LAN91C11X_RCR_RXEN)); - - -} /* mc9328mxl_enet_init() */ - -void mc9328mxl_enet_init_hw(mc9328mxl_enet_softc_t *sc) -{ - uint16_t stat; - uint16_t my = 0; - rtems_status_code status = RTEMS_SUCCESSFUL; - - lan91c11x_write_reg(LAN91C11X_RCR, LAN91C11X_RCR_RST); - lan91c11x_write_reg(LAN91C11X_RCR, 0); - rtems_task_wake_after(1); - - /* Reset the PHY */ - lan91c11x_write_phy_reg(PHY_CTRL, PHY_CTRL_RST); - while(lan91c11x_read_phy_reg(PHY_CTRL) & PHY_CTRL_RST) { - rtems_task_wake_after(1); - } - - - stat = lan91c11x_read_phy_reg(PHY_STAT); - - if(stat & PHY_STAT_CAPT4) { - my |= PHY_ADV_T4; - } -/* 100Mbs doesn't work, so we won't advertise it */ - - if(stat & PHY_STAT_CAPTXF) { - my |= PHY_ADV_TXFDX; - } - if(stat & PHY_STAT_CAPTXH) { - my |= PHY_ADV_TXHDX; - } - - if(stat & PHY_STAT_CAPTF) { - my |= PHY_ADV_10FDX; - } - - if(stat & PHY_STAT_CAPTH) { - my |= PHY_ADV_10HDX; - } - - my |= PHY_ADV_CSMA; - - lan91c11x_write_phy_reg(PHY_AD, my); - - - /* Enable Autonegotiation */ -#if 0 - lan91c11x_write_phy_reg(PHY_CTRL, - (PHY_CTRL_ANEGEN | PHY_CTRL_ANEGRST)); -#endif - - /* Enable full duplex, let MAC take care - * of padding and CRC. - */ - lan91c11x_write_reg(LAN91C11X_TCR, - (LAN91C11X_TCR_PADEN | - LAN91C11X_TCR_SWFDUP)); - - /* Disable promisc, don'tstrip CRC */ - lan91c11x_write_reg(LAN91C11X_RCR, 0); - - /* Enable auto-negotiation, LEDA is link, LEDB is traffic */ - lan91c11x_write_reg(LAN91C11X_RPCR, - (LAN91C11X_RPCR_ANEG | - LAN91C11X_RPCR_LS2B)); - - /* Don't add wait states, enable PHY power */ - lan91c11x_write_reg(LAN91C11X_CONFIG, - (LAN91C11X_CONFIG_NOWAIT | - LAN91C11X_CONFIG_PWR)); - - /* Disable error interrupts, enable auto release */ - lan91c11x_write_reg(LAN91C11X_CTRL, LAN91C11X_CTRL_AUTO); - - /* Reset MMU */ - lan91c11x_write_reg(LAN91C11X_MMUCMD, - LAN91C11X_MMUCMD_RESETMMU ); - - - rtems_task_wake_after(100); - /* Enable Autonegotiation */ - lan91c11x_write_phy_reg(PHY_CTRL, 0x3000); - rtems_task_wake_after(100); - - /* Enable Interrupts for RX */ - lan91c11x_write_reg(LAN91C11X_INT, LAN91C11X_INT_RXMASK); - - /* Enable interrupts on GPIO Port A3 */ - /* Make pin 3 an input */ - MC9328MXL_GPIOA_DDIR &= ~bit(3); - - /* Use GPIO function for pin 3 */ - MC9328MXL_GPIOA_GIUS |= bit(3); - - /* Set for active high, level triggered interupt */ - MC9328MXL_GPIOA_ICR1 = ((MC9328MXL_GPIOA_ICR1 & ~(3 << 6)) | - (2 << 6)); - - /* Enable GPIO port A3 interrupt */ - MC9328MXL_GPIOA_IMR |= bit(3); - - /* Install the interrupt handler */ - status = rtems_interrupt_handler_install( - BSP_INT_GPIO_PORTA, - "Network", - RTEMS_INTERRUPT_UNIQUE, - enet_isr, - (void *)BSP_INT_GPIO_PORTA - ); - assert(status == RTEMS_SUCCESSFUL); - enet_isr_on(); - -} /* mc9328mxl_enet_init_hw() */ - -void mc9328mxl_enet_start(struct ifnet *ifp) -{ - mc9328mxl_enet_softc_t *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->tx_task, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -void mc9328mxl_enet_stop (mc9328mxl_enet_softc_t *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - - /* Stop the transmitter and receiver. */ - lan91c11x_write_reg(LAN91C11X_TCR, - (lan91c11x_read_reg(LAN91C11X_TCR) & - ~LAN91C11X_TCR_TXENA)); - - lan91c11x_write_reg(LAN91C11X_RCR, - (lan91c11x_read_reg(LAN91C11X_RCR) & - ~LAN91C11X_RCR_RXEN)); - -} - -/* - * Driver transmit daemon - */ -void mc9328mxl_enet_tx_task(void *arg) -{ - mc9328mxl_enet_softc_t *sc = (mc9328mxl_enet_softc_t *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) - { - rtems_bsdnet_event_receive( - START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - - /* Send packets till queue is empty */ - for (;;) - { - /* Get the next mbuf chain to transmit. */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) { - break; - } - mc9328mxl_enet_sendpacket (ifp, m); - softc.stats.tx_packets++; - - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* Send packet */ -void mc9328mxl_enet_sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct mbuf *l = NULL; - int size = 0; - int tmp; - int i; - int start; - uint16_t d; - - /* How big is the packet ? */ - l = m; - do { - size += l->m_len; - l = l->m_next; - } while (l != NULL); - - /* Allocate a TX buffer */ - lan91c11x_write_reg(LAN91C11X_MMUCMD, - (LAN91C11X_MMUCMD_ALLOCTX | - (size >> 8))); - - /* Wait for the allocation */ - while ((lan91c11x_read_reg(LAN91C11X_INT) & LAN91C11X_INT_ALLOC) == 0) { - continue; - } - - tmp = lan91c11x_read_reg(LAN91C11X_PNR); - lan91c11x_write_reg(LAN91C11X_PNR, ((tmp >> 8) & 0xff)); - - /* Set the data pointer for auto increment */ - lan91c11x_write_reg(LAN91C11X_PTR, LAN91C11X_PTR_AUTOINC); - - /* A delay is needed between pointer and data access ?!? */ - for (i = 0; i < 10; i++) { - continue; - } - - /* Write status word */ - lan91c11x_write_reg(LAN91C11X_DATA, 0); - - /* Write byte count */ - if (size & 1) { - size++; - } - lan91c11x_write_reg(LAN91C11X_DATA, size + 6); - - lan91c11x_lock(); - - /* Copy the mbuf */ - l = m; - start = 0; - d = 0; - while (l != NULL) - { - uint8_t *data; - - data = mtod(l, uint8_t *); - - for (i = start; i < l->m_len; i++) { - if ((i & 1) == 0) { - d = data[i] << 8; - } else { - d = d | data[i]; - lan91c11x_write_reg_fast(LAN91C11X_DATA, htons(d)); - } - } - - /* If everything is 2 byte aligned, i will be even */ - start = (i & 1); - - l = l->m_next; - } - - /* write control byte */ - if (i & 1) { - lan91c11x_write_reg_fast(LAN91C11X_DATA, - htons(LAN91C11X_PKT_CTRL_ODD | d)); - } else { - lan91c11x_write_reg_fast(LAN91C11X_DATA, 0); - } - - lan91c11x_unlock(); - - /* Enable TX interrupts */ - lan91c11x_write_reg(LAN91C11X_INT, - (lan91c11x_read_reg(LAN91C11X_INT) | - LAN91C11X_INT_TXMASK | - LAN91C11X_INT_TXEMASK)); - - /* Enqueue it */ - lan91c11x_write_reg(LAN91C11X_MMUCMD, - LAN91C11X_MMUCMD_ENQUEUE); - - /* free the mbuf chain we just copied */ - m_freem(m); - -} /* mc9328mxl_enet_sendpacket () */ - - -/* reader task */ -void mc9328mxl_enet_rx_task(void *arg) -{ - mc9328mxl_enet_softc_t *sc = (mc9328mxl_enet_softc_t *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - struct ether_header *eh; - rtems_event_set events; - int pktlen; - uint16_t rsw; - uint16_t bc; - uint16_t cbyte; - int i; - uint16_t int_reg; - - /* Input packet handling loop */ - while (1) { - rtems_bsdnet_event_receive( - START_RECEIVE_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - - /* Configure for reads from RX data area */ - lan91c11x_write_reg(LAN91C11X_PTR, - (LAN91C11X_PTR_AUTOINC | - LAN91C11X_PTR_RCV | - LAN91C11X_PTR_READ)); - - /* read the receive status word */ - rsw = lan91c11x_read_reg(LAN91C11X_DATA); - /* TBD: Need to check rsw here */ - - /* read the byte count */ - bc = lan91c11x_read_reg(LAN91C11X_DATA); - pktlen = (bc & 0x7ff) - 6; - - /* get an mbuf for this packet */ - MGETHDR(m, M_WAIT, MT_DATA); - - /* now get a cluster pointed to by the mbuf */ - /* since an mbuf by itself is too small */ - MCLGET(m, M_WAIT); - - lan91c11x_lock(); - - /* Copy the received packet into an mbuf */ - for (i = 0; i < (pktlen / 2); i++) { - ((uint16_t*)m->m_ext.ext_buf)[i] = - lan91c11x_read_reg_fast(LAN91C11X_DATA); - } - - cbyte = lan91c11x_read_reg_fast(LAN91C11X_DATA); - if (cbyte & LAN91C11X_PKT_CTRL_ODD) { - ((uint16_t*)m->m_ext.ext_buf)[i] = cbyte; - pktlen++; - } - lan91c11x_unlock(); - - /* Release the packets memory */ - lan91c11x_write_reg(LAN91C11X_MMUCMD, - LAN91C11X_MMUCMD_REMTOP); - - /* set the receiving interface */ - m->m_pkthdr.rcvif = ifp; - m->m_nextpkt = 0; - - /* set the length of the mbuf */ - m->m_len = pktlen - (sizeof(struct ether_header)); - m->m_pkthdr.len = m->m_len; - - /* strip off the ethernet header from the mbuf */ - /* but save the pointer to it */ - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - - - softc.stats.rx_packets++; - - /* give all this stuff to the stack */ - ether_input(ifp, eh, m); - - /* renable RX interrupts */ - int_reg = lan91c11x_read_reg(LAN91C11X_INT); - int_reg |= LAN91C11X_INT_RXMASK; - lan91c11x_write_reg(LAN91C11X_INT, int_reg); - - } -} /* mc9328mxl_enet_rx_task */ - - -/* Show interface statistics */ -void mc9328mxl_enet_stats (mc9328mxl_enet_softc_t *sc) -{ - printf (" Total Interrupts:%-8lu", sc->stats.interrupts); - printf (" Rx Interrupts:%-8lu", sc->stats.rx_interrupts); - printf (" Tx Interrupts:%-8lu\n", sc->stats.tx_interrupts); - printf (" Tx Error Interrupts:%-8lu\n", sc->stats.txerr_interrupts); - printf (" Rx Packets:%-8lu", sc->stats.rx_packets); - printf (" Tx Packets:%-8lu\n", sc->stats.tx_packets); -} - - -/* Enables mc9328mxl_enet interrupts. */ -static void enet_isr_on(void) -{ - /* Enable interrupts */ - MC9328MXL_AITC_INTENNUM = MC9328MXL_INT_GPIO_PORTA; - - return; -} - -/* Driver ioctl handler */ -static int -mc9328mxl_enet_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - mc9328mxl_enet_softc_t *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - mc9328mxl_enet_stop (sc); - break; - - case IFF_UP: - mc9328mxl_enet_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - mc9328mxl_enet_stop (sc); - mc9328mxl_enet_init (sc); - break; - - default: - break; - } /* switch (if_flags) */ - break; - - case SIO_RTEMS_SHOW_STATS: - mc9328mxl_enet_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } /* switch (command) */ - return error; -} - -/* interrupt handler */ -static void enet_isr(void * unused) -{ - uint16_t int_reg; - - softc.stats.interrupts++; - /* get the ISR status and determine RX or TX */ - int_reg = lan91c11x_read_reg(LAN91C11X_INT); - - /* Handle RX interrupts */ - if ((int_reg & LAN91C11X_INT_RX) && (int_reg & LAN91C11X_INT_RXMASK)) { - softc.stats.rx_interrupts++; - - /* Disable the interrupt */ - int_reg &= ~LAN91C11X_INT_RXMASK; - - rtems_bsdnet_event_send (softc.rx_task, START_RECEIVE_EVENT); - } - - /* Handle TX Empty interrupts */ - if ((int_reg & LAN91C11X_INT_TXE) && (int_reg & LAN91C11X_INT_TXEMASK)) { - softc.stats.tx_interrupts++; - - /* Disable the interrupt */ - int_reg &= ~LAN91C11X_INT_TXEMASK; - - /* Acknowledge the interrupt */ - int_reg |= LAN91C11X_INT_TXE; - - rtems_bsdnet_event_send(softc.tx_task, START_TRANSMIT_EVENT); - - } - - /* Handle interrupts for transmit errors */ - if ((int_reg & LAN91C11X_INT_TX) && (int_reg & LAN91C11X_INT_TXMASK)) { - softc.stats.txerr_interrupts++; - printk("Caught TX interrupt - error on transmission\n"); - } - - /* Update the interrupt register on the 91c11x */ - lan91c11x_write_reg(LAN91C11X_INT, int_reg); - - /* clear GPIO Int. status */ - MC9328MXL_GPIOA_ISR |= bit(3); -} - diff --git a/bsps/arm/csb337/net/network.c b/bsps/arm/csb337/net/network.c deleted file mode 100644 index b795cf4bce..0000000000 --- a/bsps/arm/csb337/net/network.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * AT91RM9200 ethernet driver - * - * Copyright (c) 2003 by Cogent Computer Systems - * Written by Mike Kelly <mike@cogcomp.com> - * and Jay Monkman <jtm@lopingdog.com> - * - * - * July 2009: Joel Sherrill merged csb637 PHY differences from - * MicroMonitor 1.17. - */ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <rtems.h> -#include <rtems/rtems_bsdnet.h> -#include <rtems/bspIo.h> -#include <at91rm9200.h> -#include <at91rm9200_emac.h> -#include <at91rm9200_gpio.h> -#include <at91rm9200_pmc.h> - -#include <stdio.h> -#include <string.h> - -#include <errno.h> -#include <rtems/error.h> -#include <assert.h> - -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/if.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <bsp/irq.h> -#include <bspopts.h> - -/* enable debugging of the PHY code */ -#define PHY_DBG - -/* enable debugging of the EMAC code */ -/* #define EMAC_DBG */ - -#if csb637 - /* Bit defines for the PHY Status Register #1 (phy address 0x01) */ - /* 1 = PHY able to perform 100BASE-T4 */ - #define PHY_STAT_100BASE_T4 BIT15 - /* 1 = PHY able to perform full-duplex 100BASE-X */ - #define PHY_STAT_100BASE_X_FDX BIT14 - /* 1 = PHY able to perform half-duplex 100BASE-X */ - #define PHY_STAT_100BASE_X_HDX BIT13 - /* 1 = PHY able to operate at 10 Mbps in full-duplex mode */ - #define PHY_STAT_10BASE_FDX BIT12 - /* 1 = PHY able to operate at 10 Mbps in half-duplex mode */ - #define PHY_STAT_10BASE_HDX BIT11 - /* 1 = PHY will accept management frames with preamble suppressed */ - #define PHY_STAT_MF_PREAMBLE BIT6 - /* 1 = Auto-negotiation complete */ - #define PHY_STAT_AUTO_NEG_DONE BIT5 - /* 1 = Remote fault condition detected */ - #define PHY_STAT_REM_FLT BIT4 - /* 1 = PHY is able to perform Auto-Negotiation */ - #define PHY_STAT_AUTO_NEG_ABLE BIT3 - /* 1 = Link is up */ - #define PHY_STAT_LINK_UP BIT2 - /* 1 = Jabber condition detected */ - #define PHY_STAT_JABBER BIT1 - /* 1 = Extended register capabilities */ - #define PHY_STAT_EXT_REG BIT0 - - /* Bit defines for the Auxillary Mode 3 register */ - #define PHY_AUX_MODE2_TRAFFIC_LED BIT6 -#endif - - /* interrupt stuff */ - #define EMAC_INT_PRIORITY 0 /* lowest priority */ - - /* RTEMS event used by interrupt handler to start receive daemon. */ - #define START_RECEIVE_EVENT RTEMS_EVENT_1 - - /* RTEMS event used to start transmit daemon. */ - #define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -static void at91rm9200_emac_isr (void *); -static void at91rm9200_emac_isr_on(void); - -/* use the values defined in linkcmds for our use of SRAM */ -extern void * at91rm9200_emac_rxbuf_hdrs; -extern void * at91rm9200_emac_txbuf; -extern void * at91rm9200_emac_rxbufs; - -/* Set up EMAC hardware */ -/* Number of Receive and Transmit Buffers and Buffer Descriptors */ -#define NUM_RXBDS 8 -#define NUM_TXBDS 1 -#define RX_BUFFER_SIZE 0x600 - -/* use internal SRAM for buffers and descriptors - * also insure that the receive descriptors - * start on a 64byte boundary - * Receive Buffer Descriptor Header - */ - -typedef struct -{ - unsigned long address; - unsigned long status; -} RXBUF_HDR; - -RXBUF_HDR *rxbuf_hdrs; -unsigned char *txbuf; -unsigned char *rxbuf; - -int delay_cnt; - -/* - * Hardware-specific storage - */ -typedef struct -{ - /* - * Connection to networking code - * This entry *must* be the first in the sonic_softc structure. - */ - struct arpcom arpcom; - - /* - * Interrupt vector - */ - rtems_vector_number vector; - - /* - * Indicates configuration - */ - int acceptBroadcast; - - /* - * Task waiting for interrupts - */ - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * current receive header - */ - int rx_buf_idx; - - - - /* - * Statistics - */ - unsigned long Interrupts; - unsigned long rxInterrupts; - unsigned long rxMissed; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxBadCRC; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txSingleCollision; - unsigned long txMultipleCollision; - unsigned long txCollision; - unsigned long txDeferred; - unsigned long txUnderrun; - unsigned long txLateCollision; - unsigned long txExcessiveCollision; - unsigned long txExcessiveDeferral; - unsigned long txLostCarrier; - unsigned long txRawWait; -} at91rm9200_emac_softc_t; - -static at91rm9200_emac_softc_t softc; - - -/* The AT91RM9200 ethernet fifos are very undersized. Therefore - * we use the internal SRAM to hold 4 receive packets and one - * transmit packet. Note that the AT91RM9200 can only queue - * one transmit packet at a time. - */ - -/* function prototypes */ -int rtems_at91rm9200_emac_attach (struct rtems_bsdnet_ifconfig *config, - void *chip); -void at91rm9200_emac_init(void *arg); -void at91rm9200_emac_init_hw(at91rm9200_emac_softc_t *sc); -void at91rm9200_emac_start(struct ifnet *ifp); -void at91rm9200_emac_stop (at91rm9200_emac_softc_t *sc); -void at91rm9200_emac_txDaemon (void *arg); -void at91rm9200_emac_sendpacket (struct ifnet *ifp, struct mbuf *m); -void at91rm9200_emac_rxDaemon(void *arg); -void at91rm9200_emac_stats (at91rm9200_emac_softc_t *sc); -static int at91rm9200_emac_ioctl (struct ifnet *ifp, - ioctl_command_t command, - caddr_t data); - -#if csb637 -/* - * phyread(): Read the PHY - */ -static uint32_t phyread(uint8_t reg) -{ - EMAC_REG(EMAC_MAN) = (0x01 << 30 /* Start of Frame Delimiter */ - | 0x02 << 28 /* Operation, 0x01 = Write, 0x02 = Read */ - | 0x00 << 23 /* Phy Number, 0 as we only have one */ - | reg << 18 /* Phy Register */ - | 0x02 << 16); /* must be 0x02 for turn around field */ - - /* wait for phy read to complete (was udelay(5000)) */ - rtems_task_wake_after(1); - - #if defined(EMAC_DBG) - printk( - "EMAC: Phy 0, Reg %d, Read 0x%04lx.\n", - reg, - (EMAC_REG(EMAC_MAN) & 0xffff) - ); - #endif - - return EMAC_REG(EMAC_MAN) & 0xffff; -} -#endif - -/* - * phywrite(): Write the PHY - */ -static void phywrite(uint8_t reg, uint16_t data) -{ - EMAC_REG(EMAC_MAN) = (0x01 << 30 /* Start of Frame Delimiter */ - | 0x01 << 28 /* Operation, 0x01 = Write, 0x02 = Read */ - | 0x00 << 23 /* Phy Number, BCM5221 is address 0 */ - | reg << 18 /* Phy Register */ - | 0x02 << 16 /* must be 0x02 for turn around field */ - | data); - #if defined(EMAC_DBG) - printk("EMAC: Phy 0, Reg %d, Write 0x%04x.\n", reg, data); - #endif - - /* wait for phy write to complete (was udelay(5000)) */ - rtems_task_wake_after(1); -} - - -int rtems_at91rm9200_emac_attach ( - struct rtems_bsdnet_ifconfig *config, - void *chip /* only one ethernet, so no chip number */ - ) -{ - struct ifnet *ifp; - int mtu; - int unitnumber; - char *unitname; - void *p; - - /* an array of receive buffer descriptors -- avoid type punned warning */ - p = (void *)&at91rm9200_emac_rxbuf_hdrs; - rxbuf_hdrs = (RXBUF_HDR *)p; - - /* one transmit buffer, 1536 bytes maximum */ - txbuf = (unsigned char *)&at91rm9200_emac_txbuf; - - /* receive buffers starting address */ - rxbuf = (unsigned char *)&at91rm9200_emac_rxbufs; - /* - * Parse driver name - */ - if ((unitnumber = rtems_bsdnet_parse_driver_name (config, &unitname)) < 0) - return 0; - - /* - * Is driver free? - */ - if (unitnumber != 0) { - printk ("Bad AT91RM9200 EMAC unit number.\n"); - return 0; - } - ifp = &softc.arpcom.ac_if; - if (ifp->if_softc != NULL) { - printk ("Driver already in use.\n"); - return 0; - } - - /* - * zero out the control structure - */ - - memset( &softc, 0, sizeof(softc) ); - - - /* get the MAC address from the chip */ - softc.arpcom.ac_enaddr[0] = (EMAC_REG(EMAC_SA1L) >> 0) & 0xff; - softc.arpcom.ac_enaddr[1] = (EMAC_REG(EMAC_SA1L) >> 8) & 0xff; - softc.arpcom.ac_enaddr[2] = (EMAC_REG(EMAC_SA1L) >> 16) & 0xff; - softc.arpcom.ac_enaddr[3] = (EMAC_REG(EMAC_SA1L) >> 24) & 0xff; - softc.arpcom.ac_enaddr[4] = (EMAC_REG(EMAC_SA1H) >> 0) & 0xff; - softc.arpcom.ac_enaddr[5] = (EMAC_REG(EMAC_SA1H) >> 8) & 0xff; - - #if 0 - printk( "MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - softc.arpcom.ac_enaddr[0], - softc.arpcom.ac_enaddr[1], - softc.arpcom.ac_enaddr[2], - softc.arpcom.ac_enaddr[3], - softc.arpcom.ac_enaddr[4], - softc.arpcom.ac_enaddr[5] - ); - #endif - - if (config->mtu) { - mtu = config->mtu; - } else { - mtu = ETHERMTU; - } - - softc.acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = &softc; - ifp->if_unit = unitnumber; - ifp->if_name = unitname; - ifp->if_mtu = mtu; - ifp->if_init = at91rm9200_emac_init; - ifp->if_ioctl = at91rm9200_emac_ioctl; - ifp->if_start = at91rm9200_emac_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST; - if (ifp->if_snd.ifq_maxlen == 0) { - ifp->if_snd.ifq_maxlen = ifqmaxlen; - } - - softc.rx_buf_idx = 0; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -} - -void at91rm9200_emac_init(void *arg) -{ - at91rm9200_emac_softc_t *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - rtems_status_code status = RTEMS_SUCCESSFUL; - - /* - *This is for stuff that only gets done once (at91rm9200_emac_init() - * gets called multiple times - */ - if (sc->txDaemonTid == 0) { - /* Set up EMAC hardware */ - at91rm9200_emac_init_hw(sc); - - /* Start driver tasks */ - sc->rxDaemonTid = rtems_bsdnet_newproc("ENrx", - 4096, - at91rm9200_emac_rxDaemon, - sc); - sc->txDaemonTid = rtems_bsdnet_newproc("ENtx", - 4096, - at91rm9200_emac_txDaemon, - sc); - } /* if txDaemonTid */ - - /* set our priority in the AIC */ - AIC_SMR_REG(AIC_SMR_EMAC) = AIC_SMR_PRIOR(EMAC_INT_PRIORITY); - - /* install the interrupt handler */ - status = rtems_interrupt_handler_install( - AT91RM9200_INT_EMAC, - "Network", - RTEMS_INTERRUPT_UNIQUE, - at91rm9200_emac_isr, - NULL - ); - assert(status == RTEMS_SUCCESSFUL); - at91rm9200_emac_isr_on(); - - /* EMAC doesn't support promiscuous, so ignore requests */ - if (ifp->if_flags & IFF_PROMISC) { - printk ("Warning - AT91RM9200 Ethernet driver" - " doesn't support Promiscuous Mode!\n"); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* Enable TX/RX and clear the statistics counters */ - EMAC_REG(EMAC_CTL) = (EMAC_CTL_TE | EMAC_CTL_RE | EMAC_CTL_CSR); - - /* clear any pending interrupts */ - EMAC_REG(EMAC_TSR) = 0xffffffff; - EMAC_REG(EMAC_RSR) = 0xffffffff; - -} /* at91rm9200_emac_init() */ - -void at91rm9200_emac_init_hw(at91rm9200_emac_softc_t *sc) -{ - int i; - - /* Configure shared pins for Ethernet, not GPIO */ - PIOA_REG(PIO_PDR) = ( BIT7 | /* tx clock */ - BIT8 | /* tx enable */ - BIT9 | /* tx data 0 */ - BIT10 | /* tx data 1 */ - BIT11 | /* carrier sense */ - BIT12 | /* rx data 0 */ - BIT13 | /* rx data 1 */ - BIT14 | /* rx error */ - BIT15 | /* MII clock */ - BIT16 ); /* MII data */ - - PIOB_REG(PIO_PDR) = ( BIT12 | /* tx data 2 */ - BIT13 | /* tx data 3 */ - BIT14 | /* tx error */ - BIT15 | /* rx data 2 */ - BIT16 | /* rx data 3 */ - BIT17 | /* rx data valid */ - BIT18 | /* rx collistion */ - BIT19 ); /* rx clock */ - - PIOB_REG(PIO_BSR) = ( BIT12 | /* tx data 2 */ - BIT13 | /* tx data 3 */ - BIT14 | /* tx error */ - BIT15 | /* rx data 2 */ - BIT16 | /* rx data 3 */ - BIT17 | /* rx data valid */ - BIT18 | /* rx collistion */ - BIT19 ); /* rx clock */ - - - /* Enable the clock to the EMAC */ - PMC_REG(PMC_PCER) |= PMC_PCR_PID_EMAC; - - /* initialize our receive buffer descriptors */ - for (i = 0; i < NUM_RXBDS-1; i++) { - rxbuf_hdrs[i].address = (unsigned long)(&rxbuf[i * RX_BUFFER_SIZE]); - rxbuf_hdrs[i].status = 0x00000000; - } - - /* last one needs the wrapbit set as well */ - rxbuf_hdrs[i].address = ((unsigned long)(&rxbuf[i * RX_BUFFER_SIZE]) | - RXBUF_ADD_WRAP); - rxbuf_hdrs[i].status = 0x00000000; - - /* point to our receive buffer queue */ - EMAC_REG(EMAC_RBQP) = (unsigned long)rxbuf_hdrs; - - /* clear any left over status bits */ - EMAC_REG(EMAC_RSR) &= ~(EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA); - - /* set the MII clock divder to MCK/64 */ - EMAC_REG(EMAC_CFG) &= EMAC_CFG_CLK_MASK; - EMAC_REG(EMAC_CFG) = (EMAC_CFG_CLK_64 | EMAC_CFG_BIG | EMAC_CFG_FD); - - /* enable the MII interface */ - EMAC_REG(EMAC_CTL) = EMAC_CTL_MPE; - - #if csb637 - { - int timeout; - uint32_t emac_link_status; - - #if defined(PHY_DBG) - printk("EMAC: Getting Link Status.\n"); - #endif - /* read the PHY ID registers */ - emac_link_status = phyread(0x02); - emac_link_status = phyread(0x03); - - /* Get the link status - wait for done with a timeout */ - for (timeout = 10000 ; timeout ; ) { - for (i = 0; i < 100; i++) - ; - emac_link_status = phyread(0x01); - if (!(emac_link_status & PHY_STAT_AUTO_NEG_ABLE)) { - #if defined(PHY_DBG) - printk("EMAC: PHY is unable to Auto-Negotatiate!\n"); - #endif - timeout = 0; - break; - } - if (emac_link_status & PHY_STAT_AUTO_NEG_DONE) { - #if defined(PHY_DBG) - printk("EMAC: Auto-Negotiate Complete, Link = "); - #endif - break; - } - timeout-- ; - } - if (!timeout) { - #if defined(PHY_DBG) - printk( - "EMAC: Auto-Negotatiate Failed, Status = 0x%04lx!\n" - "EMAC: Initialization Halted.\n", - emac_link_status - ); - #endif - /* if autonegotiation fails, just force to 10HD... */ - emac_link_status = PHY_STAT_10BASE_HDX; - } - - /* Set SPD and FD based on the return link status */ - if (emac_link_status & (PHY_STAT_100BASE_X_FDX | PHY_STAT_100BASE_X_HDX)){ - EMAC_REG(EMAC_CFG) |= EMAC_CFG_SPD; - #if defined(PHY_DBG) - printk("100MBIT, "); - #endif - } else { - EMAC_REG(EMAC_CFG) &= ~EMAC_CFG_SPD; - #if defined(PHY_DBG) - printk("10MBIT, "); - #endif - } - - if (emac_link_status & (PHY_STAT_100BASE_X_FDX | PHY_STAT_10BASE_FDX)) { - EMAC_REG(EMAC_CFG) |= EMAC_CFG_FD; - #if defined(PHY_DBG) - printk("Full Duplex.\n"); - #endif - } else { - EMAC_REG(EMAC_CFG) &= ~EMAC_CFG_FD; - #if defined(PHY_DBG) - printk("Half Duplex.\n"); - #endif - } - - /* Set PHY LED modes. Traffic Meter Mode for ACTLED - * Set Bit 6 - Traffic Mode on - */ - phywrite(0x1b, PHY_AUX_MODE2_TRAFFIC_LED); - } - #else - /* must be csb337 */ - /* Set PHY LED2 to combined Link/Activity and enable pulse stretching */ - phywrite( 18, 0x0d0a ); - #endif - - #if 0 - EMAC_REG(EMAC_MAN) = (0x01 << 30 | /* Start of Frame Delimiter */ - 0x01 << 28 | /* Operation, 0x01 = Write */ - 0x00 << 23 | /* Phy Number */ - 0x14 << 18 | /* Phy Register */ - 0x02 << 16 | /* must be 0x02 */ - 0x0D0A); /* Write data (0x0000 if read) */ - #endif - -} /* at91rm9200_emac_init_hw() */ - -void at91rm9200_emac_start(struct ifnet *ifp) -{ - at91rm9200_emac_softc_t *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -void at91rm9200_emac_stop (at91rm9200_emac_softc_t *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Stop the transmitter and receiver. - */ - EMAC_REG(EMAC_CTL) &= ~(EMAC_CTL_TE | EMAC_CTL_RE); -} - -/* - * Driver transmit daemon - */ -void at91rm9200_emac_txDaemon (void *arg) -{ - at91rm9200_emac_softc_t *sc = (at91rm9200_emac_softc_t *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) - { - /* turn on TX interrupt, then wait for one */ - EMAC_REG(EMAC_IER) = EMAC_INT_TCOM; /* Transmit complete */ - - rtems_bsdnet_event_receive( - START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - - /* Send packets till queue is empty */ - for (;;) - { - /* Get the next mbuf chain to transmit. */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - at91rm9200_emac_sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* Send packet */ -void at91rm9200_emac_sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct mbuf *l = NULL; - unsigned int pkt_offset = 0; - delay_cnt = 0; - /* printk("at91rm9200_emac_sendpacket %p\n", m); */ - - /* Wait for EMAC Transmit Queue to become available. */ - while (((EMAC_REG(EMAC_TSR) & EMAC_TSR_COMP) == 0) && - ((EMAC_REG(EMAC_TSR) & EMAC_TSR_TXIDLE) == 0)) - - { - delay_cnt++; -/* sleep(0); make sure we don't hog the cpu */ - continue; - } - - /* copy the mbuf chain into the transmit buffer */ - l = m; - while (l != NULL) { - memcpy(((char *)txbuf + pkt_offset), /* offset into pkt for mbuf */ - (char *)mtod(l, void *), /* cast to void */ - l->m_len); /* length of this mbuf */ - - pkt_offset += l->m_len; /* update offset */ - l = l->m_next; /* get next mbuf, if any */ - } - - /* free the mbuf chain we just copied */ - m_freem(m); - - /* clear any pending status */ - EMAC_REG(EMAC_TSR) = (EMAC_TSR_OVR | EMAC_TSR_COL | EMAC_TSR_RLE - | EMAC_TSR_COMP | EMAC_TSR_UND); - - /* tell the EMAC about our buffer */ - EMAC_REG(EMAC_TAR) = (unsigned long)txbuf; - EMAC_REG(EMAC_TCR) = (unsigned long)pkt_offset; -} /* at91rm9200_emac_sendpacket () */ - - -/* SONIC reader task */ -void at91rm9200_emac_rxDaemon(void *arg) -{ - at91rm9200_emac_softc_t *sc = (at91rm9200_emac_softc_t *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - struct ether_header *eh; - rtems_event_set events; - int pktlen; - - /* Input packet handling loop */ - for (;;) { - /* turn on RX interrupts, then wait for one */ - EMAC_REG(EMAC_IER) = (EMAC_INT_RCOM | /* Receive complete */ - EMAC_INT_RBNA | /* Receive buf not available */ - EMAC_INT_ROVR); /* Receive overrun */ - - rtems_bsdnet_event_receive( - START_RECEIVE_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - - if (EMAC_REG(EMAC_RSR) & EMAC_RSR_BNA) { - printk("1: EMAC_BNA\n"); - } - - if (EMAC_REG(EMAC_RSR) & EMAC_RSR_OVR) { - printk("1: EMAC_OVR\n"); - } - - /* clear the receive status as we do not use it anyway */ - EMAC_REG(EMAC_RSR) = (EMAC_RSR_REC | EMAC_RSR_OVR | EMAC_RSR_BNA); - - /* scan the buffer descriptors looking for any with data in them */ - while (rxbuf_hdrs[sc->rx_buf_idx].address & RXBUF_ADD_OWNED) { - pktlen = rxbuf_hdrs[sc->rx_buf_idx].status & RXBUF_STAT_LEN_MASK; - - /* get an mbuf this packet */ - MGETHDR(m, M_WAIT, MT_DATA); - - /* now get a cluster pointed to by the mbuf */ - /* since an mbuf by itself is too small */ - MCLGET(m, M_WAIT); - - /* set the type of mbuf to ifp (ethernet I/F) */ - m->m_pkthdr.rcvif = ifp; - m->m_nextpkt = 0; - - /* copy the packet into the cluster pointed to by the mbuf */ - memcpy((char *)m->m_ext.ext_buf, - (char *)(rxbuf_hdrs[sc->rx_buf_idx].address & 0xfffffffc), - pktlen); - - /* Release the buffer ASAP back to the EMAC */ - rxbuf_hdrs[sc->rx_buf_idx].address &= ~RXBUF_ADD_OWNED; - - /* set the length of the mbuf */ - m->m_len = pktlen - (sizeof(struct ether_header) + 4); - m->m_pkthdr.len = m->m_len; - - /* strip off the ethernet header from the mbuf */ - /* but save the pointer to it */ - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - - /* increment the buffer index */ - sc->rx_buf_idx++; - if (sc->rx_buf_idx >= NUM_RXBDS) { - sc->rx_buf_idx = 0; - } - - /* give all this stuff to the stack */ - ether_input(ifp, eh, m); - - } /* while ADD_OWNED = 0 */ - - if (EMAC_REG(EMAC_RSR) & EMAC_RSR_BNA) { - printk("2:EMAC_BNA\n"); - } - if (EMAC_REG(EMAC_RSR) & EMAC_RSR_OVR) { - printk("2:EMAC_OVR\n"); - } - - - } /* for (;;) */ -} /* at91rm9200_emac_rxDaemon() */ - - -/* Show interface statistics */ -void at91rm9200_emac_stats (at91rm9200_emac_softc_t *sc) -{ - printf (" Total Interrupts:%-8lu", sc->Interrupts); - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Collision:%-8lu", sc->rxCollision); - printf (" Missed:%-8lu\n", sc->rxMissed); - - printf ( " Tx Interrupts:%-8lu", sc->txInterrupts); - printf ( " Deferred:%-8lu", sc->txDeferred); - printf (" Lost Carrier:%-8lu\n", sc->txLostCarrier); - printf ( "Single Collisions:%-8lu", sc->txSingleCollision); - printf ( "Multiple Collisions:%-8lu", sc->txMultipleCollision); - printf ("Excessive Collisions:%-8lu\n", sc->txExcessiveCollision); - printf ( " Total Collisions:%-8lu", sc->txCollision); - printf ( " Late Collision:%-8lu", sc->txLateCollision); - printf (" Underrun:%-8lu\n", sc->txUnderrun); - printf ( " Raw output wait:%-8lu\n", sc->txRawWait); -} - - -/* Enables at91rm9200_emac interrupts. */ -static void at91rm9200_emac_isr_on(void) -{ - /* Enable various TX/RX interrupts */ - EMAC_REG(EMAC_IER) = (EMAC_INT_RCOM | /* Receive complete */ - EMAC_INT_RBNA | /* Receive buffer not available */ - EMAC_INT_TCOM | /* Transmit complete */ - EMAC_INT_ROVR | /* Receive overrun */ - EMAC_INT_ABT); /* Abort on DMA transfer */ - - return; -} - -/* Driver ioctl handler */ -static int -at91rm9200_emac_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - at91rm9200_emac_softc_t *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - at91rm9200_emac_stop (sc); - break; - - case IFF_UP: - at91rm9200_emac_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - at91rm9200_emac_stop (sc); - at91rm9200_emac_init (sc); - break; - - default: - break; - } /* switch (if_flags) */ - break; - - case SIO_RTEMS_SHOW_STATS: - at91rm9200_emac_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } /* switch (command) */ - return error; -} - -/* interrupt handler */ -static void at91rm9200_emac_isr (void * unused) -{ - unsigned long status32; - - /* get the ISR status and determine RX or TX */ - status32 = EMAC_REG(EMAC_ISR); - - if (status32 & EMAC_INT_ABT) { - EMAC_REG(EMAC_IDR) = EMAC_INT_ABT; /* disable it */ - rtems_panic("AT91RM9200 Ethernet MAC has received an Abort.\n"); - } - - if (status32 & (EMAC_INT_RCOM | /* Receive complete */ - EMAC_INT_RBNA | /* Receive buffer not available */ - EMAC_INT_ROVR)) { /* Receive overrun */ - - /* disable the RX interrupts */ - EMAC_REG(EMAC_IDR) = (EMAC_INT_RCOM | /* Receive complete */ - EMAC_INT_RBNA | /* Receive buf not available */ - EMAC_INT_ROVR); /* Receive overrun */ - - rtems_bsdnet_event_send (softc.rxDaemonTid, START_RECEIVE_EVENT); - } - - if (status32 & EMAC_INT_TCOM) { /* Transmit buffer register empty */ - - /* disable the TX interrupts */ - EMAC_REG(EMAC_IDR) = EMAC_INT_TCOM; - - rtems_bsdnet_event_send (softc.txDaemonTid, START_TRANSMIT_EVENT); - } -} - diff --git a/bsps/arm/edb7312/net/network.c b/bsps/arm/edb7312/net/network.c deleted file mode 100644 index 9a832293f9..0000000000 --- a/bsps/arm/edb7312/net/network.c +++ /dev/null @@ -1,126 +0,0 @@ -#include <machine/rtems-bsd-kernel-space.h> - -#include <rtems.h> -#include <sys/param.h> -#include <sys/mbuf.h> -#include <bsp/irq.h> -#include <libchip/cs8900.h> -#include <assert.h> - -#define CS8900_BASE 0x20000300 -unsigned int bsp_cs8900_io_base = 0; -unsigned int bsp_cs8900_memory_base = 0; -static void cs8900_isr(void *); - -char g_enetbuf[1520]; - -static void cs8900_isr(void *arg) -{ - cs8900_interrupt(BSP_EINT3, arg); -} - -/* cs8900_io_set_reg - set one of the I/O addressed registers */ -void cs8900_io_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) -{ - /* works the same for all values of dev */ -/* - printf("cs8900_io_set_reg: reg: %#6x, val %#6x\n", - CS8900_BASE + reg, - data); -*/ - *(unsigned short *)(CS8900_BASE + reg) = data; -} - -/* cs8900_io_get_reg - reads one of the I/O addressed registers */ -unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg) -{ - unsigned short val; - /* works the same for all values of dev */ - val = *(unsigned short *)(CS8900_BASE + reg); -/* - printf("cs8900_io_get_reg: reg: %#6x, val %#6x\n", reg, val); -*/ - return val; -} - -/* cs8900_mem_set_reg - sets one of the registers mapped through - * PacketPage - */ -void cs8900_mem_set_reg (cs8900_device *cs, unsigned long reg, unsigned short data) -{ - /* works the same for all values of dev */ - cs8900_io_set_reg(cs, CS8900_IO_PACKET_PAGE_PTR, reg); - cs8900_io_set_reg(cs, CS8900_IO_PP_DATA_PORT0, data); -} - -/* cs8900_mem_get_reg - reads one of the registers mapped through - * PacketPage - */ -unsigned short cs8900_mem_get_reg (cs8900_device *cs, unsigned long reg) -{ - /* works the same for all values of dev */ - cs8900_io_set_reg(cs, CS8900_IO_PACKET_PAGE_PTR, reg); - return cs8900_io_get_reg(cs, CS8900_IO_PP_DATA_PORT0); -} - -void cs8900_attach_interrupt (cs8900_device *cs) -{ - rtems_status_code status = RTEMS_SUCCESSFUL; - - status = rtems_interrupt_handler_install( - BSP_EINT3, - "Network", - RTEMS_INTERRUPT_UNIQUE, - cs8900_isr, - cs - ); - assert(status == RTEMS_SUCCESSFUL); -} - -void cs8900_detach_interrupt (cs8900_device *cs) -{ - rtems_status_code status = RTEMS_SUCCESSFUL; - - status = rtems_interrupt_handler_remove( - BSP_EINT3, - cs8900_isr, - cs - ); - assert(status == RTEMS_SUCCESSFUL); -} - -unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data) -{ - int len; - int i; - - len = cs8900_mem_get_reg(cs, CS8900_PP_RxLength); - - for (i = 0; i < ((len + 1) / 2); i++) { - ((short *)data)[i] = cs8900_io_get_reg(cs, - CS8900_IO_RX_TX_DATA_PORT0); - } - return len; -} - -void cs8900_tx_load (cs8900_device *cs, struct mbuf *m) -{ - int len; - unsigned short *data; - int i; - - len = 0; - - do { - memcpy(&g_enetbuf[len], mtod(m, const void *), m->m_len); - len += m->m_len; - m = m->m_next; - } while (m != 0); - - data = (unsigned short *) &g_enetbuf[0]; - for (i = 0; i < ((len + 1) / 2); i++) { - cs8900_io_set_reg(cs, - CS8900_IO_RX_TX_DATA_PORT0, - data[i]); - } -} diff --git a/bsps/arm/gumstix/net/rtl8019.c b/bsps/arm/gumstix/net/rtl8019.c deleted file mode 100644 index 00fd2fdf09..0000000000 --- a/bsps/arm/gumstix/net/rtl8019.c +++ /dev/null @@ -1,1197 +0,0 @@ -/* - *By Yang Xi <hiyangxi@gmail.com>. - *RTL8019 ethernet driver for Gumstix on SKYEYE simulator - *Based on NE2000 driver for pc386 bsp - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <bsp.h> -#include <bsp/irq.h> -#include "wd80x3.h" - -#include <stdio.h> -#include <assert.h> -#include <errno.h> - -#include <rtems/bspIo.h> -#include <rtems/error.h> -#include <rtems/rtems_bsdnet.h> - -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/if.h> -#include <net/if_arp.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - - -/* Define this to force byte-wide data transfers with the NIC. This - is needed for boards like the TS-1325 386EX PC, which support only - an 8-bit PC/104 bus. Undefine this on a normal PC.*/ - -#define NE2000_BYTE_TRANSFERS - -/* Define this to print debugging messages with printk. */ - -/*#define DEBUG_NE2000 - #define DEBUG_NE*/ - -/* We expect to be able to read a complete packet into an mbuf. */ - -#if (MCLBYTES < 1520) -# error "Driver must have MCLBYTES >= 1520" -#endif - -/* The 8390 macro definitions in wd80x3.h expect RO to be defined. */ -#define RO 0 - -/* Minimum size of Ethernet packet. */ -#define ET_MINLEN 60 - -/* The number of NE2000 devices supported by this driver. */ - -#define NNEDRIVER 1 - -/* RTEMS event number used by the interrupt handler to signal the - driver task. This must not be any of the events used by the - network task synchronization. */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* RTEMS event number used to start the transmit daemon. This must - not be the same as INTERRUPT_EVENT. */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* Interrupts we want to handle from the device. */ - -#define NE_INTERRUPTS \ - (MSK_PRX | MSK_PTX | MSK_RXE | MSK_TXE | MSK_OVW | MSK_CNT) - -/* The size of a page in device memory. */ - -#define NE_PAGE_SIZE (256) - -/* The first page address in device memory. */ - -#define NE_START_PAGE (0x40) - -/* The last page address, plus 1. */ - -#define NE_STOP_PAGE (0x80) - -/* The number of pages used for a single transmit buffer. This is - 1536 bytes, enough for a full size packet. */ - -#define NE_TX_PAGES (6) - -/* The number of transmit buffers. We use two, so we can load one - packet while the other is being sent. */ - -#define NE_TX_BUFS (2) - -/* We use the first pages in memory as transmit buffers, and the - remaining ones as receive buffers. */ - -#define NE_FIRST_TX_PAGE (NE_START_PAGE) - -#define NE_FIRST_RX_PAGE (NE_FIRST_TX_PAGE + NE_TX_PAGES * NE_TX_BUFS) - -/* Data we store for each NE2000 device. */ - -struct ne_softc { - /* The bsdnet information structure. */ - struct arpcom arpcom; - - /* The interrupt request number. */ - unsigned int irno; - /* The base IO port number. */ - unsigned int port; - - /* Whether we accept broadcasts. */ - int accept_broadcasts; - - /* The thread ID of the transmit task. */ - rtems_id tx_daemon_tid; - /* The thread ID of the receive task. */ - rtems_id rx_daemon_tid; - - /* Whether we use byte-transfers with the device. */ - bool byte_transfers; - - /* The number of memory buffers which the transmit daemon has loaded - with data to be sent, but which have not yet been completely - sent. */ - int inuse; - /* The index of the next available transmit memory buffer. */ - int nextavail; - /* The index of the next transmit buffer to send. */ - int nextsend; - /* Nonzero if the device is currently transmitting a packet. */ - int transmitting; - /* The length of the data stored in each transmit buffer. */ - int sendlen[NE_TX_BUFS]; - - /* Set if we have a packet overrun while receiving. */ - int overrun; - /* Set if we should resend after an overrun. */ - int resend; - - /* Statistics. */ - struct { - /* Number of packets received. */ - unsigned long rx_packets; - /* Number of packets sent. */ - unsigned long tx_packets; - /* Number of interrupts. */ - unsigned long interrupts; - /* Number of receive acknowledgements. */ - unsigned long rx_acks; - /* Number of transmit acknowledgements. */ - unsigned long tx_acks; - /* Number of packet overruns. */ - unsigned long overruns; - /* Number of frame errors. */ - unsigned long rx_frame_errors; - /* Number of CRC errors. */ - unsigned long rx_crc_errors; - /* Number of missed packets. */ - unsigned long rx_missed_errors; - } stats; -}; - -/* The list of NE2000 devices on this system. */ - -static struct ne_softc ne_softc[NNEDRIVER]; - -/* - * receive ring descriptor - * - * The National Semiconductor DS8390 Network interface controller uses - * the following receive ring headers. The way this works is that the - * memory on the interface card is chopped up into 256 bytes blocks. - * A contiguous portion of those blocks are marked for receive packets - * by setting start and end block #'s in the NIC. For each packet that - * is put into the receive ring, one of these headers (4 bytes each) is - * tacked onto the front. The first byte is a copy of the receiver status - * register at the time the packet was received. - */ -struct ne_ring -{ - unsigned char rsr; /* receiver status */ - unsigned char next; /* pointer to next packet */ - unsigned short count; /* bytes in packet (length + 4) */ -}; - -/* Forward declarations to avoid warnings */ - -static void ne_init_irq_handler (struct ne_softc *sc); -static void ne_stop (struct ne_softc *sc); -static void ne_stop_hardware (struct ne_softc *sc); -static void ne_init (void *arg); -static void ne_init_hardware (struct ne_softc *sc); - -static void ne_reset(struct ne_softc *sc); -#ifdef DEBUG_NE -static void ne_dump(struct ne_softc *sc); -#endif - -/* Read data from an NE2000 device. Read LEN bytes at ADDR, storing - them into P. */ - -static void -ne_read_data (struct ne_softc *sc, int addr, int len, unsigned char *p) -{ - unsigned int port = sc->port; - unsigned int dport = port + DATAPORT; - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA); - outport_byte (port + RBCR0, len); - outport_byte (port + RBCR1, len >> 8); - outport_byte (port + RSAR0, addr); - outport_byte (port + RSAR1, addr >> 8); - outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA); - - if (sc->byte_transfers) - { - unsigned char d; - while (len > 0) - { - inport_byte(dport, d); - *p++ = d; - len--; - } - } - else /* word transfers */ - { - unsigned short d; - while (len > 1) - { - inport_word(dport, d); - *p++ = d; - *p++ = d >> 8; - len -= 2; - } - if (len) - { - inport_word(dport, d); - *p++ = d; - } - } - - outport_byte (port + ISR, MSK_RDC); -} - -/* Handle the current NE2000 status. This is called when the device - signals an interrupt. It is also called at other times while - NE2000 interrupts have been disabled. */ - -static void -ne_check_status (struct ne_softc *sc, int from_irq_handler) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - unsigned int port = sc->port; - unsigned char status; - - /* It seems that we need to use a loop here, because if the NE2000 - signals an interrupt because packet transmission is complete, and - then receives a packet while interrupts are disabled, it seems to - sometimes fail to signal the interrupt for the received packet - when interrupts are reenabled. (Based on the behaviour of the - Realtek 8019AS chip). */ - - /* int count = 0; */ - while (1) - { - inport_byte (port + ISR, status); -#ifdef DEBUG_NE2000 - printk ("NE2000 status 0x%x\n", status); -#endif - if (status == 0) - break; - - /* ack */ - outport_byte (port + ISR, status); - - /* Check for incoming packet overwrite. */ - if (status & MSK_OVW) - { - ifp->if_timer = 0; -#ifdef DEBUG_NE - printk("^\n"); -#endif - ++sc->stats.overruns; - ne_reset(sc); - /* Reenable device interrupts. */ - if (from_irq_handler) - outport_byte(port + IMR, NE_INTERRUPTS); - return; - } - - /* Check for transmitted packet. The transmit daemon may now be - able to send another packet to the device. */ - if ((status & (MSK_PTX | MSK_TXE)) != 0) - { - ifp->if_timer = 0; - ++sc->stats.tx_acks; - --sc->inuse; - sc->transmitting = 0; - if (sc->inuse > 0 || (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) != 0) - rtems_bsdnet_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT); - } - - /* Check for received packet. */ - if ((status & (MSK_PRX | MSK_RXE)) != 0) - { - ++sc->stats.rx_acks; - rtems_bsdnet_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT); - } - - /* Check for counter change. */ - if ((status & MSK_CNT) != 0) - { - unsigned char add; - inport_byte (port + CNTR0, add); - sc->stats.rx_frame_errors += add; - inport_byte (port + CNTR1, add); - sc->stats.rx_crc_errors += add; - inport_byte (port + CNTR2, add); - sc->stats.rx_missed_errors += add; - } - - break; - } - - outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2); - -} - -/* Handle an NE2000 interrupt. */ - -static void -ne_interrupt_handler (void *arg) -{ - struct ne_softc *sc = arg; - - if (sc == NULL) - return; - - ++sc->stats.interrupts; - -#ifdef DEBUG_NE - printk("!"); -#endif - ne_check_status(sc, 1); -} - -/* Turn NE2000 interrupts on. */ - -static void -ne_interrupt_on (struct ne_softc *sc) -{ -#ifdef DEBUG_NE - printk ("ne_interrupt_on()\n"); -#endif - if (sc != NULL) - outport_byte (sc->port + IMR, NE_INTERRUPTS); -} - -/* Initialize the NE2000 hardware. */ - -static void -ne_init_hardware (struct ne_softc *sc) -{ - unsigned int port = sc->port; - int i; - -#ifdef DEBUG_NE2000 - printk ("ne_init_hardware()\n"); -#endif - - /* Initialize registers. */ - - /* Set interface for page 0, Remote DMA complete, Stopped */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - /* Set FIFO threshold to 8, No auto-init Remote DMA, byte order=80x86 */ - /* byte-wide DMA xfers */ - if (sc->byte_transfers) - outport_byte (port + DCR, MSK_FT10 | MSK_BMS); - /* word-wide DMA xfers */ - else - outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS); - - /* Clear Remote Byte Count Registers */ - outport_byte (port + RBCR0, 0); - outport_byte (port + RBCR1, 0); - - /* For the moment, don't store incoming packets in memory. */ - outport_byte (port + RCR, MSK_MON); - - /* Place NIC in internal loopback mode */ - outport_byte (port + TCR, MSK_LOOP); - - /* Initialize transmit/receive (ring-buffer) Page Start */ - outport_byte (port + TPSR, NE_FIRST_TX_PAGE); - outport_byte (port + PSTART, NE_FIRST_RX_PAGE); - - /* Initialize Receiver (ring-buffer) Page Stop and Boundary */ - outport_byte (port + PSTOP, NE_STOP_PAGE); - outport_byte (port + BNRY, NE_STOP_PAGE - 1); - - /* Clear all interrupts */ - outport_byte (port + ISR, 0xff); - /* Disable all interrupts */ - outport_byte (port + IMR, 0); - - /* Program Command Register for page 1 */ - outport_byte (port + CMDR, MSK_PG1 | MSK_RD2 | MSK_STP); - - /* Set the Ethernet hardware address. */ - for (i = 0; i < ETHER_ADDR_LEN; ++i) - outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]); - - /* Set Current Page pointer to next_packet */ - outport_byte (port + CURR, NE_FIRST_RX_PAGE); - - /* Clear the multicast address. */ - for (i = 0; i < MARsize; ++i) - outport_byte (port + MAR + i, 0); - - /* Set page 0 registers */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - /* accept broadcast */ - outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0)); - - /* Start interface */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA); - - /* Take interface out of loopback */ - outport_byte (port + TCR, 0); -} - -/* Set up interrupts. -*/ -static void -ne_init_irq_handler(struct ne_softc *sc) -{ - rtems_status_code status = RTEMS_SUCCESSFUL; - -#ifdef DEBUG_NE - printk("ne_init_irq_handler(%d)\n", sc->irno); -#endif - - status = rtems_interrupt_handler_install( - sc->irno, - "RTL8019", - RTEMS_INTERRUPT_UNIQUE, - ne_interrupt_handler, - sc - ); - assert(status == RTEMS_SUCCESSFUL); - ne_interrupt_on(sc); -} - -/* The NE2000 packet receive daemon. This task is started when the - NE2000 driver is initialized. */ - -#ifdef DEBUG_NE -static int ccc = 0; /* experinent! */ -#endif - -static void -ne_rx_daemon (void *arg) -{ - struct ne_softc *sc = (struct ne_softc *) arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - unsigned int port = sc->port; - - while (1) - { - rtems_event_set events; - - /* Wait for the interrupt handler to tell us that there is a - packet ready to receive. */ - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - /* Don't let the device interrupt us now. */ - outport_byte (port + IMR, 0); - - while (1) - { - unsigned char startpage, currpage; - unsigned short len; - unsigned char next, cnt1, cnt2; - struct mbuf *m = NULL; - unsigned char *p; - int startaddr; - int toend; - struct ether_header *eh; - struct ne_ring hdr; /* ring buffer header */ - int reset; - - inport_byte (port + BNRY, startpage); - - outport_byte (port + CMDR, MSK_PG1 | MSK_RD2); - inport_byte (port + CURR, currpage); - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2); - - ++startpage; - if (startpage >= NE_STOP_PAGE) - startpage = NE_FIRST_RX_PAGE; - - if (startpage == currpage) - break; - -#ifdef DEBUG_NE2000 - printk ("ne_rx_daemon: start page %x; current page %x\n", - startpage, currpage); -#endif - - reset = 0; - - /* Read the buffer header */ - startaddr = startpage * NE_PAGE_SIZE; - ne_read_data(sc, startaddr, sizeof(hdr), (unsigned char *)&hdr); - next = hdr.next; - - if (next >= NE_STOP_PAGE) - next = NE_FIRST_RX_PAGE; - - /* check packet length */ - len = hdr.count; - if (currpage < startpage) - cnt1 = currpage + (NE_STOP_PAGE - NE_FIRST_RX_PAGE) - startpage; - else - cnt1 = currpage - startpage; - cnt2 = len / NE_PAGE_SIZE; - if (len % NE_PAGE_SIZE) - cnt2++; - if (cnt1 < cnt2) - { -#ifdef DEBUG_NE - printk("(%x<%x:%x)\n", cnt1, cnt2, len); -/* - printk("start page 0x%x; current page 0x%x\n", - startpage, currpage); - printk("cnt1 < cnt2 (0x%x, 0x%x); len 0x%x\n", - cnt1, cnt2, len); -*/ -#endif - reset = 1; - } - if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) || - len < (ETHER_MIN_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) || - len > MCLBYTES) - { -#ifdef DEBUG_NE - printk("(%x)", len); - - printk("start page 0x%x; current page 0x%x\n", - startpage, currpage); - printk("len out of range: 0x%x\n", len); - printk("stat: 0x%x, next: 0x%x\n", hdr.rsr, hdr.next); -#endif - reset = 1; - } -#ifdef DEBUG_NE - if (++ccc == 100) - { ccc = 0; reset = 1; - printk("T"); - } -#endif - - /* reset interface */ - if (reset) - { - printk("Reset in RX\n"); - ne_reset(sc); - goto Next; - } - - /* The first four bytes of the length are the buffer header - * Just decrease them by 2 since in ARM, we have to make sure - * 4bytes memory access align on 4bytes - */ - len -= 2; - startaddr += 2; - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - - if (m == NULL) - panic ("ne_rx_daemon"); - - m->m_pkthdr.rcvif = ifp; - m->m_nextpkt = 0; - - p = mtod (m, unsigned char *); - m->m_len = m->m_pkthdr.len = len - (sizeof(struct ether_header) + 2); - - toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr; - if (toend < len) - { - ne_read_data (sc, startaddr, toend, p); - p += toend; - len -= toend; - startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE; - } - - if (len > 0) - ne_read_data (sc, startaddr, len, p); - - m->m_data +=2; - eh = mtod(m, struct ether_header *); - m->m_data += sizeof (struct ether_header); - -#ifdef DEBUG_NE - /*printk("[r%d]", hdr.count - sizeof(hdr));*/ - printk("<\n"); -#endif - ether_input (ifp, eh, m); - ++sc->stats.rx_packets; - outport_byte (port + BNRY, next - 1); - } - - if (sc->overrun) { - outport_byte (port + ISR, MSK_OVW); - outport_byte (port + TCR, 0); - if (sc->resend) - outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA); - sc->resend = 0; - sc->overrun = 0; - } - - Next: - /* Reenable device interrupts. */ - outport_byte (port + IMR, NE_INTERRUPTS); - } -} - -/* Load an NE2000 packet onto the device. */ - -static void -ne_loadpacket (struct ne_softc *sc, struct mbuf *m) -{ - unsigned int port = sc->port; - unsigned int dport = port + DATAPORT; - struct mbuf *mhold = m; - int leftover; - unsigned char leftover_data; - int timeout; - int send_cnt = 0; - -#ifdef DEBUG_NE2000 - printk ("Uploading NE2000 packet\n"); -#endif - - /* Reset remote DMA complete flag. */ - outport_byte (port + ISR, MSK_RDC); - - /* Write out the count. */ - outport_byte (port + RBCR0, m->m_pkthdr.len); - outport_byte (port + RBCR1, m->m_pkthdr.len >> 8); - - sc->sendlen[sc->nextavail] = m->m_pkthdr.len; - - /* Tell the device which address we want to write to. */ - outport_byte (port + RSAR0, 0); - outport_byte (port + RSAR1, - NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES)); - - /* Set up the write. */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA); - - /* Transfer the mbuf chain to device memory. NE2000 devices require - that the data be transferred as words, so we need to handle odd - length mbufs. Never occurs if we force byte transfers. */ - - leftover = 0; - leftover_data = '\0'; - - for (; m != NULL; m = m->m_next) { - int len; - unsigned char *data; - - len = m->m_len; - if (len == 0) - continue; - - data = mtod (m, unsigned char *); - - if (leftover) { - unsigned char next; - - /* Data left over from previous mbuf in chain. */ - next = *data++; - --len; - outport_word (dport, leftover_data | (next << 8)); - send_cnt += 2; - leftover = 0; - } - - /* If using byte transfers, len always ends up as zero so - there are no leftovers. */ - - if (sc->byte_transfers) - while (len > 0) { - outport_byte (dport, *data++); - len--; - } - else - while (len > 1) { - outport_word (dport, data[0] | (data[1] << 8)); - data += 2; - len -= 2; - send_cnt += 2; - } - - if (len > 0) - { - leftover = 1; - leftover_data = *data++; - } - } - - if (leftover) - { - outport_word (dport, leftover_data); - send_cnt += 2; - } - -#ifdef DEBUG_NE - /* printk("{l%d|%d}", send_cnt, sc->nextavail); */ - printk("v"); -#endif - m_freem (mhold); - - /* Wait for the device to complete accepting the data, with a - limiting counter so that we don't wait too long. */ - for (timeout = 0; timeout < 1000; ++timeout) - { - unsigned char status; - - inport_byte (port + ISR, status); - -#ifdef DEBUG_NE2000 - if ((status &~ MSK_RDC) != 0) - printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n", - status); -#endif - - if ((status & MSK_RDC) != 0) { - outport_byte (port + ISR, MSK_RDC); - break; - } - } - - if (timeout >= 1000) - printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n"); - - ++sc->nextavail; - if (sc->nextavail == NE_TX_BUFS) - sc->nextavail = 0; -} - -/* Tell the NE2000 to transmit a buffer whose contents we have already - loaded onto the device. */ - -static void -ne_transmit (struct ne_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - unsigned int port = sc->port; - int len; - -#ifdef DEBUG_NE2000 - printk ("Transmitting NE2000 packet\n"); -#endif - - len = sc->sendlen[sc->nextsend]; - if (len < ET_MINLEN) - len = ET_MINLEN; - outport_byte (port + TBCR0, len); - outport_byte (port + TBCR1, len >> 8); - - outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES)); - - outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA); - -#ifdef DEBUG_NE - /* printk("{s%d|%d}", len, sc->nextsend); */ - printk(">"); -#endif - ++sc->nextsend; - if (sc->nextsend == NE_TX_BUFS) - sc->nextsend = 0; - - ++sc->stats.tx_packets; - - /* set watchdog timer */ - ifp->if_timer = 2; -} - -/* The NE2000 packet transmit daemon. This task is started when the - NE2000 driver is initialized. */ - -static void -ne_tx_daemon (void *arg) -{ - struct ne_softc *sc = (struct ne_softc *) arg; - unsigned int port = sc->port; - struct ifnet *ifp = &sc->arpcom.ac_if; - - while (1) { - rtems_event_set events; - - /* Wait for a packet to be ready for sending, or for there to be - room for another packet in the device memory. */ - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - -#ifdef DEBUG_NE2000 - printk ("ne_tx_daemon\n"); -#endif - - /* This daemon handles both uploading data onto the device and - telling the device to transmit data which has been uploaded. - These are separate tasks, because while the device is - transmitting one buffer we will upload another. */ - - /* Don't let the device interrupt us now. */ - outport_byte (port + IMR, 0); - - while (1) { - struct mbuf *m; - - /* If the device is not transmitting a packet, and we have - uploaded a packet, tell the device to transmit it. */ - if (! sc->transmitting && sc->inuse > 0) { - sc->transmitting = 1; - ne_transmit (sc); - } - - /* If we don't have any more buffers to send, quit now. */ - if (ifp->if_snd.ifq_head == NULL) { - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - - /* Allocate a buffer to load data into. If there are none - available, quit until a buffer has been transmitted. */ - if (sc->inuse >= NE_TX_BUFS) - break; - - ++sc->inuse; - - IF_DEQUEUE (&ifp->if_snd, m); - if (m == NULL) - panic ("ne_tx_daemon"); - - ne_loadpacket (sc, m); - - /* Check the device status. It may have finished transmitting - the last packet. */ - ne_check_status(sc, 0); - } - - /* Reenable device interrupts. */ - outport_byte (port + IMR, NE_INTERRUPTS); - } -} - -/* Start sending an NE2000 packet. */ - -static void -ne_start (struct ifnet *ifp) -{ - struct ne_softc *sc = ifp->if_softc; - -#ifdef DEBUG_NE - printk("S"); -#endif - /* Tell the transmit daemon to wake up and send a packet. */ - rtems_bsdnet_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* Initialize and start and NE2000. */ - -static void -ne_init (void *arg) -{ - struct ne_softc *sc = (struct ne_softc *) arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - -#ifdef DEBUG_NE - printk("ne_init()\n"); - ne_dump(sc); -#endif - - /* only once... */ - if (sc->tx_daemon_tid == 0) - { - sc->inuse = 0; - sc->nextavail = 0; - sc->nextsend = 0; - sc->transmitting = 0; - - ne_init_hardware (sc); - - sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc); - sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc); - - /* install rtems irq handler */ - ne_init_irq_handler(sc); - } - - ifp->if_flags |= IFF_RUNNING; -} - -/* Stop an NE2000. */ - -static void -ne_stop (struct ne_softc *sc) -{ - sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; - - ne_stop_hardware(sc); - - sc->inuse = 0; - sc->nextavail = 0; - sc->nextsend = 0; - sc->transmitting = 0; - sc->overrun = 0; - sc->resend = 0; -} - -static void -ne_stop_hardware (struct ne_softc *sc) -{ - unsigned int port = sc->port; - int i; - - /* Stop everything. */ - outport_byte (port + CMDR, MSK_STP | MSK_RD2); - - /* Wait for the interface to stop, using I as a time limit. */ - for (i = 0; i < 5000; ++i) - { - unsigned char status; - - inport_byte (port + ISR, status); - if ((status & MSK_RST) != 0) - break; - } -} - -/* reinitializing interface -*/ -static void -ne_reset(struct ne_softc *sc) -{ - ne_stop(sc); - ne_init_hardware(sc); - sc->arpcom.ac_if.if_flags |= IFF_RUNNING; - sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; -#ifdef DEBUG_NE - printk("*"); -#endif -} - -#ifdef DEBUG_NE -/* show anything about ne -*/ -static void -ne_dump(struct ne_softc *sc) -{ - int i; - printk("\nne configuration:\n"); - printk("ethernet addr:"); - for (i=0; i<ETHER_ADDR_LEN; i++) - printk(" %x", sc->arpcom.ac_enaddr[i]); - printk("\n"); - printk("irq = %d\n", sc->irno); - printk("port = 0x%x\n", sc->port); - printk("accept_broadcasts = %d\n", sc->accept_broadcasts); - printk("byte_transfers = %d\n", sc->byte_transfers); -} -#endif - -/* Show NE2000 interface statistics. */ - -static void -ne_stats (struct ne_softc *sc) -{ - printf (" Received packets: %-8lu", sc->stats.rx_packets); - printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets); - printf (" Receive acks: %-8lu", sc->stats.rx_acks); - printf (" Transmit acks: %-8lu\n", sc->stats.tx_acks); - printf (" Packet overruns: %-8lu", sc->stats.overruns); - printf (" Frame errors: %-8lu\n", sc->stats.rx_frame_errors); - printf (" CRC errors: %-8lu", sc->stats.rx_crc_errors); - printf (" Missed packets: %-8lu\n", sc->stats.rx_missed_errors); - printf (" Interrupts: %-8lu\n", sc->stats.interrupts); -} - -/* NE2000 driver ioctl handler. */ - -static int -ne_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct ne_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - error = ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - ne_stop (sc); - break; - - case IFF_UP: - printk("IFF_UP\n"); - ne_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - ne_stop (sc); - ne_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - ne_stats (sc); - break; - - /* FIXME: Multicast commands must be added here. */ - - default: - error = EINVAL; - break; - } - - return error; -} - -/* - * Device timeout/watchdog routine. Entered if the device neglects to - * generate an interrupt after a transmit has been started on it. - */ -static void -ne_watchdog(struct ifnet *ifp) -{ - struct ne_softc *sc = ifp->if_softc; - - printk("ne2000: device timeout\n"); - ifp->if_oerrors++; - - ne_reset(sc); -} - -static void -print_byte(unsigned char b) -{ - printk("%x%x", b >> 4, b & 0x0f); -} - -/* Attach an NE2000 driver to the system. */ - -int -rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) -{ - int i; - struct ne_softc *sc; - struct ifnet *ifp; - int mtu; - - /* dettach ... */ - if (!attach) - return 0; - - /* Find a free driver. */ - sc = NULL; - for (i = 0; i < NNEDRIVER; ++i) { - sc = &ne_softc[i]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc == NULL) - break; - } - - if (sc == NULL) { - printf ("Too many NE2000 drivers.\n"); - return 0; - } - - memset (sc, 0, sizeof *sc); - - /* Check whether we do byte-wide or word-wide transfers. */ - -#ifdef NE2000_BYTE_TRANSFERS - sc->byte_transfers = true; -#else - sc->byte_transfers = false; -#endif - - /* Handle the options passed in by the caller. */ - - if (config->mtu != 0) - mtu = config->mtu; - else - mtu = ETHERMTU; - - /* We use 16 as the default IRQ. */ - sc->irno = XSCALE_IRQ_NETWORK; - - - - /*IO prts are mapped to 0X40000600 */ - sc->port = 0x40000600; - - sc->accept_broadcasts = ! config->ignore_broadcast; - - if (config->hardware_address != NULL) - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - else - { - unsigned char prom[16]; - int ia; - - /* Read the PROM to get the Ethernet hardware address. */ - - outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - if (sc->byte_transfers) { - outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS); - } - else { - outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS); - } - - outport_byte (sc->port + RBCR0, 0); - outport_byte (sc->port + RBCR1, 0); - outport_byte (sc->port + RCR, MSK_MON); - outport_byte (sc->port + TCR, MSK_LOOP); - outport_byte (sc->port + IMR, 0); - outport_byte (sc->port + ISR, 0xff); - - ne_read_data (sc, 0, sizeof prom, prom); - - outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - for (ia = 0; ia < ETHER_ADDR_LEN; ++ia) - sc->arpcom.ac_enaddr[ia] = prom[ia * 2]; - } - - /* Set up the network interface. */ - - ifp->if_softc = sc; - ifp->if_unit = i + 1; - ifp->if_name = "ne"; - ifp->if_mtu = mtu; - ifp->if_init = ne_init; - ifp->if_ioctl = ne_ioctl; - ifp->if_watchdog = ne_watchdog; - ifp->if_start = ne_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* Attach the interface. */ - - if_attach (ifp); - ether_ifattach (ifp); - - printk("network device '%s' <", config->name); - print_byte(sc->arpcom.ac_enaddr[0]); - for (i=1; i<ETHER_ADDR_LEN; i++) - { printk(":"); - print_byte(sc->arpcom.ac_enaddr[i]); - } - printk("> initialized on port 0x%x, irq %d\n", sc->port, sc->irno); - - return 1; -} diff --git a/bsps/arm/gumstix/net/wd80x3.h b/bsps/arm/gumstix/net/wd80x3.h deleted file mode 100644 index 0a9f3432bc..0000000000 --- a/bsps/arm/gumstix/net/wd80x3.h +++ /dev/null @@ -1,303 +0,0 @@ -/** - * @file - * @ingroup gumstix_dp8390 - * @brief DP8390 Ethernet Controller Support - */ - -/* - * Information about the DP8390 Ethernet controller. - */ - -#ifndef __BSP_WD80x3_h -#define __BSP_WD80x3_h - -/* Register descriptions */ - -/** - * @defgroup gumstix_dp8390 DP8390 Support - * @ingroup RTEMSBSPsARMGumstix - * @brief DP8390 Ethernet Controller Support - * @{ - */ - -/** - * @name Controller DP8390. - * @{ - */ - -/** @brief Port Window. */ -#define DATAPORT 0x10 -/** @brief Issue a read for reset */ -#define RESET 0x1f -/** @brief I/O port definition */ -#define W83CREG 0x00 -#define ADDROM 0x08 - -/** @} */ - -/** - * @name page 0 read or read/write registers - * @{ - */ - -#define CMDR 0x00+RO -/** @brief current local dma addr 0 for read */ -#define CLDA0 0x01+RO -/** @brief current local dma addr 1 for read */ -#define CLDA1 0x02+RO -/** @brief boundary reg for rd and wr */ -#define BNRY 0x03+RO -/** @brief tx status reg for rd */ -#define TSR 0x04+RO -/** @brief number of collision reg for rd */ -#define NCR 0x05+RO -/** @breif FIFO for rd */ -#define FIFO 0x06+RO -/** @brief interrupt status reg for rd and wr */ -#define ISR 0x07+RO -/** @brief current remote dma address 0 for rd */ -#define CRDA0 0x08+RO -/** @brief current remote dma address 1 for rd */ -#define CRDA1 0x09+RO -/** @brief rx status reg for rd */ -#define RSR 0x0C+RO -/** @brief tally cnt 0 for frm alg err for rd */ -#define CNTR0 0x0D+RO -/** @brief tally cnt 1 for crc err for rd */ -#define CNTR1 RO+0x0E -/** @brief tally cnt 2 for missed pkt for rd */ -#define CNTR2 0x0F+RO - -/** @} */ - -/** - * @name page 0 write registers - * @{ - */ - -/** @brief page start register */ -#define PSTART 0x01+RO -/** @brief page stop register */ -#define PSTOP 0x02+RO -/** @breif tx start page start reg */ -#define TPSR 0x04+RO -/** @brief tx byte count 0 reg */ -#define TBCR0 0x05+RO -/** @brief tx byte count 1 reg */ -#define TBCR1 0x06+RO -/** @brief remote start address reg 0 */ -#define RSAR0 0x08+RO -/** @brief remote start address reg 1 */ -#define RSAR1 0x09+RO -/** @brief remote byte count reg 0 */ -#define RBCR0 0x0A+RO -/** @brief remote byte count reg 1 */ -#define RBCR1 0x0B+RO -/** @brief rx configuration reg */ -#define RCR 0x0C+RO -/** @brief tx configuration reg */ -#define TCR 0x0D+RO -/** @brief data configuration reg */ -#define DCR RO+0x0E -/** @brief interrupt mask reg */ -#define IMR 0x0F+RO - -/** @} */ - -/** - * @name page 1 registers - * @{ - */ - -/** @brief physical addr reg base for rd and wr */ -#define PAR 0x01+RO -/** @brief current page reg for rd and wr */ -#define CURR 0x07+RO -/** @brief multicast addr reg base fro rd and WR */ -#define MAR 0x08+RO -/** @brief size of multicast addr space */ -#define MARsize 8 - -/** @} */ - -/** - * @name W83CREG command bits - * @{ - */ - -/** @brief W83CREG masks */ -#define MSK_RESET 0x80 -#define MSK_ENASH 0x40 -/** @brief memory decode bits, corresponding */ -#define MSK_DECOD 0x3F - -/** @} */ - -/** - * @name CMDR command bits - * @{ - */ - -/** @brief stop the chip */ -#define MSK_STP 0x01 -/** @brief start the chip */ -#define MSK_STA 0x02 -/** @brief initial txing of a frm */ -#define MSK_TXP 0x04 -/** @brief remote read */ -#define MSK_RRE 0x08 -/** @brief remote write */ -#define MSK_RWR 0x10 -/** @brief no DMA used */ -#define MSK_RD2 0x20 -/** @brief select register page 0 */ -#define MSK_PG0 0x00 -/** @brief select register page 1 */ -#define MSK_PG1 0x40 -/** @brief select register page 2 */ -#define MSK_PG2 0x80 - -/** @} */ - -/** - * @name ISR and TSR status bits - * @{ - */ - -/* @brief rx with no error */ -#define MSK_PRX 0x01 -/* @brief tx with no error */ -#define MSK_PTX 0x02 -/* @brief rx with error */ -#define MSK_RXE 0x04 -/* @brief tx with error */ -#define MSK_TXE 0x08 -/* @brief overwrite warning */ -#define MSK_OVW 0x10 -/* @brief MSB of one of the tally counters is set */ -#define MSK_CNT 0x20 -/* @brief remote dma completed */ -#define MSK_RDC 0x40 -/* @brief reset state indicator */ -#define MSK_RST 0x80 - -/** @} */ - -/** - * @name DCR command bits - * @{ - */ - -/** @brief word transfer mode selection */ -#define MSK_WTS 0x01 -/** @brief byte order selection */ -#define MSK_BOS 0x02 -/** @brief long addr selection */ -#define MSK_LAS 0x04 -/** @brief burst mode selection */ -#define MSK_BMS 0x08 -/** @brief autoinitialize remote */ -#define MSK_ARM 0x10 -/** @brief burst lrngth selection */ -#define MSK_FT00 0x00 -/** @brief burst lrngth selection */ -#define MSK_FT01 0x20 -/** @brief burst lrngth selection */ -#define MSK_FT10 0x40 -/** @brief burst lrngth selection */ -#define MSK_FT11 0x60 - -/** @} */ - -/** - * @name RCR command bits - * @{ - */ - -/** @brief save error pkts */ -#define MSK_SEP 0x01 -/** @brief accept runt pkt */ -#define MSK_AR 0x02 -/** @brief 8390 RCR */ -#define MSK_AB 0x04 -/** @brief accept multicast */ -#define MSK_AM 0x08 -/** @brief accept all pkt with physical adr */ -#define MSK_PRO 0x10 -/** @brief monitor mode */ -#define MSK_MON 0x20 - -/** @} */ - -/** - * @name TCR command bits - * @{ - */ - -/** @brief inhibit CRC, do not append crc */ -#define MSK_CRC 0x01 -/** @brief set loopback mode */ -#define MSK_LOOP 0x02 -/** @brief Accept broadcasts */ -#define MSK_BCST 0x04 -/** @brief encoded loopback control */ -#define MSK_LB01 0x06 -/** @brief auto tx disable */ -#define MSK_ATD 0x08 -/** @brief collision offset enable */ -#define MSK_OFST 0x10 - -/** @} */ - -/** - * @name receive status bits - * @{ - */ - -/** @brief rx without error */ -#define SMK_PRX 0x01 -/** @brief CRC error */ -#define SMK_CRC 0x02 -/** @brief frame alignment error */ -#define SMK_FAE 0x04 -/** @brief FIFO overrun */ -#define SMK_FO 0x08 -/** @brief missed pkt */ -#define SMK_MPA 0x10 -/** @brief physical/multicase address */ -#define SMK_PHY 0x20 -/** @brief receiver disable. set in monitor mode */ -#define SMK_DIS 0x40 -/** @brief deferring */ -#define SMK_DEF 0x80 - -/** @} */ - -/** - * @name transmit status bits - * @{ - */ - -/** @brief tx without error */ -#define SMK_PTX 0x01 -/** @brief non deferred tx */ -#define SMK_DFR 0x02 -/** @brief tx collided */ -#define SMK_COL 0x04 -/** @brief tx abort because of excessive collisions */ -#define SMK_ABT 0x08 -/** @brief carrier sense lost */ -#define SMK_CRS 0x10 -/** @brief FIFO underrun */ -#define SMK_FU 0x20 -/** @brief collision detect heartbeat */ -#define SMK_CDH 0x40 -/** @brief out of window collision */ -#define SMK_OWC 0x80 - -/** @} */ - -/** @} */ - -#endif -/* end of include */ diff --git a/bsps/arm/rtl22xx/net/network.c b/bsps/arm/rtl22xx/net/network.c deleted file mode 100644 index 5581b8fab5..0000000000 --- a/bsps/arm/rtl22xx/net/network.c +++ /dev/null @@ -1,126 +0,0 @@ -/*Note: this file is copy from 7312 BSP, and untested yet*/ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <rtems.h> -#include <sys/param.h> -#include <sys/mbuf.h> -#include <bsp/irq.h> -#include <libchip/cs8900.h> -#include <assert.h> - -#define CS8900_BASE 0x20000300 -unsigned int bsp_cs8900_io_base = 0; -unsigned int bsp_cs8900_memory_base = 0; -static void cs8900_isr(void *); - -char g_enetbuf[1520]; - -static void cs8900_isr(void *arg) -{ - cs8900_interrupt(LPC22xx_INTERRUPT_EINT2, arg); -} - -/* cs8900_io_set_reg - set one of the I/O addressed registers */ -void cs8900_io_set_reg (cs8900_device *cs, unsigned short reg, unsigned short data) -{ - /* works the same for all values of dev */ -/* - printf("cs8900_io_set_reg: reg: %#6x, val %#6x\n", - CS8900_BASE + reg, - data); -*/ - *(unsigned short *)(CS8900_BASE + reg) = data; -} - -/* cs8900_io_get_reg - reads one of the I/O addressed registers */ -unsigned short cs8900_io_get_reg (cs8900_device *cs, unsigned short reg) -{ - unsigned short val; - /* works the same for all values of dev */ - val = *(unsigned short *)(CS8900_BASE + reg); -/* - printf("cs8900_io_get_reg: reg: %#6x, val %#6x\n", reg, val); -*/ - return val; -} - -/* cs8900_mem_set_reg - sets one of the registers mapped through - * PacketPage - */ -void cs8900_mem_set_reg (cs8900_device *cs, unsigned long reg, unsigned short data) -{ - /* works the same for all values of dev */ - cs8900_io_set_reg(cs, CS8900_IO_PACKET_PAGE_PTR, reg); - cs8900_io_set_reg(cs, CS8900_IO_PP_DATA_PORT0, data); -} - -/* cs8900_mem_get_reg - reads one of the registers mapped through - * PacketPage - */ -unsigned short cs8900_mem_get_reg (cs8900_device *cs, unsigned long reg) -{ - /* works the same for all values of dev */ - cs8900_io_set_reg(cs, CS8900_IO_PACKET_PAGE_PTR, reg); - return cs8900_io_get_reg(cs, CS8900_IO_PP_DATA_PORT0); -} - -void cs8900_attach_interrupt (cs8900_device *cs) -{ - rtems_status_code status = RTEMS_SUCCESSFUL; - status = rtems_interrupt_handler_install( - LPC22xx_INTERRUPT_EINT2, - "Network", - RTEMS_INTERRUPT_UNIQUE, - cs8900_isr, - cs - ); - assert(status == RTEMS_SUCCESSFUL); -} - -void cs8900_detach_interrupt (cs8900_device *cs) -{ - rtems_status_code status = RTEMS_SUCCESSFUL; - status = rtems_interrupt_handler_remove( - LPC22xx_INTERRUPT_EINT2, - cs8900_isr, - cs - ); - assert(status == RTEMS_SUCCESSFUL); -} - -unsigned short cs8900_get_data_block (cs8900_device *cs, unsigned char *data) -{ - int len; - int i; - - len = cs8900_mem_get_reg(cs, CS8900_PP_RxLength); - - for (i = 0; i < ((len + 1) / 2); i++) { - ((short *)data)[i] = cs8900_io_get_reg(cs, - CS8900_IO_RX_TX_DATA_PORT0); - } - return len; -} - -void cs8900_tx_load (cs8900_device *cs, struct mbuf *m) -{ - int len; - unsigned short *data; - int i; - - len = 0; - - do { - memcpy(&g_enetbuf[len], mtod(m, const void *), m->m_len); - len += m->m_len; - m = m->m_next; - } while (m != 0); - - data = (unsigned short *) &g_enetbuf[0]; - for (i = 0; i < ((len + 1) / 2); i++) { - cs8900_io_set_reg(cs, - CS8900_IO_RX_TX_DATA_PORT0, - data[i]); - } -} diff --git a/bsps/arm/shared/net/lpc-ethernet.c b/bsps/arm/shared/net/lpc-ethernet.c deleted file mode 100644 index ccfe1696eb..0000000000 --- a/bsps/arm/shared/net/lpc-ethernet.c +++ /dev/null @@ -1,1839 +0,0 @@ -/** - * @file - * - * @ingroup lpc_eth - * - * @brief Ethernet driver. - */ - -/* - * Copyright (c) 2009-2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * <rtems@embedded-brains.de> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <machine/rtems-bsd-kernel-space.h> - -#include <errno.h> -#include <inttypes.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -#include <rtems.h> -#include <rtems/rtems_bsdnet.h> -#include <rtems/rtems_mii_ioctl.h> - -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> - -#include <bsp.h> -#include <bsp/irq.h> -#include <bsp/lpc-ethernet-config.h> -#include <bsp/utility.h> - -#if MCLBYTES > (2 * 1024) - #error "MCLBYTES to large" -#endif - -#ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - #define LPC_ETH_CONFIG_TX_BUF_SIZE sizeof(struct mbuf *) -#else - #define LPC_ETH_CONFIG_TX_BUF_SIZE 1518U -#endif - -#define DEFAULT_PHY 0 -#define WATCHDOG_TIMEOUT 5 - -typedef struct { - uint32_t start; - uint32_t control; -} lpc_eth_transfer_descriptor; - -typedef struct { - uint32_t info; - uint32_t hash_crc; -} lpc_eth_receive_status; - -typedef struct { - uint32_t mac1; - uint32_t mac2; - uint32_t ipgt; - uint32_t ipgr; - uint32_t clrt; - uint32_t maxf; - uint32_t supp; - uint32_t test; - uint32_t mcfg; - uint32_t mcmd; - uint32_t madr; - uint32_t mwtd; - uint32_t mrdd; - uint32_t mind; - uint32_t reserved_0 [2]; - uint32_t sa0; - uint32_t sa1; - uint32_t sa2; - uint32_t reserved_1 [45]; - uint32_t command; - uint32_t status; - uint32_t rxdescriptor; - uint32_t rxstatus; - uint32_t rxdescriptornum; - uint32_t rxproduceindex; - uint32_t rxconsumeindex; - uint32_t txdescriptor; - uint32_t txstatus; - uint32_t txdescriptornum; - uint32_t txproduceindex; - uint32_t txconsumeindex; - uint32_t reserved_2 [10]; - uint32_t tsv0; - uint32_t tsv1; - uint32_t rsv; - uint32_t reserved_3 [3]; - uint32_t flowcontrolcnt; - uint32_t flowcontrolsts; - uint32_t reserved_4 [34]; - uint32_t rxfilterctrl; - uint32_t rxfilterwolsts; - uint32_t rxfilterwolclr; - uint32_t reserved_5 [1]; - uint32_t hashfilterl; - uint32_t hashfilterh; - uint32_t reserved_6 [882]; - uint32_t intstatus; - uint32_t intenable; - uint32_t intclear; - uint32_t intset; - uint32_t reserved_7 [1]; - uint32_t powerdown; -} lpc_eth_controller; - -static volatile lpc_eth_controller *const lpc_eth = - (volatile lpc_eth_controller *) LPC_ETH_CONFIG_REG_BASE; - -/* ETH_RX_CTRL */ - -#define ETH_RX_CTRL_SIZE_MASK 0x000007ffU -#define ETH_RX_CTRL_INTERRUPT 0x80000000U - -/* ETH_RX_STAT */ - -#define ETH_RX_STAT_RXSIZE_MASK 0x000007ffU -#define ETH_RX_STAT_BYTES 0x00000100U -#define ETH_RX_STAT_CONTROL_FRAME 0x00040000U -#define ETH_RX_STAT_VLAN 0x00080000U -#define ETH_RX_STAT_FAIL_FILTER 0x00100000U -#define ETH_RX_STAT_MULTICAST 0x00200000U -#define ETH_RX_STAT_BROADCAST 0x00400000U -#define ETH_RX_STAT_CRC_ERROR 0x00800000U -#define ETH_RX_STAT_SYMBOL_ERROR 0x01000000U -#define ETH_RX_STAT_LENGTH_ERROR 0x02000000U -#define ETH_RX_STAT_RANGE_ERROR 0x04000000U -#define ETH_RX_STAT_ALIGNMENT_ERROR 0x08000000U -#define ETH_RX_STAT_OVERRUN 0x10000000U -#define ETH_RX_STAT_NO_DESCRIPTOR 0x20000000U -#define ETH_RX_STAT_LAST_FLAG 0x40000000U -#define ETH_RX_STAT_ERROR 0x80000000U - -/* ETH_TX_CTRL */ - -#define ETH_TX_CTRL_SIZE_MASK 0x7ffU -#define ETH_TX_CTRL_SIZE_SHIFT 0 -#define ETH_TX_CTRL_OVERRIDE 0x04000000U -#define ETH_TX_CTRL_HUGE 0x08000000U -#define ETH_TX_CTRL_PAD 0x10000000U -#define ETH_TX_CTRL_CRC 0x20000000U -#define ETH_TX_CTRL_LAST 0x40000000U -#define ETH_TX_CTRL_INTERRUPT 0x80000000U - -/* ETH_TX_STAT */ - -#define ETH_TX_STAT_COLLISION_COUNT_MASK 0x01e00000U -#define ETH_TX_STAT_DEFER 0x02000000U -#define ETH_TX_STAT_EXCESSIVE_DEFER 0x04000000U -#define ETH_TX_STAT_EXCESSIVE_COLLISION 0x08000000U -#define ETH_TX_STAT_LATE_COLLISION 0x10000000U -#define ETH_TX_STAT_UNDERRUN 0x20000000U -#define ETH_TX_STAT_NO_DESCRIPTOR 0x40000000U -#define ETH_TX_STAT_ERROR 0x80000000U - -/* ETH_INT */ - -#define ETH_INT_RX_OVERRUN 0x00000001U -#define ETH_INT_RX_ERROR 0x00000002U -#define ETH_INT_RX_FINISHED 0x00000004U -#define ETH_INT_RX_DONE 0x00000008U -#define ETH_INT_TX_UNDERRUN 0x00000010U -#define ETH_INT_TX_ERROR 0x00000020U -#define ETH_INT_TX_FINISHED 0x00000040U -#define ETH_INT_TX_DONE 0x00000080U -#define ETH_INT_SOFT 0x00001000U -#define ETH_INT_WAKEUP 0x00002000U - -/* ETH_RX_FIL_CTRL */ - -#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST 0x00000001U -#define ETH_RX_FIL_CTRL_ACCEPT_BROADCAST 0x00000002U -#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST 0x00000004U -#define ETH_RX_FIL_CTRL_ACCEPT_UNICAST_HASH 0x00000008U -#define ETH_RX_FIL_CTRL_ACCEPT_MULTICAST_HASH 0x00000010U -#define ETH_RX_FIL_CTRL_ACCEPT_PERFECT 0x00000020U -#define ETH_RX_FIL_CTRL_MAGIC_PACKET_WOL 0x00001000U -#define ETH_RX_FIL_CTRL_RX_FILTER_WOL 0x00002000U - -/* ETH_CMD */ - -#define ETH_CMD_RX_ENABLE 0x00000001U -#define ETH_CMD_TX_ENABLE 0x00000002U -#define ETH_CMD_REG_RESET 0x00000008U -#define ETH_CMD_TX_RESET 0x00000010U -#define ETH_CMD_RX_RESET 0x00000020U -#define ETH_CMD_PASS_RUNT_FRAME 0x00000040U -#define ETH_CMD_PASS_RX_FILTER 0X00000080U -#define ETH_CMD_TX_FLOW_CONTROL 0x00000100U -#define ETH_CMD_RMII 0x00000200U -#define ETH_CMD_FULL_DUPLEX 0x00000400U - -/* ETH_STAT */ - -#define ETH_STAT_RX_ACTIVE 0x00000001U -#define ETH_STAT_TX_ACTIVE 0x00000002U - -/* ETH_MAC2 */ - -#define ETH_MAC2_FULL_DUPLEX BSP_BIT32(8) - -/* ETH_SUPP */ - -#define ETH_SUPP_SPEED BSP_BIT32(8) - -/* ETH_MCFG */ - -#define ETH_MCFG_CLOCK_SELECT(val) BSP_FLD32(val, 2, 4) - -#define ETH_MCFG_RESETMIIMGMT BSP_BIT32(15) - -/* ETH_MCMD */ - -#define ETH_MCMD_READ BSP_BIT32(0) -#define ETH_MCMD_SCAN BSP_BIT32(1) - -/* ETH_MADR */ - -#define ETH_MADR_REG(val) BSP_FLD32(val, 0, 4) -#define ETH_MADR_PHY(val) BSP_FLD32(val, 8, 12) - -/* ETH_MIND */ - -#define ETH_MIND_BUSY BSP_BIT32(0) -#define ETH_MIND_SCANNING BSP_BIT32(1) -#define ETH_MIND_NOT_VALID BSP_BIT32(2) -#define ETH_MIND_MII_LINK_FAIL BSP_BIT32(3) - -/* Events */ - -#define LPC_ETH_EVENT_INITIALIZE RTEMS_EVENT_1 - -#define LPC_ETH_EVENT_TXSTART RTEMS_EVENT_2 - -#define LPC_ETH_EVENT_INTERRUPT RTEMS_EVENT_3 - -#define LPC_ETH_EVENT_STOP RTEMS_EVENT_4 - -/* Status */ - -#define LPC_ETH_INTERRUPT_RECEIVE \ - (ETH_INT_RX_ERROR | ETH_INT_RX_FINISHED | ETH_INT_RX_DONE) - -#define LPC_ETH_INTERRUPT_TRANSMIT \ - (ETH_INT_TX_DONE | ETH_INT_TX_FINISHED | ETH_INT_TX_ERROR) - -#define LPC_ETH_RX_STAT_ERRORS \ - (ETH_RX_STAT_CRC_ERROR \ - | ETH_RX_STAT_SYMBOL_ERROR \ - | ETH_RX_STAT_LENGTH_ERROR \ - | ETH_RX_STAT_ALIGNMENT_ERROR \ - | ETH_RX_STAT_OVERRUN \ - | ETH_RX_STAT_NO_DESCRIPTOR) - -#define LPC_ETH_LAST_FRAGMENT_FLAGS \ - (ETH_TX_CTRL_OVERRIDE \ - | ETH_TX_CTRL_PAD \ - | ETH_TX_CTRL_CRC \ - | ETH_TX_CTRL_INTERRUPT \ - | ETH_TX_CTRL_LAST) - -/* Debug */ - -#ifdef DEBUG - #define LPC_ETH_PRINTF(...) printf(__VA_ARGS__) - #define LPC_ETH_PRINTK(...) printk(__VA_ARGS__) -#else - #define LPC_ETH_PRINTF(...) - #define LPC_ETH_PRINTK(...) -#endif - -typedef enum { - LPC_ETH_STATE_NOT_INITIALIZED = 0, - LPC_ETH_STATE_DOWN, - LPC_ETH_STATE_UP -} lpc_eth_state; - -typedef struct { - struct arpcom arpcom; - lpc_eth_state state; - struct rtems_mdio_info mdio; - uint32_t anlpar; - rtems_id receive_task; - rtems_id transmit_task; - unsigned rx_unit_count; - unsigned tx_unit_count; - volatile lpc_eth_transfer_descriptor *rx_desc_table; - volatile lpc_eth_receive_status *rx_status_table; - struct mbuf **rx_mbuf_table; - volatile lpc_eth_transfer_descriptor *tx_desc_table; - volatile uint32_t *tx_status_table; - void *tx_buf_table; - unsigned received_frames; - unsigned receive_interrupts; - unsigned transmitted_frames; - unsigned transmit_interrupts; - unsigned receive_drop_errors; - unsigned receive_overrun_errors; - unsigned receive_fragment_errors; - unsigned receive_crc_errors; - unsigned receive_symbol_errors; - unsigned receive_length_errors; - unsigned receive_alignment_errors; - unsigned receive_no_descriptor_errors; - unsigned receive_fatal_errors; - unsigned transmit_underrun_errors; - unsigned transmit_late_collision_errors; - unsigned transmit_excessive_collision_errors; - unsigned transmit_excessive_defer_errors; - unsigned transmit_no_descriptor_errors; - unsigned transmit_overflow_errors; - unsigned transmit_fatal_errors; - uint32_t phy_id; - int phy; - rtems_vector_number interrupt_number; - rtems_id control_task; -} lpc_eth_driver_entry; - -static lpc_eth_driver_entry lpc_eth_driver_data; - -static void lpc_eth_control_request_complete(const lpc_eth_driver_entry *e) -{ - rtems_status_code sc = rtems_event_transient_send(e->control_task); - assert(sc == RTEMS_SUCCESSFUL); -} - -static void lpc_eth_control_request( - lpc_eth_driver_entry *e, - rtems_id task, - rtems_event_set event -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - uint32_t nest_count = 0; - - e->control_task = rtems_task_self(); - - sc = rtems_bsdnet_event_send(task, event); - assert(sc == RTEMS_SUCCESSFUL); - - nest_count = rtems_bsdnet_semaphore_release_recursive(); - sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT); - assert(sc == RTEMS_SUCCESSFUL); - rtems_bsdnet_semaphore_obtain_recursive(nest_count); - - e->control_task = 0; -} - -static inline uint32_t lpc_eth_increment( - uint32_t value, - uint32_t cycle -) -{ - if (value < cycle) { - return ++value; - } else { - return 0; - } -} - -static void lpc_eth_enable_promiscous_mode(bool enable) -{ - if (enable) { - lpc_eth->rxfilterctrl = ETH_RX_FIL_CTRL_ACCEPT_UNICAST - | ETH_RX_FIL_CTRL_ACCEPT_MULTICAST - | ETH_RX_FIL_CTRL_ACCEPT_BROADCAST; - } else { - lpc_eth->rxfilterctrl = ETH_RX_FIL_CTRL_ACCEPT_PERFECT - | ETH_RX_FIL_CTRL_ACCEPT_MULTICAST_HASH - | ETH_RX_FIL_CTRL_ACCEPT_BROADCAST; - } -} - -static void lpc_eth_interrupt_handler(void *arg) -{ - lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg; - rtems_event_set re = 0; - rtems_event_set te = 0; - uint32_t ie = 0; - - /* Get interrupt status */ - uint32_t im = lpc_eth->intenable; - uint32_t is = lpc_eth->intstatus & im; - - /* Check receive interrupts */ - if ((is & ETH_INT_RX_OVERRUN) != 0) { - re = LPC_ETH_EVENT_INITIALIZE; - ++e->receive_fatal_errors; - } else if ((is & LPC_ETH_INTERRUPT_RECEIVE) != 0) { - re = LPC_ETH_EVENT_INTERRUPT; - ie |= LPC_ETH_INTERRUPT_RECEIVE; - } - - /* Send events to receive task */ - if (re != 0) { - ++e->receive_interrupts; - (void) rtems_bsdnet_event_send(e->receive_task, re); - } - - /* Check transmit interrupts */ - if ((is & ETH_INT_TX_UNDERRUN) != 0) { - te = LPC_ETH_EVENT_INITIALIZE; - ++e->transmit_fatal_errors; - } else if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) { - te = LPC_ETH_EVENT_INTERRUPT; - ie |= LPC_ETH_INTERRUPT_TRANSMIT; - } - - /* Send events to transmit task */ - if (te != 0) { - ++e->transmit_interrupts; - (void) rtems_bsdnet_event_send(e->transmit_task, te); - } - - LPC_ETH_PRINTK("interrupt: rx = 0x%08x, tx = 0x%08x\n", re, te); - - /* Update interrupt mask */ - lpc_eth->intenable = im & ~ie; - - /* Clear interrupts */ - lpc_eth->intclear = is; -} - -static void lpc_eth_enable_receive_interrupts(void) -{ - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - lpc_eth->intenable |= LPC_ETH_INTERRUPT_RECEIVE; - rtems_interrupt_enable(level); -} - -static void lpc_eth_disable_receive_interrupts(void) -{ - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_RECEIVE; - rtems_interrupt_enable(level); -} - -static void lpc_eth_enable_transmit_interrupts(void) -{ - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - lpc_eth->intenable |= LPC_ETH_INTERRUPT_TRANSMIT; - rtems_interrupt_enable(level); -} - -static void lpc_eth_disable_transmit_interrupts(void) -{ - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_TRANSMIT; - rtems_interrupt_enable(level); -} - -#define LPC_ETH_RX_DATA_OFFSET 2 - -static struct mbuf *lpc_eth_new_mbuf(struct ifnet *ifp, bool wait) -{ - struct mbuf *m = NULL; - int mw = wait ? M_WAIT : M_DONTWAIT; - - MGETHDR(m, mw, MT_DATA); - if (m != NULL) { - MCLGET(m, mw); - if ((m->m_flags & M_EXT) != 0) { - /* Set receive interface */ - m->m_pkthdr.rcvif = ifp; - - /* Adjust by two bytes for proper IP header alignment */ - m->m_data = mtod(m, char *) + LPC_ETH_RX_DATA_OFFSET; - - return m; - } else { - m_free(m); - } - } - - return NULL; -} - -static bool lpc_eth_add_new_mbuf( - struct ifnet *ifp, - volatile lpc_eth_transfer_descriptor *desc, - struct mbuf **mbufs, - uint32_t i, - bool wait -) -{ - /* New mbuf */ - struct mbuf *m = lpc_eth_new_mbuf(ifp, wait); - - /* Check mbuf */ - if (m != NULL) { - /* Cache invalidate */ - rtems_cache_invalidate_multiple_data_lines( - mtod(m, void *), - MCLBYTES - LPC_ETH_RX_DATA_OFFSET - ); - - /* Add mbuf to queue */ - desc [i].start = mtod(m, uint32_t); - desc [i].control = (MCLBYTES - LPC_ETH_RX_DATA_OFFSET - 1) - | ETH_RX_CTRL_INTERRUPT; - - /* Cache flush of descriptor */ - rtems_cache_flush_multiple_data_lines( - (void *) &desc [i], - sizeof(desc [0]) - ); - - /* Add mbuf to table */ - mbufs [i] = m; - - return true; - } else { - return false; - } -} - -static void lpc_eth_receive_task(void *arg) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - rtems_event_set events = 0; - lpc_eth_driver_entry *const e = (lpc_eth_driver_entry *) arg; - struct ifnet *const ifp = &e->arpcom.ac_if; - volatile lpc_eth_transfer_descriptor *const desc = e->rx_desc_table; - volatile lpc_eth_receive_status *const status = e->rx_status_table; - struct mbuf **const mbufs = e->rx_mbuf_table; - uint32_t const index_max = e->rx_unit_count - 1; - uint32_t produce_index = 0; - uint32_t consume_index = 0; - - LPC_ETH_PRINTF("%s\n", __func__); - - /* Main event loop */ - while (true) { - /* Wait for events */ - sc = rtems_bsdnet_event_receive( - LPC_ETH_EVENT_INITIALIZE - | LPC_ETH_EVENT_STOP - | LPC_ETH_EVENT_INTERRUPT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events - ); - assert(sc == RTEMS_SUCCESSFUL); - - LPC_ETH_PRINTF("rx: wake up: 0x%08" PRIx32 "\n", events); - - /* Stop receiver? */ - if ((events & LPC_ETH_EVENT_STOP) != 0) { - lpc_eth_control_request_complete(e); - - /* Wait for events */ - continue; - } - - /* Initialize receiver? */ - if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) { - /* Disable receive interrupts */ - lpc_eth_disable_receive_interrupts(); - - /* Disable receiver */ - lpc_eth->command &= ~ETH_CMD_RX_ENABLE; - - /* Wait for inactive status */ - while ((lpc_eth->status & ETH_STAT_RX_ACTIVE) != 0) { - /* Wait */ - } - - /* Reset */ - lpc_eth->command |= ETH_CMD_RX_RESET; - - /* Clear receive interrupts */ - lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE; - - /* Move existing mbufs to the front */ - consume_index = 0; - for (produce_index = 0; produce_index <= index_max; ++produce_index) { - if (mbufs [produce_index] != NULL) { - mbufs [consume_index] = mbufs [produce_index]; - ++consume_index; - } - } - - /* Fill receive queue */ - for ( - produce_index = consume_index; - produce_index <= index_max; - ++produce_index - ) { - lpc_eth_add_new_mbuf(ifp, desc, mbufs, produce_index, true); - } - - /* Receive descriptor table */ - lpc_eth->rxdescriptornum = index_max; - lpc_eth->rxdescriptor = (uint32_t) desc; - lpc_eth->rxstatus = (uint32_t) status; - - /* Initialize indices */ - produce_index = lpc_eth->rxproduceindex; - consume_index = lpc_eth->rxconsumeindex; - - /* Enable receiver */ - lpc_eth->command |= ETH_CMD_RX_ENABLE; - - /* Enable receive interrupts */ - lpc_eth_enable_receive_interrupts(); - - lpc_eth_control_request_complete(e); - - /* Wait for events */ - continue; - } - - while (true) { - /* Clear receive interrupt status */ - lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE; - - /* Get current produce index */ - produce_index = lpc_eth->rxproduceindex; - - if (consume_index != produce_index) { - uint32_t stat = 0; - - /* Fragment status */ - rtems_cache_invalidate_multiple_data_lines( - (void *) &status [consume_index], - sizeof(status [0]) - ); - stat = status [consume_index].info; - - if ( - (stat & ETH_RX_STAT_LAST_FLAG) != 0 - && (stat & LPC_ETH_RX_STAT_ERRORS) == 0 - ) { - /* Received mbuf */ - struct mbuf *m = mbufs [consume_index]; - - if (lpc_eth_add_new_mbuf(ifp, desc, mbufs, consume_index, false)) { - /* Ethernet header */ - struct ether_header *eh = mtod(m, struct ether_header *); - - /* Discard Ethernet header and CRC */ - int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1 - - ETHER_HDR_LEN - ETHER_CRC_LEN; - - /* Update mbuf */ - m->m_len = sz; - m->m_pkthdr.len = sz; - m->m_data = mtod(m, char *) + ETHER_HDR_LEN; - - LPC_ETH_PRINTF("rx: %02" PRIu32 ": %u\n", consume_index, sz); - - /* Hand over */ - ether_input(ifp, eh, m); - - /* Increment received frames counter */ - ++e->received_frames; - } else { - ++e->receive_drop_errors; - } - } else { - /* Update error counters */ - if ((stat & ETH_RX_STAT_OVERRUN) != 0) { - ++e->receive_overrun_errors; - } - if ((stat & ETH_RX_STAT_LAST_FLAG) == 0) { - ++e->receive_fragment_errors; - } - if ((stat & ETH_RX_STAT_CRC_ERROR) != 0) { - ++e->receive_crc_errors; - } - if ((stat & ETH_RX_STAT_SYMBOL_ERROR) != 0) { - ++e->receive_symbol_errors; - } - if ((stat & ETH_RX_STAT_LENGTH_ERROR) != 0) { - ++e->receive_length_errors; - } - if ((stat & ETH_RX_STAT_ALIGNMENT_ERROR) != 0) { - ++e->receive_alignment_errors; - } - if ((stat & ETH_RX_STAT_NO_DESCRIPTOR) != 0) { - ++e->receive_no_descriptor_errors; - } - } - - /* Increment and update consume index */ - consume_index = lpc_eth_increment(consume_index, index_max); - lpc_eth->rxconsumeindex = consume_index; - } else { - /* Nothing to do, enable receive interrupts */ - lpc_eth_enable_receive_interrupts(); - break; - } - } - } -} - -static struct mbuf *lpc_eth_next_fragment( - struct ifnet *ifp, - struct mbuf *m, - uint32_t *ctrl -) -{ - struct mbuf *n = NULL; - int size = 0; - - while (true) { - if (m == NULL) { - /* Dequeue first fragment of the next frame */ - IF_DEQUEUE(&ifp->if_snd, m); - - /* Empty queue? */ - if (m == NULL) { - return m; - } - } - - /* Get fragment size */ - size = m->m_len; - - if (size > 0) { - /* Now we have a not empty fragment */ - break; - } else { - /* Discard empty fragments */ - m = m_free(m); - } - } - - /* Set fragment size */ - *ctrl = (uint32_t) (size - 1); - - /* Discard empty successive fragments */ - n = m->m_next; - while (n != NULL && n->m_len <= 0) { - n = m_free(n); - } - m->m_next = n; - - /* Is our fragment the last in the frame? */ - if (n == NULL) { - *ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS; - } - - return m; -} - -static void lpc_eth_transmit_task(void *arg) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - rtems_event_set events = 0; - lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg; - struct ifnet *ifp = &e->arpcom.ac_if; - volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table; - volatile uint32_t *const status = e->tx_status_table; - #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - struct mbuf **const mbufs = e->tx_buf_table; - #else - char *const buf = e->tx_buf_table; - #endif - struct mbuf *m = NULL; - uint32_t const index_max = e->tx_unit_count - 1; - uint32_t produce_index = 0; - uint32_t consume_index = 0; - uint32_t ctrl = 0; - #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - uint32_t frame_length = 0; - char *frame_buffer = NULL; - #endif - - LPC_ETH_PRINTF("%s\n", __func__); - - #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - /* Initialize descriptor table */ - for (produce_index = 0; produce_index <= index_max; ++produce_index) { - desc [produce_index].start = - (uint32_t) (buf + produce_index * LPC_ETH_CONFIG_TX_BUF_SIZE); - } - #endif - - /* Main event loop */ - while (true) { - /* Wait for events */ - sc = rtems_bsdnet_event_receive( - LPC_ETH_EVENT_INITIALIZE - | LPC_ETH_EVENT_STOP - | LPC_ETH_EVENT_TXSTART - | LPC_ETH_EVENT_INTERRUPT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events - ); - assert(sc == RTEMS_SUCCESSFUL); - - LPC_ETH_PRINTF("tx: wake up: 0x%08" PRIx32 "\n", events); - - /* Stop transmitter? */ - if ((events & LPC_ETH_EVENT_STOP) != 0) { - lpc_eth_control_request_complete(e); - - /* Wait for events */ - continue; - } - - /* Initialize transmitter? */ - if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) { - /* Disable transmit interrupts */ - lpc_eth_disable_transmit_interrupts(); - - /* Disable transmitter */ - lpc_eth->command &= ~ETH_CMD_TX_ENABLE; - - /* Wait for inactive status */ - while ((lpc_eth->status & ETH_STAT_TX_ACTIVE) != 0) { - /* Wait */ - } - - /* Reset */ - lpc_eth->command |= ETH_CMD_TX_RESET; - - /* Clear transmit interrupts */ - lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT; - - /* Transmit descriptors */ - lpc_eth->txdescriptornum = index_max; - lpc_eth->txdescriptor = (uint32_t) desc; - lpc_eth->txstatus = (uint32_t) status; - - #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - /* Discard outstanding fragments (= data loss) */ - for (produce_index = 0; produce_index <= index_max; ++produce_index) { - struct mbuf *victim = mbufs [produce_index]; - - if (victim != NULL) { - m_free(victim); - mbufs [produce_index] = NULL; - } - } - #endif - - /* Initialize indices */ - produce_index = lpc_eth->txproduceindex; - consume_index = lpc_eth->txconsumeindex; - - #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - /* Fresh frame length and buffer start */ - frame_length = 0; - frame_buffer = (char *) desc [produce_index].start; - #endif - - /* Enable transmitter */ - lpc_eth->command |= ETH_CMD_TX_ENABLE; - - lpc_eth_control_request_complete(e); - } - - /* Free consumed fragments */ - while (true) { - /* Save last known consume index */ - uint32_t c = consume_index; - - /* Clear transmit interrupt status */ - lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT; - - /* Get new consume index */ - consume_index = lpc_eth->txconsumeindex; - - /* Nothing consumed in the meantime? */ - if (c == consume_index) { - break; - } - - while (c != consume_index) { - uint32_t s = status [c]; - - /* Update error counters */ - if ((s & (ETH_TX_STAT_ERROR | ETH_TX_STAT_NO_DESCRIPTOR)) != 0) { - if ((s & ETH_TX_STAT_UNDERRUN) != 0) { - ++e->transmit_underrun_errors; - } - if ((s & ETH_TX_STAT_LATE_COLLISION) != 0) { - ++e->transmit_late_collision_errors; - } - if ((s & ETH_TX_STAT_EXCESSIVE_COLLISION) != 0) { - ++e->transmit_excessive_collision_errors; - } - if ((s & ETH_TX_STAT_EXCESSIVE_DEFER) != 0) { - ++e->transmit_excessive_defer_errors; - } - if ((s & ETH_TX_STAT_NO_DESCRIPTOR) != 0) { - ++e->transmit_no_descriptor_errors; - } - } - - #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - /* Release mbuf */ - m_free(mbufs [c]); - mbufs [c] = NULL; - #endif - - /* Next consume index */ - c = lpc_eth_increment(c, index_max); - } - } - - /* Transmit new fragments */ - while (true) { - /* Compute next produce index */ - uint32_t p = lpc_eth_increment(produce_index, index_max); - - /* Get next fragment and control value */ - m = lpc_eth_next_fragment(ifp, m, &ctrl); - - /* Queue full? */ - if (p == consume_index) { - LPC_ETH_PRINTF("tx: full queue: 0x%08x\n", m); - - /* The queue is full, wait for transmit interrupt */ - break; - } - - /* New fragment? */ - if (m != NULL) { - #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA - /* Set the transfer data */ - rtems_cache_flush_multiple_data_lines( - mtod(m, const void *), - (size_t) m->m_len - ); - desc [produce_index].start = mtod(m, uint32_t); - desc [produce_index].control = ctrl; - rtems_cache_flush_multiple_data_lines( - (void *) &desc [produce_index], - sizeof(desc [0]) - ); - mbufs [produce_index] = m; - - LPC_ETH_PRINTF( - "tx: %02" PRIu32 ": %u %s\n", - produce_index, m->m_len, - (ctrl & ETH_TX_CTRL_LAST) != 0 ? "L" : "" - ); - - /* Next produce index */ - produce_index = p; - - /* Last fragment of a frame? */ - if ((ctrl & ETH_TX_CTRL_LAST) != 0) { - /* Update the produce index */ - lpc_eth->txproduceindex = produce_index; - - /* Increment transmitted frames counter */ - ++e->transmitted_frames; - } - - /* Next fragment of the frame */ - m = m->m_next; - #else - size_t fragment_length = (size_t) m->m_len; - void *fragment_start = mtod(m, void *); - uint32_t new_frame_length = frame_length + fragment_length; - - /* Check buffer size */ - if (new_frame_length > LPC_ETH_CONFIG_TX_BUF_SIZE) { - LPC_ETH_PRINTF("tx: overflow\n"); - - /* Discard overflow data */ - new_frame_length = LPC_ETH_CONFIG_TX_BUF_SIZE; - fragment_length = new_frame_length - frame_length; - - /* Finalize frame */ - ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS; - - /* Update error counter */ - ++e->transmit_overflow_errors; - } - - LPC_ETH_PRINTF( - "tx: copy: %" PRIu32 "%s%s\n", - fragment_length, - (m->m_flags & M_EXT) != 0 ? ", E" : "", - (m->m_flags & M_PKTHDR) != 0 ? ", H" : "" - ); - - /* Copy fragment to buffer in Ethernet RAM */ - memcpy(frame_buffer, fragment_start, fragment_length); - - if ((ctrl & ETH_TX_CTRL_LAST) != 0) { - /* Finalize descriptor */ - desc [produce_index].control = (ctrl & ~ETH_TX_CTRL_SIZE_MASK) - | (new_frame_length - 1); - - LPC_ETH_PRINTF( - "tx: %02" PRIu32 ": %" PRIu32 "\n", - produce_index, - new_frame_length - ); - - /* Cache flush of data */ - rtems_cache_flush_multiple_data_lines( - (const void *) desc [produce_index].start, - new_frame_length - ); - - /* Cache flush of descriptor */ - rtems_cache_flush_multiple_data_lines( - (void *) &desc [produce_index], - sizeof(desc [0]) - ); - - /* Next produce index */ - produce_index = p; - - /* Update the produce index */ - lpc_eth->txproduceindex = produce_index; - - /* Fresh frame length and buffer start */ - frame_length = 0; - frame_buffer = (char *) desc [produce_index].start; - - /* Increment transmitted frames counter */ - ++e->transmitted_frames; - } else { - /* New frame length */ - frame_length = new_frame_length; - - /* Update current frame buffer start */ - frame_buffer += fragment_length; - } - - /* Free mbuf and get next */ - m = m_free(m); - #endif - } else { - /* Nothing to transmit */ - break; - } - } - - /* No more fragments? */ - if (m == NULL) { - /* Interface is now inactive */ - ifp->if_flags &= ~IFF_OACTIVE; - } else { - LPC_ETH_PRINTF("tx: enable interrupts\n"); - - /* Enable transmit interrupts */ - lpc_eth_enable_transmit_interrupts(); - } - } -} - -static int lpc_eth_mdio_wait_for_not_busy(void) -{ - rtems_interval one_second = rtems_clock_get_ticks_per_second(); - rtems_interval i = 0; - - while ((lpc_eth->mind & ETH_MIND_BUSY) != 0 && i < one_second) { - rtems_task_wake_after(1); - ++i; - } - - LPC_ETH_PRINTK("tx: lpc_eth_mdio_wait %s after %d\n", - i != one_second? "succeed": "timeout", i); - - return i != one_second ? 0 : ETIMEDOUT; -} - -static uint32_t lpc_eth_mdio_read_anlpar(int phy) -{ - uint32_t madr = ETH_MADR_REG(MII_ANLPAR) | ETH_MADR_PHY(phy); - uint32_t anlpar = 0; - int eno = 0; - - if (lpc_eth->madr != madr) { - lpc_eth->madr = madr; - } - - if (lpc_eth->mcmd != ETH_MCMD_READ) { - lpc_eth->mcmd = 0; - lpc_eth->mcmd = ETH_MCMD_READ; - } - - eno = lpc_eth_mdio_wait_for_not_busy(); - if (eno == 0) { - anlpar = lpc_eth->mrdd; - } - - /* Start next read */ - lpc_eth->mcmd = 0; - lpc_eth->mcmd = ETH_MCMD_READ; - - return anlpar; -} - -static int lpc_eth_mdio_read( - int phy, - void *arg RTEMS_UNUSED, - unsigned reg, - uint32_t *val -) -{ - int eno = 0; - - if (0 <= phy && phy <= 31) { - lpc_eth->madr = ETH_MADR_REG(reg) | ETH_MADR_PHY(phy); - lpc_eth->mcmd = 0; - lpc_eth->mcmd = ETH_MCMD_READ; - eno = lpc_eth_mdio_wait_for_not_busy(); - - if (eno == 0) { - *val = lpc_eth->mrdd; - } - } else { - eno = EINVAL; - } - - return eno; -} - -static int lpc_eth_mdio_write( - int phy, - void *arg RTEMS_UNUSED, - unsigned reg, - uint32_t val -) -{ - int eno = 0; - - if (0 <= phy && phy <= 31) { - lpc_eth->madr = ETH_MADR_REG(reg) | ETH_MADR_PHY(phy); - lpc_eth->mwtd = val; - eno = lpc_eth_mdio_wait_for_not_busy(); - } else { - eno = EINVAL; - } - - return eno; -} - -static int lpc_eth_phy_get_id(int phy, uint32_t *id) -{ - uint32_t id1 = 0; - int eno = lpc_eth_mdio_read(phy, NULL, MII_PHYIDR1, &id1); - - if (eno == 0) { - uint32_t id2 = 0; - - eno = lpc_eth_mdio_read(phy, NULL, MII_PHYIDR2, &id2); - if (eno == 0) { - *id = (id1 << 16) | (id2 & 0xfff0); - } - } - - return eno; -} - -#define PHY_KSZ80X1RNL 0x221550 -#define PHY_DP83848 0x20005c90 - -typedef struct { - unsigned reg; - uint32_t set; - uint32_t clear; -} lpc_eth_phy_action; - -static int lpc_eth_phy_set_and_clear( - lpc_eth_driver_entry *e, - const lpc_eth_phy_action *actions, - size_t n -) -{ - int eno = 0; - size_t i; - - for (i = 0; eno == 0 && i < n; ++i) { - const lpc_eth_phy_action *action = &actions [i]; - uint32_t val; - - eno = lpc_eth_mdio_read(e->phy, NULL, action->reg, &val); - if (eno == 0) { - val |= action->set; - val &= ~action->clear; - eno = lpc_eth_mdio_write(e->phy, NULL, action->reg, val); - } - } - - return eno; -} - -static const lpc_eth_phy_action lpc_eth_phy_up_action_default [] = { - { MII_BMCR, 0, BMCR_PDOWN }, - { MII_BMCR, BMCR_RESET, 0 }, - { MII_BMCR, BMCR_AUTOEN, 0 } -}; - -static const lpc_eth_phy_action lpc_eth_phy_up_pre_action_KSZ80X1RNL [] = { - /* Disable slow oscillator mode */ - { 0x11, 0, 0x10 } -}; - -static const lpc_eth_phy_action lpc_eth_phy_up_post_action_KSZ80X1RNL [] = { - /* Enable energy detect power down (EDPD) mode */ - { 0x18, 0x0800, 0 }, - /* Turn PLL of automatically in EDPD mode */ - { 0x10, 0x10, 0 } -}; - -static int lpc_eth_phy_up(lpc_eth_driver_entry *e) -{ - int eno; - int retries = 64; - uint32_t val; - - e->phy = DEFAULT_PHY - 1; - while (true) { - e->phy = (e->phy + 1) % 32; - - --retries; - eno = lpc_eth_phy_get_id(e->phy, &e->phy_id); - if ( - (eno == 0 && e->phy_id != 0xfffffff0 && e->phy_id != 0) - || retries <= 0 - ) { - break; - } - - rtems_task_wake_after(1); - } - - LPC_ETH_PRINTF("lpc_eth_phy_get_id: 0x%08" PRIx32 " from phy %d retries %d\n", - e->phy_id, e->phy, retries); - - if (eno == 0) { - switch (e->phy_id) { - case PHY_KSZ80X1RNL: - eno = lpc_eth_phy_set_and_clear( - e, - &lpc_eth_phy_up_pre_action_KSZ80X1RNL [0], - RTEMS_ARRAY_SIZE(lpc_eth_phy_up_pre_action_KSZ80X1RNL) - ); - break; - case PHY_DP83848: - eno = lpc_eth_mdio_read(e->phy, NULL, 0x17, &val); - LPC_ETH_PRINTF("phy PHY_DP83848 RBR 0x%08" PRIx32 "\n", val); - /* val = 0x21; */ - val = 0x32 ; - eno = lpc_eth_mdio_write(e->phy, NULL, 0x17, val); - break; - case 0: - case 0xfffffff0: - eno = EIO; - e->phy = DEFAULT_PHY; - break; - default: - break; - } - - if (eno == 0) { - eno = lpc_eth_phy_set_and_clear( - e, - &lpc_eth_phy_up_action_default [0], - RTEMS_ARRAY_SIZE(lpc_eth_phy_up_action_default) - ); - } - - if (eno == 0) { - switch (e->phy_id) { - case PHY_KSZ80X1RNL: - eno = lpc_eth_phy_set_and_clear( - e, - &lpc_eth_phy_up_post_action_KSZ80X1RNL [0], - RTEMS_ARRAY_SIZE(lpc_eth_phy_up_post_action_KSZ80X1RNL) - ); - break; - default: - break; - } - } - } else { - e->phy_id = 0; - } - - return eno; -} - -static const lpc_eth_phy_action lpc_eth_phy_down_action_default [] = { - { MII_BMCR, BMCR_PDOWN, 0 } -}; - -static const lpc_eth_phy_action lpc_eth_phy_down_post_action_KSZ80X1RNL [] = { - /* Enable slow oscillator mode */ - { 0x11, 0x10, 0 } -}; - -static void lpc_eth_phy_down(lpc_eth_driver_entry *e) -{ - int eno = lpc_eth_phy_set_and_clear( - e, - &lpc_eth_phy_down_action_default [0], - RTEMS_ARRAY_SIZE(lpc_eth_phy_down_action_default) - ); - - if (eno == 0) { - switch (e->phy_id) { - case PHY_KSZ80X1RNL: - eno = lpc_eth_phy_set_and_clear( - e, - &lpc_eth_phy_down_post_action_KSZ80X1RNL [0], - RTEMS_ARRAY_SIZE(lpc_eth_phy_down_post_action_KSZ80X1RNL) - ); - break; - default: - break; - } - } -} - -static void lpc_eth_soft_reset(void) -{ - lpc_eth->command = 0x38; - lpc_eth->mac1 = 0xcf00; - lpc_eth->mac1 = 0x0; -} - -static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up) -{ - int eno = 0; - rtems_status_code sc = RTEMS_SUCCESSFUL; - struct ifnet *ifp = &e->arpcom.ac_if; - - if (up && e->state == LPC_ETH_STATE_DOWN) { - - lpc_eth_config_module_enable(); - - /* Enable RX/TX reset and disable soft reset */ - lpc_eth->mac1 = 0xf00; - - /* Initialize PHY */ - /* Clock value 10 (divide by 44 ) is safe on LPC178x up to 100 MHz AHB clock */ - lpc_eth->mcfg = ETH_MCFG_CLOCK_SELECT(10) | ETH_MCFG_RESETMIIMGMT; - rtems_task_wake_after(1); - lpc_eth->mcfg = ETH_MCFG_CLOCK_SELECT(10); - rtems_task_wake_after(1); - eno = lpc_eth_phy_up(e); - - if (eno == 0) { - /* - * We must have a valid external clock from the PHY at this point, - * otherwise the system bus hangs and only a watchdog reset helps. - */ - lpc_eth_soft_reset(); - - /* Reinitialize registers */ - lpc_eth->mac2 = 0x31; - lpc_eth->ipgt = 0x15; - lpc_eth->ipgr = 0x12; - lpc_eth->clrt = 0x370f; - lpc_eth->maxf = 0x0600; - lpc_eth->supp = ETH_SUPP_SPEED; - lpc_eth->test = 0; - #ifdef LPC_ETH_CONFIG_RMII - lpc_eth->command = 0x0600; - #else - lpc_eth->command = 0x0400; - #endif - lpc_eth->intenable = ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN; - lpc_eth->intclear = 0x30ff; - lpc_eth->powerdown = 0; - - /* MAC address */ - lpc_eth->sa0 = ((uint32_t) e->arpcom.ac_enaddr [5] << 8) - | (uint32_t) e->arpcom.ac_enaddr [4]; - lpc_eth->sa1 = ((uint32_t) e->arpcom.ac_enaddr [3] << 8) - | (uint32_t) e->arpcom.ac_enaddr [2]; - lpc_eth->sa2 = ((uint32_t) e->arpcom.ac_enaddr [1] << 8) - | (uint32_t) e->arpcom.ac_enaddr [0]; - - /* Enable receiver */ - lpc_eth->mac1 = 0x03; - - /* Initialize tasks */ - lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INITIALIZE); - lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_INITIALIZE); - - /* Install interrupt handler */ - sc = rtems_interrupt_handler_install( - e->interrupt_number, - "Ethernet", - RTEMS_INTERRUPT_UNIQUE, - lpc_eth_interrupt_handler, - e - ); - assert(sc == RTEMS_SUCCESSFUL); - - /* Start watchdog timer */ - ifp->if_timer = 1; - - /* Change state */ - e->state = LPC_ETH_STATE_UP; - } - - if (eno != 0) { - ifp->if_flags &= ~IFF_UP; - } - } else if (!up && e->state == LPC_ETH_STATE_UP) { - /* Remove interrupt handler */ - sc = rtems_interrupt_handler_remove( - e->interrupt_number, - lpc_eth_interrupt_handler, - e - ); - assert(sc == RTEMS_SUCCESSFUL); - - /* Stop tasks */ - lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_STOP); - lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_STOP); - - lpc_eth_soft_reset(); - lpc_eth_phy_down(e); - lpc_eth_config_module_disable(); - - /* Stop watchdog timer */ - ifp->if_timer = 0; - - /* Change state */ - e->state = LPC_ETH_STATE_DOWN; - } - - return eno; -} - -static void lpc_eth_interface_init(void *arg) -{ - /* Nothing to do */ -} - -static void lpc_eth_interface_stats(lpc_eth_driver_entry *e) -{ - int eno = EIO; - int media = 0; - - if (e->state == LPC_ETH_STATE_UP) { - media = IFM_MAKEWORD(0, 0, 0, 0); - eno = rtems_mii_ioctl(&e->mdio, e, SIOCGIFMEDIA, &media); - } - - rtems_bsdnet_semaphore_release(); - - if (eno == 0) { - rtems_ifmedia2str(media, NULL, 0); - printf("\n"); - } - - printf("received frames: %u\n", e->received_frames); - printf("receive interrupts: %u\n", e->receive_interrupts); - printf("transmitted frames: %u\n", e->transmitted_frames); - printf("transmit interrupts: %u\n", e->transmit_interrupts); - printf("receive drop errors: %u\n", e->receive_drop_errors); - printf("receive overrun errors: %u\n", e->receive_overrun_errors); - printf("receive fragment errors: %u\n", e->receive_fragment_errors); - printf("receive CRC errors: %u\n", e->receive_crc_errors); - printf("receive symbol errors: %u\n", e->receive_symbol_errors); - printf("receive length errors: %u\n", e->receive_length_errors); - printf("receive alignment errors: %u\n", e->receive_alignment_errors); - printf("receive no descriptor errors: %u\n", e->receive_no_descriptor_errors); - printf("receive fatal errors: %u\n", e->receive_fatal_errors); - printf("transmit underrun errors: %u\n", e->transmit_underrun_errors); - printf("transmit late collision errors: %u\n", e->transmit_late_collision_errors); - printf("transmit excessive collision errors: %u\n", e->transmit_excessive_collision_errors); - printf("transmit excessive defer errors: %u\n", e->transmit_excessive_defer_errors); - printf("transmit no descriptor errors: %u\n", e->transmit_no_descriptor_errors); - printf("transmit overflow errors: %u\n", e->transmit_overflow_errors); - printf("transmit fatal errors: %u\n", e->transmit_fatal_errors); - - rtems_bsdnet_semaphore_obtain(); -} - -static int lpc_eth_multicast_control( - bool add, - struct ifreq *ifr, - struct arpcom *ac -) -{ - int eno = 0; - - if (add) { - eno = ether_addmulti(ifr, ac); - } else { - eno = ether_delmulti(ifr, ac); - } - - if (eno == ENETRESET) { - struct ether_multistep step; - struct ether_multi *enm; - - eno = 0; - - lpc_eth->hashfilterl = 0; - lpc_eth->hashfilterh = 0; - - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - uint64_t addrlo = 0; - uint64_t addrhi = 0; - - memcpy(&addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); - memcpy(&addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); - while (addrlo <= addrhi) { - /* XXX: ether_crc32_le() does not work, why? */ - uint32_t crc = ether_crc32_be((uint8_t *) &addrlo, ETHER_ADDR_LEN); - uint32_t index = (crc >> 23) & 0x3f; - - if (index < 32) { - lpc_eth->hashfilterl |= 1U << index; - } else { - lpc_eth->hashfilterh |= 1U << (index - 32); - } - ++addrlo; - } - ETHER_NEXT_MULTI(step, enm); - } - } - - return eno; -} - -static int lpc_eth_interface_ioctl( - struct ifnet *ifp, - ioctl_command_t cmd, - caddr_t data -) -{ - lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc; - struct ifreq *ifr = (struct ifreq *) data; - int eno = 0; - - LPC_ETH_PRINTF("%s\n", __func__); - - switch (cmd) { - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - rtems_mii_ioctl(&e->mdio, e, cmd, &ifr->ifr_media); - break; - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl(ifp, cmd, data); - break; - case SIOCSIFFLAGS: - eno = lpc_eth_up_or_down(e, (ifp->if_flags & IFF_UP) != 0); - if (eno == 0 && (ifp->if_flags & IFF_UP) != 0) { - lpc_eth_enable_promiscous_mode((ifp->if_flags & IFF_PROMISC) != 0); - } - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - eno = lpc_eth_multicast_control(cmd == SIOCADDMULTI, ifr, &e->arpcom); - break; - case SIO_RTEMS_SHOW_STATS: - lpc_eth_interface_stats(e); - break; - default: - eno = EINVAL; - break; - } - - return eno; -} - -static void lpc_eth_interface_start(struct ifnet *ifp) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc; - - ifp->if_flags |= IFF_OACTIVE; - - if (e->state == LPC_ETH_STATE_UP) { - sc = rtems_bsdnet_event_send(e->transmit_task, LPC_ETH_EVENT_TXSTART); - assert(sc == RTEMS_SUCCESSFUL); - } -} - -static void lpc_eth_interface_watchdog(struct ifnet *ifp) -{ - lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc; - - if (e->state == LPC_ETH_STATE_UP) { - uint32_t anlpar = lpc_eth_mdio_read_anlpar(e->phy); - - if (e->anlpar != anlpar) { - bool full_duplex = false; - bool speed = false; - - e->anlpar = anlpar; - - if ((anlpar & ANLPAR_TX_FD) != 0) { - full_duplex = true; - speed = true; - } else if ((anlpar & ANLPAR_T4) != 0) { - speed = true; - } else if ((anlpar & ANLPAR_TX) != 0) { - speed = true; - } else if ((anlpar & ANLPAR_10_FD) != 0) { - full_duplex = true; - } - - if (full_duplex) { - lpc_eth->mac2 |= ETH_MAC2_FULL_DUPLEX; - } else { - lpc_eth->mac2 &= ~ETH_MAC2_FULL_DUPLEX; - } - - if (speed) { - lpc_eth->supp |= ETH_SUPP_SPEED; - } else { - lpc_eth->supp &= ~ETH_SUPP_SPEED; - } - } - - ifp->if_timer = WATCHDOG_TIMEOUT; - } -} - -static unsigned lpc_eth_fixup_unit_count(int count, int default_value, int max) -{ - if (count <= 0) { - count = default_value; - } else if (count > max) { - count = max; - } - - return LPC_ETH_CONFIG_UNIT_MULTIPLE - + (((unsigned) count - 1U) & ~(LPC_ETH_CONFIG_UNIT_MULTIPLE - 1U)); -} - -static int lpc_eth_attach(struct rtems_bsdnet_ifconfig *config) -{ - lpc_eth_driver_entry *e = &lpc_eth_driver_data; - struct ifnet *ifp = &e->arpcom.ac_if; - char *unit_name = NULL; - int unit_index = rtems_bsdnet_parse_driver_name(config, &unit_name); - size_t table_area_size = 0; - char *table_area = NULL; - char *table_location = NULL; - - /* Check parameter */ - if (unit_index < 0) { - return 0; - } - if (unit_index != 0) { - goto cleanup; - } - if (config->hardware_address == NULL) { - goto cleanup; - } - if (e->state != LPC_ETH_STATE_NOT_INITIALIZED) { - goto cleanup; - } - - /* MDIO */ - e->mdio.mdio_r = lpc_eth_mdio_read; - e->mdio.mdio_w = lpc_eth_mdio_write; - e->mdio.has_gmii = 0; - e->anlpar = 0; - - /* Interrupt number */ - config->irno = LPC_ETH_CONFIG_INTERRUPT; - - /* Device control */ - config->drv_ctrl = e; - - /* Receive unit count */ - e->rx_unit_count = lpc_eth_fixup_unit_count( - config->rbuf_count, - LPC_ETH_CONFIG_RX_UNIT_COUNT_DEFAULT, - LPC_ETH_CONFIG_RX_UNIT_COUNT_MAX - ); - config->rbuf_count = (int) e->rx_unit_count; - - /* Transmit unit count */ - e->tx_unit_count = lpc_eth_fixup_unit_count( - config->xbuf_count, - LPC_ETH_CONFIG_TX_UNIT_COUNT_DEFAULT, - LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX - ); - config->xbuf_count = (int) e->tx_unit_count; - - /* Remember interrupt number */ - e->interrupt_number = config->irno; - - /* Copy MAC address */ - memcpy(e->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - - /* Allocate and clear table area */ - table_area_size = - e->rx_unit_count - * (sizeof(lpc_eth_transfer_descriptor) - + sizeof(lpc_eth_receive_status) - + sizeof(struct mbuf *)) - + e->tx_unit_count - * (sizeof(lpc_eth_transfer_descriptor) - + sizeof(uint32_t) - + LPC_ETH_CONFIG_TX_BUF_SIZE); - table_area = lpc_eth_config_alloc_table_area(table_area_size); - if (table_area == NULL) { - goto cleanup; - } - memset(table_area, 0, table_area_size); - - table_location = table_area; - - /* - * The receive status table must be the first one since it has the strictest - * alignment requirements. - */ - e->rx_status_table = (volatile lpc_eth_receive_status *) table_location; - table_location += e->rx_unit_count * sizeof(e->rx_status_table [0]); - - e->rx_desc_table = (volatile lpc_eth_transfer_descriptor *) table_location; - table_location += e->rx_unit_count * sizeof(e->rx_desc_table [0]); - - e->rx_mbuf_table = (struct mbuf **) table_location; - table_location += e->rx_unit_count * sizeof(e->rx_mbuf_table [0]); - - e->tx_desc_table = (volatile lpc_eth_transfer_descriptor *) table_location; - table_location += e->tx_unit_count * sizeof(e->tx_desc_table [0]); - - e->tx_status_table = (volatile uint32_t *) table_location; - table_location += e->tx_unit_count * sizeof(e->tx_status_table [0]); - - e->tx_buf_table = table_location; - - /* Set interface data */ - ifp->if_softc = e; - ifp->if_unit = (short) unit_index; - ifp->if_name = unit_name; - ifp->if_mtu = (config->mtu > 0) ? (u_long) config->mtu : ETHERMTU; - ifp->if_init = lpc_eth_interface_init; - ifp->if_ioctl = lpc_eth_interface_ioctl; - ifp->if_start = lpc_eth_interface_start; - ifp->if_output = ether_output; - ifp->if_watchdog = lpc_eth_interface_watchdog; - ifp->if_flags = IFF_MULTICAST | IFF_BROADCAST | IFF_SIMPLEX; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_timer = 0; - - /* Create tasks */ - e->receive_task = rtems_bsdnet_newproc( - "ntrx", - 4096, - lpc_eth_receive_task, - e - ); - e->transmit_task = rtems_bsdnet_newproc( - "nttx", - 4096, - lpc_eth_transmit_task, - e - ); - - /* Change status */ - ifp->if_flags |= IFF_RUNNING; - e->state = LPC_ETH_STATE_DOWN; - - /* Attach the interface */ - if_attach(ifp); - ether_ifattach(ifp); - - return 1; - -cleanup: - - lpc_eth_config_free_table_area(table_area); - - /* FIXME: Type */ - free(unit_name, (int) 0xdeadbeef); - - return 0; -} - -static int lpc_eth_detach( - struct rtems_bsdnet_ifconfig *config RTEMS_UNUSED -) -{ - /* FIXME: Detach the interface from the upper layers? */ - - /* Module soft reset */ - lpc_eth->command = 0x38; - lpc_eth->mac1 = 0xcf00; - - /* FIXME: More cleanup */ - - return 0; -} - -int lpc_eth_attach_detach( - struct rtems_bsdnet_ifconfig *config, - int attaching -) -{ - /* FIXME: Return value */ - - if (attaching) { - return lpc_eth_attach(config); - } else { - return lpc_eth_detach(config); - } -} |