From 031df3914990db0336a0d386fb53558b05de467e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Apr 2018 09:53:31 +0200 Subject: bsps: Move legacy network drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/mips/csb350/Makefile.am | 2 +- c/src/lib/libbsp/mips/csb350/network/network.c | 909 ------------------------- 2 files changed, 1 insertion(+), 910 deletions(-) delete mode 100644 c/src/lib/libbsp/mips/csb350/network/network.c (limited to 'c/src/lib/libbsp/mips') 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 - * - * 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 -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#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); - } -} - -- cgit v1.2.3