summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/mips/csb350
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-23 09:53:31 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-23 15:18:44 +0200
commit031df3914990db0336a0d386fb53558b05de467e (patch)
tree4661e22f0cdb3f9d06879f0194b77c75f62bac79 /c/src/lib/libbsp/mips/csb350
parentbsps: Move interrupt controller support to bsps (diff)
downloadrtems-031df3914990db0336a0d386fb53558b05de467e.tar.bz2
bsps: Move legacy network drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'c/src/lib/libbsp/mips/csb350')
-rw-r--r--c/src/lib/libbsp/mips/csb350/Makefile.am2
-rw-r--r--c/src/lib/libbsp/mips/csb350/network/network.c909
2 files changed, 1 insertions, 910 deletions
diff --git a/c/src/lib/libbsp/mips/csb350/Makefile.am b/c/src/lib/libbsp/mips/csb350/Makefile.am
index cda24059e0..a42d884468 100644
--- a/c/src/lib/libbsp/mips/csb350/Makefile.am
+++ b/c/src/lib/libbsp/mips/csb350/Makefile.am
@@ -39,7 +39,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/csb350/irq/vectorisrs.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/interruptmask.c
if HAS_NETWORKING
-librtemsbsp_a_SOURCES += network/network.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/csb350/net/network.c
endif
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c
diff --git a/c/src/lib/libbsp/mips/csb350/network/network.c b/c/src/lib/libbsp/mips/csb350/network/network.c
deleted file mode 100644
index 15a1c320df..0000000000
--- a/c/src/lib/libbsp/mips/csb350/network/network.c
+++ /dev/null
@@ -1,909 +0,0 @@
-/**
- * @file
- *
- * Au1x00 ethernet driver
- */
-
-/*
- * Copyright (c) 2005 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.
- */
-
-#define __INSIDE_RTEMS_BSD_TCPIP_STACK__
-
-#include <rtems.h>
-#include <rtems/rtems_bsdnet.h>
-#include <bsp.h>
-#include <rtems/bspIo.h>
-#include <libcpu/au1x00.h>
-#include <bsp/irq.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include <errno.h>
-#include <rtems/error.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 <assert.h>
-
-#define NUM_IFACES 1
-#define NUM_TX_DMA_BUFS 4
-#define NUM_RX_DMA_BUFS 4
-
-/* RTEMS event used to start tx daemon. */
-#define START_TX_EVENT RTEMS_EVENT_1
-/* RTEMS event used to start rx daemon. */
-#define START_RX_EVENT RTEMS_EVENT_2
-
-rtems_isr au1x00_emac_isr(rtems_vector_number vector);
-
-#define TX_BUF_SIZE 2048
-
-char tx_buf_base[(4 * TX_BUF_SIZE) + 32];
-
-volatile int wait_count;
-/*
- * 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;
-
- /*
- * Tasks waiting for interrupts
- */
- rtems_id rx_daemon_tid;
- rtems_id tx_daemon_tid;
-
- /*
- * Buffers
- */
- au1x00_macdma_rx_t *rx_dma;
- au1x00_macdma_tx_t *tx_dma;
- int rx_head;
- int rx_tail;
- int tx_head;
- int tx_tail;
- struct mbuf *rx_mbuf[NUM_RX_DMA_BUFS];
-
- unsigned char *tx_buf[4];
-
- /*
- * register addresses
- */
- uint32_t ctrl_regs;
- uint32_t *en_reg;
- uint32_t int_mask;
- uint32_t int_ctrlr;
-
- /*
- * device
- */
- int unitnumber;
-
- /*
- * Statistics
- */
- unsigned long interrupts;
- unsigned long rx_interrupts;
- unsigned long tx_interrupts;
- unsigned long rx_missed;
- unsigned long rx_bcast;
- unsigned long rx_mcast;
- unsigned long rx_unsupp;
- unsigned long rx_ctrl;
- unsigned long rx_len_err;
- unsigned long rx_crc_err;
- unsigned long rx_dribble;
- unsigned long rx_mii_err;
- unsigned long rx_collision;
- unsigned long rx_too_long;
- unsigned long rx_runt;
- unsigned long rx_watchdog;
- unsigned long rx_pkts;
- unsigned long rx_dropped;
-
- unsigned long tx_deferred;
- unsigned long tx_underrun;
- unsigned long tx_aborted;
- unsigned long tx_pkts;
-} au1x00_emac_softc_t;
-
-static au1x00_emac_softc_t softc[NUM_IFACES];
-
-
-/* function prototypes */
-int rtems_au1x00_emac_attach (struct rtems_bsdnet_ifconfig *config,
- int attaching);
-void au1x00_emac_init(void *arg);
-void au1x00_emac_init_hw(au1x00_emac_softc_t *sc);
-void au1x00_emac_start(struct ifnet *ifp);
-void au1x00_emac_stop (au1x00_emac_softc_t *sc);
-void au1x00_emac_tx_daemon (void *arg);
-void au1x00_emac_rx_daemon (void *arg);
-void au1x00_emac_sendpacket (struct ifnet *ifp, struct mbuf *m);
-void au1x00_emac_stats (au1x00_emac_softc_t *sc);
-static int au1x00_emac_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data);
-static void mii_write(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t val);
-static void mii_read(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t *val);
-static void mii_init(au1x00_emac_softc_t *sc);
-
-static void mii_write(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t val)
-{
- /* wait for the interface to get unbusy */
- while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
- continue;
- }
-
- /* write to address 0 - we only support address 0 */
- AU1X00_MAC_MIIDATA(sc->ctrl_regs) = val;
- AU1X00_MAC_MIICTRL(sc->ctrl_regs) = (((reg & 0x1f) << 6) |
- AU1X00_MAC_MIICTRL_MW);
- au_sync();
-
- /* wait for it to complete */
- while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
- continue;
- }
-}
-
-static void mii_read(au1x00_emac_softc_t *sc, uint8_t reg, uint16_t *val)
-{
- /* wait for the interface to get unbusy */
- while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
- continue;
- }
-
- /* write to address 0 - we only support address 0 */
- AU1X00_MAC_MIICTRL(sc->ctrl_regs) = ((reg & 0x1f) << 6);
- au_sync();
-
- /* wait for it to complete */
- while (AU1X00_MAC_MIICTRL(sc->ctrl_regs) & AU1X00_MAC_MIICTRL_MB) {
- continue;
- }
- *val = AU1X00_MAC_MIIDATA(sc->ctrl_regs);
-}
-
-static void mii_init(au1x00_emac_softc_t *sc)
-{
- uint16_t data;
-
- mii_write(sc, 0, 0x8000); /* reset */
- do {
- mii_read(sc, 0, &data);
- } while (data & 0x8000);
-
- mii_write(sc, 0, 0x3200); /* reset autonegotiation */
- mii_write(sc, 17, 0xffc0); /* setup LEDs */
-
-}
-
-
-
-int rtems_au1x00_emac_attach (
- struct rtems_bsdnet_ifconfig *config,
- int attaching
- )
-{
- struct ifnet *ifp;
- int mtu;
- int unitnumber;
- char *unitname;
- static au1x00_emac_softc_t *sc;
-
- /*
- * Parse driver name
- */
- if ((unitnumber = rtems_bsdnet_parse_driver_name (config, &unitname)) < 0)
- return 0;
-
- /*
- * Is driver free?
- */
- if (unitnumber > NUM_IFACES) {
- printf ("Bad AU1X00 EMAC unit number.\n");
- return 0;
- }
-
- sc = &softc[unitnumber];
-
- ifp = &sc->arpcom.ac_if;
- if (ifp->if_softc != NULL) {
- printf ("Driver already in use.\n");
- return 0;
- }
-
- /*
- * zero out the control structure
- */
-
- memset((void *)sc, 0, sizeof(*sc));
-
- sc->unitnumber = unitnumber;
- sc->int_ctrlr = AU1X00_IC0_ADDR;
-
- if (unitnumber == 0) {
- sc->ctrl_regs = AU1100_MAC0_ADDR;
- sc->en_reg = (void *)(AU1100_MACEN_ADDR + 0);
-
- sc->tx_dma = (void *)(AU1X00_MACDMA0_ADDR + 0x000);
- sc->rx_dma = (void *)(AU1X00_MACDMA0_ADDR + 0x100);
- sc->int_mask = AU1X00_IC_IRQ_MAC0;
- } else {
- printk("Unknown network device: %d\n", unitnumber);
- return 0;
- }
-
- /* If the ethernet controller is already set up, read the MAC address */
- if ((*sc->en_reg & 0x33) == 0x33) {
- sc->arpcom.ac_enaddr[5] = ((AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 8) &
- 0xff);
- sc->arpcom.ac_enaddr[4] = ((AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 0) &
- 0xff);
- sc->arpcom.ac_enaddr[3] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 24) &
- 0xff);
- sc->arpcom.ac_enaddr[2] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 16) &
- 0xff);
- sc->arpcom.ac_enaddr[1] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 8) &
- 0xff);
- sc->arpcom.ac_enaddr[0] = ((AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 0) &
- 0xff);
- } else {
- /* It's not set up yet, so we set a MAC address */
- sc->arpcom.ac_enaddr[5] = 0x05;
- sc->arpcom.ac_enaddr[4] = 0xc0;
- sc->arpcom.ac_enaddr[3] = 0x50;
- sc->arpcom.ac_enaddr[2] = 0x31;
- sc->arpcom.ac_enaddr[1] = 0x23;
- sc->arpcom.ac_enaddr[0] = 0x00;
- }
-
-
- if (config->mtu) {
- mtu = config->mtu;
- } else {
- mtu = ETHERMTU;
- }
-
- sc->acceptBroadcast = !config->ignore_broadcast;
-
- /*
- * Set up network interface values
- */
- ifp->if_softc = sc;
- ifp->if_unit = unitnumber;
- ifp->if_name = unitname;
- ifp->if_mtu = mtu;
- ifp->if_init = au1x00_emac_init;
- ifp->if_ioctl = au1x00_emac_ioctl;
- ifp->if_start = au1x00_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;
- }
-
- /*
- * Attach the interface
- */
- if_attach (ifp);
- ether_ifattach (ifp);
- return 1;
-}
-
-void au1x00_emac_init(void *arg)
-{
- au1x00_emac_softc_t *sc = arg;
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- /*
- *This is for stuff that only gets done once (au1x00_emac_init()
- * gets called multiple times
- */
- if (sc->tx_daemon_tid == 0)
- {
- /* Set up EMAC hardware */
- au1x00_emac_init_hw(sc);
-
-
- /* install the interrupt handler */
- if (sc->unitnumber == 0) {
- rtems_interrupt_handler_install(
- AU1X00_IRQ_MAC0,
- "NIC0",
- 0,
- (rtems_interrupt_handler)au1x00_emac_isr,
- NULL
- );
- } else {
- rtems_interrupt_handler_install(
- AU1X00_IRQ_MAC1,
- "NIC1",
- 0,
- (rtems_interrupt_handler)au1x00_emac_isr,
- NULL
- );
- }
- AU1X00_IC_MASKCLR(sc->int_ctrlr) = sc->int_mask;
- au_sync();
-
- /* set src bit */
- AU1X00_IC_SRCSET(sc->int_ctrlr) = sc->int_mask;
-
- /* high level */
- AU1X00_IC_CFG0SET(sc->int_ctrlr) = sc->int_mask;
- AU1X00_IC_CFG1CLR(sc->int_ctrlr) = sc->int_mask;
- AU1X00_IC_CFG2SET(sc->int_ctrlr) = sc->int_mask;
-
- /* assign to request 0 - negative logic */
- AU1X00_IC_ASSIGNSET(sc->int_ctrlr) = sc->int_mask;
- au_sync();
-
- /* Start driver tasks */
- sc->tx_daemon_tid = rtems_bsdnet_newproc("ENTx",
- 4096,
- au1x00_emac_tx_daemon,
- sc);
-
- sc->rx_daemon_tid = rtems_bsdnet_newproc("ENRx",
- 4096,
- au1x00_emac_rx_daemon,
- sc);
-
-
- }
- /* EMAC doesn't support promiscuous, so ignore requests */
- if (ifp->if_flags & IFF_PROMISC)
- printf ("Warning - AU1X00 EMAC doesn't support Promiscuous Mode!\n");
-
- /*
- * Tell the world that we're running.
- */
- ifp->if_flags |= IFF_RUNNING;
-
- /*
- * start tx, rx
- */
- AU1X00_MAC_CONTROL(sc->ctrl_regs) |= (AU1X00_MAC_CTRL_TE |
- AU1X00_MAC_CTRL_RE);
- au_sync();
-
-
-} /* au1x00_emac_init() */
-
-void au1x00_emac_init_hw(au1x00_emac_softc_t *sc)
-{
- int i;
- struct mbuf *m;
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- /* reset the MAC */
- *sc->en_reg = 0x40;
- au_sync();
- for (i = 0; i < 10000; i++) {
- continue;
- }
-
-/* *sc->en_reg = AU1X00_MAC_EN_CE; */
- *sc->en_reg = 41;
- au_sync();
- for (i = 0; i < 10000; i++) {
- continue;
- }
-
-/*
- *sc->en_reg = (AU1X00_MAC_EN_CE |
- AU1X00_MAC_EN_E2 |
- AU1X00_MAC_EN_E1 |
- AU1X00_MAC_EN_E0);
-*/
- *sc->en_reg = 0x33;
- au_sync();
- mii_init(sc);
-
- /* set the mac address */
- AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) = ((sc->arpcom.ac_enaddr[5] << 8) |
- (sc->arpcom.ac_enaddr[4] << 0));
- AU1X00_MAC_ADDRLOW(sc->ctrl_regs) = ((sc->arpcom.ac_enaddr[3] << 24) |
- (sc->arpcom.ac_enaddr[2] << 16) |
- (sc->arpcom.ac_enaddr[1] << 8) |
- (sc->arpcom.ac_enaddr[0] << 0));
-
-
- /* get the MAC address from the chip */
- sc->arpcom.ac_enaddr[5] = (AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 8) & 0xff;
- sc->arpcom.ac_enaddr[4] = (AU1X00_MAC_ADDRHIGH(sc->ctrl_regs) >> 0) & 0xff;
- sc->arpcom.ac_enaddr[3] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 24) & 0xff;
- sc->arpcom.ac_enaddr[2] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 16) & 0xff;
- sc->arpcom.ac_enaddr[1] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 8) & 0xff;
- sc->arpcom.ac_enaddr[0] = (AU1X00_MAC_ADDRLOW(sc->ctrl_regs) >> 0) & 0xff;
-
- printk("Setting mac_control to 0x%x\n",
- (AU1X00_MAC_CTRL_F |
- AU1X00_MAC_CTRL_PM |
- AU1X00_MAC_CTRL_RA |
- AU1X00_MAC_CTRL_DO |
- AU1X00_MAC_CTRL_EM));
-
- AU1X00_MAC_CONTROL(sc->ctrl_regs) = (AU1X00_MAC_CTRL_F | /* full duplex */
- AU1X00_MAC_CTRL_PM | /* pass mcast */
- AU1X00_MAC_CTRL_RA | /* recv all */
- AU1X00_MAC_CTRL_DO | /* disable own */
- AU1X00_MAC_CTRL_EM); /* Big endian */
- au_sync();
- printk("mac_control was set to 0x%x\n", AU1X00_MAC_CONTROL(sc->ctrl_regs));
- printk("mac_control addr is 0x%x\n", &AU1X00_MAC_CONTROL(sc->ctrl_regs));
-
- /* initialize our receive buffer descriptors */
- for (i = 0; i < NUM_RX_DMA_BUFS; i++) {
- MGETHDR(m, M_WAIT, MT_DATA);
- MCLGET(m, M_WAIT);
-
- m->m_pkthdr.rcvif = ifp;
- m->m_nextpkt = 0;
-
- /*
- * The receive buffer must be aligned with a cache line
- * boundary.
- */
- if (mtod(m, uint32_t) & 0x1f) {
- uint32_t *p = mtod(m, uint32_t *);
- *p = (mtod(m, uint32_t) + 0x1f) & 0x1f;
- }
- sc->rx_dma[i].addr = (mtod(m, uint32_t) & ~0xe0000000);
- sc->rx_mbuf[i] = m;
- }
-
- /* Initialize transmit buffer descriptors */
- for (i = 0; i < NUM_TX_DMA_BUFS; i++) {
- sc->tx_dma[i].addr = 0;
- }
-
- /* initialize the transmit buffers */
- sc->tx_buf[0] = (void *)((((int)&tx_buf_base[0]) + 0x1f) & ~0x1f);
- sc->tx_buf[1] = (void *)(((int)sc->tx_buf[0]) + TX_BUF_SIZE);
- sc->tx_buf[2] = (void *)(((int)sc->tx_buf[1]) + TX_BUF_SIZE);
- sc->tx_buf[3] = (void *)(((int)sc->tx_buf[2]) + TX_BUF_SIZE);
-
- sc->rx_head = (sc->rx_dma[0].addr >> 2) & 0x3;
- sc->rx_tail = (sc->rx_dma[0].addr >> 2) & 0x3;
- sc->tx_head = (sc->tx_dma[0].addr >> 2) & 0x3;
- sc->tx_tail = (sc->tx_dma[0].addr >> 2) & 0x3;
-
- for (i = 0; i < NUM_RX_DMA_BUFS; i++) {
- sc->rx_dma[i].addr |= AU1X00_MAC_DMA_RXADDR_EN;
- }
-
-} /* au1x00_emac_init_hw() */
-
-void au1x00_emac_start(struct ifnet *ifp)
-{
- au1x00_emac_softc_t *sc = ifp->if_softc;
-
- rtems_bsdnet_event_send(sc->tx_daemon_tid, START_TX_EVENT);
- ifp->if_flags |= IFF_OACTIVE;
-}
-
-void au1x00_emac_stop (au1x00_emac_softc_t *sc)
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- ifp->if_flags &= ~IFF_RUNNING;
-
- /*
- * Stop the transmitter and receiver.
- */
-
- /* Disable TX/RX */
- AU1X00_MAC_CONTROL(sc->ctrl_regs) &= ~(AU1X00_MAC_CTRL_TE |
- AU1X00_MAC_CTRL_RE);
- au_sync();
-}
-
-/*
- * Driver tx daemon
- */
-void au1x00_emac_tx_daemon (void *arg)
-{
- au1x00_emac_softc_t *sc = (au1x00_emac_softc_t *)arg;
- struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mbuf *m;
- rtems_event_set events;
- uint32_t ic_base; /* interrupt controller */
-
- ic_base = AU1X00_IC0_ADDR;
-
- /* turn on interrupt, then wait for one */
- if (sc->unitnumber == 0) {
- AU1X00_IC_MASKSET(ic_base) = AU1X00_IC_IRQ_MAC0;
- } else {
- AU1X00_IC_MASKSET(ic_base) = AU1X00_IC_IRQ_MAC1;
- }
- au_sync();
-
- for (;;)
- {
- rtems_bsdnet_event_receive(
- START_TX_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;
-
- sc->tx_pkts++;
- au1x00_emac_sendpacket (ifp, m);
- }
- ifp->if_flags &= ~IFF_OACTIVE;
- }
-}
-
-/*
- * Driver rx daemon
- */
-void au1x00_emac_rx_daemon (void *arg)
-{
- au1x00_emac_softc_t *sc = (au1x00_emac_softc_t *)arg;
- struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mbuf *m;
- struct ether_header *eh;
- rtems_event_set events;
- uint32_t status;
-
- while (1) {
- rtems_bsdnet_event_receive(
- START_RX_EVENT,
- RTEMS_EVENT_ANY | RTEMS_WAIT,
- RTEMS_NO_TIMEOUT,
- &events);
-
- /* while there are packets to receive */
-
- while (!(sc->rx_dma[sc->rx_head].addr & (AU1X00_MAC_DMA_RXADDR_DN |
- AU1X00_MAC_DMA_RXADDR_EN))) {
- status = sc->rx_dma[sc->rx_head].stat;
- if (status & AU1X00_MAC_DMA_RXSTAT_MI) {
- sc->rx_missed++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_BF) {
- sc->rx_bcast++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_MF) {
- sc->rx_mcast++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_UC) {
- sc->rx_unsupp++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_CF) {
- sc->rx_ctrl++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_LE) {
- sc->rx_len_err++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_CR) {
- sc->rx_crc_err++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_DB) {
- sc->rx_dribble++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_ME) {
- sc->rx_mii_err++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_CS) {
- sc->rx_collision++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_FL) {
- sc->rx_too_long++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_RF) {
- sc->rx_runt++;
- }
- if (status & AU1X00_MAC_DMA_RXSTAT_WT) {
- sc->rx_watchdog++;
- }
-
- /* If no errrors, accept packet */
- if ((status & (AU1X00_MAC_DMA_RXSTAT_CR |
- AU1X00_MAC_DMA_RXSTAT_DB |
- AU1X00_MAC_DMA_RXSTAT_RF)) == 0) {
-
- sc->rx_pkts++;
-
- /* find the start of the mbuf */
- m = sc->rx_mbuf[sc->rx_head];
-
- /* set the length of the mbuf */
- m->m_len = AU1X00_MAC_DMA_RXSTAT_LEN(sc->rx_dma[sc->rx_head].stat);
- m->m_len -= 4; /* remove ethernet CRC */
-
- 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);
-
- /* give the received packet to the stack */
- ether_input(ifp, eh, m);
- /* get a new buf and make it ready for the MAC */
- MGETHDR(m, M_WAIT, MT_DATA);
- MCLGET(m, M_WAIT);
-
- m->m_pkthdr.rcvif = ifp;
- m->m_nextpkt = 0;
-
- /*
- * The receive buffer must be aligned with a cache line
- * boundary.
- */
- {
- uint32_t *p = mtod(m, uint32_t *);
- *p = (mtod(m, uint32_t) + 0x1f) & ~0x1f;
- }
-
- } else {
- sc->rx_dropped++;
-
- /* find the mbuf so we can reuse it*/
- m = sc->rx_mbuf[sc->rx_head];
- }
-
- /* set up the receive dma to use the mbuf's cluster */
- sc->rx_dma[sc->rx_head].addr = (mtod(m, uint32_t) & ~0xe0000000);
- au_sync();
- sc->rx_mbuf[sc->rx_head] = m;
-
- sc->rx_dma[sc->rx_head].addr |= AU1X00_MAC_DMA_RXADDR_EN;
- au_sync();
-
-
- /* increment the buffer index */
- sc->rx_head++;
- if (sc->rx_head >= NUM_RX_DMA_BUFS) {
- sc->rx_head = 0;
- }
- }
- }
-}
-
-/* Send packet */
-void au1x00_emac_sendpacket (struct ifnet *ifp, struct mbuf *m)
-{
- struct mbuf *l = NULL;
- unsigned int pkt_offset = 0;
- au1x00_emac_softc_t *sc = (au1x00_emac_softc_t *)ifp->if_softc;
- uint32_t txbuf;
-
- /* Wait for EMAC Transmit Queue to become available. */
- while((sc->tx_dma[sc->tx_head].addr & (AU1X00_MAC_DMA_TXADDR_EN ||
- AU1X00_MAC_DMA_TXADDR_DN)) != 0) {
- continue;
- }
-
- /* copy the mbuf chain into the transmit buffer */
- l = m;
-
- txbuf = (uint32_t)sc->tx_buf[sc->tx_head];
- 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 */
- }
-
- /* Pad if necessary */
- if (pkt_offset < 60) {
- memset((char *)(txbuf + pkt_offset), 0, (60 - pkt_offset));
- pkt_offset = 60;
- }
-
- /* send it off */
- sc->tx_dma[sc->tx_head].stat = 0;
- sc->tx_dma[sc->tx_head].len = pkt_offset;
- sc->tx_dma[sc->tx_head].addr = ((txbuf & ~0xe0000000) |
- AU1X00_MAC_DMA_TXADDR_EN);
- au_sync();
-
-
- /*
- *Without this delay, some outgoing packets never
- * make it out the device. Nothing in the documentation
- * explains this.
- */
- for (wait_count = 0; wait_count < 5000; wait_count++){
- continue;
- }
-
- /* free the mbuf chain we just copied */
- m_freem(m);
-
- sc->tx_head++;
- if (sc->tx_head >= NUM_TX_DMA_BUFS) {
- sc->tx_head = 0;
- }
-
-} /* au1x00_emac_sendpacket () */
-
-
-
-/* Show interface statistics */
-void au1x00_emac_stats (au1x00_emac_softc_t *sc)
-{
- printf("Interrupts:%-8lu", sc->interrupts);
- printf(" RX Interrupts:%-8lu", sc->rx_interrupts);
- printf(" TX Interrupts:%-8lu\n", sc->tx_interrupts);
- printf("RX Packets:%-8lu", sc->rx_pkts);
- printf(" RX Control:%-8lu", sc->rx_ctrl);
- printf(" RX broadcast:%-8lu\n", sc->rx_bcast);
- printf("RX Mcast:%-8lu", sc->rx_mcast);
- printf(" RX missed:%-8lu", sc->rx_missed);
- printf(" RX Unsupported ctrl:%-8lu\n", sc->rx_unsupp);
- printf("RX Len err:%-8lu", sc->rx_len_err);
- printf(" RX CRC err:%-8lu", sc->rx_crc_err);
- printf(" RX dribble:%-8lu\n", sc->rx_dribble);
- printf("RX MII err:%-8lu", sc->rx_mii_err);
- printf(" RX collision:%-8lu", sc->rx_collision);
- printf(" RX too long:%-8lu\n", sc->rx_too_long);
- printf("RX runt:%-8lu", sc->rx_runt);
- printf(" RX watchdog:%-8lu", sc->rx_watchdog);
- printf(" RX dropped:%-8lu\n", sc->rx_dropped);
-
- printf("TX Packets:%-8lu", sc->tx_pkts);
- printf(" TX Deferred:%-8lu", sc->tx_deferred);
- printf(" TX Underrun:%-8lu\n", sc->tx_underrun);
- printf("TX Aborted:%-8lu\n", sc->tx_aborted);
-
-}
-
-
-/* Driver ioctl handler */
-static int
-au1x00_emac_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
-{
- au1x00_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:
- au1x00_emac_stop (sc);
- break;
-
- case IFF_UP:
- au1x00_emac_init (sc);
- break;
-
- case IFF_UP | IFF_RUNNING:
- au1x00_emac_stop (sc);
- au1x00_emac_init (sc);
- break;
-
- default:
- break;
- } /* switch (if_flags) */
- break;
-
- case SIO_RTEMS_SHOW_STATS:
- au1x00_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 */
-rtems_isr au1x00_emac_isr (rtems_vector_number v)
-{
- volatile au1x00_emac_softc_t *sc;
- int tx_flag = 0;
- int rx_flag = 0;
-
- sc = &softc[0];
- if (v != AU1X00_IRQ_MAC0) {
- assert(v == AU1X00_IRQ_MAC0);
- }
-
- sc->interrupts++;
-
- /*
- * Since there's no easy way to find out the source of the
- * interrupt, we have to look at the tx and rx dma buffers
- */
- /* receive interrupt */
- while(sc->rx_dma[sc->rx_tail].addr & AU1X00_MAC_DMA_RXADDR_DN) {
- rx_flag = 1;
- sc->rx_interrupts++;
- sc->rx_dma[sc->rx_tail].addr &= ~AU1X00_MAC_DMA_RXADDR_DN;
- au_sync();
-
- sc->rx_tail++;
- if (sc->rx_tail >= NUM_RX_DMA_BUFS) {
- sc->rx_tail = 0;
- }
- }
- if (rx_flag != 0) {
- rtems_bsdnet_event_send(sc->rx_daemon_tid, START_RX_EVENT);
- }
-
- /* transmit interrupt */
- while (sc->tx_dma[sc->tx_tail].addr & AU1X00_MAC_DMA_TXADDR_DN) {
- uint32_t status;
- tx_flag = 1;
- sc->tx_interrupts++;
-
- status = sc->tx_dma[sc->tx_tail].stat;
- if (status & AU1X00_MAC_DMA_TXSTAT_DF) {
- sc->tx_deferred++;
- }
- if (status & AU1X00_MAC_DMA_TXSTAT_UR) {
- sc->tx_underrun++;
- }
- if (status & AU1X00_MAC_DMA_TXSTAT_FA) {
- sc->tx_aborted++;
- }
-
- sc->tx_dma[sc->tx_tail].addr = 0;
- au_sync();
-
- sc->tx_tail++;
- if (sc->tx_tail >= NUM_TX_DMA_BUFS) {
- sc->tx_tail = 0;
- }
- }
- if (tx_flag != 0) {
- rtems_bsdnet_event_send(sc->tx_daemon_tid, START_TX_EVENT);
- }
-}
-