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/m68k/av5282/Makefile.am | 2 +- c/src/lib/libbsp/m68k/av5282/network/network.c | 940 ------ c/src/lib/libbsp/m68k/csb360/network/network.c | 984 ------- c/src/lib/libbsp/m68k/gen68360/Makefile.am | 2 +- c/src/lib/libbsp/m68k/gen68360/network/network.c | 1062 ------- c/src/lib/libbsp/m68k/genmcf548x/Makefile.am | 2 +- c/src/lib/libbsp/m68k/genmcf548x/network/network.c | 1696 ----------- c/src/lib/libbsp/m68k/mcf5235/Makefile.am | 2 +- c/src/lib/libbsp/m68k/mcf5235/network/network.c | 879 ------ c/src/lib/libbsp/m68k/mcf5329/Makefile.am | 2 +- c/src/lib/libbsp/m68k/mcf5329/network/network.c | 857 ------ c/src/lib/libbsp/m68k/mvme162/Makefile.am | 2 +- c/src/lib/libbsp/m68k/mvme167/Makefile.am | 2 +- c/src/lib/libbsp/m68k/mvme167/network/network.c | 3099 -------------------- c/src/lib/libbsp/m68k/mvme167/network/uti596.h | 369 --- c/src/lib/libbsp/m68k/uC5282/Makefile.am | 2 +- c/src/lib/libbsp/m68k/uC5282/network/network.c | 1013 ------- 17 files changed, 8 insertions(+), 10907 deletions(-) delete mode 100644 c/src/lib/libbsp/m68k/av5282/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/csb360/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/gen68360/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/genmcf548x/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/mcf5235/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/mcf5329/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/mvme167/network/network.c delete mode 100644 c/src/lib/libbsp/m68k/mvme167/network/uti596.h delete mode 100644 c/src/lib/libbsp/m68k/uC5282/network/network.c (limited to 'c/src/lib/libbsp/m68k') diff --git a/c/src/lib/libbsp/m68k/av5282/Makefile.am b/c/src/lib/libbsp/m68k/av5282/Makefile.am index 91f578f08a..456dd8a95f 100644 --- a/c/src/lib/libbsp/m68k/av5282/Makefile.am +++ b/c/src/lib/libbsp/m68k/av5282/Makefile.am @@ -34,7 +34,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/av5282/console/console.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/av5282/btimer/btimer.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/av5282/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache-mcf5282.c diff --git a/c/src/lib/libbsp/m68k/av5282/network/network.c b/c/src/lib/libbsp/m68k/av5282/network/network.c deleted file mode 100644 index 457b43c5d6..0000000000 --- a/c/src/lib/libbsp/m68k/av5282/network/network.c +++ /dev/null @@ -1,940 +0,0 @@ -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 1 - -#define FEC_INTC0_TX_VECTOR (64+23) -#define FEC_INTC0_RX_VECTOR (64+27) - -#define FEC_INTC0_TX_VECTOR (64+23) -#define FEC_INTC0_RX_VECTOR (64+27) -#define MII_VECTOR (64+7) /* IRQ7* pin connected to external transceiver */ -#define MII_EPPAR MCF5282_EPORT_EPPAR_EPPA7_LEVEL -#define MII_EPDDR MCF5282_EPORT_EPDDR_EPDD7 -#define MII_EPIER MCF5282_EPORT_EPIER_EPIE7 -#define MII_EPPDR MCF5282_EPORT_EPPDR_EPPD7 -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses three or more buffer descriptors. - */ -#define RX_BUF_COUNT 32 -#define TX_BUF_COUNT 20 -#define TX_BD_PER_BUF 3 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define TX_INTERRUPT_EVENT RTEMS_EVENT_1 -#define RX_INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). - * Round off to nearest multiple of RBUF_ALIGN. - */ -#define MAX_MTU_SIZE 1518 -#define RBUF_ALIGN 4 -#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) - -#if (MCLBYTES < RBUF_SIZE) - #error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -typedef struct mcf5282BufferDescriptor_ { - volatile uint16_t status; - uint16_t length; - volatile void *buffer; -} mcf5282BufferDescriptor_t; - -/* - * Per-device data - */ -struct mcf5282_enet_struct { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - mcf5282BufferDescriptor_t *rxBdBase; - mcf5282BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long txInterrupts; - unsigned long miiInterrupts; - unsigned long txRawWait; - unsigned long txRealign; - unsigned long txRealignDrop; - uint16_t mii_sr2; -}; -static struct mcf5282_enet_struct enet_driver[NIFACES]; - -static int -getMII(int phyNumber, int regNumber); - - -static rtems_isr -mcf5282_fec_rx_interrupt_handler( rtems_vector_number v ) -{ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF; - MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_RXF; - enet_driver[0].rxInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].rxDaemonTid, RX_INTERRUPT_EVENT); -} - -static rtems_isr -mcf5282_fec_tx_interrupt_handler( rtems_vector_number v ) -{ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF; - MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_TXF; - enet_driver[0].txInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].txDaemonTid, TX_INTERRUPT_EVENT); -} - -static rtems_isr -mcf5282_mii_interrupt_handler( rtems_vector_number v ) -{ - uint16_t sr2; - - enet_driver[0].miiInterrupts++; - getMII(1, 19); /* Read and clear interrupt status bits */ - enet_driver[0].mii_sr2 = sr2 = getMII(1, 17); - if (((sr2 & 0x200) != 0) - && ((MCF5282_FEC_TCR & MCF5282_FEC_TCR_FDEN) == 0)) - MCF5282_FEC_TCR |= MCF5282_FEC_TCR_FDEN; - else if (((sr2 & 0x200) == 0) - && ((MCF5282_FEC_TCR & MCF5282_FEC_TCR_FDEN) != 0)) - MCF5282_FEC_TCR &= ~MCF5282_FEC_TCR_FDEN; -} - -/* - * Allocate buffer descriptors from (non-cached) on-chip static RAM - * Ensure 128-bit (16-byte) alignment - */ -extern char __SRAMBASE[]; - -static mcf5282BufferDescriptor_t * -mcf5282_bd_allocate(unsigned int count) -{ - static mcf5282BufferDescriptor_t *bdp = (mcf5282BufferDescriptor_t *)__SRAMBASE; - mcf5282BufferDescriptor_t *p = bdp; - - bdp += count; - if ((int)bdp & 0xF) - bdp = (mcf5282BufferDescriptor_t *)((char *)bdp + (16 - ((int)bdp & 0xF))); - return p; -} - - -/* - * Read MII register - * Busy-waits, but transfer time should be short! - */ -static int -getMII(int phyNumber, int regNumber) -{ - MCF5282_FEC_MMFR = (0x1 << 30) | - (0x2 << 28) | - (phyNumber << 23) | - (regNumber << 18) | - (0x2 << 16); - while ((MCF5282_FEC_EIR & MCF5282_FEC_EIR_MII) == 0); - MCF5282_FEC_EIR = MCF5282_FEC_EIR_MII; - return MCF5282_FEC_MMFR & 0xFFFF; -} - - -/* - * Write MII register - * Busy-waits, but transfer time should be short! - */ -static void -setMII(int phyNumber, int regNumber, int value) -{ - MCF5282_FEC_MMFR = (0x1 << 30) | - (0x1 << 28) | - (phyNumber << 23) | - (regNumber << 18) | - (0x2 << 16) | - (value & 0xFFFF); - while ((MCF5282_FEC_EIR & MCF5282_FEC_EIR_MII) == 0); - MCF5282_FEC_EIR = MCF5282_FEC_EIR_MII; -} - -static void -mcf5282_fec_initialize_hardware(struct mcf5282_enet_struct *sc) -{ - int i; - const unsigned char *hwaddr; - rtems_status_code status; - rtems_isr_entry old_handler; - uint32_t clock_speed = get_CPU_clock_speed(); - - /* - * Issue reset to FEC - */ - MCF5282_FEC_ECR = MCF5282_FEC_ECR_RESET; - rtems_task_wake_after(1); - MCF5282_FEC_ECR = 0; - - /* - * Configuration of I/O ports is done outside of this function - */ -#if 0 - imm->gpio.pbcnt |= MCF5282_GPIO_PBCNT_SET_FEC; /* Set up port b FEC pins */ -#endif - - /* - * Set our physical address - */ - hwaddr = sc->arpcom.ac_enaddr; - MCF5282_FEC_PALR = (hwaddr[0] << 24) | (hwaddr[1] << 16) | - (hwaddr[2] << 8) | (hwaddr[3] << 0); - MCF5282_FEC_PAUR = (hwaddr[4] << 24) | (hwaddr[5] << 16); - - - /* - * Clear the hash table - */ - MCF5282_FEC_GAUR = 0; - MCF5282_FEC_GALR = 0; - - /* - * Set up receive buffer size - */ - MCF5282_FEC_EMRBR = 1520; /* Standard Ethernet */ - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = mcf5282_bd_allocate(sc->rxBdCount); - sc->txBdBase = mcf5282_bd_allocate(sc->txBdCount); - MCF5282_FEC_ERDSR = (int)sc->rxBdBase; - MCF5282_FEC_ETDSR = (int)sc->txBdBase; - - /* - * Set up Receive Control Register: - * Not promiscuous - * MII mode - * Full duplex - * No loopback - */ - MCF5282_FEC_RCR = MCF5282_FEC_RCR_MAX_FL(MAX_MTU_SIZE) | - MCF5282_FEC_RCR_MII_MODE; - - /* - * Set up Transmit Control Register: - * Full duplex - * No heartbeat - */ - MCF5282_FEC_TCR = MCF5282_FEC_TCR_FDEN; - - /* - * Initialize statistic counters - */ - MCF5282_FEC_MIBC = MCF5282_FEC_MIBC_MIB_DISABLE; - { - vuint32 *vuip = &MCF5282_FEC_RMON_T_DROP; - while (vuip <= &MCF5282_FEC_IEEE_R_OCTETS_OK) - *vuip++ = 0; - } - MCF5282_FEC_MIBC = 0; - - /* - * Set MII speed to <= 2.5 MHz - */ - i = (clock_speed + 5000000 - 1) / 5000000; - MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(i); - - /* - * Set PHYS to 100 Mb/s, full duplex - */ - setMII(1, 0, 0x2100); - setMII(1, 4, 0x0181); - setMII(1, 0, 0x0000); - rtems_task_wake_after(2); - sc->mii_sr2 = getMII(1, 17); - setMII(1, 18, 0x0072); - setMII(1, 0, 0x1000); - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) - (sc->rxBdBase + i)->status = 0; - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - sc->txBdBase[i].status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Set up interrupts - */ - status = rtems_interrupt_catch( mcf5282_fec_tx_interrupt_handler, FEC_INTC0_TX_VECTOR, &old_handler ); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5282 FEC TX interrupt handler: %s\n", - rtems_status_text(status)); - status = rtems_interrupt_catch(mcf5282_fec_rx_interrupt_handler, FEC_INTC0_RX_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5282 FEC RX interrupt handler: %s\n", - rtems_status_text(status)); - MCF5282_INTC0_ICR23 = MCF5282_INTC_ICR_IL(FEC_IRQ_LEVEL) | - MCF5282_INTC_ICR_IP(FEC_IRQ_TX_PRIORITY); - MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT23 | MCF5282_INTC_IMRL_MASKALL); - MCF5282_INTC0_ICR27 = MCF5282_INTC_ICR_IL(FEC_IRQ_LEVEL) | - MCF5282_INTC_ICR_IP(FEC_IRQ_RX_PRIORITY); - MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT27 | MCF5282_INTC_IMRL_MASKALL); - - status = rtems_interrupt_catch(mcf5282_mii_interrupt_handler, MII_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5282 FEC MII interrupt handler: %s\n", - rtems_status_text(status)); - MCF5282_EPORT_EPPAR &= ~MII_EPPAR; - MCF5282_EPORT_EPDDR &= ~MII_EPDDR; - MCF5282_EPORT_EPIER |= MII_EPIER; - MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT7 | MCF5282_INTC_IMRL_MASKALL); -} - -/* - * Soak up buffer descriptors that have been sent. - */ -void -fec_retire_tx_bd(volatile struct mcf5282_enet_struct *sc ) -{ - struct mbuf *m, *n; - uint16_t status; - - while ((sc->txBdActiveCount != 0) - && (((status = sc->txBdBase[sc->txBdTail].status) & MCF5282_FEC_TxBD_R) == 0)) { - if ((status & MCF5282_FEC_TxBD_TO1) == 0) { - m = sc->txMbuf[sc->txBdTail]; - MFREE(m, n); - } - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - sc->txBdActiveCount--; - } -} - -static void -fec_rxDaemon (void *arg) -{ - volatile struct mcf5282_enet_struct *sc = (volatile struct mcf5282_enet_struct *)arg; - struct ifnet *ifp = (struct ifnet* )&sc->arpcom.ac_if; - struct mbuf *m; - volatile uint16_t status; - volatile mcf5282BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - rxBd->status = MCF5282_FEC_RxBD_E; - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status |= MCF5282_FEC_RxBD_W; - break; - } - } - - /* - * Input packet handling loop - */ - /* Indicate we have some ready buffers available */ - MCF5282_FEC_RDAR = 0; - - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & MCF5282_FEC_RxBD_E) { - /* - * Clear old events. - */ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF; - - /* - * Wait for packet to arrive. - * Check the buffer descriptor before waiting for the event. - * This catches the case when a packet arrives between the - * `if' above, and the clearing of the RXF bit in the EIR. - */ - while ((status = rxBd->status) & MCF5282_FEC_RxBD_E) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_RXF; - rtems_interrupt_enable(level); - rtems_bsdnet_event_receive (RX_INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - } - - /* - * Check that packet is valid - */ - if (status & MCF5282_FEC_RxBD_L) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - int len = rxBd->length - sizeof(uint32_t); - - /* - * Invalidate the cache and push the packet up. - * The cache is so small that it's more efficient to just - * invalidate the whole thing unless the packet is very small. - */ - m = sc->rxMbuf[rxBdIndex]; - if (len < 128) - rtems_cache_invalidate_multiple_data_lines(m->m_data, len); - else - rtems_cache_invalidate_entire_data(); - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input(ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & MCF5282_FEC_RxBD_W) | MCF5282_FEC_RxBD_E; - MCF5282_FEC_RDAR = 0; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void -fec_sendpacket(struct ifnet *ifp, struct mbuf *m) -{ - struct mcf5282_enet_struct *sc = ifp->if_softc; - volatile mcf5282BufferDescriptor_t *firstTxBd, *txBd; - int nAdded; - uint16_t status; - - /* - * Free up buffer descriptors - */ - fec_retire_tx_bd(sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - nAdded = 0; - firstTxBd = sc->txBdBase + sc->txBdHead; - - while(m != NULL) { - /* - * Wait for buffer descriptor to become available - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events. - */ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF; - - /* - * Wait for buffer descriptor to become available. - * Check for buffer descriptors before waiting for the event. - * This catches the case when a buffer became available between - * the `if' above, and the clearing of the TXF bit in the EIR. - */ - fec_retire_tx_bd(sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_TXF; - rtems_interrupt_enable(level); - sc->txRawWait++; - rtems_bsdnet_event_receive(TX_INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - fec_retire_tx_bd(sc); - } - } - - /* - * Don't set the READY flag on the first fragment - * until the whole packet has been readied. - */ - status = nAdded ? MCF5282_FEC_TxBD_R : 0; - - /* - * The IP fragmentation routine in ip_output - * can produce fragments with zero length. - */ - if (m->m_len){ - char *p = mtod(m, char *); - int offset = (int) p & 0x3; - txBd = sc->txBdBase + sc->txBdHead; - if (offset == 0) { - txBd->buffer = p; - txBd->length = m->m_len; - sc->txMbuf[sc->txBdHead] = m; - m = m->m_next; - } - else { - /* - * Stupid FEC can't handle misaligned data! - * Move offending bytes to a local buffer. - * Use buffer descriptor TO1 bit to indicate this. - */ - int nmove = 4 - offset; - char *d = (char *)&sc->txMbuf[sc->txBdHead]; - status |= MCF5282_FEC_TxBD_TO1; - sc->txRealign++; - if (nmove > m->m_len) - nmove = m->m_len; - m->m_data += nmove; - m->m_len -= nmove; - txBd->buffer = d; - txBd->length = nmove; - while (nmove--) - *d++ = *p++; - if (m->m_len == 0) { - struct mbuf *n; - sc->txRealignDrop++; - MFREE(m, n); - m = n; - } - } - nAdded++; - if (++sc->txBdHead == sc->txBdCount) { - status |= MCF5282_FEC_TxBD_W; - sc->txBdHead = 0; - } - txBd->status = status; - } - else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - MFREE(m, n); - m = n; - } - } - if (nAdded) { - txBd->status = status | MCF5282_FEC_TxBD_R - | MCF5282_FEC_TxBD_L - | MCF5282_FEC_TxBD_TC; - if (nAdded > 1) - firstTxBd->status |= MCF5282_FEC_TxBD_R; - MCF5282_FEC_TDAR = 0; - sc->txBdActiveCount += nAdded; - } -} - -void -fec_txDaemon(void *arg) -{ - struct mcf5282_enet_struct *sc = (struct mcf5282_enet_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - 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; - fec_sendpacket(ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - - -/* - * Send packet (caller provides header). - */ -static void -mcf5282_enet_start(struct ifnet *ifp) -{ - struct mcf5282_enet_struct *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -static void -fec_init(void *arg) -{ - struct mcf5282_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - /* - * Set up hardware - */ - mcf5282_fec_initialize_hardware(sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc("FECtx", 4096, fec_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc("FECrx", 4096, fec_rxDaemon, sc); - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - MCF5282_FEC_RCR |= MCF5282_FEC_RCR_PROM; - else - MCF5282_FEC_RCR &= ~MCF5282_FEC_RCR_PROM; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - MCF5282_FEC_ECR = MCF5282_FEC_ECR_ETHER_EN; -} - - -static void -fec_stop(struct mcf5282_enet_struct *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - MCF5282_FEC_ECR = 0x0; -} - -/* - * Show interface statistics - */ -static void -enet_stats(struct mcf5282_enet_struct *sc) -{ - printf(" Rx Interrupts:%-10lu", sc->rxInterrupts); - printf("Rx Packet Count:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_PACKETS); - printf(" Rx Broadcast:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_BC_PKT); - printf(" Rx Multicast:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_MC_PKT); - printf("CRC/Align error:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_CRC_ALIGN); - printf(" Rx Undersize:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_UNDERSIZE); - printf(" Rx Oversize:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_OVERSIZE); - printf(" Rx Fragment:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_FRAG); - printf(" Rx Jabber:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_JAB); - printf(" Rx 64:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P64); - printf(" Rx 65-127:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P65T0127); - printf(" Rx 128-255:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_P128TO255); - printf(" Rx 256-511:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P256TO511); - printf(" Rx 511-1023:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P512TO1023); - printf(" Rx 1024-2047:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_P1024TO2047); - printf(" Rx >=2048:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_GTE2048); - printf(" Rx Octets:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_OCTETS); - printf(" Rx Dropped:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_R_DROP); - printf(" Rx frame OK:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_FRAME_OK); - printf(" Rx CRC error:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_CRC); - printf(" Rx Align error:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_R_ALIGN); - printf(" FIFO Overflow:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_MACERR); - printf("Rx Pause Frames:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_FDXFC); - printf(" Rx Octets OK:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_R_OCTETS_OK); - printf(" Tx Interrupts:%-10lu", sc->txInterrupts); - printf("Tx Output Waits:%-10lu", sc->txRawWait); - printf("Tx mbuf realign:%-10lu\n", sc->txRealign); - printf("Tx realign drop:%-10lu", sc->txRealignDrop); - printf(" Tx Unaccounted:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_DROP); - printf("Tx Packet Count:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_PACKETS); - printf(" Tx Broadcast:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_BC_PKT); - printf(" Tx Multicast:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_MC_PKT); - printf("CRC/Align error:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_CRC_ALIGN); - printf(" Tx Undersize:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_UNDERSIZE); - printf(" Tx Oversize:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_OVERSIZE); - printf(" Tx Fragment:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_FRAG); - printf(" Tx Jabber:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_JAB); - printf(" Tx Collisions:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_COL); - printf(" Tx 64:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_P64); - printf(" Tx 65-127:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P65TO127); - printf(" Tx 128-255:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P128TO255); - printf(" Tx 256-511:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_P256TO511); - printf(" Tx 511-1023:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P512TO1023); - printf(" Tx 1024-2047:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P1024TO2047); - printf(" Tx >=2048:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_P_GTE2048); - printf(" Tx Octets:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_OCTETS); - printf(" Tx Dropped:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_DROP); - printf(" Tx Frame OK:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_FRAME_OK); - printf(" Tx 1 Collision:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_1COL); - printf("Tx >1 Collision:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_MCOL); - printf(" Tx Deferred:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_DEF); - printf(" Late Collision:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_LCOL); - printf(" Excessive Coll:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_EXCOL); - printf(" FIFO Underrun:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_MACERR); - printf(" Carrier Error:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_CSERR); - printf(" Tx SQE Error:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_SQE); - printf("Tx Pause Frames:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_FDXFC); - printf(" Tx Octets OK:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_OCTETS_OK); - printf(" MII interrupts:%-10lu\n", sc->miiInterrupts); - - printf(" EIR:%8.8lx ", (uint32_t) MCF5282_FEC_EIR); - printf("EIMR:%8.8lx ", (uint32_t) MCF5282_FEC_EIMR); - printf("RDAR:%8.8lx ", (uint32_t) MCF5282_FEC_RDAR); - printf("TDAR:%8.8lx\n", (uint32_t) MCF5282_FEC_TDAR); - printf(" ECR:%8.8lx ", (uint32_t) MCF5282_FEC_ECR); - printf(" RCR:%8.8lx ", (uint32_t) MCF5282_FEC_RCR); - printf(" TCR:%8.8lx\n", (uint32_t) MCF5282_FEC_TCR); - printf("FRBR:%8.8lx ", (uint32_t) MCF5282_FEC_FRBR); - printf("FRSR:%8.8lx\n", (uint32_t) MCF5282_FEC_FRSR); - if (sc->txBdActiveCount != 0) { - int i, n; - /* - * Yes, there are races here with adding and retiring descriptors, - * but this diagnostic is more for when things have backed up. - */ - printf("Transmit Buffer Descriptors (Tail %d, Head %d, Unretired %d):\n", - sc->txBdTail, - sc->txBdHead, - sc->txBdActiveCount); - i = sc->txBdTail; - for (n = 0 ; n < sc->txBdCount ; n++) { - if ((sc->txBdBase[i].status & MCF5282_FEC_TxBD_R) != 0) - printf(" %3d: status:%4.4x length:%-4d buffer:%p\n", - i, - sc->txBdBase[i].status, - sc->txBdBase[i].length, - sc->txBdBase[i].buffer); - if (++i == sc->txBdCount) - i = 0; - } - } -} - -static int -fec_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct mcf5282_enet_struct *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: - fec_stop(sc); - break; - - case IFF_UP: - fec_init(sc); - break; - - case IFF_UP | IFF_RUNNING: - fec_stop(sc); - fec_init(sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - enet_stats(sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -int -rtems_fec_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching ) -{ - struct mcf5282_enet_struct *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - unsigned char *hwaddr; - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NIFACES)) { - printf("Bad FEC unit number.\n"); - return 0; - } - sc = &enet_driver[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf("Driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - printf("%s%d: Ethernet address: ", unitName, unitNumber ); - if (config->hardware_address) { - hwaddr = config->hardware_address; - printf("%02x:%02x:%02x:%02x:%02x:%02x\n", - hwaddr[0], hwaddr[1], hwaddr[2], - hwaddr[3], hwaddr[4], hwaddr[5]); - memcpy(sc->arpcom.ac_enaddr, hwaddr, ETHER_ADDR_LEN); - } else { - printf("UNKNOWN\n"); - } - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - - 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 = fec_init; - ifp->if_ioctl = fec_ioctl; - ifp->if_start = mcf5282_enet_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); - return 1; -}; - diff --git a/c/src/lib/libbsp/m68k/csb360/network/network.c b/c/src/lib/libbsp/m68k/csb360/network/network.c deleted file mode 100644 index 47e0adb44d..0000000000 --- a/c/src/lib/libbsp/m68k/csb360/network/network.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * RTEMS/TCPIP driver for MCF5272 Ethernet - * - * Modified for MPC860 by Jay Monkman (jmonkman@lopingdog.com) - * - * This supports Ethernet on either SCC1 or the FEC of the MPC860T. - * Right now, we only do 10 Mbps, even with the FEC. The function - * rtems_enet_driver_attach determines which one to use. Currently, - * only one may be used at a time. - * - * Based on the MC68360 network driver by - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - * - * This supports ethernet on SCC1. Right now, we only do 10 Mbps. - * - * Modifications by Darlene Stewart - * and Charles-Antoine Gauthier - * Copyright (c) 1999, National Research Council of Canada - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 1 - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses four or more buffer descriptors. - */ -#define RX_BUF_COUNT 32 -#define TX_BUF_COUNT 16 -#define TX_BD_PER_BUF 4 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). - * Round off to nearest multiple of RBUF_ALIGN. - */ -#define MAX_MTU_SIZE 1518 -#define RBUF_ALIGN 4 -#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -typedef struct { - uint16_t status; - uint16_t length; - void *buffer; -} bd_t; -#define MCF5272_BD_READY (bit(15)) -#define MCF5272_BD_TO1 (bit(14)) -#define MCF5272_BD_WRAP (bit(13)) -#define MCF5272_BD_TO2 (bit(12)) -#define MCF5272_BD_LAST (bit(11)) -#define MCF5272_BD_TX_CRC (bit(10)) -#define MCF5272_BD_DEFER (bit(9)) -#define MCF5272_BD_HEARTBEAT (bit(8)) -#define MCF5272_BD_LATE_COLLISION (bit(7)) -#define MCF5272_BD_RETRY_LIMIT (bit(6)) -#define MCF5272_BD_UNDERRUN (bit(1)) -#define MCF5272_BD_CARRIER_LOST (bit(0)) - -#define MCF5272_BD_EMPTY (bit(15)) -#define MCF5272_BD_RO1 (bit(14)) -#define MCF5272_BD_WRAP (bit(13)) -#define MCF5272_BD_RO2 (bit(12)) -#define MCF5272_BD_M (bit(8)) -#define MCF5272_BD_BC (bit(7)) -#define MCF5272_BD_MC (bit(6)) -#define MCF5272_BD_LONG (bit(5)) -#define MCF5272_BD_NONALIGNED (bit(4)) -#define MCF5272_BD_SHORT (bit(3)) -#define MCF5272_BD_CRC_ERROR (bit(2)) -#define MCF5272_BD_OVERRUN (bit(1)) -#define MCF5272_BD_TRUNCATED (bit(0)) - - -/* - * Per-device data - */ -struct mcf5272_enet_struct { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - bd_t *rxBdBase; - bd_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long rxNotFirst; - unsigned long rxNotLast; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxRunt; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxTruncated; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; -}; -static struct mcf5272_enet_struct enet_driver[NIFACES]; - - -void dump_enet_regs(void) -{ - printf("**************************************************************\n"); - printf("ecr: 0x%08x eir: 0x%08x eimr: 0x%08x ivsr: 0x%08x\n\r", - g_enet_regs->ecr, g_enet_regs->eir, - g_enet_regs->eimr, g_enet_regs->ivsr); - printf("rdar: 0x%08x tdar: 0x%08x mmfr: 0x%08x mscr: 0x%08x\n\r", - g_enet_regs->rdar, g_enet_regs->tdar, - g_enet_regs->mmfr, g_enet_regs->mscr); - printf("frbr: 0x%08x frsr: 0x%08x tfwr: 0x%08x tfsr: 0x%08x\n\r", - g_enet_regs->frbr, g_enet_regs->frsr, - g_enet_regs->tfwr, g_enet_regs->tfsr); - printf("rcr: 0x%08x mflr: 0x%08x tcr: 0x%08x malr: 0x%08x\n\r", - g_enet_regs->rcr, g_enet_regs->mflr, - g_enet_regs->tcr, g_enet_regs->malr); - printf("maur: 0x%08x htur: 0x%08x htlr: 0x%08x erdsr: 0x%08x\n\r", - g_enet_regs->maur, g_enet_regs->htur, - g_enet_regs->htlr, g_enet_regs->erdsr); - printf("etdsr: 0x%08x emrbr: 0x%08x\n\r", - g_enet_regs->etdsr, g_enet_regs->emrbr); -} - - - - -/*#define cp printk("%s:%d\n\r", __FUNCTION__, __LINE__) */ -#define cp -#define mcf5272_bd_allocate(_n_) malloc((_n_) * sizeof(bd_t), 0, M_NOWAIT) - - - -rtems_isr enet_rx_isr(rtems_vector_number vector) -{ - cp; - /* - * Frame received? - */ - if (g_enet_regs->eir & MCF5272_ENET_EIR_RXF) { - cp; - g_enet_regs->eir = MCF5272_ENET_EIR_RXF; - enet_driver[0].rxInterrupts++; - rtems_bsdnet_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT); - } - cp; -} - -rtems_isr enet_tx_isr(rtems_vector_number vector) -{ - cp; - /* - * Buffer transmitted or transmitter error? - */ - if (g_enet_regs->eir & MCF5272_ENET_EIR_TXF) { - cp; - g_enet_regs->eir = MCF5272_ENET_EIR_TXF; - enet_driver[0].txInterrupts++; - rtems_bsdnet_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT); - } - cp; -} - - -/* - * Initialize the ethernet hardware - */ - - -static void -mcf5272_enet_initialize_hardware (struct mcf5272_enet_struct *sc) -{ - int i; - unsigned char *hwaddr; - uint32_t icr; - /* - * Issue reset to FEC - */ - g_enet_regs->ecr=0x1; - - /* - * Set the TX and RX fifo sizes. For now, we'll split it evenly - */ - /* If you uncomment these, the FEC will not work right. - g_enet_regs->r_fstart = ((g_enet_regs->r_bound & 0x3ff) >> 2) & 0x3ff; - g_enet_regs->x_fstart = 0; - */ - - /* Copy mac address to device */ - - hwaddr = sc->arpcom.ac_enaddr; - - g_enet_regs->malr = (hwaddr[0] << 24 | - hwaddr[1] << 16 | - hwaddr[2] << 8 | - hwaddr[3]); - g_enet_regs->maur = (hwaddr[4] << 24 | - hwaddr[5] << 16); - - /* - * Clear the hash table - */ - g_enet_regs->htlr = 0; - g_enet_regs->htur = 0; - - /* - * Set up receive buffer size - */ - g_enet_regs->emrbr = 0x5f0; /* set to 1520 */ - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, - M_MBUF, M_NOWAIT); - sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, - M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) { - rtems_panic ("No memory for mbuf pointers"); - } - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = mcf5272_bd_allocate(sc->rxBdCount); - sc->txBdBase = mcf5272_bd_allocate(sc->txBdCount); - g_enet_regs->erdsr = (int)sc->rxBdBase; - g_enet_regs->etdsr = (int)sc->txBdBase; - - /* - * Set up Receive Control Register: - * Not promiscuous mode - * MII mode - * Full duplex - * No loopback - */ - g_enet_regs->rcr = 0x00000004; - - /* - * Set up Transmit Control Register: - * Full duplex - * No heartbeat - */ - g_enet_regs->tcr = 0x00000004; - - /* - * Set MII speed to 2.5 MHz for 25 Mhz system clock - */ - g_enet_regs->mscr = 0x0a; - g_enet_regs->mmfr = 0x58021000; - - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) { - (sc->rxBdBase + i)->status = 0; - } - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - (sc->txBdBase + i)->status = 0; - sc->txMbuf[i] = NULL; - } - - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Mask all FEC interrupts and clear events - */ - g_enet_regs->eimr = (MCF5272_ENET_EIR_TXF | - MCF5272_ENET_EIR_RXF); - g_enet_regs->eir = ~0; - - /* - * Set up interrupts - */ - set_vector(enet_rx_isr, BSP_INTVEC_ERX, 1); - set_vector(enet_tx_isr, BSP_INTVEC_ETX, 1); - - /* Configure ethernet interrupts */ - icr = g_intctrl_regs->icr3; - icr = icr & ~((MCF5272_ICR3_ERX_MASK | MCF5272_ICR3_ERX_PI) | - (MCF5272_ICR3_ETX_MASK | MCF5272_ICR3_ETX_PI)); - icr |= ((MCF5272_ICR3_ERX_IPL(BSP_INTLVL_ERX) | MCF5272_ICR3_ERX_PI)| - (MCF5272_ICR3_ETX_IPL(BSP_INTLVL_ETX) | MCF5272_ICR3_ETX_PI)); - g_intctrl_regs->icr3 = icr; - -} - - -/* - * Soak up buffer descriptors that have been sent. - * Note that a buffer descriptor can't be retired as soon as it becomes - * ready. The MPC860 manual (MPC860UM/AD 07/98 Rev.1) and the MPC821 - * manual state that, "If an Ethernet frame is made up of multiple - * buffers, the user should not reuse the first buffer descriptor until - * the last buffer descriptor of the frame has had its ready bit cleared - * by the CPM". - */ -static void -mcf5272_enet_retire_tx_bd (struct mcf5272_enet_struct *sc) -{ - uint16_t status; - int i; - int nRetired; - struct mbuf *m, *n; - - i = sc->txBdTail; - nRetired = 0; - while ((sc->txBdActiveCount != 0) && - (((status = sc->txBdBase[i].status) & MCF5272_BD_READY) == 0)) { - /* - * See if anything went wrong - */ - if (status & (MCF5272_BD_DEFER | - MCF5272_BD_HEARTBEAT | - MCF5272_BD_LATE_COLLISION | - MCF5272_BD_RETRY_LIMIT | - MCF5272_BD_UNDERRUN | - MCF5272_BD_CARRIER_LOST)) { - /* - * Check for errors which stop the transmitter. - */ - if (status & (MCF5272_BD_LATE_COLLISION | - MCF5272_BD_RETRY_LIMIT | - MCF5272_BD_UNDERRUN)) { - if (status & MCF5272_BD_LATE_COLLISION) { - enet_driver[0].txLateCollision++; - } - if (status & MCF5272_BD_RETRY_LIMIT) { - enet_driver[0].txRetryLimit++; - } - if (status & MCF5272_BD_UNDERRUN) { - enet_driver[0].txUnderrun++; - } - } - if (status & MCF5272_BD_DEFER) { - enet_driver[0].txDeferred++; - } - if (status & MCF5272_BD_HEARTBEAT) { - enet_driver[0].txHeartbeat++; - } - if (status & MCF5272_BD_CARRIER_LOST) { - enet_driver[0].txLostCarrier++; - } - } - nRetired++; - if (status & MCF5272_BD_LAST) { - /* - * A full frame has been transmitted. - * Free all the associated buffer descriptors. - */ - sc->txBdActiveCount -= nRetired; - while (nRetired) { - nRetired--; - m = sc->txMbuf[sc->txBdTail]; - MFREE (m, n); - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - } - } - if (++i == sc->txBdCount) { - i = 0; - } - } -} - -static void -mcf5272_enet_rxDaemon (void *arg) -{ - struct mcf5272_enet_struct *sc = (struct mcf5272_enet_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - uint16_t status; - bd_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - rxBd->status = MCF5272_BD_EMPTY; - g_enet_regs->rdar = 0x1000000; - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status |= MCF5272_BD_WRAP; - break; - } - } - - /* - * Input packet handling loop - */ - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & MCF5272_BD_EMPTY) { - /* - * Clear old events - */ - g_enet_regs->eir = MCF5272_ENET_EIR_RXF; - - /* - * Wait for packet - * Note that the buffer descriptor is checked - * *before* the event wait -- this catches the - * possibility that a packet arrived between the - * `if' above, and the clearing of the event register. - */ - while ((status = rxBd->status) & MCF5272_BD_EMPTY) { - rtems_event_set events; - - /* - * Unmask RXF (Full frame received) event - */ - g_enet_regs->eir |= MCF5272_ENET_EIR_RXF; - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - cp; - } - } - cp; - - /* - * Check that packet is valid - */ - if (status & MCF5272_BD_LAST) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - - m = sc->rxMbuf[rxBdIndex]; - m->m_len = m->m_pkthdr.len = (rxBd->length - - sizeof(uint32_t) - - sizeof(struct ether_header)); - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input (ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - } - else { - /* - * Something went wrong with the reception - */ - if (!(status & MCF5272_BD_LAST)) { - sc->rxNotLast++; - } - if (status & MCF5272_BD_LONG) { - sc->rxGiant++; - } - if (status & MCF5272_BD_NONALIGNED) { - sc->rxNonOctet++; - } - if (status & MCF5272_BD_SHORT) { - sc->rxRunt++; - } - if (status & MCF5272_BD_CRC_ERROR) { - sc->rxBadCRC++; - } - if (status & MCF5272_BD_OVERRUN) { - sc->rxOverrun++; - } - if (status & MCF5272_BD_TRUNCATED) { - sc->rxTruncated++; - } - } - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & MCF5272_BD_WRAP) | MCF5272_BD_EMPTY; - g_enet_regs->rdar = 0x1000000; - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) { - rxBdIndex = 0; - } - } -} - -static void -mcf5272_enet_sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct mcf5272_enet_struct *sc = ifp->if_softc; - volatile bd_t *firstTxBd, *txBd; - /* struct mbuf *l = NULL; */ - uint16_t status; - int nAdded; - cp; - - /* - * Free up buffer descriptors - */ - mcf5272_enet_retire_tx_bd (sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - nAdded = 0; - txBd = firstTxBd = sc->txBdBase + sc->txBdHead; - for (;;) { - cp; - /* - * Wait for buffer descriptor to become available. - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events - */ - g_enet_regs->eir = MCF5272_ENET_EIR_TXF; - - /* - * Wait for buffer descriptor to become available. - * Note that the buffer descriptors are checked - * *before* * entering the wait loop -- this catches - * the possibility that a buffer descriptor became - * available between the `if' above, and the clearing - * of the event register. - * This is to catch the case where the transmitter - * stops in the middle of a frame -- and only the - * last buffer descriptor in a frame can generate - * an interrupt. - */ - mcf5272_enet_retire_tx_bd (sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_event_set events; - - cp; - /* - * Unmask TXB (buffer transmitted) and - * TXE (transmitter error) events. - */ - g_enet_regs->eir |= MCF5272_ENET_EIR_TXF; - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - cp; - mcf5272_enet_retire_tx_bd (sc); - } - } - - /* - * Don't set the READY flag till the - * whole packet has been readied. - */ - status = nAdded ? MCF5272_BD_READY : 0; - cp; - - /* - * FIXME: Why not deal with empty mbufs at at higher level? - * The IP fragmentation routine in ip_output - * can produce packet fragments with zero length. - * I think that ip_output should be changed to get - * rid of these zero-length mbufs, but for now, - * I'll deal with them here. - */ - if (m->m_len) { - cp; - /* - * Fill in the buffer descriptor - */ - txBd->buffer = mtod (m, void *); - txBd->length = m->m_len; - - sc->txMbuf[sc->txBdHead] = m; - nAdded++; - if (++sc->txBdHead == sc->txBdCount) { - status |= MCF5272_BD_WRAP; - sc->txBdHead = 0; - } - /* l = m;*/ - m = m->m_next; - } - else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - cp; - MFREE (m, n); - m = n; - /* - if (l != NULL) - l->m_next = m; - */ - } - - /* - * Set the transmit buffer status. - * Break out of the loop if this mbuf is the last in the frame. - */ - if (m == NULL) { - cp; - if (nAdded) { - cp; - status |= MCF5272_BD_LAST | MCF5272_BD_TX_CRC; - txBd->status = status; - firstTxBd->status |= MCF5272_BD_READY; - g_enet_regs->tdar = 0x1000000; - sc->txBdActiveCount += nAdded; - } - break; - } - txBd->status = status; - txBd = sc->txBdBase + sc->txBdHead; - } - cp; -/* - dump_enet_regs(); - dump_intctrl; -*/ - -} - - -void -mcf5272_enet_txDaemon (void *arg) -{ - struct mcf5272_enet_struct *sc = (struct mcf5272_enet_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - cp; - for (;;) { - /* - * Wait for packet - */ - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - cp; - /* - * Send packets till queue is empty - */ - cp; - for (;;) { - cp; - /* - * Get the next mbuf chain to transmit. - */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - mcf5272_enet_sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - - -/* - * Send packet (caller provides header). - */ -static void -mcf5272_enet_start (struct ifnet *ifp) -{ - struct mcf5272_enet_struct *sc = ifp->if_softc; - - cp; - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); - cp; - ifp->if_flags |= IFF_OACTIVE; -} - - -static void -mcf5272_enet_init (void *arg) -{ - struct mcf5272_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Set up SCC hardware - */ - mcf5272_enet_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc("SCtx", - 4096, - mcf5272_enet_txDaemon, - sc); - sc->rxDaemonTid = rtems_bsdnet_newproc("SCrx", - 4096, - mcf5272_enet_rxDaemon, - sc); - - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) { - g_enet_regs->rcr |= 0x8; - } else { - g_enet_regs->rcr &= ~0x8; - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - g_enet_regs->ecr = 0x2; -} - - -static void -mcf5272_enet_stop (struct mcf5272_enet_struct *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - g_enet_regs->ecr = 0x0; -} - - -/* - * Show interface statistics - */ -static void -enet_stats (struct mcf5272_enet_struct *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Not First:%-8lu", sc->rxNotFirst); - printf (" Not Last:%-8lu\n", sc->rxNotLast); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Runt:%-8lu", sc->rxRunt); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Truncated:%-8lu\n", sc->rxTruncated); -/* printf (" Discarded:%-8lu\n", (unsigned long)mcf5272.scc1p.un.ethernet.disfc); */ - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Deferred:%-8lu", sc->txDeferred); - printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); - printf (" Late Collision:%-8lu\n", sc->txLateCollision); - printf (" Underrun:%-8lu", sc->txUnderrun); - printf (" Raw output wait:%-8lu\n", sc->txRawWait); -} - - -/* - * Driver ioctl handler - */ -static int -mcf5272_enet_ioctl (struct ifnet *ifp, int command, caddr_t data) -{ - struct mcf5272_enet_struct *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: - mcf5272_enet_stop (sc); - break; - - case IFF_UP: - mcf5272_enet_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - mcf5272_enet_stop (sc); - mcf5272_enet_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - enet_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - - -int -rtems_enet_driver_attach (struct rtems_bsdnet_ifconfig *config) -{ - struct mcf5272_enet_struct *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* - * Parse driver name - */ - unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName); - if (unitNumber < 0){ - return 0; - } - - /* - * Is driver free? - */ - if ((unitNumber < 0) || (unitNumber > NIFACES)) { - printf ("Bad unit number: %d.\n", unitNumber); - return 0; - } - - sc = &enet_driver[unitNumber]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf ("Driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - - sc->arpcom.ac_enaddr[0] = (g_enet_regs->malr >> 24) & 0xff; - sc->arpcom.ac_enaddr[1] = (g_enet_regs->malr >> 16) & 0xff; - sc->arpcom.ac_enaddr[2] = (g_enet_regs->malr >> 8) & 0xff; - sc->arpcom.ac_enaddr[3] = (g_enet_regs->malr >> 0) & 0xff; - sc->arpcom.ac_enaddr[4] = (g_enet_regs->maur >> 24) & 0xff; - sc->arpcom.ac_enaddr[5] = (g_enet_regs->maur >> 16) & 0xff; - - if (config->mtu) { - mtu = config->mtu; - } else { - mtu = ETHERMTU; - } - - if (config->rbuf_count) { - sc->rxBdCount = config->rbuf_count; - } else { - sc->rxBdCount = RX_BUF_COUNT; - } - if (config->xbuf_count) { - sc->txBdCount = config->xbuf_count; - } else { - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - } - 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 = mcf5272_enet_init; - ifp->if_ioctl = mcf5272_enet_ioctl; - ifp->if_start = mcf5272_enet_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); - cp; - ether_ifattach (ifp); - cp; - return 1; -}; - - diff --git a/c/src/lib/libbsp/m68k/gen68360/Makefile.am b/c/src/lib/libbsp/m68k/gen68360/Makefile.am index d78babc776..d3cbc78599 100644 --- a/c/src/lib/libbsp/m68k/gen68360/Makefile.am +++ b/c/src/lib/libbsp/m68k/gen68360/Makefile.am @@ -38,7 +38,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68360/btimer/btimer.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/gen68360/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache.c diff --git a/c/src/lib/libbsp/m68k/gen68360/network/network.c b/c/src/lib/libbsp/m68k/gen68360/network/network.c deleted file mode 100644 index 0a038d3348..0000000000 --- a/c/src/lib/libbsp/m68k/gen68360/network/network.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * RTEMS driver for M68360 SCC1 Ethernet - * - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -/* - * Number of SCCs supported by this driver - */ -#define NSCCDRIVER 1 - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses four or more buffer descriptors. - */ -#define RX_BUF_COUNT 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1520 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct scc_softc { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - m360BufferDescriptor_t *rxBdBase; - m360BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long rxNotFirst; - unsigned long rxNotLast; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxRunt; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; - unsigned long txCoalesced; - unsigned long txCoalesceFailed; - unsigned long txRetry; -}; -static struct scc_softc scc_softc[NSCCDRIVER]; - -extern void *_RomBase; /* From linkcmds */ - -/* - * SCC1 interrupt handler - */ -static rtems_isr -m360Enet_interrupt_handler (rtems_vector_number v) -{ - /* - * Frame received? - */ - if ((m360.scc1.sccm & 0x8) && (m360.scc1.scce & 0x8)) { - m360.scc1.scce = 0x8; - m360.scc1.sccm &= ~0x8; - scc_softc[0].rxInterrupts++; - rtems_bsdnet_event_send (scc_softc[0].rxDaemonTid, INTERRUPT_EVENT); - } - - /* - * Buffer transmitted or transmitter error? - */ - if ((m360.scc1.sccm & 0x12) && (m360.scc1.scce & 0x12)) { - m360.scc1.scce = 0x12; - m360.scc1.sccm &= ~0x12; - scc_softc[0].txInterrupts++; - rtems_bsdnet_event_send (scc_softc[0].txDaemonTid, INTERRUPT_EVENT); - } - m360.cisr = 1UL << 30; /* Clear SCC1 interrupt-in-service bit */ -} - -/* - * Initialize the ethernet hardware - */ -static void -m360Enet_initialize_hardware (struct scc_softc *sc) -{ - int i; - unsigned char *hwaddr; - rtems_status_code status; - rtems_isr_entry old_handler; - - /* - * Configure port A CLK1, CLK2, TXD1 and RXD1 pins - */ - m360.papar |= 0x303; - m360.padir &= ~0x303; - m360.paodr &= ~0x303; - - /* - * Configure port C CTS1* and CD1* pins - */ - m360.pcpar &= ~0x30; - m360.pcdir &= ~0x30; - m360.pcso |= 0x30; - - /* - * Connect CLK1 and CLK2 to SCC1 - */ - m360.sicr &= ~0xFF; - m360.sicr |= (5 << 3) | 4; - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic ("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = M360AllocateBufferDescriptors(sc->rxBdCount); - sc->txBdBase = M360AllocateBufferDescriptors(sc->txBdCount); - m360.scc1p.rbase = (char *)sc->rxBdBase - (char *)&m360; - m360.scc1p.tbase = (char *)sc->txBdBase - (char *)&m360; - - /* - * Send "Init parameters" command - */ - M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SCC1); - - /* - * Set receive and transmit function codes - */ - m360.scc1p.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE; - m360.scc1p.tfcr = M360_TFCR_MOT | M360_TFCR_DMA_SPACE; - - /* - * Set maximum receive buffer length - */ - m360.scc1p.mrblr = RBUF_SIZE; - - /* - * Set CRC parameters - */ - m360.scc1p.un.ethernet.c_pres = 0xFFFFFFFF; - m360.scc1p.un.ethernet.c_mask = 0xDEBB20E3; - - /* - * Clear diagnostic counters - */ - m360.scc1p.un.ethernet.crcec = 0; - m360.scc1p.un.ethernet.alec = 0; - m360.scc1p.un.ethernet.disfc = 0; - - /* - * Set pad value - */ - m360.scc1p.un.ethernet.pads = 0x8888; - - /* - * Set retry limit - */ - m360.scc1p.un.ethernet.ret_lim = 15; - - /* - * Set maximum and minimum frame length - */ - m360.scc1p.un.ethernet.mflr = 1518; - m360.scc1p.un.ethernet.minflr = 64; - m360.scc1p.un.ethernet.maxd1 = RBUF_SIZE; - m360.scc1p.un.ethernet.maxd2 = RBUF_SIZE; - - /* - * Clear group address hash table - */ - m360.scc1p.un.ethernet.gaddr1 = 0; - m360.scc1p.un.ethernet.gaddr2 = 0; - m360.scc1p.un.ethernet.gaddr3 = 0; - m360.scc1p.un.ethernet.gaddr4 = 0; - - /* - * Set our physical address - */ - hwaddr = sc->arpcom.ac_enaddr; - m360.scc1p.un.ethernet.paddr_h = (hwaddr[5] << 8) | hwaddr[4]; - m360.scc1p.un.ethernet.paddr_m = (hwaddr[3] << 8) | hwaddr[2]; - m360.scc1p.un.ethernet.paddr_l = (hwaddr[1] << 8) | hwaddr[0]; - - /* - * Aggressive retry - */ - m360.scc1p.un.ethernet.p_per = 0; - - /* - * Clear individual address hash table - */ - m360.scc1p.un.ethernet.iaddr1 = 0; - m360.scc1p.un.ethernet.iaddr2 = 0; - m360.scc1p.un.ethernet.iaddr3 = 0; - m360.scc1p.un.ethernet.iaddr4 = 0; - - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) - (sc->rxBdBase + i)->status = 0; - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - (sc->txBdBase + i)->status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Clear any outstanding events - */ - m360.scc1.scce = 0xFFFF; - - /* - * Set up interrupts - */ - status = rtems_interrupt_catch (m360Enet_interrupt_handler, - (m360.cicr & 0xE0) | 0x1E, - &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach M360 SCC1 interrupt handler: %s\n", - rtems_status_text (status)); - m360.scc1.sccm = 0; /* No interrupts unmasked till necessary */ - m360.cimr |= (1UL << 30); /* Enable SCC1 interrupt */ - - /* - * Set up General SCC Mode Register - * Ethernet configuration - */ - m360.scc1.gsmr_h = 0x0; - m360.scc1.gsmr_l = 0x1088000c; - - /* - * Set up data synchronization register - * Ethernet synchronization pattern - */ - m360.scc1.dsr = 0xd555; - - /* - * Set up protocol-specific mode register - * Heartbeat check - * No force collision - * Discard short frames - * Individual address mode - * Ethernet CRC - * Not promisuous - * Ignore/accept broadcast packets as specified - * Normal backoff timer - * No loopback - * No input sample at end of frame - * 64-byte limit for late collision - * Wait 22 bits before looking for start of frame delimiter - * Disable full-duplex operation - */ - m360.scc1.psmr = 0x880A | (sc->acceptBroadcast ? 0 : 0x100); - - /* - * Enable the TENA (RTS1*) pin - */ -#if (defined (M68360_ATLAS_HSB)) - m360.pbpar |= 0x1000; - m360.pbdir |= 0x1000; -#else - m360.pcpar |= 0x1; - m360.pcdir &= ~0x1; -#endif -} - -/* - * Soak up buffer descriptors that have been sent - * Note that a buffer descriptor can't be retired as soon as it becomes - * ready. The MC68360 Errata (May 96) says that, "If an Ethernet frame is - * made up of multiple buffers, the user should not reuse the first buffer - * descriptor until the last buffer descriptor of the frame has had its - * ready bit cleared by the CPM". - */ -static void -m360Enet_retire_tx_bd (struct scc_softc *sc) -{ - uint16_t status; - int i; - int nRetired; - struct mbuf *m, *n; - int retries = 0; - int saveStatus = 0; - - i = sc->txBdTail; - nRetired = 0; - while ((sc->txBdActiveCount != 0) - && (((status = (sc->txBdBase + i)->status) & M360_BD_READY) == 0)) { - /* - * Check for errors which stop the transmitter. - */ - if (status & (M360_BD_LATE_COLLISION | - M360_BD_RETRY_LIMIT | - M360_BD_UNDERRUN)) { - int j; - - if (status & M360_BD_LATE_COLLISION) - sc->txLateCollision++; - if (status & M360_BD_RETRY_LIMIT) - sc->txRetryLimit++; - if (status & M360_BD_UNDERRUN) - sc->txUnderrun++; - - /* - * Reenable buffer descriptors - */ - j = sc->txBdTail; - for (;;) { - status = (sc->txBdBase + j)->status; - if (status & M360_BD_READY) - break; - (sc->txBdBase + j)->status = M360_BD_READY | - (status & (M360_BD_PAD | - M360_BD_WRAP | - M360_BD_INTERRUPT | - M360_BD_LAST | - M360_BD_TX_CRC)); - if (status & M360_BD_LAST) - break; - if (++j == sc->txBdCount) - j = 0; - } - - /* - * Move transmitter back to the first - * buffer descriptor in the frame. - */ - m360.scc1p._tbptr = m360.scc1p.tbase + - sc->txBdTail * sizeof (m360BufferDescriptor_t); - - /* - * Restart the transmitter - */ - M360ExecuteRISC (M360_CR_OP_RESTART_TX | M360_CR_CHAN_SCC1); - continue; - } - saveStatus |= status; - retries += (status >> 2) & 0xF; - nRetired++; - if (status & M360_BD_LAST) { - /* - * A full frame has been transmitted. - * Free all the associated buffer descriptors. - */ - if (saveStatus & M360_BD_DEFER) - sc->txDeferred++; - if (saveStatus & M360_BD_HEARTBEAT) - sc->txHeartbeat++; - if (saveStatus & M360_BD_CARRIER_LOST) - sc->txLostCarrier++; - saveStatus = 0; - sc->txRetry += retries; - retries = 0; - sc->txBdActiveCount -= nRetired; - while (nRetired) { - nRetired--; - m = sc->txMbuf[sc->txBdTail]; - MFREE (m, n); - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - } - } - if (++i == sc->txBdCount) - i = 0; - } -} - -/* - * SCC reader task - */ -static void -scc_rxDaemon (void *arg) -{ - struct scc_softc *sc = (struct scc_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - uint16_t status; - volatile m360BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status = M360_BD_EMPTY | M360_BD_INTERRUPT | M360_BD_WRAP; - break; - } - rxBd->status = M360_BD_EMPTY | M360_BD_INTERRUPT; - } - - /* - * Input packet handling loop - */ - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & M360_BD_EMPTY) { - /* - * Clear old events - */ - m360.scc1.scce = 0x8; - - /* - * Wait for packet - * Note that the buffer descriptor is checked - * *before* the event wait -- this catches the - * possibility that a packet arrived between the - * `if' above, and the clearing of the event register. - */ - while ((status = rxBd->status) & M360_BD_EMPTY) { - rtems_interrupt_level level; - rtems_event_set events; - - /* - * Unmask RXF (Full frame received) event - */ - rtems_interrupt_disable (level); - m360.scc1.sccm |= 0x8; - rtems_interrupt_enable (level); - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - } - - /* - * Check that packet is valid - */ - if ((status & (M360_BD_LAST | - M360_BD_FIRST_IN_FRAME | - M360_BD_LONG | - M360_BD_NONALIGNED | - M360_BD_SHORT | - M360_BD_CRC_ERROR | - M360_BD_OVERRUN | - M360_BD_COLLISION)) == - (M360_BD_LAST | - M360_BD_FIRST_IN_FRAME)) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - - m = sc->rxMbuf[rxBdIndex]; - m->m_len = m->m_pkthdr.len = rxBd->length - - sizeof(uint32_t) - - sizeof(struct ether_header); - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input (ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - } - else { - /* - * Something went wrong with the reception - */ - if (!(status & M360_BD_LAST)) - sc->rxNotLast++; - if (!(status & M360_BD_FIRST_IN_FRAME)) - sc->rxNotFirst++; - if (status & M360_BD_LONG) - sc->rxGiant++; - if (status & M360_BD_NONALIGNED) - sc->rxNonOctet++; - if (status & M360_BD_SHORT) - sc->rxRunt++; - if (status & M360_BD_CRC_ERROR) - sc->rxBadCRC++; - if (status & M360_BD_OVERRUN) - sc->rxOverrun++; - if (status & M360_BD_COLLISION) - sc->rxCollision++; - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & (M360_BD_WRAP | M360_BD_INTERRUPT)) | M360_BD_EMPTY; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct scc_softc *sc = ifp->if_softc; - volatile m360BufferDescriptor_t *firstTxBd, *txBd; - struct mbuf *l = NULL; - uint16_t status; - int nAdded; - - /* - * Free up buffer descriptors - */ - m360Enet_retire_tx_bd (sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - status = 0; - nAdded = 0; - txBd = firstTxBd = sc->txBdBase + sc->txBdHead; - while (m) { - /* - * There are more mbufs in the packet than there - * are transmit buffer descriptors. - * Coalesce into a single buffer. - */ - if (nAdded == sc->txBdCount) { - struct mbuf *nm; - int j; - char *dest; - - /* - * Get the pointer to the first mbuf of the packet - */ - if (sc->txBdTail != sc->txBdHead) - rtems_panic ("sendpacket coalesce"); - m = sc->txMbuf[sc->txBdTail]; - - /* - * Rescind the buffer descriptor READY bits - */ - for (j = 0 ; j < sc->txBdCount ; j++) - (sc->txBdBase + j)->status = 0; - - /* - * Allocate an mbuf cluster - * Toss the packet if allocation fails - */ - MGETHDR (nm, M_DONTWAIT, MT_DATA); - if (nm == NULL) { - sc->txCoalesceFailed++; - m_freem (m); - return; - } - MCLGET (nm, M_DONTWAIT); - if (nm->m_ext.ext_buf == NULL) { - sc->txCoalesceFailed++; - m_freem (m); - m_free (nm); - return; - } - nm->m_pkthdr = m->m_pkthdr; - nm->m_len = nm->m_pkthdr.len; - - /* - * Copy data from packet chain to mbuf cluster - */ - sc->txCoalesced++; - dest = nm->m_ext.ext_buf; - while (m) { - struct mbuf *n; - - if (m->m_len) { - memcpy (dest, mtod(m, caddr_t), m->m_len); - dest += m->m_len; - } - MFREE (m, n); - m = n; - } - - /* - * Redo the send with the new mbuf cluster - */ - m = nm; - nAdded = 0; - status = 0; - continue; - } - - /* - * Wait for buffer descriptor to become available. - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events - */ - m360.scc1.scce = 0x12; - - /* - * Wait for buffer descriptor to become available. - * Note that the buffer descriptors are checked - * *before* entering the wait loop -- this catches - * the possibility that a buffer descriptor became - * available between the `if' above, and the clearing - * of the event register. - * This is to catch the case where the transmitter - * stops in the middle of a frame -- and only the - * last buffer descriptor in a frame can generate - * an interrupt. - */ - m360Enet_retire_tx_bd (sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_interrupt_level level; - rtems_event_set events; - - /* - * Unmask TXB (buffer transmitted) and - * TXE (transmitter error) events. - */ - rtems_interrupt_disable (level); - m360.scc1.sccm |= 0x12; - rtems_interrupt_enable (level); - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - m360Enet_retire_tx_bd (sc); - } - } - - /* - * The IP fragmentation routine in ip_output - * can produce packet fragments with zero length. - */ - if (m->m_len) { - /* - * Fill in the buffer descriptor. - * Don't set the READY flag in the first buffer - * descriptor till the whole packet has been readied. - */ - txBd = sc->txBdBase + sc->txBdHead; - txBd->buffer = mtod (m, void *); - txBd->length = m->m_len; - sc->txMbuf[sc->txBdHead] = m; - status = nAdded ? M360_BD_READY : 0; - if (++sc->txBdHead == sc->txBdCount) { - status |= M360_BD_WRAP; - sc->txBdHead = 0; - } - txBd->status = status; - l = m; - m = m->m_next; - nAdded++; - } - else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - MFREE (m, n); - m = n; - if (l != NULL) - l->m_next = m; - } - } - if (nAdded) { - /* - * Send the packet - */ - txBd->status = status | M360_BD_PAD | M360_BD_LAST | M360_BD_TX_CRC | M360_BD_INTERRUPT; - firstTxBd->status |= M360_BD_READY; - sc->txBdActiveCount += nAdded; - } -} - -/* - * Driver transmit daemon - */ -void -scc_txDaemon (void *arg) -{ - struct scc_softc *sc = (struct scc_softc *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - 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; - sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* - * Send packet (caller provides header). - */ -static void -scc_start (struct ifnet *ifp) -{ - struct scc_softc *sc = ifp->if_softc; - - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* - * Initialize and start the device - */ -static void -scc_init (void *arg) -{ - struct scc_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Set up SCC hardware - */ - m360Enet_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc); - - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - m360.scc1.psmr |= 0x200; - else - m360.scc1.psmr &= ~0x200; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - m360.scc1.gsmr_l |= 0x30; -} - -/* - * Stop the device - */ -static void -scc_stop (struct scc_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - m360.scc1.gsmr_l &= ~0x30; -} - -/* - * Show interface statistics - */ -static void -scc_stats (struct scc_softc *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Not First:%-8lu", sc->rxNotFirst); - printf (" Not Last:%-8lu\n", sc->rxNotLast); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Runt:%-8lu", sc->rxRunt); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Collision:%-8lu\n", sc->rxCollision); - printf (" Discarded:%-8lu\n", (unsigned long)m360.scc1p.un.ethernet.disfc); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Deferred:%-8lu", sc->txDeferred); - printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); - printf (" Late Collision:%-8lu\n", sc->txLateCollision); - printf (" Underrun:%-8lu", sc->txUnderrun); - printf (" Raw output wait:%-8lu", sc->txRawWait); - printf (" Coalesced:%-8lu\n", sc->txCoalesced); - printf (" Coalesce failed:%-8lu", sc->txCoalesceFailed); - printf (" Retries:%-8lu\n", sc->txRetry); -} - -/* - * Driver ioctl handler - */ -static int -scc_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct scc_softc *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: - scc_stop (sc); - break; - - case IFF_UP: - scc_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - scc_stop (sc); - scc_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - scc_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Attach an SCC driver to the system - */ -int -rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config, int attaching) -{ - struct scc_softc *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* - * Make sure we're really being attached - */ - if (!attaching) { - printf ("SCC1 driver can not be detached.\n"); - return 0; - } - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NSCCDRIVER)) { - printf ("Bad SCC unit number.\n"); - return 0; - } - sc = &scc_softc[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf ("Driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - if (config->hardware_address) { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else { - /* - * The first 4 bytes of the bootstrap prom - * contain the value loaded into the stack - * pointer as part of the CPU32's hardware - * reset exception handler. The following - * 4 bytes contain the value loaded into the - * program counter. The boards' Ethernet - * address is stored in the six bytes - * immediately preceding this initial - * program counter value. - * - * See start360/start360.s. - */ - const unsigned long *ExceptionVectors; - const unsigned char *entryPoint; - - /* - * Sanity check -- assume entry point must be - * within 1 MByte of beginning of boot ROM. - */ - ExceptionVectors = (const unsigned long *)&_RomBase; - entryPoint = (const unsigned char *)ExceptionVectors[1]; - if (((unsigned long)entryPoint - (unsigned long)ExceptionVectors) - >= (1 * 1024 * 1024)) { - printf ("Warning -- Ethernet address can not be found in bootstrap PROM.\n"); - sc->arpcom.ac_enaddr[0] = 0x08; - sc->arpcom.ac_enaddr[1] = 0xF3; - sc->arpcom.ac_enaddr[2] = 0x3E; - sc->arpcom.ac_enaddr[3] = 0xC2; - sc->arpcom.ac_enaddr[4] = 0x7E; - sc->arpcom.ac_enaddr[5] = 0x38; - } - else { - memcpy (sc->arpcom.ac_enaddr, entryPoint - ETHER_ADDR_LEN, ETHER_ADDR_LEN); - } - } - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - 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 = scc_init; - ifp->if_ioctl = scc_ioctl; - ifp->if_start = scc_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); - return 1; -} diff --git a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am index b84cda2236..7cc1e39bb6 100644 --- a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am +++ b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am @@ -51,7 +51,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/mcdma/mcdma_glue librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/start/cache.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/net/network.c endif include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/m68k/genmcf548x/network/network.c b/c/src/lib/libbsp/m68k/genmcf548x/network/network.c deleted file mode 100644 index 13cb5fbdce..0000000000 --- a/c/src/lib/libbsp/m68k/genmcf548x/network/network.c +++ /dev/null @@ -1,1696 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS generic MCF548X BSP | -+-----------------------------------------------------------------+ -| Partially based on the code references which are named below. | -| Adaptions, modifications, enhancements and any recent parts of | -| the code are: | -| Copyright (c) 2009 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-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. | -| | -+-----------------------------------------------------------------+ -| this file contains the networking driver | -\*===============================================================*/ -/* - * RTEMS/TCPIP driver for MCF548X FEC Ethernet - * - * Modified for Motorola MPC5200 by Thomas Doerfler, - * COPYRIGHT (c) 2003, IMD - * - * Modified for Motorola IceCube (mgt5100) by Peter Rasmussen - * COPYRIGHT (c) 2003, IPR Engineering - * - * Parts of code are also under property of Driver Information Systems and based - * on Motorola Proprietary Information. - * COPYRIGHT (c) 2002 MOTOROLA INC. - * - * Modified for Motorola MCF548X by Thomas Doerfler, - * COPYRIGHT (c) 2009, IMD - * - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* freescale-api-specifics... */ -#include -#include - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 2 - -#define FEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */ - -#define DMA_BD_RX_NUM 32 /* Number of receive buffer descriptors */ -#define DMA_BD_TX_NUM 32 /* Number of transmit buffer descriptors */ - -#define FEC_EVENT RTEMS_EVENT_0 - -/* - * internal SRAM - * Layout: - * - RxBD channel 0 - * - TxBD channel 0 - * - RxBD channel 1 - * - TxBD channel 1 - * - DMA task memory - */ -extern char _SysSramBase[]; -#define SRAM_RXBD_BASE(base,chan) (((MCD_bufDescFec*)(base)) \ - +((chan) \ - *(DMA_BD_RX_NUM+DMA_BD_TX_NUM))) - -#define SRAM_TXBD_BASE(base,chan) (((MCD_bufDescFec*)(base)) \ - +((chan) \ - *(DMA_BD_RX_NUM+DMA_BD_TX_NUM) \ - +DMA_BD_RX_NUM)) - -#define SRAM_DMA_BASE(base) ((void *)SRAM_RXBD_BASE(base,NIFACES+1)) - - -#undef ETH_DEBUG - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses four or more buffer descriptors. - */ -#define RX_BUF_COUNT DMA_BD_RX_NUM -#define TX_BUF_COUNT DMA_BD_TX_NUM -#define TX_BD_PER_BUF 1 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -#define MCF548X_FEC0_IRQ_VECTOR (39+64) -#define MCF548X_FEC1_IRQ_VECTOR (38+64) - -#define MCF548X_FEC_IRQ_VECTOR(chan) (MCF548X_FEC0_IRQ_VECTOR \ - +(chan)*(MCF548X_FEC1_IRQ_VECTOR \ - -MCF548X_FEC0_IRQ_VECTOR)) - -#define MCF548X_FEC_VECTOR2CHAN(vector) (((int)(vector)-MCF548X_FEC0_IRQ_VECTOR) \ - /(MCF548X_FEC1_IRQ_VECTOR \ - -MCF548X_FEC0_IRQ_VECTOR)) - -#define MCDMA_FEC_RX_CHAN(chan) (0 + NIFACES*(chan)) -#define MCDMA_FEC_TX_CHAN(chan) (1 + NIFACES*(chan)) - -#define MCF548X_FEC0_RX_INITIATOR (16) -#define MCF548X_FEC1_RX_INITIATOR (30) -#define MCF548X_FEC_RX_INITIATOR(chan) (MCF548X_FEC0_RX_INITIATOR \ - +(chan)*(MCF548X_FEC1_RX_INITIATOR \ - -MCF548X_FEC0_RX_INITIATOR)) -#define MCF548X_FEC0_TX_INITIATOR (17) -#define MCF548X_FEC1_TX_INITIATOR (31) -#define MCF548X_FEC_TX_INITIATOR(chan) (MCF548X_FEC0_TX_INITIATOR \ - +(chan)*(MCF548X_FEC1_TX_INITIATOR \ - -MCF548X_FEC0_TX_INITIATOR)) - -/* BD and parameters are stored in SRAM(refer to sdma.h) */ -#define MCF548X_FEC_BD_BASE ETH_BD_BASE - -/* RBD bits definitions */ -#define MCF548X_FEC_RBD_EMPTY 0x8000 /* Buffer is empty */ -#define MCF548X_FEC_RBD_WRAP 0x2000 /* Last BD in ring */ -#define MCF548X_FEC_RBD_INT 0x1000 /* Interrupt */ -#define MCF548X_FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */ -#define MCF548X_FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */ -#define MCF548X_FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */ -#define MCF548X_FEC_RBD_MC 0x0040 /* The received frame is multicast frame */ -#define MCF548X_FEC_RBD_LG 0x0020 /* Frame length violation */ -#define MCF548X_FEC_RBD_NO 0x0010 /* Nonoctet align frame */ -#define MCF548X_FEC_RBD_SH 0x0008 /* Short frame, FEC does not support SH and this bit is always cleared */ -#define MCF548X_FEC_RBD_CR 0x0004 /* CRC error */ -#define MCF548X_FEC_RBD_OV 0x0002 /* Receive FIFO overrun */ -#define MCF548X_FEC_RBD_TR 0x0001 /* The receive frame is truncated */ -#define MCF548X_FEC_RBD_ERR (MCF548X_FEC_RBD_LG | \ - MCF548X_FEC_RBD_NO | \ - MCF548X_FEC_RBD_CR | \ - MCF548X_FEC_RBD_OV | \ - MCF548X_FEC_RBD_TR) - -/* TBD bits definitions */ -#define MCF548X_FEC_TBD_READY 0x8000 /* Buffer is ready */ -#define MCF548X_FEC_TBD_WRAP 0x2000 /* Last BD in ring */ -#define MCF548X_FEC_TBD_INT 0x1000 /* Interrupt */ -#define MCF548X_FEC_TBD_LAST 0x0800 /* Buffer is last in frame */ -#define MCF548X_FEC_TBD_TC 0x0400 /* Transmit the CRC */ -#define MCF548X_FEC_TBD_ABC 0x0200 /* Append bad CRC */ - -#define FEC_INTR_MASK_USED \ -(MCF548X_FEC_EIMR_LC | MCF548X_FEC_EIMR_RL | \ - MCF548X_FEC_EIMR_XFUN | MCF548X_FEC_EIMR_XFERR | MCF548X_FEC_EIMR_RFERR) - -typedef enum { - FEC_STATE_RESTART_0, - FEC_STATE_RESTART_1, - FEC_STATE_NORMAL, -} fec_state; - -/* - * Device data - */ -struct mcf548x_enet_struct { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int chan; - fec_state state; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - MCD_bufDescFec *rxBd; - MCD_bufDescFec *txBd; - int rxDmaChan; /* dma task */ - int txDmaChan; /* dma task */ - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * MDIO/Phy info - */ - struct rtems_mdio_info mdio_info; - int phy_default; - int phy_chan; /* which fec channel services this phy access? */ - int media_state; /* (last detected) state of media */ - - unsigned long rxInterrupts; - unsigned long rxNotLast; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxBadCRC; - unsigned long rxFIFOError; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txLateCollision; - unsigned long txUnderrun; - unsigned long txFIFOError; - unsigned long txMisaligned; - unsigned long rxNotFirst; - unsigned long txRetryLimit; - }; - -static struct mcf548x_enet_struct enet_driver[NIFACES]; - -static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon); - -static void fec_send_event(rtems_id task) -{ - rtems_bsdnet_event_send(task, FEC_EVENT); -} - -static void fec_wait_for_event(void) -{ - rtems_event_set out; - rtems_bsdnet_event_receive( - FEC_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &out - ); -} - -static void mcf548x_fec_request_restart(struct mcf548x_enet_struct *sc) -{ - sc->state = FEC_STATE_RESTART_0; - fec_send_event(sc->txDaemonTid); - fec_send_event(sc->rxDaemonTid); -} - -/* - * Function: MCF548X_eth_addr_filter_set - * - * Description: Set individual address filter for unicast address and - * set physical address registers. - * - * Returns: void - * - * Notes: - * - */ -static void mcf548x_eth_addr_filter_set(struct mcf548x_enet_struct *sc) { - unsigned char *mac; - unsigned char currByte; /* byte for which to compute the CRC */ - int byte; /* loop - counter */ - int bit; /* loop - counter */ - unsigned long crc = 0xffffffff; /* initial value */ - int chan = sc->chan; - - /* - * Get the mac address of ethernet controller - */ - mac = (unsigned char *)(&sc->arpcom.ac_enaddr); - - /* - * The algorithm used is the following: - * we loop on each of the six bytes of the provided address, - * and we compute the CRC by left-shifting the previous - * value by one position, so that each bit in the current - * byte of the address may contribute the calculation. If - * the latter and the MSB in the CRC are different, then - * the CRC value so computed is also ex-ored with the - * "polynomium generator". The current byte of the address - * is also shifted right by one bit at each iteration. - * This is because the CRC generatore in hardware is implemented - * as a shift-register with as many ex-ores as the radixes - * in the polynomium. This suggests that we represent the - * polynomiumm itsc as a 32-bit constant. - */ - for(byte = 0; byte < 6; byte++) - { - - currByte = mac[byte]; - - for(bit = 0; bit < 8; bit++) - { - - if((currByte & 0x01) ^ (crc & 0x01)) - { - - crc >>= 1; - crc = crc ^ 0xedb88320; - - } - else - { - - crc >>= 1; - - } - - currByte >>= 1; - - } - - } - - crc = crc >> 26; - - /* - * Set individual hash table register - */ - if(crc >= 32) - { - - MCF548X_FEC_IAUR(chan) = (1 << (crc - 32)); - MCF548X_FEC_IALR(chan) = 0; - - } - else - { - - MCF548X_FEC_IAUR(chan) = 0; - MCF548X_FEC_IALR(chan) = (1 << crc); - - } - - /* - * Set physical address - */ - MCF548X_FEC_PALR(chan) = ((mac[0] << 24) + - (mac[1] << 16) + - (mac[2] << 8) + - mac[3]); - MCF548X_FEC_PAUR(chan) = ((mac[4] << 24) - + (mac[5] << 16)) + 0x8808; - - } - - -/* - * Function: mcf548x_eth_mii_read - * - * Description: Read a media independent interface (MII) register on an - * 18-wire ethernet tranceiver (PHY). Please see your PHY - * documentation for the register map. - * - * Returns: 0 if ok - * - * Notes: - * - */ -int mcf548x_eth_mii_read( - int phyAddr, /* PHY number to access or -1 */ - void *uarg, /* unit argument */ - unsigned regAddr, /* register address */ - uint32_t *retVal) /* ptr to read buffer */ -{ - struct mcf548x_enet_struct *sc = uarg; - int timeout = 0xffff; - int chan = sc->phy_chan; - - /* - * reading from any PHY's register is done by properly - * programming the FEC's MII data register. - */ - MCF548X_FEC_MMFR(chan) = (MCF548X_FEC_MMFR_ST_01 | - MCF548X_FEC_MMFR_OP_READ | - MCF548X_FEC_MMFR_TA_10 | - MCF548X_FEC_MMFR_PA(phyAddr) | - MCF548X_FEC_MMFR_RA(regAddr)); - - /* - * wait for the related interrupt - */ - while ((timeout--) && (!(MCF548X_FEC_EIR(chan) & MCF548X_FEC_EIR_MII))); - - if(timeout == 0) { - -#ifdef ETH_DEBUG - iprintf ("Read MDIO failed..." "\r\n"); -#endif - - return 1; - - } - - /* - * clear mii interrupt bit - */ - MCF548X_FEC_EIR(chan) = MCF548X_FEC_EIR_MII; - - /* - * it's now safe to read the PHY's register - */ - *retVal = (unsigned short) MCF548X_FEC_MMFR(chan); - - return 0; - -} - -/* - * Function: mcf548x_eth_mii_write - * - * Description: Write a media independent interface (MII) register on an - * 18-wire ethernet tranceiver (PHY). Please see your PHY - * documentation for the register map. - * - * Returns: Success (boolean) - * - * Notes: - * - */ -static int mcf548x_eth_mii_write( - int phyAddr, /* PHY number to access or -1 */ - void *uarg, /* unit argument */ - unsigned regAddr, /* register address */ - uint32_t data) /* write data */ -{ - struct mcf548x_enet_struct *sc = uarg; - int chan = sc->phy_chan; - int timeout = 0xffff; - - MCF548X_FEC_MMFR(chan) = (MCF548X_FEC_MMFR_ST_01 | - MCF548X_FEC_MMFR_OP_WRITE | - MCF548X_FEC_MMFR_TA_10 | - MCF548X_FEC_MMFR_PA(phyAddr) | - MCF548X_FEC_MMFR_RA(regAddr) | - MCF548X_FEC_MMFR_DATA(data)); - - /* - * wait for the MII interrupt - */ - while ((timeout--) && (!(MCF548X_FEC_EIR(chan) & MCF548X_FEC_EIR_MII))); - - if(timeout == 0) - { - -#ifdef ETH_DEBUG - iprintf ("Write MDIO failed..." "\r\n"); -#endif - - return 1; - - } - - /* - * clear MII interrupt bit - */ - MCF548X_FEC_EIR(chan) = MCF548X_FEC_EIR_MII; - - return 0; - - } - - -/* - * Function: mcf548x_fec_reset - * - * Description: Reset a running ethernet driver including the hardware - * FIFOs and the FEC. - * - * Returns: Success (boolean) - * - * Notes: - * - */ -static void mcf548x_fec_reset(struct mcf548x_enet_struct *sc) { - volatile int delay; - int chan = sc->chan; - /* - * Clear FIFO status registers - */ - MCF548X_FEC_FECRFSR(chan) = ~0; - MCF548X_FEC_FECTFSR(chan) = ~0; - - /* - * reset the FIFOs - */ - MCF548X_FEC_FRST(chan) = 0x03000000; - - for (delay = 0;delay < 16*4;delay++) {}; - - MCF548X_FEC_FRST(chan) = 0x01000000; - - /* - * Issue a reset command to the FEC chip - */ - MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_RESET; - - /* - * wait at least 16 clock cycles - */ - for (delay = 0;delay < 16*4;delay++) {}; -} - - -/* - * Function: mcf548x_fec_off - * - * Description: Stop the FEC and disable the ethernet SmartComm tasks. - * This function "turns off" the driver. - * - * Returns: void - * - * Notes: - * - */ -void mcf548x_fec_off(struct mcf548x_enet_struct *sc) - { - int counter = 0xffff; - int chan = sc->chan; - - -#if defined(ETH_DEBUG) - uint32_t phyStatus; - int i; - - for(i = 0; i < 9; i++) - { - - mcf548x_eth_mii_read(sc->phy_default, sc, i, &phyStatus); - iprintf ("Mii reg %d: 0x%04lx" "\r\n", i, phyStatus); - - } - - for(i = 16; i < 21; i++) - { - - mcf548x_eth_mii_read(sc->phy_default, sc, i, &phyStatus); - iprintf ("Mii reg %d: 0x%04lx" "\r\n", i, phyStatus); - - } - for(i = 0; i < 32; i++) - { - - mcf548x_eth_mii_read(i, sc, 0, &phyStatus); - iprintf ("Mii Phy=%d, reg 0: 0x%04lx" "\r\n", i, phyStatus); - - } -#endif /* ETH_DEBUG */ - - /* - * block FEC chip interrupts - */ - MCF548X_FEC_EIMR(chan) = 0; - - /* - * issue graceful stop command to the FEC transmitter if necessary - */ - MCF548X_FEC_TCR(chan) |= MCF548X_FEC_TCR_GTS; - - /* - * wait for graceful stop to register - * FIXME: add rtems_task_wake_after here, if it takes to long - */ - while((counter--) && (!( MCF548X_FEC_EIR(chan) & MCF548X_FEC_EIR_GRA))); - - /* - * Disable the SmartDMA transmit and receive tasks. - */ - MCD_killDma( sc->rxDmaChan ); - MCD_killDma( sc->txDmaChan ); - /* - * Disable transmit / receive interrupts - */ - mcdma_glue_irq_disable(sc->txDmaChan); - mcdma_glue_irq_disable(sc->rxDmaChan); - - /* - * Disable the Ethernet Controller - */ - MCF548X_FEC_ECR(chan) &= ~(MCF548X_FEC_ECR_ETHER_EN); -} - -/* - * MCF548X FEC interrupt handler - */ -void mcf548x_fec_irq_handler(rtems_vector_number vector) -{ - struct mcf548x_enet_struct *sc; - volatile uint32_t ievent; - int chan; - - sc = &(enet_driver[MCF548X_FEC_VECTOR2CHAN(vector)]); - chan = sc->chan; - ievent = MCF548X_FEC_EIR(chan); - - MCF548X_FEC_EIR(chan) = ievent; - /* - * check errors, update statistics - */ - if (ievent & MCF548X_FEC_EIR_LC) { - sc->txLateCollision++; - } - if (ievent & MCF548X_FEC_EIR_RL) { - sc->txRetryLimit++; - } - if (ievent & MCF548X_FEC_EIR_XFUN) { - sc->txUnderrun++; - } - if (ievent & MCF548X_FEC_EIR_XFERR) { - sc->txFIFOError++; - } - if (ievent & MCF548X_FEC_EIR_RFERR) { - sc->rxFIFOError++; - } - /* - * fatal error ocurred? - */ - if (ievent & (MCF548X_FEC_EIR_RFERR | MCF548X_FEC_EIR_XFERR)) { - MCF548X_FEC_EIMR(chan) &=~(MCF548X_FEC_EIMR_RFERR | MCF548X_FEC_EIMR_XFERR); - printk("fifo\n"); - mcf548x_fec_request_restart(sc); - } -} - -/* - * MCF548X DMA ethernet interrupt handler - */ -void mcf548x_mcdma_rx_irq_handler(void * param) -{ - struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)param; - /* Frame received? */ - if(MCDMA_GET_PENDING(sc->rxDmaChan)) { - MCDMA_CLR_PENDING(sc->rxDmaChan); - - mcdma_glue_irq_disable(sc->rxDmaChan);/*Disable receive ints*/ - sc->rxInterrupts++; /* Rx int has occurred */ - fec_send_event(sc->rxDaemonTid); - } -} - -/* - * MCF548X DMA ethernet interrupt handler - */ -void mcf548x_mcdma_tx_irq_handler(void * param) -{ - struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)param; - - /* Buffer transmitted or transmitter error? */ - if(MCDMA_GET_PENDING(sc->txDmaChan)) { - - MCDMA_CLR_PENDING(sc->txDmaChan); - - mcdma_glue_irq_disable(sc->txDmaChan);/*Disable tx ints*/ - - sc->txInterrupts++; /* Tx int has occurred */ - - fec_send_event(sc->txDaemonTid); - } -} - -/* - * Function: mcf548x_fec_initialize_hardware - * - * Description: Configure the MCF548X FEC registers and enable the - * SmartComm tasks. This function "turns on" the driver. - * - * Returns: void - * - * Notes: - * - */ -static void mcf548x_fec_initialize_hardware(struct mcf548x_enet_struct *sc) - { - int chan = sc->chan; - - /* - * Reset mcf548x FEC - */ - mcf548x_fec_reset(sc); - - /* - * Clear FEC-Lite interrupt event register (IEVENT) - */ - MCF548X_FEC_EIR(chan) = MCF548X_FEC_EIR_CLEAR_ALL; - - /* - * Set interrupt mask register - */ - MCF548X_FEC_EIMR(chan) = FEC_INTR_MASK_USED; - /* - * Set FEC-Lite receive control register (R_CNTRL) - * frame length=1518, MII mode for 18-wire-transceiver - */ - MCF548X_FEC_RCR(chan) = (MCF548X_FEC_RCR_MAX_FL(ETHER_MAX_LEN) - | MCF548X_FEC_RCR_FCE - | MCF548X_FEC_RCR_MII_MODE); - - /* - * Set FEC-Lite transmit control register (X_CNTRL) - * full-duplex, heartbeat disabled - */ - MCF548X_FEC_TCR(chan) = MCF548X_FEC_TCR_FDEN; - - - - /* - * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock(33Mhz) - * and do not drop the Preamble. - */ - MCF548X_FEC_MSCR(chan) = MCF548X_FEC_MSCR_MII_SPEED(7); /* ipb_clk = 33 MHz */ - - /* - * Set Opcode/Pause Duration Register - */ - MCF548X_FEC_PAUR(chan) = 0x00010020; - - /* - * Set Rx FIFO alarm and granularity value - */ - MCF548X_FEC_FECRFCR(chan) = (MCF548X_FEC_FECRFCR_FRM - | MCF548X_FEC_FECRFCR_GR(0x7)); - MCF548X_FEC_FECRFAR(chan) = MCF548X_FEC_FECRFAR_ALARM(256); - - /* - * Set Tx FIFO granularity value - */ - MCF548X_FEC_FECTFCR(chan) = (MCF548X_FEC_FECTFCR_FRM - | MCF548X_FEC_FECTFCR_GR(7)); - - /* - * Set transmit fifo watermark register (X_WMRK), default = 64 - */ - MCF548X_FEC_FECTFAR(chan) = MCF548X_FEC_FECTFAR_ALARM(512); - MCF548X_FEC_FECTFWR(chan) = MCF548X_FEC_FECTFWR_X_WMRK_256; - - /* - * Set individual address filter for unicast address - * and set physical address registers. - */ - mcf548x_eth_addr_filter_set(sc); - - /* - * Set multicast address filter - */ - MCF548X_FEC_GAUR(chan) = 0x00000000; - MCF548X_FEC_GALR(chan) = 0x00000000; - - /* - * enable CRC in finite state machine register - */ - MCF548X_FEC_CTCWR(chan) = MCF548X_FEC_CTCWR_TFCW | MCF548X_FEC_CTCWR_CRC; - } - - -/* - * Send packet (caller provides header). - */ -static void mcf548x_fec_tx_start(struct ifnet *ifp) - { - - struct mcf548x_enet_struct *sc = ifp->if_softc; - - ifp->if_flags |= IFF_OACTIVE; - - fec_send_event(sc->txDaemonTid); - - } - -static void fec_start_dma_and_controller(struct mcf548x_enet_struct *sc) -{ - int chan = sc->chan; - int mcdma_rc; - /* - * Enable the SmartDMA receive task. - */ - mcdma_rc = MCD_startDma - (sc->rxDmaChan, /* the channel on which to run the DMA */ - (void *)sc->rxBd, /* the address to move data from, or buffer-descriptor addr */ - 0, /* the amount to increment the source address per transfer */ - (void *)&MCF548X_FEC_FECRFDR(chan), /* the address to move data to */ - 0, /* the amount to increment the destination address per transfer */ - ETHER_MAX_LEN, /* the number of bytes to transfer independent of the transfer size */ - 0, /* the number bytes in of each data movement (1, 2, or 4) */ - MCF548X_FEC_RX_INITIATOR(chan), /* what device initiates the DMA */ - 2, /* priority of the DMA */ - 0 /* flags describing the DMA */ - | MCD_FECRX_DMA - | MCD_INTERRUPT - | MCD_TT_FLAGS_CW - | MCD_TT_FLAGS_RL - | MCD_TT_FLAGS_SP - , - 0 /* a description of byte swapping, bit swapping, and CRC actions */ - | MCD_NO_CSUM - | MCD_NO_BYTE_SWAP - ); - if (mcdma_rc != MCD_OK) { - rtems_panic("FEC: cannot start rx DMA"); - } - mcdma_rc = MCD_startDma - (sc->txDmaChan, /* the channel on which to run the DMA */ - (void *)sc->txBd, /* the address to move data from, or buffer-descriptor addr */ - 0, /* the amount to increment the source address per transfer */ - (void *)&MCF548X_FEC_FECTFDR(chan), /* the address to move data to */ - 0, /* the amount to increment the destination address per transfer */ - ETHER_MAX_LEN, /* the number of bytes to transfer independent of the transfer size */ - 0, /* the number bytes in of each data movement (1, 2, or 4) */ - MCF548X_FEC_TX_INITIATOR(chan), /* what device initiates the DMA */ - 1, /* priority of the DMA */ - 0 /* flags describing the DMA */ - | MCD_FECTX_DMA - | MCD_INTERRUPT - | MCD_TT_FLAGS_CW - | MCD_TT_FLAGS_RL - | MCD_TT_FLAGS_SP - , - 0 /* a description of byte swapping, bit swapping, and CRC actions */ - | MCD_NO_CSUM - | MCD_NO_BYTE_SWAP - ); - if (mcdma_rc != MCD_OK) { - rtems_panic("FEC: cannot start tx DMA"); - } - - /* - * Enable FEC-Lite controller - */ - MCF548X_FEC_ECR(chan) |= MCF548X_FEC_ECR_ETHER_EN; -} - -static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon) -{ - if (sc->state == FEC_STATE_RESTART_1) { - mcf548x_fec_initialize_hardware(sc); - fec_start_dma_and_controller(sc); - sc->state = FEC_STATE_NORMAL; - } else { - sc->state = FEC_STATE_RESTART_1; - } - - fec_send_event(otherDaemon); - while (sc->state != FEC_STATE_NORMAL) { - fec_wait_for_event(); - } -} - -static void fec_reset_bd_and_discard_tx_frames( - int bdCount, - MCD_bufDescFec *bdRing, - struct mbuf **mbufs -) -{ - int bdIndex = 0; - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - bool bdIsLast = bdIndex == bdCount - 1; - struct mbuf *m = mbufs[bdIndex]; - - bdRing[bdIndex].statCtrl = bdIsLast ? MCF548X_FEC_TBD_WRAP : 0; - - if (m != NULL) { - mbufs[bdIndex] = NULL; - m_free(m); - } - } -} - -static void fec_reset_tx_dma( - int dmaChan, - int bdCount, - MCD_bufDescFec *bdRing, - struct mbuf **mbufs, - struct mbuf *m -) -{ - if (m != NULL) { - m_freem(m); - } - - MCD_killDma(dmaChan); - - fec_reset_bd_and_discard_tx_frames(bdCount, bdRing, mbufs); -} - -static struct mbuf *fec_next_fragment( - struct ifnet *ifp, - struct mbuf *m, - bool *isFirst -) -{ - struct mbuf *n = NULL; - - *isFirst = false; - - while (true) { - if (m == NULL) { - IF_DEQUEUE(&ifp->if_snd, m); - - if (m != NULL) { - *isFirst = true; - } else { - ifp->if_flags &= ~IFF_OACTIVE; - - return NULL; - } - } - - if (m->m_len > 0) { - break; - } else { - m = m_free(m); - } - } - - n = m->m_next; - while (n != NULL && n->m_len <= 0) { - n = m_free(n); - } - m->m_next = n; - - return m; -} - -static bool fec_transmit( - struct ifnet *ifp, - int dmaChan, - int bdCount, - MCD_bufDescFec *bdRing, - struct mbuf **mbufs, - int *bdIndexPtr, - struct mbuf **mPtr, - MCD_bufDescFec **firstPtr -) -{ - bool bdShortage = false; - int bdIndex = *bdIndexPtr; - struct mbuf *m = *mPtr; - MCD_bufDescFec *first = *firstPtr; - - while (true) { - MCD_bufDescFec *bd = &bdRing[bdIndex]; - - MCDMA_CLR_PENDING(dmaChan); - if ((bd->statCtrl & MCF548X_FEC_TBD_READY) == 0) { - struct mbuf *done = mbufs[bdIndex]; - bool isFirst = false; - - if (done != NULL) { - m_free(done); - mbufs[bdIndex] = NULL; - } - - m = fec_next_fragment(ifp, m, &isFirst); - if (m != NULL) { - bool bdIsLast = bdIndex == bdCount - 1; - u16 status = bdIsLast ? MCF548X_FEC_TBD_WRAP : 0; - - bd->length = (u16) m->m_len; - bd->dataPointer = mtod(m, u32); - - mbufs[bdIndex] = m; - - rtems_cache_flush_multiple_data_lines(mtod(m, void *), m->m_len); - - if (isFirst) { - first = bd; - } else { - status |= MCF548X_FEC_TBD_READY; - } - - if (m->m_next != NULL) { - bd->statCtrl = status; - } else { - bd->statCtrl = status | MCF548X_FEC_TBD_INT | MCF548X_FEC_TBD_LAST; - first->statCtrl |= MCF548X_FEC_TBD_READY; - MCD_continDma(dmaChan); - } - - m = m->m_next; - } else { - break; - } - } else { - bdShortage = true; - break; - } - - if (bdIndex < bdCount - 1) { - ++bdIndex; - } else { - bdIndex = 0; - } - } - - *bdIndexPtr = bdIndex; - *mPtr = m; - *firstPtr = first; - - return bdShortage; -} - -static MCD_bufDescFec *fec_init_tx_dma( - MCD_bufDescFec *bdRing, - int bdCount -) -{ - int bdIndex; - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - bool bdIsLast = bdIndex == bdCount - 1; - - bdRing[bdIndex].dataPointer = 0; - bdRing[bdIndex].length = 0; - bdRing[bdIndex].statCtrl = bdIsLast ? MCF548X_FEC_RBD_WRAP : 0; - } - - return bdRing; -} - -static void mcf548x_fec_txDaemon(void *arg) -{ - struct mcf548x_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - int dmaChan = sc->txDmaChan; - int bdIndex = 0; - int bdCount = sc->txBdCount; - struct mbuf **mbufs = &sc->txMbuf[0]; - struct mbuf *m = NULL; - MCD_bufDescFec *bdRing = fec_init_tx_dma(sc->txBd, bdCount); - MCD_bufDescFec *first = NULL; - bool bdShortage = false; - - memset(mbufs, 0, bdCount * sizeof(*mbufs)); - - while (true) { - if (bdShortage) { - mcdma_glue_irq_enable(dmaChan); - } - fec_wait_for_event(); - - if (sc->state != FEC_STATE_NORMAL) { - fec_reset_tx_dma(dmaChan, bdCount, bdRing, mbufs, m); - mcf548x_fec_restart(sc, sc->rxDaemonTid); - bdIndex = 0; - m = NULL; - first = NULL; - } - - bdShortage = fec_transmit( - ifp, - dmaChan, - bdCount, - bdRing, - mbufs, - &bdIndex, - &m, - &first - ); - } -} - -static struct mbuf *fec_add_mbuf( - int how, - struct ifnet *ifp, - MCD_bufDescFec *bd, - bool bdIsLast -) -{ - struct mbuf *m; - - MGETHDR(m, how, MT_DATA); - if (m != NULL) { - MCLGET(m, how); - if ((m->m_flags & M_EXT) != 0) { - m->m_pkthdr.rcvif = ifp; - - rtems_cache_invalidate_multiple_data_lines(mtod(m, void *), ETHER_MAX_LEN); - - bd->dataPointer = mtod(m, u32); - bd->length = ETHER_MAX_LEN; - bd->statCtrl = MCF548X_FEC_RBD_EMPTY - | MCF548X_FEC_RBD_INT - | (bdIsLast ? MCF548X_FEC_RBD_WRAP : 0); - } else { - m_free(m); - } - } - - return m; -} - -static MCD_bufDescFec *fec_init_rx_dma( - MCD_bufDescFec *bdRing, - struct ifnet *ifp, - int bdCount, - struct mbuf **mbufs -) -{ - int bdIndex; - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - bool bdIsLast = bdIndex == bdCount - 1; - - mbufs[bdIndex] = fec_add_mbuf(M_WAIT, ifp, &bdRing[bdIndex], bdIsLast); - } - - return bdRing; -} - -static void fec_reset_rx_dma( - int dmaChan, - int bdCount, - MCD_bufDescFec *bdRing -) -{ - int bdIndex; - - MCD_killDma(dmaChan); - - for (bdIndex = 0; bdIndex < bdCount - 1; ++bdIndex) { - bdRing[bdIndex].length = ETHER_MAX_LEN; - bdRing[bdIndex].statCtrl = MCF548X_FEC_RBD_EMPTY | MCF548X_FEC_RBD_INT; - } - - bdRing[bdIndex].length = ETHER_MAX_LEN; - bdRing[bdIndex].statCtrl = MCF548X_FEC_RBD_EMPTY | MCF548X_FEC_RBD_INT | MCF548X_FEC_RBD_WRAP; -} - -static int fec_ether_input( - struct ifnet *ifp, - int dmaChan, - int bdIndex, - int bdCount, - MCD_bufDescFec *bdRing, - struct mbuf **mbufs -) -{ - while (true) { - bool bdIsLast = bdIndex == bdCount - 1; - MCD_bufDescFec *bd = &bdRing[bdIndex]; - struct mbuf *m = mbufs[bdIndex]; - struct mbuf *n; - u16 status; - - MCDMA_CLR_PENDING(dmaChan); - status = bd->statCtrl; - - if ((status & MCF548X_FEC_RBD_EMPTY) != 0) { - break; - } - - n = fec_add_mbuf(0, ifp, bd, bdIsLast); - if (n != NULL) { - int len = bd->length - ETHER_HDR_LEN - ETHER_CRC_LEN; - struct ether_header *eh = mtod(m, struct ether_header *); - - m->m_len = len; - m->m_pkthdr.len = len; - m->m_data = mtod(m, char *) + ETHER_HDR_LEN; - - ether_input(ifp, eh, m); - } else { - n = m; - } - - mbufs[bdIndex] = n; - - if (bdIndex < bdCount - 1) { - ++bdIndex; - } else { - bdIndex = 0; - } - } - - return bdIndex; -} - -static void mcf548x_fec_rxDaemon(void *arg) -{ - struct mcf548x_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - int dmaChan = sc->rxDmaChan; - int bdIndex = 0; - int bdCount = sc->rxBdCount; - struct mbuf **mbufs = &sc->rxMbuf[0]; - MCD_bufDescFec *bdRing = fec_init_rx_dma(sc->rxBd, ifp, bdCount, mbufs); - - while (true) { - mcdma_glue_irq_enable(dmaChan); - fec_wait_for_event(); - - bdIndex = fec_ether_input(ifp, dmaChan, bdIndex, bdCount, bdRing, mbufs); - - if (sc->state != FEC_STATE_NORMAL) { - fec_reset_rx_dma(dmaChan, bdCount, bdRing); - mcf548x_fec_restart(sc, sc->txDaemonTid); - bdIndex = 0; - } - } -} - -/* - * Initialize and start the device - */ -static void mcf548x_fec_init(void *arg) -{ - struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - int chan = sc->chan; - rtems_isr_entry old_handler; - char *txTaskName = "FTx0"; - char *rxTaskName = "FRx0"; - if(sc->txDaemonTid == 0) - { - /* - * Allocate a set of BDs - */ - sc->rxBd = SRAM_RXBD_BASE(_SysSramBase,chan); - sc->txBd = SRAM_TXBD_BASE(_SysSramBase,chan); - - if(!sc->rxBd || !sc->txBd) - rtems_panic ("No memory for BDs"); - /* - * clear the BDs - */ - memset((void *)sc->rxBd,0,sc->rxBdCount * sizeof *(sc->rxBd)); - memset((void *)sc->txBd,0,sc->txBdCount * sizeof *(sc->txBd)); - /* - * Allocate a set of mbuf pointers - */ - sc->rxMbuf = - malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = - malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - - if(!sc->rxMbuf || !sc->txMbuf) - rtems_panic ("No memory for mbuf pointers"); - - sc->txDmaChan = MCDMA_FEC_TX_CHAN(chan); - sc->rxDmaChan = MCDMA_FEC_RX_CHAN(chan); - - mcdma_glue_init(SRAM_DMA_BASE(_SysSramBase)); - - /* - * Set up interrupts - */ - mcdma_glue_irq_install(sc->rxDmaChan, - mcf548x_mcdma_rx_irq_handler, - sc); - mcdma_glue_irq_install(sc->txDmaChan, - mcf548x_mcdma_tx_irq_handler, - sc); - if(rtems_interrupt_catch(mcf548x_fec_irq_handler, - MCF548X_FEC_IRQ_VECTOR(chan), - &old_handler)) { - rtems_panic ("Can't attach MFC54xx FEX interrupt handler\n"); - } - - bsp_interrupt_vector_enable(MCF548X_IRQ_FEC(chan)); - - MCF548X_FEC_EIMR(chan) = FEC_INTR_MASK_USED; - - /* - * Start driver tasks - */ - txTaskName[3] = '0'+chan; - rxTaskName[3] = '0'+chan; - sc->txDaemonTid = rtems_bsdnet_newproc(txTaskName, 4096, - mcf548x_fec_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc(rxTaskName, 4096, - mcf548x_fec_rxDaemon, sc); - } - - mcf548x_fec_request_restart(sc); - - /* - * Set flags appropriately - */ - if(ifp->if_flags & IFF_PROMISC) - MCF548X_FEC_RCR(chan) |= MCF548X_FEC_RCR_PROM; - else - MCF548X_FEC_RCR(chan) &= ~MCF548X_FEC_RCR_PROM; - - /* - * init timer so the "watchdog function gets called periodically - */ - ifp->if_timer = 1; - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - - -static void enet_stats (struct mcf548x_enet_struct *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Rx Not First:%-8lu", sc->rxNotFirst); - printf (" Rx Not Last:%-8lu\n", sc->rxNotLast); - printf (" Rx Giant:%-8lu", sc->rxGiant); - printf (" Rx Non-octet:%-8lu", sc->rxNonOctet); - printf (" Rx Bad CRC:%-8lu\n", sc->rxBadCRC); - printf (" Rx FIFO Error:%-8lu", sc->rxFIFOError); - printf (" Rx Collision:%-8lu", sc->rxCollision); - - printf (" Tx Interrupts:%-8lu\n", sc->txInterrupts); - printf (" Tx Deferred:%-8lu", sc->txDeferred); - printf (" Tx Late Collision:%-8lu", sc->txLateCollision); - printf (" Tx Retransmit Limit:%-8lu\n", sc->txRetryLimit); - printf (" Tx Underrun:%-8lu", sc->txUnderrun); - printf (" Tx FIFO Error:%-8lu", sc->txFIFOError); - printf (" Tx Misaligned:%-8lu\n", sc->txMisaligned); - -} - -int32_t mcf548x_fec_setMultiFilter(struct ifnet *ifp) -{ - /*struct mcf548x_enet_struct *sc = ifp->if_softc; */ - /* XXX anything to do? */ - return 0; -} - - -/* - * Driver ioctl handler - */ -static int mcf548x_fec_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) - { - struct mcf548x_enet_struct *sc = ifp->if_softc; - int error = 0; - - switch(command) - { - - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - rtems_mii_ioctl (&(sc->mdio_info),sc,command,(void *)data); - break; - - case SIOCGIFADDR: - case SIOCSIFADDR: - - ether_ioctl(ifp, command, data); - - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: { - struct ifreq* ifr = (struct ifreq*) data; - error = (command == SIOCADDMULTI) - ? ether_addmulti(ifr, &sc->arpcom) - : ether_delmulti(ifr, &sc->arpcom); - - if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) - error = mcf548x_fec_setMultiFilter(ifp); - else - error = 0; - } - break; - } - - case SIOCSIFFLAGS: - - switch(ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - - case IFF_RUNNING: - - mcf548x_fec_off(sc); - - break; - - case IFF_UP: - - mcf548x_fec_init(sc); - - break; - - case IFF_UP | IFF_RUNNING: - - mcf548x_fec_off(sc); - mcf548x_fec_init(sc); - - break; - - default: - break; - - } - - break; - - case SIO_RTEMS_SHOW_STATS: - - enet_stats(sc); - - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - - error = EINVAL; - - break; - - } - - return error; - - } - - -/* - * init the PHY and adapt FEC settings - */ -int mcf548x_fec_mode_adapt(struct ifnet *ifp) -{ - int result = 0; - struct mcf548x_enet_struct *sc = ifp->if_softc; - int media = IFM_MAKEWORD( 0, 0, 0, sc->phy_default); - int chan = sc->chan; - - /* - * fetch media status - */ - result = mcf548x_fec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media); - if (result != 0) { - return result; - } - /* - * status is unchanged? then do nothing - */ - if (media == sc->media_state) { - return 0; - } - /* - * otherwise: for the first call, try to negotiate mode - */ - if (sc->media_state == 0) { - /* - * set media status: set auto negotiation -> start auto-negotiation - */ - media = IFM_MAKEWORD(0,IFM_AUTO,0,sc->phy_default); - result = mcf548x_fec_ioctl(ifp,SIOCSIFMEDIA,(caddr_t)&media); - if (result != 0) { - return result; - } - /* - * wait for auto-negotiation to terminate - */ - do { - media = IFM_MAKEWORD(0,0,0,sc->phy_default); - result = mcf548x_fec_ioctl(ifp,SIOCGIFMEDIA,(caddr_t)&media); - if (result != 0) { - return result; - } - } while (IFM_NONE == IFM_SUBTYPE(media)); - } - - /* - * now set HW according to media results: - */ - - /* - * if we are half duplex then switch to half duplex - */ - if (0 == (IFM_FDX & IFM_OPTIONS(media))) { - MCF548X_FEC_TCR(chan) &= ~MCF548X_FEC_TCR_FDEN; - } - else { - MCF548X_FEC_TCR(chan) |= MCF548X_FEC_TCR_FDEN; - } - /* - * store current media state for future compares - */ - sc->media_state = media; - - return 0; -} - -/* - * periodically poll the PHY. if mode has changed, - * then adjust the FEC settings - */ -static void mcf548x_fec_watchdog( struct ifnet *ifp) -{ - mcf548x_fec_mode_adapt(ifp); - ifp->if_timer = FEC_WATCHDOG_TIMEOUT; -} - -/* - * Attach the MCF548X fec driver to the system - */ -int rtems_mcf548x_fec_driver_attach(struct rtems_bsdnet_ifconfig *config) - { - struct mcf548x_enet_struct *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* - * Parse driver name - */ - if((unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NIFACES)) - { - - printf ("Bad FEC unit number.\n"); - return 0; - - } - - sc = &enet_driver[unitNumber - 1]; - sc->chan = unitNumber-1; - ifp = &sc->arpcom.ac_if; - - if(ifp->if_softc != NULL) - { - - printf ("Driver already in use.\n"); - return 0; - - } - - /* - * Process options - */ -#if NVRAM_CONFIGURE == 1 - - /* Configure from NVRAM */ - if(addr = nvram->ipaddr) - { - - /* We have a non-zero entry, copy the value */ - if(pAddr = malloc(INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT)) - config->ip_address = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1); - else - rtems_panic("Can't allocate ip_address buffer!\n"); - - } - - if(addr = nvram->netmask) - { - - /* We have a non-zero entry, copy the value */ - if (pAddr = malloc (INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT)) - config->ip_netmask = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1); - else - rtems_panic("Can't allocate ip_netmask buffer!\n"); - - } - - /* Ethernet address requires special handling -- it must be copied into - * the arpcom struct. The following if construct serves only to give the - * User Area NVRAM parameter the highest priority. - * - * If the ethernet address is specified in NVRAM, go ahead and copy it. - * (ETHER_ADDR_LEN = 6 bytes). - */ - if(nvram->enaddr[0] || nvram->enaddr[1] || nvram->enaddr[2]) - { - - /* Anything in the first three bytes indicates a non-zero entry, copy value */ - memcpy((void *)sc->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN); - - } - else - if(config->hardware_address) - { - - /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */ - memcpy((void *)sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - -#else /* NVRAM_CONFIGURE != 1 */ - - if(config->hardware_address) - { - - memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - - } - -#endif /* NVRAM_CONFIGURE != 1 */ -#ifdef HAS_UBOOT - if ((sc->arpcom.ac_enaddr[0] == 0) && - (sc->arpcom.ac_enaddr[1] == 0) && - (sc->arpcom.ac_enaddr[2] == 0)) { - memcpy( - (void *)sc->arpcom.ac_enaddr, - bsp_uboot_board_info.bi_enetaddr, - ETHER_ADDR_LEN - ); - } -#endif -#ifdef HAS_DBUG - if ((sc->arpcom.ac_enaddr[0] == 0) && - (sc->arpcom.ac_enaddr[1] == 0) && - (sc->arpcom.ac_enaddr[2] == 0)) { - memcpy( - (void *)sc->arpcom.ac_enaddr, - DBUG_SETTINGS.macaddr, - ETHER_ADDR_LEN - ); - } -#endif - if ((sc->arpcom.ac_enaddr[0] == 0) && - (sc->arpcom.ac_enaddr[1] == 0) && - (sc->arpcom.ac_enaddr[2] == 0)) { - /* There is no ethernet address provided, so it could be read - * from the Ethernet protocol block of SCC1 in DPRAM. - */ - rtems_panic("No Ethernet address specified!\n"); - } - if(config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - if(config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - - if(config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * setup info about mdio interface - */ - sc->mdio_info.mdio_r = mcf548x_eth_mii_read; - sc->mdio_info.mdio_w = mcf548x_eth_mii_write; - sc->mdio_info.has_gmii = 0; /* we do not support gigabit IF */ - - /* - * XXX: Although most hardware builders will assign the PHY addresses - * like this, this should be more configurable - */ - sc->phy_default = unitNumber-1; - sc->phy_chan = 0; /* assume all MII accesses are via FEC0 */ - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = mcf548x_fec_init; - ifp->if_ioctl = mcf548x_fec_ioctl; - ifp->if_start = mcf548x_fec_tx_start; - ifp->if_output = ether_output; - ifp->if_watchdog = mcf548x_fec_watchdog; /* XXX: timer is set in "init" */ - ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; - /*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); - - return 1; - } - - -int rtems_mcf548x_fec_driver_attach_detach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - if (attaching) { - return rtems_mcf548x_fec_driver_attach(config); - } - else { - return 0; - } -} - - diff --git a/c/src/lib/libbsp/m68k/mcf5235/Makefile.am b/c/src/lib/libbsp/m68k/mcf5235/Makefile.am index e6b30e5470..c036171923 100644 --- a/c/src/lib/libbsp/m68k/mcf5235/Makefile.am +++ b/c/src/lib/libbsp/m68k/mcf5235/Makefile.am @@ -38,7 +38,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5235/console/console.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5235/btimer/btimer.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5235/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache-mcf5235.c diff --git a/c/src/lib/libbsp/m68k/mcf5235/network/network.c b/c/src/lib/libbsp/m68k/mcf5235/network/network.c deleted file mode 100644 index 6c8fa88be2..0000000000 --- a/c/src/lib/libbsp/m68k/mcf5235/network/network.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * RTEMS/TCPIP driver for MCF5235 Fast Ethernet Controller - * - * TO DO: Check network stack code -- force longword alignment of all tx mbufs? - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 1 - -#define FEC_INTC0_TX_VECTOR (64+23) -#define FEC_INTC0_RX_VECTOR (64+27) - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses three or more buffer descriptors. - */ -#define RX_BUF_COUNT 32 -#define TX_BUF_COUNT 20 -#define TX_BD_PER_BUF 3 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define TX_INTERRUPT_EVENT RTEMS_EVENT_1 -#define RX_INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). - * Round off to nearest multiple of RBUF_ALIGN. - */ -#define MAX_MTU_SIZE 1518 -#define RBUF_ALIGN 4 -#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) - -#if (MCLBYTES < RBUF_SIZE) - #error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -typedef struct mcf5235BufferDescriptor_ { - volatile uint16_t status; - uint16_t length; - volatile void *buffer; -} mcf5235BufferDescriptor_t; - -/* - * Per-device data - */ -struct mcf5235_enet_struct { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - mcf5235BufferDescriptor_t *rxBdBase; - mcf5235BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long txInterrupts; - unsigned long txRawWait; - unsigned long txRealign; -}; -static struct mcf5235_enet_struct enet_driver[NIFACES]; - -static rtems_isr -mcf5235_fec_rx_interrupt_handler( rtems_vector_number v ) -{ - MCF5235_FEC_EIR = MCF5235_FEC_EIR_RXF; - MCF5235_FEC_EIMR &= ~MCF5235_FEC_EIMR_RXF; - enet_driver[0].rxInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].rxDaemonTid, RX_INTERRUPT_EVENT); -} - -static rtems_isr -mcf5235_fec_tx_interrupt_handler( rtems_vector_number v ) -{ - MCF5235_FEC_EIR = MCF5235_FEC_EIR_TXF; - MCF5235_FEC_EIMR &= ~MCF5235_FEC_EIMR_TXF; - enet_driver[0].txInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].txDaemonTid, TX_INTERRUPT_EVENT); -} - -/* - * Allocate buffer descriptors from (non-cached) on-chip static RAM - * Ensure 128-bit (16-byte) alignment - */ -extern char __SRAMBASE[]; - -static mcf5235BufferDescriptor_t * -mcf5235_bd_allocate(unsigned int count) -{ - static mcf5235BufferDescriptor_t *bdp = (mcf5235BufferDescriptor_t *)__SRAMBASE; - mcf5235BufferDescriptor_t *p = bdp; - - bdp += count; - if ((int)bdp & 0xF) - bdp = (mcf5235BufferDescriptor_t *)((char *)bdp + (16 - ((int)bdp & 0xF))); - return p; -} - -#if UNUSED -/* - * Read MII register - * Busy-waits, but transfer time should be short! - */ -static int -getMII(int phyNumber, int regNumber) -{ - MCF5235_FEC_MMFR = (0x1 << 30) | - (0x2 << 28) | - (phyNumber << 23) | - (regNumber << 18) | - (0x2 << 16); - while ((MCF5235_FEC_EIR & MCF5235_FEC_EIR_MII) == 0); - MCF5235_FEC_EIR = MCF5235_FEC_EIR_MII; - return MCF5235_FEC_MMFR & 0xFFFF; -} -#endif - -/* - * Write MII register - * Busy-waits, but transfer time should be short! - */ -static void -setMII(int phyNumber, int regNumber, int value) -{ - MCF5235_FEC_MMFR = (0x1 << 30) | - (0x1 << 28) | - (phyNumber << 23) | - (regNumber << 18) | - (0x2 << 16) | - (value & 0xFFFF); - while ((MCF5235_FEC_EIR & MCF5235_FEC_EIR_MII) == 0); - MCF5235_FEC_EIR = MCF5235_FEC_EIR_MII; -} - -static void -mcf5235_fec_initialize_hardware(struct mcf5235_enet_struct *sc) -{ - int i; - const unsigned char *hwaddr = 0; - rtems_status_code status; - rtems_isr_entry old_handler; - uint32_t clock_speed = get_CPU_clock_speed(); - - /* - * Issue reset to FEC - */ - MCF5235_FEC_ECR = MCF5235_FEC_ECR_RESET; - rtems_task_wake_after(1); - MCF5235_FEC_ECR = 0; - - /* - * Configuration of I/O ports is done outside of this function - */ -#if 0 - imm->gpio.pbcnt |= MCF5235_GPIO_PBCNT_SET_FEC; /* Set up port b FEC pins */ -#endif - - /* - * Set our physical address - */ - hwaddr = sc->arpcom.ac_enaddr; - MCF5235_FEC_PALR = (hwaddr[0] << 24) | (hwaddr[1] << 16) | - (hwaddr[2] << 8) | (hwaddr[3] << 0); - MCF5235_FEC_PAUR = (hwaddr[4] << 24) | (hwaddr[5] << 16); - - - /* - * Clear the hash table - */ - MCF5235_FEC_GAUR = 0; - MCF5235_FEC_GALR = 0; - - /* - * Set up receive buffer size - */ - MCF5235_FEC_EMRBR = 1520; /* Standard Ethernet */ - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = mcf5235_bd_allocate(sc->rxBdCount); - sc->txBdBase = mcf5235_bd_allocate(sc->txBdCount); - MCF5235_FEC_ERDSR = (int)sc->rxBdBase; - MCF5235_FEC_ETDSR = (int)sc->txBdBase; - - /* - * Set up Receive Control Register: - * Not promiscuous - * MII mode - * Full duplex - * No loopback - */ - MCF5235_FEC_RCR = MCF5235_FEC_RCR_MAX_FL(MAX_MTU_SIZE) | - MCF5235_FEC_RCR_MII_MODE; - - /* - * Set up Transmit Control Register: - * Full duplex - * No heartbeat - */ - MCF5235_FEC_TCR = MCF5235_FEC_TCR_FDEN; - - /* - * Initialize statistic counters - */ - MCF5235_FEC_MIBC = MCF5235_FEC_MIBC_MIB_DISABLE; - { - vuint32 *vuip = &MCF5235_FEC_RMON_T_DROP; - while (vuip <= &MCF5235_FEC_IEEE_R_OCTETS_OK) - *vuip++ = 0; - } - MCF5235_FEC_MIBC = 0; - - /* - * Set MII speed to <= 2.5 MHz - */ - i = (clock_speed + 5000000 - 1) / 5000000; - MCF5235_FEC_MSCR = MCF5235_FEC_MSCR_MII_SPEED(i); - - /* - * Set PHYS to 100 Mb/s, full duplex - */ - setMII(1, 0, 0x2100); - - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) - (sc->rxBdBase + i)->status = 0; - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - sc->txBdBase[i].status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Set up interrupts - */ - status = rtems_interrupt_catch( mcf5235_fec_tx_interrupt_handler, FEC_INTC0_TX_VECTOR, &old_handler ); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5235 FEC TX interrupt handler: %s\n", - rtems_status_text(status)); - status = rtems_interrupt_catch(mcf5235_fec_rx_interrupt_handler, FEC_INTC0_RX_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5235 FEC RX interrupt handler: %s\n", - rtems_status_text(status)); - MCF5235_INTC0_ICR23 = MCF5235_INTC_ICR_IL(FEC_IRQ_LEVEL) | - MCF5235_INTC_ICR_IP(FEC_IRQ_TX_PRIORITY); - MCF5235_INTC0_IMRL &= ~(MCF5235_INTC0_IMRL_INT23 | MCF5235_INTC0_IMRL_MASKALL); - MCF5235_INTC0_ICR27 = MCF5235_INTC_ICR_IL(FEC_IRQ_LEVEL) | - MCF5235_INTC_ICR_IP(FEC_IRQ_RX_PRIORITY); - MCF5235_INTC0_IMRL &= ~(MCF5235_INTC0_IMRL_INT27 | MCF5235_INTC0_IMRL_MASKALL); -} - -/* - * Get the MAC address from the hardware. - */ -static void -fec_get_mac_address(volatile struct mcf5235_enet_struct *sc, unsigned char* hwaddr) -{ - unsigned long addr; - - addr = MCF5235_FEC_PALR; - - hwaddr[0] = (addr >> 24) & 0xff; - hwaddr[1] = (addr >> 16) & 0xff; - hwaddr[2] = (addr >> 8) & 0xff; - hwaddr[3] = (addr >> 0) & 0xff; - - addr = MCF5235_FEC_PAUR; - - hwaddr[4] = (addr >> 24) & 0xff; - hwaddr[5] = (addr >> 16) & 0xff; -} - - -/* - * Soak up buffer descriptors that have been sent. - */ -static void -fec_retire_tx_bd(volatile struct mcf5235_enet_struct *sc ) -{ - struct mbuf *m, *n; - - while ((sc->txBdActiveCount != 0) - && ((sc->txBdBase[sc->txBdTail].status & MCF5235_FEC_TxBD_R) == 0)) { - m = sc->txMbuf[sc->txBdTail]; - MFREE(m, n); - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - sc->txBdActiveCount--; - } -} - -static void -fec_rxDaemon (void *arg) -{ - volatile struct mcf5235_enet_struct *sc = (volatile struct mcf5235_enet_struct *)arg; - struct ifnet *ifp = (struct ifnet* )&sc->arpcom.ac_if; - struct mbuf *m; - volatile uint16_t status; - volatile mcf5235BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - rxBd->status = MCF5235_FEC_RxBD_E; - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status |= MCF5235_FEC_RxBD_W; - break; - } - } - - /* - * Input packet handling loop - */ - /* Indicate we have some ready buffers available */ - MCF5235_FEC_RDAR = MCF5235_FEC_RDAR_R_DES_ACTIVE; - - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & MCF5235_FEC_RxBD_E) { - /* - * Clear old events. - */ - MCF5235_FEC_EIR = MCF5235_FEC_EIR_RXF; - - /* - * Wait for packet to arrive. - * Check the buffer descriptor before waiting for the event. - * This catches the case when a packet arrives between the - * `if' above, and the clearing of the RXF bit in the EIR. - */ - while ((status = rxBd->status) & MCF5235_FEC_RxBD_E) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF5235_FEC_EIMR |= MCF5235_FEC_EIMR_RXF; - rtems_interrupt_enable(level); - rtems_bsdnet_event_receive (RX_INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - } - - /* - * Check that packet is valid - */ - if (status & MCF5235_FEC_RxBD_L) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - int len = rxBd->length - sizeof(uint32_t); - - /* - * Invalidate the cache and push the packet up. - * The cache is so small that it's more efficient to just - * invalidate the whole thing unless the packet is very small. - */ - m = sc->rxMbuf[rxBdIndex]; - if (len < 128) - rtems_cache_invalidate_multiple_data_lines(m->m_data, len); - else - rtems_cache_invalidate_entire_data(); - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input(ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & MCF5235_FEC_RxBD_W) | MCF5235_FEC_RxBD_E; - MCF5235_FEC_RDAR = MCF5235_FEC_RDAR_R_DES_ACTIVE; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void -fec_sendpacket(struct ifnet *ifp, struct mbuf *m) -{ - struct mcf5235_enet_struct *sc = ifp->if_softc; - volatile mcf5235BufferDescriptor_t *firstTxBd, *txBd; - uint16_t status; - int nAdded; - - /* - * Free up buffer descriptors - */ - fec_retire_tx_bd(sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - nAdded = 0; - firstTxBd = sc->txBdBase + sc->txBdHead; - - for (;;) { - /* - * Wait for buffer descriptor to become available - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events. - */ - MCF5235_FEC_EIR = MCF5235_FEC_EIR_TXF; - - /* - * Wait for buffer descriptor to become available. - * Check for buffer descriptors before waiting for the event. - * This catches the case when a buffer became available between - * the `if' above, and the clearing of the TXF bit in the EIR. - */ - fec_retire_tx_bd(sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF5235_FEC_EIMR |= MCF5235_FEC_EIMR_TXF; - rtems_interrupt_enable(level); - sc->txRawWait++; - rtems_bsdnet_event_receive(TX_INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - fec_retire_tx_bd(sc); - } - } - - /* - * Don't set the READY flag on the first fragment - * until the whole packet has been readied. - */ - status = nAdded ? MCF5235_FEC_TxBD_R : 0; - - /* - * The IP fragmentation routine in ip_output - * can produce fragments with zero length. - */ - txBd = sc->txBdBase + sc->txBdHead; - if (m->m_len) { - char *p = mtod(m, char *); - /* - * Stupid FEC can't handle misaligned data! - * Given the way that mbuf's are layed out it should be - * safe to shuffle the data down like this..... - * Perhaps this code could be improved with a "Duff's Device". - */ - if ((int)p & 0x3) { - int l = m->m_len; - char *dest = p - ((int)p & 0x3); - uint16_t *o = (uint16_t *)dest, *i = (uint16_t *)p; - while (l > 0) { - *o++ = *i++; - l -= sizeof(uint16_t); - } - p = dest; - sc->txRealign++; - } - txBd->buffer = p; - txBd->length = m->m_len; - sc->txMbuf[sc->txBdHead] = m; - nAdded++; - if (++sc->txBdHead == sc->txBdCount) { - status |= MCF5235_FEC_TxBD_W; - sc->txBdHead = 0; - } - m = m->m_next; - } - else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - MFREE(m, n); - m = n; - } - if (m == NULL) { - if (nAdded) { - txBd->status = status | MCF5235_FEC_TxBD_R - | MCF5235_FEC_TxBD_L - | MCF5235_FEC_TxBD_TC; - if (nAdded > 1) - firstTxBd->status |= MCF5235_FEC_TxBD_R; - MCF5235_FEC_TDAR = MCF5235_FEC_TDAR_X_DES_ACTIVE; - sc->txBdActiveCount += nAdded; - } - break; - } - txBd->status = status; - } -} - -void -fec_txDaemon(void *arg) -{ - struct mcf5235_enet_struct *sc = (struct mcf5235_enet_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - 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; - fec_sendpacket(ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - - -/* - * Send packet (caller provides header). - */ -static void -mcf5235_enet_start(struct ifnet *ifp) -{ - struct mcf5235_enet_struct *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -static void -fec_init(void *arg) -{ - struct mcf5235_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - /* - * Set up hardware - */ - mcf5235_fec_initialize_hardware(sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc("FECtx", 4096, fec_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc("FECrx", 4096, fec_rxDaemon, sc); - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - MCF5235_FEC_RCR |= MCF5235_FEC_RCR_PROM; - else - MCF5235_FEC_RCR &= ~MCF5235_FEC_RCR_PROM; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - MCF5235_FEC_ECR = MCF5235_FEC_ECR_ETHER_EN; -} - - -static void -fec_stop(struct mcf5235_enet_struct *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - MCF5235_FEC_ECR = 0x0; -} - -/* - * Show interface statistics - */ -static void -enet_stats(struct mcf5235_enet_struct *sc) -{ - printf(" Rx Interrupts:%-10lu", sc->rxInterrupts); - printf("Rx Packet Count:%-10lu", MCF5235_FEC_RMON_R_PACKETS); - printf(" Rx Broadcast:%-10lu\n", MCF5235_FEC_RMON_R_BC_PKT); - printf(" Rx Multicast:%-10lu", MCF5235_FEC_RMON_R_MC_PKT); - printf("CRC/Align error:%-10lu", MCF5235_FEC_RMON_R_CRC_ALIGN); - printf(" Rx Undersize:%-10lu\n", MCF5235_FEC_RMON_R_UNDERSIZE); - printf(" Rx Oversize:%-10lu", MCF5235_FEC_RMON_R_OVERSIZE); - printf(" Rx Fragment:%-10lu", MCF5235_FEC_RMON_R_FRAG); - printf(" Rx Jabber:%-10lu\n", MCF5235_FEC_RMON_R_JAB); - printf(" Rx 64:%-10lu", MCF5235_FEC_RMON_R_P64); - printf(" Rx 65-127:%-10lu", MCF5235_FEC_RMON_R_P65T0127); - printf(" Rx 128-255:%-10lu\n", MCF5235_FEC_RMON_R_P128TO255); - printf(" Rx 256-511:%-10lu", MCF5235_FEC_RMON_R_P256TO511); - printf(" Rx 511-1023:%-10lu", MCF5235_FEC_RMON_R_P512TO1023); - printf(" Rx 1024-2047:%-10lu\n", MCF5235_FEC_RMON_R_P1024TO2047); - printf(" Rx >=2048:%-10lu", MCF5235_FEC_RMON_R_GTE2048); - printf(" Rx Octets:%-10lu", MCF5235_FEC_RMON_R_OCTETS); - printf(" Rx Dropped:%-10lu\n", MCF5235_FEC_IEEE_R_DROP); - printf(" Rx frame OK:%-10lu", MCF5235_FEC_IEEE_R_FRAME_OK); - printf(" Rx CRC error:%-10lu", MCF5235_FEC_IEEE_R_CRC); - printf(" Rx Align error:%-10lu\n", MCF5235_FEC_IEEE_R_ALIGN); - printf(" FIFO Overflow:%-10lu", MCF5235_FEC_IEEE_R_MACERR); - printf("Rx Pause Frames:%-10lu", MCF5235_FEC_IEEE_R_FDXFC); - printf(" Rx Octets OK:%-10lu\n", MCF5235_FEC_IEEE_R_OCTETS_OK); - printf(" Tx Interrupts:%-10lu", sc->txInterrupts); - printf("Tx Output Waits:%-10lu", sc->txRawWait); - printf("Tx Realignments:%-10lu\n", sc->txRealign); - printf(" Tx Unaccounted:%-10lu", MCF5235_FEC_RMON_T_DROP); - printf("Tx Packet Count:%-10lu", MCF5235_FEC_RMON_T_PACKETS); - printf(" Tx Broadcast:%-10lu\n", MCF5235_FEC_RMON_T_BC_PKT); - printf(" Tx Multicast:%-10lu", MCF5235_FEC_RMON_T_MC_PKT); - printf("CRC/Align error:%-10lu", MCF5235_FEC_RMON_T_CRC_ALIGN); - printf(" Tx Undersize:%-10lu\n", MCF5235_FEC_RMON_T_UNDERSIZE); - printf(" Tx Oversize:%-10lu", MCF5235_FEC_RMON_T_OVERSIZE); - printf(" Tx Fragment:%-10lu", MCF5235_FEC_RMON_T_FRAG); - printf(" Tx Jabber:%-10lu\n", MCF5235_FEC_RMON_T_JAB); - printf(" Tx Collisions:%-10lu", MCF5235_FEC_RMON_T_COL); - printf(" Tx 64:%-10lu", MCF5235_FEC_RMON_T_P64); - printf(" Tx 65-127:%-10lu\n", MCF5235_FEC_RMON_T_P65TO127); - printf(" Tx 128-255:%-10lu", MCF5235_FEC_RMON_T_P128TO255); - printf(" Tx 256-511:%-10lu", MCF5235_FEC_RMON_T_P256TO511); - printf(" Tx 511-1023:%-10lu\n", MCF5235_FEC_RMON_T_P512TO1023); - printf(" Tx 1024-2047:%-10lu", MCF5235_FEC_RMON_T_P1024TO2047); - printf(" Tx >=2048:%-10lu", MCF5235_FEC_RMON_T_P_GTE2048); - printf(" Tx Octets:%-10lu\n", MCF5235_FEC_RMON_T_OCTETS); - printf(" Tx Dropped:%-10lu", MCF5235_FEC_IEEE_T_DROP); - printf(" Tx Frame OK:%-10lu", MCF5235_FEC_IEEE_T_FRAME_OK); - printf(" Tx 1 Collision:%-10lu\n", MCF5235_FEC_IEEE_T_1COL); - printf("Tx >1 Collision:%-10lu", MCF5235_FEC_IEEE_T_MCOL); - printf(" Tx Deferred:%-10lu", MCF5235_FEC_IEEE_T_DEF); - printf(" Late Collision:%-10lu\n", MCF5235_FEC_IEEE_T_LCOL); - printf(" Excessive Coll:%-10lu", MCF5235_FEC_IEEE_T_EXCOL); - printf(" FIFO Underrun:%-10lu", MCF5235_FEC_IEEE_T_MACERR); - printf(" Carrier Error:%-10lu\n", MCF5235_FEC_IEEE_T_CSERR); - printf(" Tx SQE Error:%-10lu", MCF5235_FEC_IEEE_T_SQE); - printf("Tx Pause Frames:%-10lu", MCF5235_FEC_IEEE_T_FDXFC); - printf(" Tx Octets OK:%-10lu\n", MCF5235_FEC_IEEE_T_OCTETS_OK); -} - -static int -fec_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct mcf5235_enet_struct *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: - fec_stop(sc); - break; - - case IFF_UP: - fec_init(sc); - break; - - case IFF_UP | IFF_RUNNING: - fec_stop(sc); - fec_init(sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - enet_stats(sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -int -rtems_fec_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching ) -{ - struct mcf5235_enet_struct *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - unsigned char *hwaddr; - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber < 0) || (unitNumber >= NIFACES)) { - printf("mcf5235: bad FEC unit number.\n"); - return 0; - } - sc = &enet_driver[unitNumber]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf("mcf5235: driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - if (config->hardware_address) - memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - else - fec_get_mac_address(sc, sc->arpcom.ac_enaddr); - - hwaddr = config->hardware_address; - printf("%s%d: mac: %02x:%02x:%02x:%02x:%02x:%02x\n", - unitName, unitNumber, - hwaddr[0], hwaddr[1], hwaddr[2], - hwaddr[3], hwaddr[4], hwaddr[5]); - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - - 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 = fec_init; - ifp->if_ioctl = fec_ioctl; - ifp->if_start = mcf5235_enet_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); - return 1; -}; - diff --git a/c/src/lib/libbsp/m68k/mcf5329/Makefile.am b/c/src/lib/libbsp/m68k/mcf5329/Makefile.am index 7dd2265c7f..f269f930e3 100644 --- a/c/src/lib/libbsp/m68k/mcf5329/Makefile.am +++ b/c/src/lib/libbsp/m68k/mcf5329/Makefile.am @@ -36,7 +36,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5329/console/console.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5329/btimer/btimer.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mcf5329/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache-mcf532x.c diff --git a/c/src/lib/libbsp/m68k/mcf5329/network/network.c b/c/src/lib/libbsp/m68k/mcf5329/network/network.c deleted file mode 100644 index c752f8d669..0000000000 --- a/c/src/lib/libbsp/m68k/mcf5329/network/network.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * RTEMS/TCPIP driver for MCF5329 Fast Ethernet Controller - * - * TO DO: Check network stack code -- force longword alignment of all tx mbufs? - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 1 - -#define FEC_INTC0_TX_VECTOR (64+36) -#define FEC_INTC0_RX_VECTOR (64+40) - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses three or more buffer descriptors. - */ -#define RX_BUF_COUNT 32 -#define TX_BUF_COUNT 20 -#define TX_BD_PER_BUF 3 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define TX_INTERRUPT_EVENT RTEMS_EVENT_1 -#define RX_INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). - * Round off to nearest multiple of RBUF_ALIGN. - */ -#define MAX_MTU_SIZE 1518 -#define RBUF_ALIGN 4 -#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -typedef struct mcf5329BufferDescriptor_ -{ - volatile uint16_t status; - uint16_t length; - volatile void *buffer; -} mcf5329BufferDescriptor_t; - -/* - * Per-device data - */ -struct mcf5329_enet_struct -{ - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - mcf5329BufferDescriptor_t *rxBdBase; - mcf5329BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long txInterrupts; - unsigned long txRawWait; - unsigned long txRealign; -}; -static struct mcf5329_enet_struct enet_driver[NIFACES]; - -static rtems_isr mcf5329_fec_rx_interrupt_handler(rtems_vector_number v) -{ - MCF_FEC_EIR = MCF_FEC_EIR_RXF; - MCF_FEC_EIMR &= ~MCF_FEC_EIMR_RXF; - enet_driver[0].rxInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].rxDaemonTid, RX_INTERRUPT_EVENT); -} - -static rtems_isr mcf5329_fec_tx_interrupt_handler(rtems_vector_number v) -{ - MCF_FEC_EIR = MCF_FEC_EIR_TXF; - MCF_FEC_EIMR &= ~MCF_FEC_EIMR_TXF; - enet_driver[0].txInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].txDaemonTid, TX_INTERRUPT_EVENT); -} - -extern char _CoreSRamBase[]; - -/* - * Allocate buffer descriptors from (non-cached) on-chip static RAM - * Ensure 128-bit (16-byte) alignment - */ -static mcf5329BufferDescriptor_t *mcf5329_bd_allocate(unsigned int count) -{ - static mcf5329BufferDescriptor_t *bdp = - (mcf5329BufferDescriptor_t *) _CoreSRamBase; - mcf5329BufferDescriptor_t *p = bdp; - - bdp += count; - if ((int) bdp & 0xF) - bdp = - (mcf5329BufferDescriptor_t *) ((char *) bdp + (16 - ((int) bdp & 0xF))); - return p; -} - -#if UNUSED - -/* - * Read MII register - * Busy-waits, but transfer time should be short! - */ -static int getMII(int phyNumber, int regNumber) -{ - MCF_FEC_MMFR = (0x1 << 30) | - (0x2 << 28) | (phyNumber << 23) | (regNumber << 18) | (0x2 << 16); - while ((MCF_FEC_EIR & MCF_FEC_EIR_MII) == 0) ; - MCF_FEC_EIR = MCF_FEC_EIR_MII; - return MCF_FEC_MMFR & 0xFFFF; -} -#endif - -/* - * Write MII register - * Busy-waits, but transfer time should be short! - */ -static void setMII(int phyNumber, int regNumber, int value) -{ - MCF_FEC_MMFR = (0x1 << 30) | - (0x1 << 28) | - (phyNumber << 23) | (regNumber << 18) | (0x2 << 16) | (value & 0xFFFF); - while ((MCF_FEC_EIR & MCF_FEC_EIR_MII) == 0) ; - MCF_FEC_EIR = MCF_FEC_EIR_MII; -} - -static void mcf5329_fec_initialize_hardware(struct mcf5329_enet_struct *sc) -{ - int i; - const unsigned char *hwaddr = 0; - rtems_status_code status; - rtems_isr_entry old_handler; - uint32_t clock_speed = bsp_get_BUS_clock_speed(); - - /* - * Issue reset to FEC - */ - MCF_FEC_ECR = MCF_FEC_ECR_RESET; - rtems_task_wake_after(1); - MCF_FEC_ECR = 0; - - /* - * Configuration of I/O ports is done outside of this function - */ -#if 0 - imm->gpio.pbcnt |= MCF_GPIO_PBCNT_SET_FEC; /* Set up port b FEC pins */ -#endif - - /* - * Set our physical address - */ - hwaddr = sc->arpcom.ac_enaddr; - MCF_FEC_PALR = (hwaddr[0] << 24) | (hwaddr[1] << 16) | - (hwaddr[2] << 8) | (hwaddr[3] << 0); - MCF_FEC_PAUR = (hwaddr[4] << 24) | (hwaddr[5] << 16); - - /* - * Clear the hash table - */ - MCF_FEC_GAUR = 0; - MCF_FEC_GALR = 0; - - /* - * Set up receive buffer size - */ - MCF_FEC_EMRBR = 1520; /* Standard Ethernet */ - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = mcf5329_bd_allocate(sc->rxBdCount); - sc->txBdBase = mcf5329_bd_allocate(sc->txBdCount); - MCF_FEC_ERDSR = (int) sc->rxBdBase; - MCF_FEC_ETDSR = (int) sc->txBdBase; - - /* - * Set up Receive Control Register: - * Not promiscuous - * MII mode - * Full duplex - * No loopback - */ - MCF_FEC_RCR = MCF_FEC_RCR_MAX_FL(MAX_MTU_SIZE) | MCF_FEC_RCR_MII_MODE; - - /* - * Set up Transmit Control Register: - * Full duplex - * No heartbeat - */ - MCF_FEC_TCR = MCF_FEC_TCR_FDEN; - - /* - * Initialize statistic counters - */ - MCF_FEC_MIBC = MCF_FEC_MIBC_MIB_DISABLE; - { - vuint32 *vuip = &MCF_FEC_RMON_T_DROP; - - while (vuip <= &MCF_FEC_IEEE_R_OCTETS_OK) - *vuip++ = 0; - } - MCF_FEC_MIBC = 0; - - /* - * Set MII speed to <= 2.5 MHz - */ - i = (clock_speed + 5000000 - 1) / 5000000; - MCF_FEC_MSCR = MCF_FEC_MSCR_MII_SPEED(i); - - /* - * Set PHYS to 100 Mb/s, full duplex - */ - setMII(1, 0, 0x2100); - - /* - * Set up receive buffer descriptors - */ - for (i = 0; i < sc->rxBdCount; i++) - (sc->rxBdBase + i)->status = 0; - - /* - * Set up transmit buffer descriptors - */ - for (i = 0; i < sc->txBdCount; i++) { - sc->txBdBase[i].status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Set up interrupts - */ - status = - rtems_interrupt_catch(mcf5329_fec_tx_interrupt_handler, - FEC_INTC0_TX_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic("Can't attach MCF FEC TX interrupt handler: %s\n", - rtems_status_text(status)); - status = - rtems_interrupt_catch(mcf5329_fec_rx_interrupt_handler, - FEC_INTC0_RX_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic("Can't attach MCF FEC RX interrupt handler: %s\n", - rtems_status_text(status)); - MCF_INTC0_ICR36 = MCF_INTC_ICR_IL(FEC_IRQ_LEVEL); - MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK36); - MCF_INTC0_ICR40 = MCF_INTC_ICR_IL(FEC_IRQ_LEVEL); - MCF_INTC0_IMRH &= ~(MCF_INTC_IMRH_INT_MASK40); -} - -/* - * Get the MAC address from the hardware. - */ -static void -fec_get_mac_address(volatile struct mcf5329_enet_struct *sc, - unsigned char *hwaddr) -{ - unsigned long addr; - - addr = MCF_FEC_PALR; - - hwaddr[0] = (addr >> 24) & 0xff; - hwaddr[1] = (addr >> 16) & 0xff; - hwaddr[2] = (addr >> 8) & 0xff; - hwaddr[3] = (addr >> 0) & 0xff; - - addr = MCF_FEC_PAUR; - - hwaddr[4] = (addr >> 24) & 0xff; - hwaddr[5] = (addr >> 16) & 0xff; -} - -/* - * Soak up buffer descriptors that have been sent. - */ -static void fec_retire_tx_bd(volatile struct mcf5329_enet_struct *sc) -{ - struct mbuf *m, *n; - - while ((sc->txBdActiveCount != 0) - && ((sc->txBdBase[sc->txBdTail].status & MCF_FEC_TxBD_R) == 0)) { - m = sc->txMbuf[sc->txBdTail]; - MFREE(m, n); - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - sc->txBdActiveCount--; - } -} - -static void fec_rxDaemon(void *arg) -{ - volatile struct mcf5329_enet_struct *sc = - (volatile struct mcf5329_enet_struct *) arg; - struct ifnet *ifp = (struct ifnet *) &sc->arpcom.ac_if; - struct mbuf *m; - volatile uint16_t status; - volatile mcf5329BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0;;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - - rxBd->status = MCF_FEC_RxBD_E; - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status |= MCF_FEC_RxBD_W; - break; - } - } - - /* - * Input packet handling loop - */ - /* Indicate we have some ready buffers available */ - MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; - - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & MCF_FEC_RxBD_E) { - /* - * Clear old events. - */ - MCF_FEC_EIR = MCF_FEC_EIR_RXF; - - /* - * Wait for packet to arrive. - * Check the buffer descriptor before waiting for the event. - * This catches the case when a packet arrives between the - * `if' above, and the clearing of the RXF bit in the EIR. - */ - while ((status = rxBd->status) & MCF_FEC_RxBD_E) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF_FEC_EIMR |= MCF_FEC_EIMR_RXF; - rtems_interrupt_enable(level); - rtems_bsdnet_event_receive(RX_INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, &events); - } - } - - /* - * Check that packet is valid - */ - if (status & MCF_FEC_RxBD_L) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - int len = rxBd->length - sizeof(uint32_t); - - m = sc->rxMbuf[rxBdIndex]; - - rtems_cache_invalidate_multiple_data_lines(m->m_data, len); - - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input(ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & MCF_FEC_RxBD_W) | MCF_FEC_RxBD_E; - MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void fec_sendpacket(struct ifnet *ifp, struct mbuf *m) -{ - struct mcf5329_enet_struct *sc = ifp->if_softc; - volatile mcf5329BufferDescriptor_t *firstTxBd, *txBd; - uint16_t status; - int nAdded; - - /* - * Free up buffer descriptors - */ - fec_retire_tx_bd(sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - nAdded = 0; - firstTxBd = sc->txBdBase + sc->txBdHead; - - for (;;) { - /* - * Wait for buffer descriptor to become available - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events. - */ - MCF_FEC_EIR = MCF_FEC_EIR_TXF; - - /* - * Wait for buffer descriptor to become available. - * Check for buffer descriptors before waiting for the event. - * This catches the case when a buffer became available between - * the `if' above, and the clearing of the TXF bit in the EIR. - */ - fec_retire_tx_bd(sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF_FEC_EIMR |= MCF_FEC_EIMR_TXF; - rtems_interrupt_enable(level); - sc->txRawWait++; - rtems_bsdnet_event_receive(TX_INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, &events); - fec_retire_tx_bd(sc); - } - } - - /* - * Don't set the READY flag on the first fragment - * until the whole packet has been readied. - */ - status = nAdded ? MCF_FEC_TxBD_R : 0; - - /* - * The IP fragmentation routine in ip_output - * can produce fragments with zero length. - */ - txBd = sc->txBdBase + sc->txBdHead; - if (m->m_len) { - char *p = mtod(m, char *); - - /* - * Stupid FEC can't handle misaligned data! - * Given the way that mbuf's are layed out it should be - * safe to shuffle the data down like this..... - * Perhaps this code could be improved with a "Duff's Device". - */ - if ((int) p & 0x3) { - int l = m->m_len; - char *dest = p - ((int) p & 0x3); - uint16_t *o = (uint16_t *) dest, *i = (uint16_t *) p; - - while (l > 0) { - *o++ = *i++; - l -= sizeof(uint16_t); - } - p = dest; - sc->txRealign++; - } - - txBd->buffer = p; - txBd->length = m->m_len; - - rtems_cache_flush_multiple_data_lines(txBd->buffer, txBd->length); - - sc->txMbuf[sc->txBdHead] = m; - nAdded++; - if (++sc->txBdHead == sc->txBdCount) { - status |= MCF_FEC_TxBD_W; - sc->txBdHead = 0; - } - m = m->m_next; - } else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - - MFREE(m, n); - m = n; - } - if (m == NULL) { - if (nAdded) { - txBd->status = status | MCF_FEC_TxBD_R - | MCF_FEC_TxBD_L | MCF_FEC_TxBD_TC; - if (nAdded > 1) - firstTxBd->status |= MCF_FEC_TxBD_R; - MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE; - sc->txBdActiveCount += nAdded; - } - break; - } - txBd->status = status; - } -} - -void fec_txDaemon(void *arg) -{ - struct mcf5329_enet_struct *sc = (struct mcf5329_enet_struct *) arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - 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; - fec_sendpacket(ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* - * Send packet (caller provides header). - */ -static void mcf5329_enet_start(struct ifnet *ifp) -{ - struct mcf5329_enet_struct *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -static void fec_init(void *arg) -{ - struct mcf5329_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - /* - * Set up hardware - */ - mcf5329_fec_initialize_hardware(sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc("FECtx", 4096, fec_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc("FECrx", 4096, fec_rxDaemon, sc); - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - MCF_FEC_RCR |= MCF_FEC_RCR_PROM; - else - MCF_FEC_RCR &= ~MCF_FEC_RCR_PROM; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN; -} - -static void fec_stop(struct mcf5329_enet_struct *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - MCF_FEC_ECR = 0x0; -} - -/* - * Show interface statistics - */ -static void enet_stats(struct mcf5329_enet_struct *sc) -{ - printf(" Rx Interrupts:%-10lu", sc->rxInterrupts); - printf("Rx Packet Count:%-10lu", MCF_FEC_RMON_R_PACKETS); - printf(" Rx Broadcast:%-10lu\n", MCF_FEC_RMON_R_BC_PKT); - printf(" Rx Multicast:%-10lu", MCF_FEC_RMON_R_MC_PKT); - printf("CRC/Align error:%-10lu", MCF_FEC_RMON_R_CRC_ALIGN); - printf(" Rx Undersize:%-10lu\n", MCF_FEC_RMON_R_UNDERSIZE); - printf(" Rx Oversize:%-10lu", MCF_FEC_RMON_R_OVERSIZE); - printf(" Rx Fragment:%-10lu", MCF_FEC_RMON_R_FRAG); - printf(" Rx Jabber:%-10lu\n", MCF_FEC_RMON_R_JAB); - printf(" Rx 64:%-10lu", MCF_FEC_RMON_R_P64); - printf(" Rx 65-127:%-10lu", MCF_FEC_RMON_R_P65TO127); - printf(" Rx 128-255:%-10lu\n", MCF_FEC_RMON_R_P128TO255); - printf(" Rx 256-511:%-10lu", MCF_FEC_RMON_R_P256TO511); - printf(" Rx 511-1023:%-10lu", MCF_FEC_RMON_R_512TO1023); - printf(" Rx 1024-2047:%-10lu\n", MCF_FEC_RMON_R_1024TO2047); - printf(" Rx >=2048:%-10lu", MCF_FEC_RMON_R_P_GTE2048); - printf(" Rx Octets:%-10lu", MCF_FEC_RMON_R_OCTETS); - printf(" Rx Dropped:%-10lu\n", MCF_FEC_IEEE_R_DROP); - printf(" Rx frame OK:%-10lu", MCF_FEC_IEEE_R_FRAME_OK); - printf(" Rx CRC error:%-10lu", MCF_FEC_IEEE_R_CRC); - printf(" Rx Align error:%-10lu\n", MCF_FEC_IEEE_R_ALIGN); - printf(" FIFO Overflow:%-10lu", MCF_FEC_IEEE_R_MACERR); - printf("Rx Pause Frames:%-10lu", MCF_FEC_IEEE_R_FDXFC); - printf(" Rx Octets OK:%-10lu\n", MCF_FEC_IEEE_R_OCTETS_OK); - printf(" Tx Interrupts:%-10lu", sc->txInterrupts); - printf("Tx Output Waits:%-10lu", sc->txRawWait); - printf("Tx Realignments:%-10lu\n", sc->txRealign); - printf(" Tx Unaccounted:%-10lu", MCF_FEC_RMON_T_DROP); - printf("Tx Packet Count:%-10lu", MCF_FEC_RMON_T_PACKETS); - printf(" Tx Broadcast:%-10lu\n", MCF_FEC_RMON_T_BC_PKT); - printf(" Tx Multicast:%-10lu", MCF_FEC_RMON_T_MC_PKT); - printf("CRC/Align error:%-10lu", MCF_FEC_RMON_T_CRC_ALIGN); - printf(" Tx Undersize:%-10lu\n", MCF_FEC_RMON_T_UNDERSIZE); - printf(" Tx Oversize:%-10lu", MCF_FEC_RMON_T_OVERSIZE); - printf(" Tx Fragment:%-10lu", MCF_FEC_RMON_T_FRAG); - printf(" Tx Jabber:%-10lu\n", MCF_FEC_RMON_T_JAB); - printf(" Tx Collisions:%-10lu", MCF_FEC_RMON_T_COL); - printf(" Tx 64:%-10lu", MCF_FEC_RMON_T_P64); - printf(" Tx 65-127:%-10lu\n", MCF_FEC_RMON_T_P65TO127); - printf(" Tx 128-255:%-10lu", MCF_FEC_RMON_T_P128TO255); - printf(" Tx 256-511:%-10lu", MCF_FEC_RMON_T_P256TO511); - printf(" Tx 511-1023:%-10lu\n", MCF_FEC_RMON_T_P512TO1023); - printf(" Tx 1024-2047:%-10lu", MCF_FEC_RMON_T_P1024TO2047); - printf(" Tx >=2048:%-10lu", MCF_FEC_RMON_T_P_GTE2048); - printf(" Tx Octets:%-10lu\n", MCF_FEC_RMON_T_OCTETS); - printf(" Tx Dropped:%-10lu", MCF_FEC_IEEE_T_DROP); - printf(" Tx Frame OK:%-10lu", MCF_FEC_IEEE_T_FRAME_OK); - printf(" Tx 1 Collision:%-10lu\n", MCF_FEC_IEEE_T_1COL); - printf("Tx >1 Collision:%-10lu", MCF_FEC_IEEE_T_MCOL); - printf(" Tx Deferred:%-10lu", MCF_FEC_IEEE_T_DEF); - printf(" Late Collision:%-10lu\n", MCF_FEC_IEEE_T_LCOL); - printf(" Excessive Coll:%-10lu", MCF_FEC_IEEE_T_EXCOL); - printf(" FIFO Underrun:%-10lu", MCF_FEC_IEEE_T_MACERR); - printf(" Carrier Error:%-10lu\n", MCF_FEC_IEEE_T_CSERR); - printf(" Tx SQE Error:%-10lu", MCF_FEC_IEEE_T_SQE); - printf("Tx Pause Frames:%-10lu", MCF_FEC_IEEE_T_FDXFC); - printf(" Tx Octets OK:%-10lu\n", MCF_FEC_IEEE_T_OCTETS_OK); -} - -static int fec_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct mcf5329_enet_struct *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: - fec_stop(sc); - break; - - case IFF_UP: - fec_init(sc); - break; - - case IFF_UP | IFF_RUNNING: - fec_stop(sc); - fec_init(sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - enet_stats(sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -int -rtems_fec_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - struct mcf5329_enet_struct *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - unsigned char *hwaddr; - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber < 0) || (unitNumber >= NIFACES)) { - printf("mcf5329: bad FEC unit number.\n"); - return 0; - } - sc = &enet_driver[unitNumber]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf("mcf5329: driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - if (config->hardware_address) - memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - else - fec_get_mac_address(sc, sc->arpcom.ac_enaddr); - - hwaddr = config->hardware_address; - printf("%s%d: mac: %02x:%02x:%02x:%02x:%02x:%02x\n", - unitName, unitNumber, - hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - - 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 = fec_init; - ifp->if_ioctl = fec_ioctl; - ifp->if_start = mcf5329_enet_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); - return 1; -}; diff --git a/c/src/lib/libbsp/m68k/mvme162/Makefile.am b/c/src/lib/libbsp/m68k/mvme162/Makefile.am index 3847969efc..cfc146678a 100644 --- a/c/src/lib/libbsp/m68k/mvme162/Makefile.am +++ b/c/src/lib/libbsp/m68k/mvme162/Makefile.am @@ -39,7 +39,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme162/btimer/timerisr.S librtemsbsp_a_SOURCES += tod/tod.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += ../mvme167/network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache.c diff --git a/c/src/lib/libbsp/m68k/mvme167/Makefile.am b/c/src/lib/libbsp/m68k/mvme167/Makefile.am index 665b65fcea..01899a9076 100644 --- a/c/src/lib/libbsp/m68k/mvme167/Makefile.am +++ b/c/src/lib/libbsp/m68k/mvme167/Makefile.am @@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/btimer/btimer.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/btimer/timerisr.S if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/mvme167/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache.c diff --git a/c/src/lib/libbsp/m68k/mvme167/network/network.c b/c/src/lib/libbsp/m68k/mvme167/network/network.c deleted file mode 100644 index 06bcbfa84a..0000000000 --- a/c/src/lib/libbsp/m68k/mvme167/network/network.c +++ /dev/null @@ -1,3099 +0,0 @@ -/* network.c: An 82596 ethernet driver for rtems-bsd. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ -#define KERNEL - -/* - * Selectively define to debug the network driver. If you define any of these - * you must run with polled console I/O. - */ - -/* -#define DBG_ADD_CMD -#define DBG_WAIT -#define DBG_SEND -#define DBG_MEM -#define DBG_SELFTEST_CMD -#define DBG_DUMP_CMD -#define DBG_RESET -#define DBG_ATTACH -#define DBG_START -#define DBG_INIT -#define DBG_STOP -#define DBG_RX -#define DBG_ISR -#define DBG_IOCTL -#define DBG_STAT -#define DBG_PACKETS -*/ - -#define IGNORE_SPURIOUS_IRQ -#define IGNORE_NO_RFA -#define IGNORE_MULTIPLE_RF - -/* - * Default number of buffer descriptors and buffer sizes. - */ -#define RX_BUF_COUNT 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 - -#define RBUF_SIZE 1520 - -#define UTI_596_ETH_MIN_SIZE 60 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -/* - * RTEMS events - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 -#define NIC_RESET_EVENT RTEMS_EVENT_3 - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "uti596.h" - -/* If we are running interrupt driven I/O no debug output is printed */ -#if CD2401_IO_MODE == 0 - #define printk(arglist) do { printk arglist; printk("\r"); } while (0); -#else - #define printk(arglist) -#endif - -#define UTI_596_ASSERT( condition, str ) if (!( condition ) ) { printk((str)) } - -/* Types of PORT commands */ -#define UTI596_RESET_PORT_FUNCTION 0 -#define UTI596_SELFTEST_PORT_FUNCTION 1 -#define UTI596_SCP_PORT_FUNCTION 2 -#define UTI596_DUMP_PORT_FUNCTION 3 - -/* Types of waiting for commands */ -#define UTI596_NO_WAIT 0 -#define UTI596_WAIT_FOR_CU_ACCEPT 1 -#define UTI596_WAIT_FOR_INITIALIZATION 2 -#define UTI596_WAIT_FOR_STAT_C 3 - -/* Device dependent data structure */ -static uti596_softc_ uti596_softc; - -/* Globals */ -int count_rx = 0; -static int scbStatus; -static rtems_status_code sc; -static i596_cmd *pIsrCmd; -static i596_rfd *pIsrRfd; - -/* - * Initial 596 configuration - */ -char uti596initSetup[] = { - 0x0E, /* Byte 0: length, prefetch off ( no RBD's ) */ - 0xC8, /* Byte 1: fifo to 8, monitor off */ - 0x40, /* Byte 2: don't save bad frames ( was save= 80, use intel's 40 )*/ - 0x2E, /* Byte 3: No source address insertion, 8 byte preamble */ - 0x00, /* Byte 4: priority and backoff defaults */ - 0x60, /* Byte 5: interframe spacing */ - 0x00, /* Byte 6: slot time LSB */ - 0xf2, /* Byte 7: slot time and retries */ - 0x0C, /* Byte 8: not promisc, enable bcast, tx no crs, crc inserted 32bit, 802.3 framing */ - 0x08, /* Byte 9: collision detect */ - 0x40, /* Byte 10: minimum frame length */ - 0xfb, /* Byte 11: tried C8 same as byte 1 in bits 6-7, else ignored*/ - 0x00, /* Byte 12: disable full duplex */ - 0x3f /* Byte 13: no multi IA, backoff enabled */ -}; - -/* Local Routines */ - -static unsigned long word_swap ( unsigned long ); -static void * malloc_16byte_aligned ( void **, void ** adjusted_pointer, size_t ); -RTEMS_INLINE_ROUTINE void uti596_writePortFunction ( volatile void *, unsigned long ); -/* currently unused by RTEMS */ -#if 0 -RTEMS_INLINE_ROUTINE void uti596_portReset( void ); -static unsigned long uti596_portSelfTest( i596_selftest * ); -static int uti596_portDump ( i596_dump_result * ); -static void uti596_CU_dump ( i596_dump_result * ); -#endif -static int uti596_wait ( uti596_softc_ *, uint8_t); -static int uti596_issueCA ( uti596_softc_ *, uint8_t); -static void uti596_addCmd ( i596_cmd * ); -static void uti596_addPolledCmd ( i596_cmd * ); -static int uti596_setScpAndScb ( uti596_softc_ * ); -static int uti596_diagnose ( void ); -static int uti596_configure ( uti596_softc_ * ); -static int uti596_IAsetup ( uti596_softc_ * ); -static int uti596_initTBD ( uti596_softc_ * ); -static int uti596_initRFA ( int ); -static void uti596_initMem ( uti596_softc_ * ); -static void uti596_initialize ( uti596_softc_ * ); -static void uti596_initialize_hardware ( uti596_softc_ * ); -static void uti596_reset_hardware ( uti596_softc_ *); -static void uti596_reset ( void ); -static void uti596_clearListStatus ( i596_rfd * ); -static i596_rfd * uti596_dequeue ( i596_rfd ** ); -static void uti596_append ( i596_rfd ** , i596_rfd * ); -static void uti596_supplyFD ( i596_rfd * ); -static void send_packet ( struct ifnet *, struct mbuf * ); - -/* Required RTEMS network driver functions and tasks (plus reset daemon) */ - -static void uti596_start ( struct ifnet * ); -void uti596_init ( void * ); -void uti596_stop ( uti596_softc_ * ); -void uti596_txDaemon ( void * ); -void uti596_rxDaemon ( void * ); -void uti596_resetDaemon( void * ); -rtems_isr uti596_DynamicInterruptHandler ( rtems_vector_number ); -static int uti596_ioctl ( struct ifnet *, u_long, caddr_t ); -void uti596_stats ( uti596_softc_ * ); - -#ifdef DBG_PACKETS -static void dumpQ( void ); -static void show_buffers( void ); -static void show_queues( void ); -static void print_eth ( unsigned char * ); -static void print_hdr ( unsigned char * ); -static void print_pkt ( unsigned char * ); -static void print_echo ( unsigned char * ); -#endif - -/* - * word_swap - * - * Return a 32 bit value, swapping the upper and lower words first. - * - * Input parameters: - * val - 32 bit value to swap - * - * Output parameters: NONE - * - * Return value: - * Input value with upper and lower 16-bit words swapped - */ -static unsigned long word_swap( - unsigned long val -) -{ - return (((val >> 16)&(0x0000ffff)) | ((val << 16)&(0xffff0000))); -} - -/* - * malloc_16byte_aligned - * - * Allocate a block of a least nbytes aligned on a 16-byte boundary. - * Clients are responsible to store both the real address and the adjusted - * address. The real address must be used to free the block. - * - * Input parameters: - * real_pointer - pointer to a void * pointer in which to store the starting - * address of the block. Required for free. - * adjusted_pointer - pointer to a void * pointer in which to store the - * starting address of the block rounded up to the next - * 16 byte boundary. - * nbytes - number of bytes of storage requested - * - * Output parameters: - * real_pointer - starting address of the block. - * adjusted_pointer - starting address of the block rounded up to the next - * 16 byte boundary. - * - * Return value: - * starting address of the block rounded up to the next 16 byte boundary. - * NULL if no storage was allocated. - */ -static void * malloc_16byte_aligned( - void ** real_pointer, - void ** adjusted_pointer, - size_t nbytes -) -{ - *real_pointer = malloc( nbytes + 0xF, 0, M_NOWAIT ); - *adjusted_pointer = (void *)(((unsigned long)*real_pointer + 0xF ) & 0xFFFFFFF0 ); - return *adjusted_pointer; -} - -/* - * uti596_scp_alloc - * - * Allocate a new scp, possibly freeing a previously allocated one. - * - * Input parameters: - * sc - pointer to the global uti596_softc in which to store pointers - * to the newly allocated block. - * - * Output parameters: NONE - * - * Return value: - * Pointer to the newly allocated, 16-byte aligned scp. - */ -static i596_scp * uti596_scp_alloc( - uti596_softc_ * sc -) -{ - if( sc->base_scp != NULL ) { - #ifdef DBG_MEM - printk(("uti596_scp_alloc: Already have an SCP at %p\n", sc->base_scp)) - #endif - return sc->pScp; - } - - /* allocate enough memory for the Scp block to be aligned on 16 byte boundary */ - malloc_16byte_aligned( (void *)&(sc->base_scp), (void *)&(sc->pScp), sizeof( i596_scp ) ); - - #ifdef DBG_MEM - printk(("uti596_scp_alloc: Scp base address is %p\n", sc->base_scp)) - printk(("uti596_scp_alloc: Scp aligned address is : %p\n",sc->pScp)) - #endif - - return sc->pScp; -} - -/* - * uti596_writePortFunction - * - * Write the command into the PORT. - * - * Input parameters: - * addr - 16-byte aligned address to write into the PORT. - * cmd - 4-bit cmd to write into the PORT - * - * Output parameters: NONE - * - * Return value: NONE - * - * The Motorola manual swapped the high and low registers. - */ -RTEMS_INLINE_ROUTINE void uti596_writePortFunction( - volatile void * addr, - unsigned long cmd -) -{ - i82596->port_lower = (unsigned short)(((unsigned long)addr & 0xFFF0) | cmd); - i82596->port_upper = (unsigned short)(((unsigned long)addr >> 16 ) & 0xFFFF); -} - -/* - * uti596_portReset - * - * Issue a port Reset to the uti596 - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return value: NONE - */ -RTEMS_INLINE_ROUTINE void uti596_portReset( void ) -{ - uti596_writePortFunction( NULL, UTI596_RESET_PORT_FUNCTION ); -} - -/* currently unused by RTEMS */ -#if 0 -/* - * uti596_portSelfTest - * - * Perform a self-test. Wait for up to 1 second for the test to - * complete. Normally, the test should complete in a very short time, - * so busy waiting is not an issue. - * - * Input parameters: - * stp - pointer to a 16-byte aligned uti596_selftest structure. - * - * Output parameters: NONE - * - * Return value: - * 32-bit result field if successful, -1 otherwise. - */ -static unsigned long uti596_portSelfTest( - i596_selftest * stp -) -{ - rtems_interval ticks_per_second, start_ticks, end_ticks; - - stp->results = 0xFFFFFFFF; - uti596_writePortFunction( stp, UTI596_SELFTEST_PORT_FUNCTION ); - - ticks_per_second = rtems_clock_get_ticks_per_second(); - - start_ticks = rtems_clock_get_ticks_since_boot(); - end_ticks = start_ticks + ticks_per_second; - - do { - if( stp->results != 0xFFFFFFFF ) - break; - else - start_ticks = rtems_clock_get_ticks_since_boot(); - } while (start_ticks <= end_ticks); - - if (start_ticks > end_ticks ) { - #ifdef DBG_SELFTEST_CMD - printk(("uti596_selftest: Timed out\n" )) - #endif - return -1; - } - else { - #ifdef DBG_SELFTEST_CMD - printk(("uti596_selftest: Succeeded with signature = 0x%08x, result = 0x%08x\n", - stp->signature, - stp->results)) - #endif - return stp->results; - } -} -#endif - -/* currently unused by RTEMS */ -#if 0 -/* - * uti596_portDump - * - * Perform a dump Wait for up to 1 second for the test to - * complete. Normally, the test should complete in a very short time, - * so busy waiting is not an issue. - * - * Input parameters: - * dp - pointer to a 16-byte aligned uti596_dump structure. - * - * Output parameters: NONE - * - * Return value: - * 16-bit dump_status field if successful, -1 otherwise. - */ -static int uti596_portDump( - i596_dump_result * dp -) -{ - rtems_interval ticks_per_second, start_ticks, end_ticks; - - dp->dump_status = 0; - uti596_writePortFunction( dp, UTI596_DUMP_PORT_FUNCTION ); - - ticks_per_second = rtems_clock_get_ticks_per_second(); - start_ticks = rtems_clock_get_ticks_since_boot(); - end_ticks = start_ticks + ticks_per_second; - - do { - if( dp->dump_status != 0xA006 ) - break; - else - start_ticks = rtems_clock_get_ticks_since_boot(); - } while (start_ticks <= end_ticks); - - if (start_ticks > end_ticks ) { - #ifdef DBG_DUMP_CMD - printk(("uti596_dump: Timed out with dump at 0x%08x\n", (unsigned long)dp )) - #endif - return -1; - } - else { - #ifdef DBG_DUMP_CMD - printk(("uti596_dump: Succeeded with dump at = 0x%08x\n", (unsigned long)dp )) - #endif - return dp->dump_status; - } -} -#endif - -/* - * uti596_wait - * - * Wait for a certain condition. - * - * Input parameters: - * sc - pointer to the uti596_softc struct - * wait_type - UTI596_NO_WAIT - * UTI596_WAIT - * UTI596_WAIT_FOR_CU_ACCEPT - * UTI596_WAIT_FOR_INITIALIZATION - * UTI596_WAIT_FOR_STAT_C - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise. - */ -static int uti596_wait( - uti596_softc_ *sc, - uint8_t waitType -) -{ - rtems_interval ticks_per_second, start_ticks, end_ticks; - - ticks_per_second = rtems_clock_get_ticks_per_second(); - start_ticks = rtems_clock_get_ticks_since_boot(); - end_ticks = start_ticks + ticks_per_second; - - switch( waitType ) { - - case UTI596_NO_WAIT: - return 0; - - case UTI596_WAIT_FOR_CU_ACCEPT: - do { - if (sc->scb.command == 0) - break; - else - - start_ticks = rtems_clock_get_ticks_since_boot(); - - } while (start_ticks <= end_ticks); - - if( (sc->scb.command != 0) || (start_ticks > end_ticks) ) { - printf("i82596 timed out with status %x, cmd %x.\n", - sc->scb.status, sc->scb.command); - return -1; - } - else - return 0; - - case UTI596_WAIT_FOR_INITIALIZATION: - do { - if( !sc->iscp.busy ) - break; - else - start_ticks = rtems_clock_get_ticks_since_boot(); - } while (start_ticks <= end_ticks); - - if (start_ticks > end_ticks ) { - #ifdef DBG_WAIT - printk(("uti596_setScpAndScb: Timed out\n" )) - #endif - return -1; - } - else { - #ifdef DBG_WAIT - printk(("uti596_setScpAndScb: Succeeded\n" )) - #endif - return 0; - } - - case UTI596_WAIT_FOR_STAT_C: - do { - if( *sc->pCurrent_command_status & STAT_C ) - break; - else - start_ticks = rtems_clock_get_ticks_since_boot(); - } while (start_ticks <= end_ticks); - - if (start_ticks > end_ticks ) { - #ifdef DBG_WAIT - printk(("uti596_initMem: timed out - STAT_C not obtained\n" )) - #endif - return -1; - } - else { - #ifdef DBG_WAIT - printk(("uti596_initMem: STAT_C obtained OK\n" )) - #endif - return 0; - } - } - return -1; -} - -/* - * uti596_issueCA - * - * Issue a Channel Attention command. Possibly wait for the - * command to start or complete. - * - * Input parameters: - * sc - pointer to the uti596_softc - * wait_type - UTI596_NO_WAIT - * UTI596_WAIT_BEGIN - * UTI596_WAIT_COMPLETION - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise. - */ -static int uti596_issueCA( - uti596_softc_ *sc, - uint8_t waitType -) -{ - /* Issue Channel Attention */ - i82596->chan_attn = 0x00000000; - - return (uti596_wait ( sc, waitType )); -} - -/* - * uti596_addCmd - * - * Add a uti596_cmd onto the end of the CBL command chain, - * or to the start if the chain is empty. - * - * Input parameters: - * pCmd - a pointer to the command to be added. - * - * Output parameters: NONE - * - * Return value: NONE - */ -static void uti596_addCmd( - i596_cmd *pCmd -) -{ - ISR_Level level; - - #ifdef DBG_ADD_CMD - printk(("uti596_addCmd: Adding command 0x%x\n", pCmd -> command )) - #endif - - /* Mark command as last in list, to return an interrupt */ - pCmd->command |= (CMD_EOL | CMD_INTR ); - pCmd->status = 0; - pCmd->next = I596_NULL; - - _ISR_Local_disable(level); - - if (uti596_softc.pCmdHead == I596_NULL) { - uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd; - uti596_softc.scb.cmd_pointer = word_swap ((unsigned long)pCmd); - - uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); - uti596_softc.scb.command = CUC_START; - uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); - - _ISR_Local_enable(level); - } - else { - uti596_softc.pCmdTail->next = (i596_cmd *) word_swap ((unsigned long)pCmd); - uti596_softc.pCmdTail = pCmd; - _ISR_Local_enable(level); - } - - #ifdef DBG_ADD_CMD - printk(("uti596_addCmd: Scb status & command 0x%x 0x%x\n", - uti596_softc.scb.status, - uti596_softc.scb.command )) - #endif -} - -/* - * uti596_addPolledCmd - * - * Add a single uti596_cmd to the end of the command block list - * for processing, send a CU_START and wait for its acceptance - * - * Input parameters: - * sc - a pointer to the uti596_softc struct - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_addPolledCmd( - i596_cmd *pCmd -) -{ - - #ifdef DBG_ADD_CMD - printk(("uti596_addPolledCmd: Adding command 0x%x\n", pCmd -> command )) - #endif - - pCmd->status = 0; - pCmd->command |= CMD_EOL ; /* only command in list*/ - pCmd->next = I596_NULL; - - uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); - - uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = pCmd; - uti596_softc.scb.cmd_pointer = word_swap((unsigned long)pCmd); - uti596_softc.scb.command = CUC_START; - uti596_issueCA ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); - - uti596_softc.pCmdHead = uti596_softc.pCmdTail = uti596_softc.scb.pCmd = I596_NULL; - uti596_softc.scb.cmd_pointer = (unsigned long) I596_NULL; - - #ifdef DBG_ADD_CMD - printk(("uti596_addPolledCmd: Scb status & command 0x%x 0x%x\n", - uti596_softc.scb.status, - uti596_softc.scb.command )) - #endif -} - -/* currently unused by RTEMS */ -#if 0 -/* - * uti596_CU_dump - * - * Dump the LANC 82596 registers - * The outcome is the same as the portDump() but executed - * via the CU instead of via a PORT access. - * - * Input parameters: - * drp - a pointer to a i596_dump_result structure. - * - * Output parameters: NONE - * - * Return value: NONE - */ -static void uti596_CU_dump ( i596_dump_result * drp) -{ - i596_dump dumpCmd; - - dumpCmd.cmd.command = CmdDump; - dumpCmd.cmd.next = I596_NULL; - dumpCmd.pData = (char *) drp; - uti596_softc.cmdOk = 0; - uti596_addCmd ( (i596_cmd *) &dumpCmd ); - -} -#endif - -#if defined(DBG_STAT) || !defined(IGNORE_NO_RFA) -/* - * uti596_dump_scb - * - * Dump the system control block - * This function expands to nothing when using interrupt driven I/O - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return value: NONE - */ -static void uti596_dump_scb ( void ) -{ - printk(("status 0x%x\n",uti596_softc.scb.status)) - printk(("command 0x%x\n",uti596_softc.scb.command)) - printk(("cmd 0x%x\n",(int)uti596_softc.scb.pCmd)) - printk(("rfd 0x%x\n",(int)uti596_softc.scb.pRfd)) - printk(("crc_err 0x%" PRIx32 "\n",uti596_softc.scb.crc_err)) - printk(("align_err 0x%" PRIx32 "\n",uti596_softc.scb.align_err)) - printk(("resource_err 0x%" PRIx32 "\n",uti596_softc.scb.resource_err )) - printk(("over_err 0x%" PRIx32 "\n",uti596_softc.scb.over_err)) - printk(("rcvdt_err 0x%" PRIx32 "\n",uti596_softc.scb.rcvdt_err)) - printk(("short_err 0x%" PRIx32 "\n",uti596_softc.scb.short_err)) - printk(("t_on 0x%x\n",uti596_softc.scb.t_on)) - printk(("t_off 0x%x\n",uti596_softc.scb.t_off)) -} -#endif - -/* - * uti596_setScpAndScb - * - * Issue the first channel attention after reset and wait for the busy - * field to clear in the iscp. - * - * Input parameters: - * sc - pointer to the global uti596_softc - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise. - */ -static int uti596_setScpAndScb( - uti596_softc_ * sc -) -{ - /* set the busy flag in the iscp */ - sc->iscp.busy = 1; - - /* the command block list (CBL) is empty */ - sc->scb.command = 0; - sc->scb.cmd_pointer = (unsigned long) I596_NULL; /* all 1's */ - sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ - - uti596_writePortFunction( sc->pScp, UTI596_SCP_PORT_FUNCTION ); - - /* Issue CA: pass the scb address to the 596 */ - return ( uti596_issueCA ( sc, UTI596_WAIT_FOR_INITIALIZATION ) ); -} - -/* - * uti596_diagnose - * - * Send a diagnose command to the CU - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise - */ -static int uti596_diagnose( void ) -{ - i596_cmd diagnose; - - diagnose.command = CmdDiagnose; - diagnose.status = 0; - uti596_softc.pCurrent_command_status = (unsigned short *)&diagnose.status; - uti596_addPolledCmd(&diagnose); - return (uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_STAT_C )); - - #ifdef DBG_INIT - printk(("Status diagnostic: 0xa000 is a success ... 0x%2.2x\n", diagnose.status)) - #endif -} - -/* - * uti596_configure - * - * Send the CU a configure command with the desired - * configuration structure - * - * Input parameters: - * sc - a pointer to the uti596_softc struct - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise - */ -static int uti596_configure ( - uti596_softc_ * sc -) -{ - sc->set_conf.cmd.command = CmdConfigure; - memcpy ( (void *)sc->set_conf.data, uti596initSetup, 14); - uti596_addPolledCmd( (i596_cmd *) &sc->set_conf); - - /* Poll for successful command completion */ - sc->pCurrent_command_status = (unsigned short *)&(sc->set_conf.cmd.status); - return ( uti596_wait ( sc, UTI596_WAIT_FOR_STAT_C ) ); -} - -/* - * uti596_IAsetup - * - * Send the CU an Individual Address setup command with - * the ethernet hardware address - * - * Input parameters: - * sc - a pointer to the uti596_softc struct - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise - */ -static int uti596_IAsetup ( - uti596_softc_ * sc -) -{ - int i; - - sc->set_add.cmd.command = CmdSASetup; - for ( i=0; i<6; i++) { - sc->set_add.data[i]=sc->arpcom.ac_enaddr[i]; - } - sc->cmdOk = 0; - uti596_addPolledCmd((i596_cmd *)&sc->set_add); - - /* Poll for successful command completion */ - sc->pCurrent_command_status = (unsigned short *)&(sc->set_add.cmd.status); - return ( uti596_wait ( sc, UTI596_WAIT_FOR_STAT_C ) ); -} - -/* - * uti596_initTBD - * - * Initialize transmit buffer descriptors - * dynamically allocate mem for the number of tbd's required - * - * Input parameters: - * sc - a pointer to the uti596_softc struct - * - * Output parameters: NONE - * - * Return value: - * 0 if successful, -1 otherwise - */ -static int uti596_initTBD ( uti596_softc_ * sc ) -{ - int i; - i596_tbd *pTbd, *pPrev; - - /* Set up a transmit command with a tbd ready */ - sc->pLastUnkRFD = I596_NULL; - sc->pTxCmd = (i596_tx *) calloc (1,sizeof (struct i596_tx) ); - sc->pTbd = (i596_tbd *) calloc (1,sizeof (struct i596_tbd) ); - if ((sc->pTxCmd == NULL) || (sc->pTbd == NULL)) { - return -1; - } - sc->pTxCmd->pTbd = (i596_tbd *) word_swap ((unsigned long) sc->pTbd); - sc->pTxCmd->cmd.command = CMD_FLEX|CmdTx; - sc->pTxCmd->pad = 0; - sc->pTxCmd->count = 0; /* all bytes are in list of TBD's */ - - pPrev = pTbd = sc->pTbd; - - /* Allocate a linked list of tbd's each with it's 'next' field written - * with upper and lower words swapped (for big endian), and mark the end. - */ - for ( i=0; itxBdCount; i++) { - if ( (pTbd = (i596_tbd *) calloc (1,sizeof (struct i596_tbd) )) == NULL ) { - return -1; - } - pPrev->next = (i596_tbd *) word_swap ((unsigned long) pTbd); - pPrev = pTbd; - } - pTbd->next = I596_NULL; - return 0; -} - -/* - * uti596_initRFA - * - * Initialize the Receive Frame Area - * dynamically allocate mem for the number of rfd's required - * - * Input parameters: - * sc - a pointer to the uti596_softc struct - * - * Output parameters: NONE - * - * Return value: - * # of buffer descriptors successfully allocated - */ -static int uti596_initRFA( int num ) -{ - i596_rfd *pRfd; - int i = 0; - - #ifdef DBG_INIT - printk(("uti596_initRFA: begins\n Requested frame descriptors ... %d.\n", num)) - #endif - - /* - * Create the first RFD in the RFA - */ - pRfd = (i596_rfd *) calloc (1, sizeof (struct i596_rfd)); - if ( !pRfd ) { - printk(("Can't allocate first buffer.\n")) - return 0; - } - else { - uti596_softc.countRFD = 1; - uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; - } - - /* Create remaining RFDs */ - for (i = 1; i < num; i++) { - pRfd = (i596_rfd *) calloc (1, sizeof (struct i596_rfd) ); - if ( pRfd != NULL ) { - uti596_softc.countRFD++; /* update count */ - uti596_softc.pEndRFA->next = - (i596_rfd *) word_swap ((unsigned long) pRfd); /* write the link */ - uti596_softc.pEndRFA = pRfd; /* move the end */ - } - else { - printk(("Can't allocate all buffers: only %d allocated\n", i)) - break; - } - } /* end for */ - - uti596_softc.pEndRFA->next = I596_NULL; - UTI_596_ASSERT(uti596_softc.countRFD == num,"INIT:WRONG RFD COUNT\n" ) - - #ifdef DBG_INIT - printk (("uti596_initRFA: Head of RFA is buffer %p \n\ - uti596_initRFA: End of RFA is buffer %p \n", - uti596_softc.pBeginRFA, uti596_softc.pEndRFA )) - #endif - - /* Walk and initialize the RFD's */ - for ( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL; - pRfd = (i596_rfd *) word_swap ((unsigned long)pRfd->next) ) - { - pRfd->cmd = 0x0000; - pRfd->stat = 0x0000; - pRfd->pRbd = I596_NULL; - pRfd->count = 0; /* number of bytes in buffer: usually less than size */ - pRfd->size = 1532; /* was 1532; buffer size ( All RBD ) */ - } /* end for */ - - /* mark the last RFD as the last one in the RDL */ - uti596_softc.pEndRFA -> cmd = CMD_EOL; - uti596_softc.pSavedRfdQueue = - uti596_softc.pEndSavedQueue = I596_NULL; /* initially empty */ - - uti596_softc.savedCount = 0; - uti596_softc.nop.cmd.command = CmdNOp; /* initialize the nop command */ - - return (i); /* the number of allocated buffers */ -} - -/* - * uti596_initMem - * - * Initialize the 82596 memory structures for Tx and Rx - * dynamically allocate mem for the number of tbd's required - * - * Input parameters: - * sc - a pointer to the uti596_softc struct - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_initMem( - uti596_softc_ * sc -) -{ - int i; - - #ifdef DBG_INIT - printk(("uti596_initMem: begins\n")) - #endif - - sc->resetDone = 0; - - /* - * Set up receive frame area (RFA) - */ - i = uti596_initRFA( sc->rxBdCount ); - if ( i < sc->rxBdCount ) { - printk(("init_rfd: only able to allocate %d receive frame descriptors\n", i)) - } - - /* - * Write the SCB with a pointer to the receive frame area - * and keep a pointer for our use. - */ - sc->scb.rfd_pointer = word_swap((unsigned long)sc->pBeginRFA); - sc->scb.pRfd = sc->pBeginRFA; - - /* - * Diagnose the health of the board - */ - uti596_diagnose(); - - /* - * Configure the 82596 - */ - uti596_configure( sc ); - - /* - * Set up the Individual (hardware) Address - */ - uti596_IAsetup ( sc ); - - /* - * Initialize the transmit buffer descriptors - */ - uti596_initTBD( sc ); - - /* Padding used to fill short tx frames */ - memset ( RTEMS_DEVOLATILE( char *, sc->zeroes ), 0, 64); - - /* now need ISR */ - sc->resetDone = 1; -} - -/* - * uti596_initialize - * - * Reset the 82596 and initialize it with a new SCP. - * - * Input parameters: - * sc - pointer to the uti596_softc - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_initialize( - uti596_softc_ *sc -) -{ - /* Reset the device. Stops it from doing whatever it might be doing. */ - uti596_portReset(); - - /* Get a new System Configuration Pointer */ - uti596_scp_alloc( sc ); - - /* write the SYSBUS: interrupt pin active high, LOCK disabled, - * internal triggering, linear mode - */ - sc->pScp->sysbus = 0x44; - - /* provide the iscp to the scp, keep a pointer for our use */ - sc->pScp->iscp_pointer = word_swap((unsigned long)&sc->iscp); - sc->pScp->iscp = &sc->iscp; - - /* provide the scb to the iscp, keep a pointer for our use */ - sc->iscp.scb_pointer = word_swap((unsigned long)&sc->scb); - sc->iscp.scb = &sc->scb; - - #ifdef DBG_INIT - printk(("uti596_initialize: Starting i82596.\n")) - #endif - - /* Set up the 82596 */ - uti596_setScpAndScb( sc ); - - /* clear the scb command word */ - sc->scb.command = 0; -} - -/* - * uti596_initialize_hardware - * - * Reset the 82596 and initialize it with a new SCP. Enable bus snooping. - * Install the interrupt handlers. - * - * Input parameters: - * sc - pointer to the uti596_softc - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_initialize_hardware( - uti596_softc_ *sc -) -{ - printk(("uti596_initialize_hardware: begins\n")) - - /* Get the PCCChip2 to assert bus snooping signals on behalf of the i82596 */ - pccchip2->LANC_berr_ctl = 0x40; - - uti596_initialize( sc ); - - /* - * Configure interrupt control in PCCchip2 - */ - pccchip2->LANC_error = 0xff; /* clear status register */ - pccchip2->LANC_int_ctl = 0x5d; /* lvl 5, enabled, edge-sensitive rising */ - pccchip2->LANC_berr_ctl = 0x5d; /* bus error: lvl 5, enabled, snoop control - * will supply dirty data and leave dirty data - * on read access and sink any data on write - */ - /* - * Install the interrupt handler - * calls rtems_interrupt_catch - */ - set_vector( uti596_DynamicInterruptHandler, 0x57, 1 ); - - /* Initialize the 82596 memory */ - uti596_initMem(sc); - - #ifdef DBG_INIT - printk(("uti596_initialize_hardware: After attach, status of board = 0x%x\n", sc->scb.status )) - #endif -} - -/* - * uti596_reset_hardware - * - * Reset the 82596 and initialize it with an SCP. - * - * Input parameters: - * sc - pointer to the uti596_softc - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_reset_hardware( - uti596_softc_ *sc -) -{ - rtems_status_code status_code; - i596_cmd *pCmd; - - pCmd = sc->pCmdHead; /* This is a tx command for sure (99.99999%) */ - - /* the command block list (CBL) is empty */ - sc->scb.cmd_pointer = (unsigned long) I596_NULL; /* all 1's */ - sc->pCmdHead = sc->scb.pCmd = I596_NULL; /* all 1's */ - - #ifdef DBG_RESET - printk(("uti596_reset_hardware\n")) - #endif - uti596_initialize( sc ); - - /* - * Wake the transmitter if needed. - */ - if ( sc->txDaemonTid && pCmd != I596_NULL ) { - printk(("****RESET: wakes transmitter!\n")) - status_code = rtems_bsdnet_event_send (sc->txDaemonTid, - INTERRUPT_EVENT); - - if ( status_code != RTEMS_SUCCESSFUL ) { - printk(("****ERROR:Could NOT send event to tid 0x%" PRIx32 " : %s\n", - sc->txDaemonTid, rtems_status_text (status_code) )) - } - } - - #ifdef DBG_RESET - printk(("uti596_reset_hardware: After reset_hardware, status of board = 0x%x\n", sc->scb.status )) - #endif -} - -/* - * uti596_clearListStatus - * - * Clear the stat fields for all RFDs - * - * Input parameters: - * pRfd - a pointer to the head of the RFA - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_clearListStatus( - i596_rfd *pRfd -) -{ - while ( pRfd != I596_NULL ) { - pRfd -> stat = 0; - pRfd = (i596_rfd *) word_swap((unsigned long)pRfd-> next); - } -} - -/* - * uti596_reset - * - * Reset the 82596 and reconfigure - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_reset( void ) -{ - uti596_softc_ *sc = &uti596_softc; - - #ifdef DBG_RESET - printk(("uti596_reset: begin\n")) - #endif - - /* Wait for the CU to be available, then - * reset the ethernet hardware. Must re-config. - */ - sc->resetDone = 0; - uti596_wait ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); - uti596_reset_hardware ( &uti596_softc ); - - #ifdef DBG_RESET - uti596_diagnose(); - #endif - - /* - * Configure the 82596 - */ - uti596_configure( sc ); - - /* - * Set up the Individual (hardware) Address - */ - uti596_IAsetup ( sc ); - - sc->pCmdHead = sc->pCmdTail = sc->scb.pCmd = I596_NULL; - - /* restore the RFA */ - - if ( sc->pLastUnkRFD != I596_NULL ) { - sc-> pEndRFA = sc->pLastUnkRFD; /* The end position can be updated */ - sc-> pLastUnkRFD = I596_NULL; - } - - sc->pEndRFA->next = (i596_rfd*)word_swap((uint32_t)sc->pSavedRfdQueue); - if ( sc->pSavedRfdQueue != I596_NULL ) { - sc->pEndRFA = sc->pEndSavedQueue; - sc->pSavedRfdQueue = sc->pEndSavedQueue = I596_NULL; - sc -> countRFD = sc->rxBdCount ; - } - - /* Re-address the head of the RFA in the SCB */ - sc->scb.pRfd = sc->pBeginRFA; - sc->scb.rfd_pointer = word_swap((unsigned long)sc->pBeginRFA); - - /* Clear the status of all RFDs */ - uti596_clearListStatus( sc->pBeginRFA ); - - printk(("uti596_reset: Starting NIC\n")) - - /* Start the receiver */ - sc->scb.command = RX_START; - sc->started = 1; /* assume that the start is accepted */ - sc->resetDone = 1; - uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); - - UTI_596_ASSERT(sc->pCmdHead == I596_NULL, "Reset: CMD not cleared\n") - - #ifdef DBG_RESET - printk(("uti596_reset: completed\n")) - #endif -} - -/* - * uti596_dequeue - * - * Remove an RFD from the received fram queue - * - * Input parameters: - * ppQ - a pointer to a i596_rfd pointer - * - * Output parameters: NONE - * - * Return value: - * pRfd - a pointer to the dequeued RFD - */ -i596_rfd * uti596_dequeue( - i596_rfd ** ppQ -) -{ - ISR_Level level; - i596_rfd * pRfd; - - _ISR_Local_disable(level); - - /* invalid address, or empty queue or emptied queue */ - if( ppQ == NULL || *ppQ == NULL || *ppQ == I596_NULL) { - _ISR_Local_enable(level); - return I596_NULL; - } - - /* - * Point to the dequeued buffer, then - * adjust the queue pointer and detach the buffer - */ - pRfd = *ppQ; - *ppQ = (i596_rfd *) word_swap ((unsigned long) pRfd->next); - pRfd->next = I596_NULL; /* unlink the rfd being returned */ - - _ISR_Local_enable(level); - return pRfd; -} - -/* - * uti596_append - * - * Remove an RFD buffer from the RFA and tack it on to - * the received frame queue for processing. - * - * Input parameters: - * ppQ - a pointer to the queue pointer - * pRfd - a pointer to the buffer to be returned - * - * Output parameters: NONE - * - * Return value: NONE - */ - -void uti596_append( - i596_rfd ** ppQ, - i596_rfd * pRfd -) -{ - - i596_rfd *p; - - if ( pRfd != NULL && pRfd != I596_NULL) { - pRfd -> next = I596_NULL; - pRfd -> cmd |= CMD_EOL; /* set EL bit */ - - if ( *ppQ == NULL || *ppQ == I596_NULL ) { - /* empty list */ - *ppQ = pRfd; - } - else { - /* walk to the end of the list */ - for ( p=*ppQ; - p->next != I596_NULL; - p=(i596_rfd *) word_swap ((unsigned long)p->next) ); - - /* append the rfd */ - p->cmd &= ~CMD_EOL; /* Clear EL bit at end */ - p->next = (i596_rfd *) word_swap ((unsigned long)pRfd); - } - } - else { - printk(("Illegal attempt to append: %p\n", pRfd)) - } -} - -/* - * uti596_supplyFD - * - * Return a buffer (RFD) to the receive frame area (RFA). - * Call with interrupts disabled. - * - * Input parameters: - * pRfd - a pointer to the buffer to be returned - * - * Output parameters: NONE - * - * Return value: NONE - */ -void uti596_supplyFD ( - i596_rfd * pRfd -) -{ - i596_rfd *pLastRfd; - - UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD!\n") - - pRfd -> cmd = CMD_EOL; - pRfd -> pRbd = I596_NULL; - pRfd -> next = I596_NULL; - pRfd -> stat = 0x0000; /* clear STAT_C and STAT_B bits */ - - /* - * Check if the list is empty: - */ - if ( uti596_softc.pBeginRFA == I596_NULL ) { - - /* Start a list with one entry */ - uti596_softc.pBeginRFA = uti596_softc.pEndRFA = pRfd; - UTI_596_ASSERT(uti596_softc.countRFD == 0, "Null begin, but non-zero count\n") - if ( uti596_softc.pLastUnkRFD != I596_NULL ) { - printk(("LastUnkRFD is NOT NULL!!\n")) - } - uti596_softc.countRFD = 1; - return; - } - - /* - * Check if the last RFD is used/read by the 596. - */ - pLastRfd = uti596_softc.pEndRFA; - - /* C = complete, B = busy (prefetched) */ - if ( pLastRfd != I596_NULL && ! (pLastRfd -> stat & ( STAT_C | STAT_B ) )) { - - /* - * Not yet too late to add it - */ - pLastRfd -> next = (i596_rfd *) word_swap ((unsigned long)pRfd); - pLastRfd -> cmd &= ~CMD_EOL; /* RESET_EL : reset EL bit to 0 */ - uti596_softc.countRFD++; /* Lets assume we add it successfully - If not, the RFD may be used, and may - decrement countRFD < 0 !! */ - /* - * Check if the last RFD was used while appending. - */ - if ( pLastRfd -> stat & ( STAT_C | STAT_B ) ) { /* completed or was prefetched */ - /* - * Either the EL bit of the last rfd has been read by the 82596, - * and it will stop after reception,( true when RESET_EL not reached ) or - * the EL bit was NOT read by the 82596 and it will use the linked - * RFD for the next reception. ( true when RESET_EL was reached ) - * So, it is unknown whether or not the linked rfd will be used. - * Therefore, the end of list CANNOT be updated. - */ - UTI_596_ASSERT ( uti596_softc.pLastUnkRFD == I596_NULL, "Too many Unk RFD's\n" ) - uti596_softc.pLastUnkRFD = pRfd; - return; - } - else { - /* - * The RFD being added was not touched by the 82596 - */ - if (uti596_softc.pLastUnkRFD != I596_NULL ) { - - uti596_append((i596_rfd **)&uti596_softc.pSavedRfdQueue, pRfd); /* Only here! saved Q */ - uti596_softc.pEndSavedQueue = pRfd; - uti596_softc.savedCount++; - uti596_softc.countRFD--; - - } - else { - - uti596_softc.pEndRFA = pRfd; /* the RFA has been extended */ - - if ( ( uti596_softc.scb.status & SCB_STAT_RNR || - uti596_softc.scb.status & RU_NO_RESOURCES ) && - uti596_softc.countRFD > 1 ) { - - /* Ensure that beginRFA is not EOL */ - uti596_softc.pBeginRFA -> cmd &= ~CMD_EOL; - - UTI_596_ASSERT(uti596_softc.pEndRFA -> next == I596_NULL, "supply: List buggered\n") - UTI_596_ASSERT(uti596_softc.pEndRFA -> cmd & CMD_EOL, "supply: No EOL at end.\n") - UTI_596_ASSERT(uti596_softc.scb.command == 0, "Supply: scb command must be zero\n") - - #ifdef DBG_MEM - printk(("uti596_supplyFD: starting receiver")) - #endif - - /* start the receiver */ - UTI_596_ASSERT(uti596_softc.pBeginRFA != I596_NULL, "rx start w/ NULL begin! \n") - uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; - uti596_softc.scb.rfd_pointer = word_swap ((unsigned long) uti596_softc.pBeginRFA); - - /* Don't ack RNR! The receiver should be stopped in this case */ - uti596_softc.scb.command = RX_START | SCB_STAT_RNR; - - UTI_596_ASSERT( !(uti596_softc.scb.status & SCB_STAT_FR),"FRAME RECEIVED INT COMING!\n") - - /* send CA signal */ - uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); - } - } - return; - } - } - else { - /* - * too late , pLastRfd in use ( or NULL ), - * in either case, EL bit has been read, and RNR condition will occur - */ - uti596_append( (i596_rfd **)&uti596_softc.pSavedRfdQueue, pRfd); /* save it for RNR */ - - uti596_softc.pEndSavedQueue = pRfd; /* reset end of saved queue */ - uti596_softc.savedCount++; - - return; - } -} - -/* - * send_packet - * - * Send a raw ethernet packet, add a - * transmit command to the CBL - * - * Input parameters: - * ifp - a pointer to the ifnet structure - * m - a pointer to the mbuf being sent - * - * Output parameters: NONE - * - * Return value: NONE - */ -void send_packet( - struct ifnet *ifp, struct mbuf *m -) -{ - i596_tbd *pPrev = I596_NULL; - i596_tbd *pRemainingTbdList; - i596_tbd *pTbd; - struct mbuf *n, *input_m = m; - uti596_softc_ *sc = ifp->if_softc; - struct mbuf *l = NULL; - unsigned int length = 0; - rtems_status_code status; - int bd_count = 0; - rtems_event_set events; - - /* - * For all mbufs in the chain, - * fill a transmit buffer descriptor for each - */ - pTbd = (i596_tbd*) word_swap ((unsigned long)sc->pTxCmd->pTbd); - - do { - if (m->m_len) { - /* - * Fill in the buffer descriptor - */ - length += m->m_len; - pTbd->data = (char *) word_swap ((unsigned long) mtod (m, void *)); - pTbd->size = m->m_len; - pPrev = pTbd; - pTbd = (i596_tbd *) word_swap ((unsigned long) pTbd->next); - l = m; - m = m->m_next; - } - else { - /* - * Just toss empty mbufs - */ - MFREE (m, n); - m = n; - if (l != NULL) - l->m_next = m; - } - } while( m != NULL && ++bd_count < 16 ); - - if ( length < UTI_596_ETH_MIN_SIZE ) { - pTbd->data = (char *) word_swap ((unsigned long) sc->zeroes); /* add padding to pTbd */ - pTbd->size = UTI_596_ETH_MIN_SIZE - length; /* zeroes have no effect on the CRC */ - } - else /* Don't use pTbd in the send routine */ - pTbd = pPrev; - - /* Disconnect the packet from the list of Tbd's */ - pRemainingTbdList = (i596_tbd *) word_swap ((unsigned long)pTbd->next); - pTbd->next = I596_NULL; - pTbd->size |= UTI_596_END_OF_FRAME; - - sc->rawsndcnt++; - - #ifdef DBG_SEND - printk(("send_packet: sending packet\n")) - #endif - - /* Sending Zero length packet: shouldn't happen */ - if (pTbd->size <= 0) return; - - #ifdef DBG_PACKETS - printk (("\nsend_packet: Transmitter adds packet\n")) - print_hdr ( sc->pTxCmd->pTbd->data ); /* print the first part */ - print_pkt ( sc->pTxCmd->pTbd->next->data ); /* print the first part */ - print_echo (sc->pTxCmd->pTbd->data); - #endif - - /* add the command to the output command queue */ - uti596_addCmd ( (i596_cmd *) sc->pTxCmd ); - - /* sleep until the command has been processed or Timeout encountered. */ - status= rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - if ( status != RTEMS_SUCCESSFUL ) { - printk(("Could not sleep %s\n", rtems_status_text(status))) - } - - #ifdef DBG_SEND - printk(("send_packet: RAW - wake\n")) - #endif - - sc->txInterrupts++; - - if ( sc->pTxCmd -> cmd.status & STAT_OK ) { - sc->stats.tx_packets++; - } - else { - - printk(("*** send_packet: Driver Error 0x%x\n", sc->pTxCmd -> cmd.status )) - - sc->stats.tx_errors++; - if ( sc->pTxCmd->cmd.status & 0x0020 ) - sc->stats.tx_retries_exceeded++; - if (!(sc->pTxCmd->cmd.status & 0x0040)) - sc->stats.tx_heartbeat_errors++; - if ( sc->pTxCmd->cmd.status & 0x0400 ) - sc->stats.tx_carrier_errors++; - if ( sc->pTxCmd->cmd.status & 0x0800 ) - sc->stats.collisions++; - if ( sc->pTxCmd->cmd.status & 0x1000 ) - sc->stats.tx_aborted_errors++; - } /* end if stat_ok */ - - /* - * Restore the transmitted buffer descriptor chain. - */ - pTbd -> next = (i596_tbd *) word_swap ((unsigned long)pRemainingTbdList); - - /* - * Free the mbufs used by the sender. - */ - m = input_m; - while ( m != NULL ) { - MFREE(m,n); - m = n; - } -} - -/*********************************************************************** - * Function: uti596_attach - * - * Description: - * Configure the driver, and connect to the network stack - * - * Algorithm: - * - * Check parameters in the ifconfig structure, and - * set driver parameters accordingly. - * Initialize required rx and tx buffers. - * Link driver data structure onto device list. - * Return 1 on successful completion. - * - ***********************************************************************/ - -int uti596_attach( - struct rtems_bsdnet_ifconfig * pConfig, - int attaching -) -{ - uti596_softc_ *sc = &uti596_softc; /* device dependent data structure */ - struct ifnet * ifp = (struct ifnet *)&sc->arpcom.ac_if; /* ifnet structure */ - int unitNumber; - char *unitName; -#if defined(mvme167) - unsigned char j1; /* State of J1 jumpers */ - char *pAddr; - int addr; -#endif - - #ifdef DBG_ATTACH - printk(("uti596_attach: begins\n")) - #endif - - /* The NIC is not started yet */ - sc->started = 0; - - /* Indicate to ULCS that this is initialized */ - ifp->if_softc = (void *)sc; - sc->pScp = NULL; - - /* Parse driver name */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (pConfig, &unitName)) < 0) - return 0; - - ifp->if_name = unitName; - ifp->if_unit = unitNumber; - - /* Assign mtu */ - if ( pConfig -> mtu ) - ifp->if_mtu = pConfig -> mtu; - else - ifp->if_mtu = ETHERMTU; - - /* - * Check whether parameters should be obtained from NVRAM. If - * yes, and if an IP address, netmask, or ethernet address are - * provided in NVRAM, cheat, and stuff them into the ifconfig - * structure, OVERRIDING and existing or NULL values. - * - * Warning: If values are provided in NVRAM, the ifconfig entries - * must be NULL because buffer memory allocated to hold the - * structure values is unrecoverable and would be lost here. - */ - -#if defined(mvme167) - /* Read the J1 header */ - j1 = (unsigned char)(lcsr->vector_base & 0xFF); - - if ( !(j1 & 0x10) ) { - /* Jumper J1-4 is on, configure from NVRAM */ - - if ( (addr = nvram->ipaddr) ) { - /* We have a non-zero entry, copy the value */ - if ( (pAddr = malloc ( INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT )) ) - pConfig->ip_address = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1 ); - else - rtems_panic("Can't allocate ip_address buffer!\n"); - } - - if ( (addr = nvram->netmask) ) { - /* We have a non-zero entry, copy the value */ - if ( (pAddr = malloc ( INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT )) ) - pConfig->ip_netmask = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1 ); - else - rtems_panic("Can't allocate ip_netmask buffer!\n"); - } - - /* Ethernet address requires special handling -- it must be copied into - * the arpcom struct. The following if construct serves only to give the - * NVRAM parameter the highest priority if J1-4 indicates we are configuring - * from NVRAM. - * - * If the ethernet address is specified in NVRAM, go ahead and copy it. - * (ETHER_ADDR_LEN = 6 bytes). - */ - if ( nvram->enaddr[0] || nvram->enaddr[1] || nvram->enaddr[2] ) { - /* Anything in the first three bytes indicates a non-zero entry, copy value */ - memcpy ((void *)sc->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN); - } - else if ( pConfig->hardware_address) { - /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */ - memcpy ((void *)sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN); - } - else { - /* There is no ethernet address provided, so it will be read - * from BBRAM at $FFFC1F2C by default. [mvme167 manual p. 1-47] - */ - memcpy ((void *)sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN); - } - } - else if ( pConfig->hardware_address) { - /* We are not configuring from NVRAM (J1-4 is off), and the ethernet address - * is given in the ifconfig structure. Copy it. - */ - memcpy ((void *)sc->arpcom.ac_enaddr, pConfig->hardware_address, ETHER_ADDR_LEN); - } - else -#endif - { - /* We are not configuring from NVRAM (J1-4 is off), and there is no ethernet - * address provided in the ifconfig struct, so it will be read from BBRAM at - * $FFFC1F2C by default. [mvme167 manual p. 1-47] - */ - memcpy ((void *)sc->arpcom.ac_enaddr, (char *)0xFFFC1F2C, ETHER_ADDR_LEN); - } - - /* Possibly override default acceptance of broadcast packets */ - if (pConfig->ignore_broadcast) - uti596initSetup[8] |= 0x02; - - /* Assign requested receive buffer descriptor count */ - if (pConfig->rbuf_count) - sc->rxBdCount = pConfig->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - - /* Assign requested tx buffer descriptor count */ - if (pConfig->xbuf_count) - sc->txBdCount = pConfig->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - - /* Set up fields in the ifnet structure*/ - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - ifp->if_init = uti596_init; - ifp->if_ioctl = uti596_ioctl; - ifp->if_start = uti596_start; - ifp->if_output = ether_output; - - /* uti596_softc housekeeping */ - sc->started = 1; - sc->pInboundFrameQueue = I596_NULL; - sc->scb.command = 0; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -} - -/*********************************************************************** - * Function: uti596_start - * - * Description: - * start the driver - * - * Algorithm: - * send an event to the tx task - * set the if_flags - * - ***********************************************************************/ -static void uti596_start( - struct ifnet *ifp -) -{ - uti596_softc_ *sc = ifp->if_softc; - - #ifdef DBG_START - printk(("uti596_start: begins\n")) - #endif - - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/*********************************************************************** - * Function: uti596_init - * - * Description: - * driver initialization - * - * Algorithm: - * initialize the 82596 - * start driver tx and rx tasks, and reset task - * send the RX_START command the the RU - * set if_flags - * - * - ***********************************************************************/ -void uti596_init( - void * arg -) -{ - uti596_softc_ *sc = arg; - struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Initialize the 82596 - */ - #ifdef DBG_INIT - printk(("uti596_init: begins\nuti596_init: initializing the 82596...\n")) - #endif - uti596_initialize_hardware(sc); - - /* - * Start driver tasks - */ - #ifdef DBG_INIT - printk(("uti596_init: starting driver tasks...\n")) - #endif - sc->txDaemonTid = rtems_bsdnet_newproc ("UTtx", 2*4096, uti596_txDaemon, (void *)sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("UTrx", 2*4096, uti596_rxDaemon, (void *)sc); - sc->resetDaemonTid = rtems_bsdnet_newproc ("UTrt", 2*4096, uti596_resetDaemon, (void *)sc); - - #ifdef DBG_INIT - printk(("uti596_init: After attach, status of board = 0x%x\n", sc->scb.status )) - #endif - } - - /* - * In case the ISR discovers there are no resources it reclaims - * them and restarts - */ - sc->started = 1; - - /* - * Enable receiver - */ - #ifdef DBG_INIT - printk(("uti596_init: enabling the reciever...\n" )) - #endif - sc->scb.command = RX_START; - uti596_issueCA ( sc, UTI596_WAIT_FOR_CU_ACCEPT ); - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - #ifdef DBG_INIT - printk(("uti596_init: completed.\n")) - #endif -} - -/*********************************************************************** - * Function: uti596stop - * - * Description: - * stop the driver - * - * Algorithm: - * mark driver as not started, - * mark transmitter as busy - * abort any transmissions/receptions - * clean-up all buffers ( RFD's et. al. ) - * - * - ***********************************************************************/ - -/* static */ void uti596_stop( - uti596_softc_ *sc -) -{ - struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - sc->started = 0; - - #ifdef DBG_STOP - printk(("uti596stop: %s: Shutting down ethercard, status was %4.4x.\n", - uti596_softc.arpcom.ac_if.if_name, uti596_softc.scb.status)) - #endif - - printk(("Stopping interface\n")) - sc->scb.command = CUC_ABORT | RX_ABORT; - i82596->chan_attn = 0x00000000; -} - -/*********************************************************************** - * Function: void uti596_txDaemon - * - * Description: Transmit task - * - * Algorithm: Get mbufs to be transmitted, stuff into RFDs, send - * - ***********************************************************************/ - -void uti596_txDaemon( - void *arg -) -{ - uti596_softc_ *sc = (uti596_softc_ *)arg; - struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet from stack - */ - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); - - /* - * Send packets till queue is empty. - * Ensure that irq is on before sending. - */ - for (;;) { - /* Get the next mbuf chain to transmit. */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - - send_packet (ifp, m); /* blocks */ - } - ifp->if_flags &= ~IFF_OACTIVE; /* no more to send, mark output inactive */ - } -} - -/*********************************************************************** - * Function: uti596_rxDaemon - * - * Description: Receiver task - * - * Algorithm: Extract the packet from an RFD, and place into an - * mbuf chain. Place the mbuf chain in the network task - * queue. Assumes that the frame check sequence is removed - * by the 82596. - * - ***********************************************************************/ - -/* static */ void uti596_rxDaemon( - void *arg -) -{ - uti596_softc_ *sc = (uti596_softc_ *)arg; - struct ifnet *ifp = (struct ifnet *)&sc->arpcom.ac_if; - struct mbuf *m; - - i596_rfd *pRfd; - ISR_Level level; - rtems_id tid; - rtems_event_set events; - struct ether_header *eh; - - int frames = 0; - - #ifdef DBG_RX - printk(("uti596_rxDaemon: begin\n")) - printk(("&scb = %p, pRfd = %p\n", &sc->scb,sc->scb.pRfd)) - #endif - - rtems_task_ident (0, 0, &tid); - - for(;;) { - /* - * Wait for packet. - */ - #ifdef DBG_RX - printk(("uti596_rxDaemon: Receiver sleeps\n")) - #endif - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - #ifdef DBG_RX - printk(("uti596_rxDaemon: Receiver wakes\n")) - #endif - /* - * While received frames are available. Note that the frame may be - * a fragment, so it is NOT a complete packet. - */ - pRfd = uti596_dequeue( (i596_rfd **)&sc->pInboundFrameQueue); - while ( pRfd && - pRfd != I596_NULL && - pRfd -> stat & STAT_C ) - { - - if ( pRfd->stat & STAT_OK) { /* a good frame */ - int pkt_len = pRfd->count & 0x3fff; /* the actual # of bytes received */ - - #ifdef DBG_RX - printk(("uti596_rxDaemon: Good frame, @%p, data @%p length %d\n", pRfd, pRfd -> data , pkt_len)) - #endif - frames++; - - /* - * Allocate an mbuf to give to the stack - * The format of the data portion of the RFD is: - * . - * The FRAME CHECK SEQUENCE / CRC is stripped by the uti596. - * This is to be optimized later.... should not have to memcopy! - */ - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - - m->m_pkthdr.rcvif = ifp; - /* move everything into an mbuf */ - memcpy(m->m_data, (const char *)pRfd->data, pkt_len); - m->m_len = m->m_pkthdr.len = pkt_len - sizeof(struct ether_header) - 4; - - /* move the header to an mbuf */ - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - - #ifdef DBG_PACKETS - { - int i; - printk(("uti596_rxDaemon: mbuf contains:\n")) - print_eth( (char *) (((int)m->m_data)-sizeof(struct ether_header))); - for ( i = 0; i<20; i++) { - printk((".")) - } - } - #endif - - ether_input (ifp, eh, m); - - } /* end if STAT_OK */ - - else { - /* - * A bad frame is present: Note that this could be the last RFD! - */ - #ifdef DBG_RX - printk(("uti596_rxDaemon: Bad frame\n")) - #endif - /* - * FIX ME: use the statistics from the SCB - */ - sc->stats.rx_errors++; - if ((sc->scb.pRfd->stat) & 0x0001) - sc->stats.collisions++; - if ((sc->scb.pRfd->stat) & 0x0080) - sc->stats.rx_length_errors++; - if ((sc->scb.pRfd->stat) & 0x0100) - sc->stats.rx_over_errors++; - if ((sc->scb.pRfd->stat) & 0x0200) - sc->stats.rx_fifo_errors++; - if ((sc->scb.pRfd->stat) & 0x0400) - sc->stats.rx_frame_errors++; - if ((sc->scb.pRfd->stat) & 0x0800) - sc->stats.rx_crc_errors++; - if ((sc->scb.pRfd->stat) & 0x1000) - sc->stats.rx_length_errors++; - } - - UTI_596_ASSERT(pRfd != I596_NULL, "Supplying NULL RFD\n") - - _ISR_Local_disable(level); - uti596_supplyFD ( pRfd ); /* Return RFD to RFA. */ - _ISR_Local_enable(level); - - pRfd = uti596_dequeue( (i596_rfd **)&sc->pInboundFrameQueue); /* grab next frame */ - - } /* end while */ - } /* end for() */ - - #ifdef DBG_RX - printk (("uti596_rxDaemon: frames ... %d\n", frames)) - #endif -} - -/*********************************************************************** - * Function: void uti596_resetDaemon - * - * Description: - ***********************************************************************/ -void uti596_resetDaemon( - void *arg -) -{ - uti596_softc_ *sc = (uti596_softc_ *)arg; - rtems_event_set events; - rtems_time_of_day tm_struct; - - /* struct ifnet *ifp = &sc->arpcom.ac_if; */ - - for (;;) { - /* Wait for reset event from ISR */ - rtems_bsdnet_event_receive (NIC_RESET_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, &events); - - rtems_clock_get_tod(&tm_struct); - printk(("reset daemon: Resetting NIC @ %" PRIu32 ":%" PRIu32 ":%" PRIu32 " \n", - tm_struct.hour, tm_struct.minute, tm_struct.second)) - - sc->stats.nic_reset_count++; - /* Reinitialize the LANC */ - rtems_bsdnet_semaphore_obtain (); - uti596_reset(); - rtems_bsdnet_semaphore_release (); - } -} - -/*********************************************************************** - * Function: uti596_DynamicInterruptHandler - * - * Description: - * This is the interrupt handler for the uti596 board - * - ***********************************************************************/ - -/* static */ rtems_isr uti596_DynamicInterruptHandler( - rtems_vector_number irq -) -{ -int fullStatus; - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: begins")) - #endif - - uti596_wait (&uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT); - - scbStatus = (fullStatus = uti596_softc.scb.status) & 0xf000; - - if ( scbStatus ) { - /* acknowledge interrupts */ - - /* Write to the ICLR bit in the PCCchip2 control registers to clear - * the INT status bit. Clearing INT here *before* sending the CA signal - * to the 82596 should ensure that interrupts won't be lost. - */ - pccchip2->LANC_int_ctl |=0x08; - pccchip2->LANC_berr_ctl |=0x08; - - /* printk(("***INFO: ACK %x\n", scbStatus))*/ - - /* Send the CA signal to acknowledge interrupt */ - uti596_softc.scb.command = scbStatus; - uti596_issueCA ( &uti596_softc, UTI596_NO_WAIT ); - - if( uti596_softc.resetDone ) { - /* stack is attached */ - uti596_wait ( &uti596_softc, UTI596_WAIT_FOR_CU_ACCEPT ); - } - else { - printk(("***INFO: ACK'd w/o processing. status = %x\n", scbStatus)) - return; - } - } - else { -#ifndef IGNORE_SPURIOUS_IRQ - printk(("\n***ERROR: Spurious interrupt (full status 0x%x). Resetting...\n", fullStatus)) - uti596_softc.nic_reset = 1; -#endif - } - - if ( (scbStatus & SCB_STAT_CX) && !(scbStatus & SCB_STAT_CNA) ) { - printk(("\n*****ERROR: Command Complete, and CNA available: 0x%x\nResetting...", scbStatus)) - uti596_softc.nic_reset = 1; - return; - } - - if ( !(scbStatus & SCB_STAT_CX) && (scbStatus & SCB_STAT_CNA) ) { - printk(("\n*****ERROR: CNA, NO CX:0x%x\nResetting...",scbStatus)) - uti596_softc.nic_reset = 1; - return; - } - - if ( scbStatus & SCB_CUS_SUSPENDED ) { - printk(("\n*****ERROR: Command unit suspended!:0x%x\nResetting...",scbStatus)) - uti596_softc.nic_reset = 1; - return; - } - - if ( scbStatus & RU_SUSPENDED ) { - printk(("\n*****ERROR: Receive unit suspended!:0x%x\nResetting...",scbStatus)) - uti596_softc.nic_reset = 1; - return; - } - - if ( scbStatus & SCB_STAT_RNR ) { - printk(("\n*****WARNING: RNR %x\n",scbStatus)) - if (uti596_softc.pBeginRFA != I596_NULL) { - printk(("*****INFO: RFD cmd: %x status:%x\n", uti596_softc.pBeginRFA->cmd, - uti596_softc.pBeginRFA->stat)) - } - else { - printk(("*****WARNING: RNR condition with NULL BeginRFA\n")) - } - } - - /* - * Receive Unit Control - * a frame is received - */ - if ( scbStatus & SCB_STAT_FR ) { - uti596_softc.rxInterrupts++; - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: Frame received\n")) - #endif - if ( uti596_softc.pBeginRFA == I596_NULL || - !( uti596_softc.pBeginRFA -> stat & STAT_C)) { -#ifndef IGNORE_NO_RFA - uti596_dump_scb(); - uti596_softc.nic_reset = 1; -#endif - } - else { - while ( uti596_softc.pBeginRFA != I596_NULL && - ( uti596_softc.pBeginRFA -> stat & STAT_C)) { - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: pBeginRFA != NULL\n")) - #endif - count_rx ++; -#ifndef IGNORE_MULTIPLE_RF - if ( count_rx > 1) { - printk(("****WARNING: Received %i frames on 1 interrupt \n", count_rx)) - } -#endif - /* Give Received Frame to the ULCS */ - uti596_softc.countRFD--; - - if ( uti596_softc.countRFD < 0 ) { - printk(("ISR: Count < 0 !!! count == %d, beginRFA = %p\n", - uti596_softc.countRFD, uti596_softc.pBeginRFA)) - } - uti596_softc.stats.rx_packets++; - /* the rfd next link is stored with upper and lower words swapped so read it that way */ - pIsrRfd = (i596_rfd *) word_swap ((unsigned long)uti596_softc.pBeginRFA->next); - /* the append destroys the link */ - uti596_append( (i596_rfd **)&uti596_softc.pInboundFrameQueue , uti596_softc.pBeginRFA ); - - /* - * if we have just received the a frame in the last unknown RFD, - * then it is certain that the RFA is empty. - */ - if ( uti596_softc.pLastUnkRFD == uti596_softc.pBeginRFA ) { - UTI_596_ASSERT(uti596_softc.pLastUnkRFD != I596_NULL,"****ERROR:LastUnk is NULL, begin ptr @ end!\n") - uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD = I596_NULL; - } - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: Wake %#x\n",uti596_softc.rxDaemonTid)) - #endif - sc = rtems_bsdnet_event_send(uti596_softc.rxDaemonTid, INTERRUPT_EVENT); - if ( sc != RTEMS_SUCCESSFUL ) { - rtems_panic("Can't notify rxDaemon: %s\n", - rtems_status_text (sc)); - } - #ifdef DBG_ISR - else { - printk(("uti596_DynamicInterruptHandler: Rx Wake: %#x\n",uti596_softc.rxDaemonTid)) - } - #endif - - uti596_softc.pBeginRFA = pIsrRfd; - } /* end while */ - } /* end if */ - - if ( uti596_softc.pBeginRFA == I596_NULL ) { - /* adjust the pEndRFA to reflect an empty list */ - if ( uti596_softc.pLastUnkRFD == I596_NULL && uti596_softc.countRFD != 0 ) { - printk(("Last Unk is NULL, BeginRFA is null, and count == %d\n", - uti596_softc.countRFD)) - } - uti596_softc.pEndRFA = I596_NULL; - if ( uti596_softc.countRFD != 0 ) { - printk(("****ERROR:Count is %d, but begin ptr is NULL\n", - uti596_softc.countRFD )) - } - } - } /* end if ( scbStatus & SCB_STAT_FR ) */ - - /* - * Command Unit Control - * a command is completed - */ - if ( scbStatus & SCB_STAT_CX ) { - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: CU\n")) - #endif - - pIsrCmd = uti596_softc.pCmdHead; - - /* For ALL completed commands */ - if ( pIsrCmd != I596_NULL && pIsrCmd->status & STAT_C ) { - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: pIsrCmd != NULL\n")) - #endif - - /* Adjust the command block list */ - uti596_softc.pCmdHead = (i596_cmd *) word_swap ((unsigned long)pIsrCmd->next); - - /* - * If there are MORE commands to process, - * the serialization in the raw routine has failed. - * ( Perhaps AddCmd is bad? ) - */ - UTI_596_ASSERT(uti596_softc.pCmdHead == I596_NULL, "****ERROR: command serialization failed\n") - - /* What if the command did not complete OK? */ - switch ( pIsrCmd->command & 0x7) { - case CmdConfigure: - - uti596_softc.cmdOk = 1; - break; - - case CmdDump: - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: dump!\n")) - #endif - uti596_softc.cmdOk = 1; - break; - - case CmdDiagnose: - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: diagnose!\n")) - #endif - uti596_softc.cmdOk = 1; - break; - - case CmdSASetup: - /* printk(("****INFO:Set address interrupt\n")) */ - if ( pIsrCmd -> status & STAT_OK ) { - uti596_softc.cmdOk = 1; - } - else { - printk(("****ERROR:SET ADD FAILED\n")) - } - break; - - case CmdTx: - UTI_596_ASSERT(uti596_softc.txDaemonTid, "****ERROR:Null txDaemonTid\n") - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: wake TX:0x%x\n",uti596_softc.txDaemonTid)) - #endif - if ( uti596_softc.txDaemonTid ) { - /* Ensure that the transmitter is present */ - sc = rtems_bsdnet_event_send (uti596_softc.txDaemonTid, - INTERRUPT_EVENT); - - if ( sc != RTEMS_SUCCESSFUL ) { - printk(("****ERROR:Could NOT send event to tid 0x%" PRIu32 " : %s\n", - uti596_softc.txDaemonTid, rtems_status_text (sc) )) - } - #ifdef DBG_ISR - else { - printk(("****INFO:Tx wake: %#x\n",uti596_softc.txDaemonTid)) - } - #endif - } - break; - - case CmdMulticastList: - printk(("***ERROR:Multicast?!\n")) - pIsrCmd->next = I596_NULL; - break; - - case CmdTDR: { - unsigned long status = *( (unsigned long *)pIsrCmd)+1; - printk(("****ERROR:TDR?!\n")) - - if (status & STAT_C) { - /* mark the TDR command successful */ - uti596_softc.cmdOk = 1; - } - else { - if (status & 0x4000) { - printk(("****WARNING:Transceiver problem.\n")) - } - if (status & 0x2000) { - printk(("****WARNING:Termination problem.\n")) - } - if (status & 0x1000) { - printk(("****WARNING:Short circuit.\n")) - /* printk(("****INFO:Time %ld.\n", status & 0x07ff)) */ - } - } - } - break; - - default: { - /* - * This should never be reached - */ - printk(("CX but NO known command\n")) - } - } /* end switch */ - - pIsrCmd = uti596_softc.pCmdHead; /* next command */ - if ( pIsrCmd != I596_NULL ) { - printk(("****WARNING: more commands in list, but no start to NIC\n")) - } - } /* end if pIsrCmd != NULL && pIsrCmd->stat & STAT_C */ - - else { - if ( pIsrCmd != I596_NULL ) { - /* The command MAY be NULL from a RESET */ - /* Reset the ethernet card, and wake the transmitter (if necessary) */ - printk(("****INFO: Request board reset ( tx )\n")) - uti596_softc.nic_reset = 1; - if ( uti596_softc.txDaemonTid) { - /* Ensure that a transmitter is present */ - sc = rtems_bsdnet_event_send (uti596_softc.txDaemonTid, - INTERRUPT_EVENT); - if ( sc != RTEMS_SUCCESSFUL ) { - printk(("****ERROR:Could NOT send event to tid 0x%" PRIu32 " : %s\n", - uti596_softc.txDaemonTid, rtems_status_text (sc) )) - } - #ifdef DBG_ISR - else { - printk(("uti596_DynamicInterruptHandler: ****INFO:Tx wake: %#x\n", - uti596_softc.txDaemonTid)) - } - #endif - } - } - } - } /* end if command complete */ - - /* - * If the receiver has stopped, - * check if this is a No Resources scenario, - * Try to add more RFD's ( no RBDs are used ) - */ - if ( uti596_softc.started ) { - if ( scbStatus & SCB_STAT_RNR ) { - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: INFO:RNR: status %#x \n", - uti596_softc.scb.status )) - #endif - /* - * THE RECEIVER IS OFF! - */ - if ( uti596_softc.pLastUnkRFD != I596_NULL ) { - /* We have an unknown RFD, it is not inbound */ - if ( uti596_softc.pLastUnkRFD -> stat & (STAT_C | STAT_B )) { /* in use */ - uti596_softc.pEndRFA = uti596_softc.pLastUnkRFD; /* update end */ - } - else { - /* - * It is NOT in use, and since RNR, we know EL bit of pEndRFA was read! - * So, unlink it from the RFA and move it to the saved queue. - * But pBegin can equal LastUnk! - */ - - if ( uti596_softc.pEndRFA != I596_NULL ) { - /* check added feb24. */ - #ifdef DBG_ISR - if ((i596_rfd *)word_swap((unsigned long)uti596_softc.pEndRFA->next) != uti596_softc.pLastUnkRFD) { - printk(("***ERROR:UNK: %p not end->next: %p, end: %p\n", - uti596_softc.pLastUnkRFD, - uti596_softc.pEndRFA -> next, - uti596_softc.pEndRFA)) - printk(("***INFO:countRFD now %d\n", - uti596_softc.countRFD)) - printk(("\n\n")) - } - #endif - uti596_softc.pEndRFA -> next = I596_NULL; /* added feb 16 */ - } - uti596_append( (i596_rfd **)&uti596_softc.pSavedRfdQueue, uti596_softc.pLastUnkRFD ); - uti596_softc.savedCount++; - uti596_softc.pEndSavedQueue = uti596_softc.pLastUnkRFD; - uti596_softc.countRFD--; /* It was not in the RFA */ - /* - * The Begin pointer CAN advance this far. We must resynch the CPU side - * with the chip. - */ - if ( uti596_softc.pBeginRFA == uti596_softc.pLastUnkRFD ) { - #ifdef DBG_ISR - if ( uti596_softc.countRFD != 0 ) { - printk(("****INFO:About to set begin to NULL, with count == %d\n\n", - uti596_softc.countRFD )) - } - #endif - uti596_softc.pBeginRFA = I596_NULL; - UTI_596_ASSERT(uti596_softc.countRFD == 0, "****ERROR:Count must be zero here!\n") - } - } - uti596_softc.pLastUnkRFD = I596_NULL; - } /* end if exists UnkRFD */ - - /* - * Append the saved queue to the RFA. - * Any further RFD's being supplied will be added to - * this new list. - */ - if ( uti596_softc.pSavedRfdQueue != I596_NULL ) { - /* entries to add */ - if ( uti596_softc.pBeginRFA == I596_NULL ) { - /* add at beginning to list */ - #ifdef DBG_ISR - if(uti596_softc.countRFD != 0) { - printk(("****ERROR:Begin pointer is NULL, but count == %d\n", - uti596_softc.countRFD)) - } - #endif - uti596_softc.pBeginRFA = uti596_softc.pSavedRfdQueue; - uti596_softc.pEndRFA = uti596_softc.pEndSavedQueue; - uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL; /* Reset the End */ - } - else { - #ifdef DBG_ISR - if ( uti596_softc.countRFD <= 0) { - printk(("****ERROR:Begin pointer is not NULL, but count == %d\n", - uti596_softc.countRFD)) - } - #endif - UTI_596_ASSERT( uti596_softc.pEndRFA != I596_NULL, "****WARNING: END RFA IS NULL\n") - UTI_596_ASSERT( uti596_softc.pEndRFA->next == I596_NULL, "****ERROR:END RFA -> next must be NULL\n") - - uti596_softc.pEndRFA->next = (i596_rfd *)word_swap((unsigned long)uti596_softc.pSavedRfdQueue); - uti596_softc.pEndRFA->cmd &= ~CMD_EOL; /* clear the end of list */ - uti596_softc.pEndRFA = uti596_softc.pEndSavedQueue; - uti596_softc.pSavedRfdQueue = uti596_softc.pEndSavedQueue = I596_NULL; /* Reset the End */ - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: count... %d, saved ... %d \n", - uti596_softc.countRFD, - uti596_softc.savedCount)) - #endif - } - /* printk(("Isr: countRFD = %d\n",uti596_softc.countRFD)) */ - uti596_softc.countRFD += uti596_softc.savedCount; - /* printk(("Isr: after countRFD = %d\n",uti596_softc.countRFD)) */ - uti596_softc.savedCount = 0; - } - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: The list starts here %p\n",uti596_softc.pBeginRFA )) - #endif - - if ( uti596_softc.countRFD > 1) { - printk(("****INFO: pBeginRFA -> stat = 0x%x\n",uti596_softc.pBeginRFA -> stat)) - printk(("****INFO: pBeginRFA -> cmd = 0x%x\n",uti596_softc.pBeginRFA -> cmd)) - uti596_softc.pBeginRFA -> stat = 0; - UTI_596_ASSERT(uti596_softc.scb.command == 0, "****ERROR:scb command must be zero\n") - uti596_softc.scb.pRfd = uti596_softc.pBeginRFA; - uti596_softc.scb.rfd_pointer = word_swap((unsigned long)uti596_softc.pBeginRFA); - /* start RX here */ - printk(("****INFO: ISR Starting receiver\n")) - uti596_softc.scb.command = RX_START; /* should this also be CU start? */ - i82596->chan_attn = 0x00000000; - } - } /* end stat_rnr */ - } /* end if receiver started */ - - #ifdef DBG_ISR - printk(("uti596_DynamicInterruptHandler: X\n")) - #endif - count_rx=0; - - /* Do this last, to ensure that the reset is called at the right time. */ - if ( uti596_softc.nic_reset ) { - uti596_softc.nic_reset = 0; - sc = rtems_bsdnet_event_send(uti596_softc.resetDaemonTid, NIC_RESET_EVENT); - if ( sc != RTEMS_SUCCESSFUL ) - rtems_panic ("Can't notify resetDaemon: %s\n", rtems_status_text (sc)); - } - return; -} - -/*********************************************************************** - * Function: uti596_ioctl - * - * Description: - * driver ioctl function - * handles SIOCGIFADDR, SIOCSIFADDR, SIOCSIFFLAGS - * - ***********************************************************************/ - -static int uti596_ioctl( - struct ifnet *ifp, - u_long command, - caddr_t data -) -{ - uti596_softc_ *sc = ifp->if_softc; - int error = 0; - - #ifdef DBG_IOCTL - printk(("uti596_ioctl: begins\n", sc->pScp)) - #endif - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - printk(("SIOCSIFADDR\n")) - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - printk(("SIOCSIFFLAGS\n")) - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - printk(("IFF_RUNNING\n")) - uti596_stop (sc); - break; - - case IFF_UP: - printk(("IFF_UP\n")) - uti596_init ( (void *)sc); - break; - - case IFF_UP | IFF_RUNNING: - printk(("IFF_UP and RUNNING\n")) - uti596_stop (sc); - uti596_init ( (void *)sc); - break; - - default: - printk(("default\n")) - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - printk(("show stats\n")) - uti596_stats (sc); - break; - - /* FIXME: All sorts of multicast commands need to be added here! */ - default: - printk(("default: EINVAL\n")) - error = EINVAL; - break; - } - - return error; -} - -/*********************************************************************** - * Function: uti596_stats - * - * Description: - * print out the collected data - * - * Algorithm: - * use printf - * - ***********************************************************************/ - -void uti596_stats( - uti596_softc_ *sc -) -{ - printf ("CPU Reports:\n"); - printf (" Tx raw send count:%-8lu", sc->rawsndcnt); - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Tx Interrupts:%-8lu\n", sc->txInterrupts); - printf (" Rx Packets:%-8u", sc->stats.rx_packets); - printf (" Tx Attempts:%-u\n", sc->stats.tx_packets); - - printf (" Rx Dropped:%-8u", sc->stats.rx_dropped); - printf (" Rx IP Packets:%-8u", sc->stats.rx_packets); - printf (" Tx Errors:%-8u\n", sc->stats.tx_errors); - printf (" Tx aborted:%-8u", sc->stats.tx_aborted_errors); - printf (" Tx Dropped:%-8u\n", sc->stats.tx_dropped); - printf (" Tx IP packets:%-8u", sc->stats.tx_packets); - - printf (" Collisions Detected:%-8u\n", sc->stats.collisions); - printf (" Tx Heartbeat Errors:%-8u", sc->stats.tx_heartbeat_errors); - printf (" Tx Carrier Errors:%-8u\n", sc->stats.tx_carrier_errors); - printf (" Tx Aborted Errors:%-8u", sc->stats.tx_aborted_errors); - printf (" Rx Length Errors:%-8u\n", sc->stats.rx_length_errors); - printf (" Rx Overrun Errors:%-8u", sc->stats.rx_over_errors); - printf (" Rx Fifo Errors:%-8u\n", sc->stats.rx_fifo_errors); - printf (" Rx Framing Errors:%-8u", sc->stats.rx_frame_errors); - printf (" Rx crc errors:%-8u\n", sc->stats.rx_crc_errors); - - printf (" TX WAITS: %-8lu\n", sc->txRawWait); - - printf (" NIC resets: %-8u\n", sc->stats.nic_reset_count); - - printf (" NIC reports\n"); - - #ifdef DBG_STAT - uti596_dump_scb(); - #endif -} - -/************************ PACKET DEBUG ROUTINES ************************/ - -#ifdef DBG_PACKETS - -/* - * dumpQ - * - * Dumps frame queues for debugging - */ -static void dumpQ( void ) -{ - i596_rfd *pRfd; - - printk(("savedQ:\n")) - - for( pRfd = uti596_softc.pSavedRfdQueue; - pRfd != I596_NULL; - pRfd = (i596_rfd*)word_swap((uint32_t)pRfd -> next)) { - printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) - } - - printk(("Inbound:\n")) - - for( pRfd = uti596_softc.pInboundFrameQueue; - pRfd != I596_NULL; - pRfd = (i596_rfd*)word_swap((uint32_t)pRfd -> next)) { - printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) - } - - printk(("Last Unk: %p\n", uti596_softc.pLastUnkRFD )) - printk(("RFA:\n")) - - for( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL; - pRfd = (i596_rfd*)word_swap((uint32_t)pRfd -> next)) { - printk(("pRfd: %p, stat: 0x%x cmd: 0x%x\n",pRfd,pRfd -> stat,pRfd -> cmd)) - } -} - -/* - * show_buffers - * - * Print out the RFA and frame queues - */ -static void show_buffers (void) -{ - i596_rfd *pRfd; - - printk(("82596 cmd: 0x%x, status: 0x%x RFA len: %d\n", - uti596_softc.scb.command, - uti596_softc.scb.status, - uti596_softc.countRFD)) - - printk(("\nRFA: \n")) - - for ( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL; - pRfd = (i596_rfd *)word_swap((uint32_t)pRfd->next) ) { - printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", - pRfd, pRfd->stat, pRfd->cmd)) - } - printk(("\nInbound: \n")) - - for ( pRfd = uti596_softc.pInboundFrameQueue; - pRfd != I596_NULL; - pRfd = (i596_rfd *)word_swap((uint32_t)pRfd->next) ) { - printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", - pRfd, pRfd->stat, pRfd->cmd)) - } - - printk(("\nSaved: \n")) - - for ( pRfd = uti596_softc.pSavedRfdQueue; - pRfd != I596_NULL; - pRfd = (i596_rfd *)word_swap((uint32_t)pRfd->next) ) { - printk(("Frame @ %p, status: %2.2x, cmd: %2.2x\n", - pRfd, pRfd->stat, pRfd->cmd)) - } - - printk(("\nUnknown: %p\n",uti596_softc.pLastUnkRFD)) -} - -/* - * show_queues - * - * Print out the saved frame queue and the RFA - */ -static void show_queues(void) -{ - i596_rfd *pRfd; - - printk(("CMD: 0x%x, Status: 0x%x\n", - uti596_softc.scb.command, - uti596_softc.scb.status)) - printk(("saved Q\n")) - - for ( pRfd = uti596_softc.pSavedRfdQueue; - pRfd != I596_NULL && - pRfd != NULL; - pRfd = (i596_rfd *)word_swap((uint32_t)pRfd->next) ) { - printk(("0x%p\n", pRfd)) - } - - printk(("End saved Q 0x%p\n", uti596_softc.pEndSavedQueue)) - - printk(("\nRFA:\n")) - - for ( pRfd = uti596_softc.pBeginRFA; - pRfd != I596_NULL && - pRfd != NULL; - pRfd = (i596_rfd *)word_swap((uint32_t)pRfd->next) ) { - printk(("0x%p\n", pRfd)) - } - - printk(("uti596_softc.pEndRFA: %p\n",uti596_softc.pEndRFA)) -} - -/* - * print_eth - * - * Print the contents of an ethernet packet - * CANNOT BE CALLED FROM ISR - */ -static void print_eth( - unsigned char *add -) -{ - int i; - short int length; - - printk (("Packet Location %p\n", add)) - printk (("Dest ")) - - for (i = 0; i < 6; i++) { - printk ((" %2.2X", add[i])) - } - printk (("\n")) - printk (("Source")) - - for (i = 6; i < 12; i++) { - printk ((" %2.2X", add[i])) - } - - printk (("\n")) - printk (("frame type %2.2X%2.2X\n", add[12], add[13])) - - if ( add[12] == 0x08 && add[13] == 0x06 ) { - /* an ARP */ - printk (("Hardware type : %2.2X%2.2X\n", add[14],add[15])) - printk (("Protocol type : %2.2X%2.2X\n", add[16],add[17])) - printk (("Hardware size : %2.2X\n", add[18])) - printk (("Protocol size : %2.2X\n", add[19])) - printk (("op : %2.2X%2.2X\n", add[20],add[21])) - printk (("Sender Enet addr: ")) - - for ( i=0; i< 5 ; i++) { - printk (("%x:", add[22 + i])) - } - printk (("%x\n", add[27])) - printk (("Sender IP addr: ")) - - for ( i=0; i< 3 ; i++) { - printk (("%u.", add[28 + i])) - } - printk (("%u\n", add[31])) - printk (("Target Enet addr: ")) - - for ( i=0; i< 5 ; i++) { - printk (( "%x:", add[32 + i])) - } - printk (("%x\n", add[37])) - printk (("Target IP addr: ")) - - for ( i=0; i< 3 ; i++) { - printk (( "%u.", add[38 + i])) - } - printk (("%u\n", add[41])) - } - - if ( add[12] == 0x08 && add[13] == 0x00 ) { - /* an IP packet */ - printk (("*********************IP HEADER******************\n")) - printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15])) - printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] ))) - printk (("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n", - add[18],add[19], add[20], add[21])) - printk (("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n", - add[22],add[23],add[24],add[25])) - printk (("IP packet type: %2.2X code %2.2X\n", add[34],add[35])) - printk (("Source IP address: ")) - - for ( i=0; i< 3 ; i++) { - printk (("%u.", add[26 + i])) - } - printk (("%u\n", add[29])) - printk (("Destination IP address: ")) - - for ( i=0; i< 3 ; i++) { - printk (("%u.", add[30 + i])) - } - printk (("%u\n", add[33])) - } -} - -/* - * print_hdr - * - * Print the contents of an ethernet packet header - * CANNOT BE CALLED FROM ISR - */ -static void print_hdr( - unsigned char *add -) -{ - int i; - - printk (("print_hdr: begins\n")) - printk (("Header Location %p\n", add)) - printk (("Dest ")) - - for (i = 0; i < 6; i++) { - printk ((" %2.2X", add[i])) - } - printk (("\nSource")) - - for (i = 6; i < 12; i++) { - printk ((" %2.2X", add[i])) - } - printk (("\nframe type %2.2X%2.2X\n", add[12], add[13])) - printk (("print_hdr: completed")) -} - -/* - * Function: print_pkt - * - * Print the contents of an ethernet packet & data - * CANNOT BE CALLED FROM ISR - */ -static void print_pkt( - unsigned char *add -) -{ - int i; - short int length; - - printk (("print_pkt: begins")) - printk (("Data Location %p\n", add)) - - if ( add[0] == 0x08 && add[1] == 0x06 ) { - /* an ARP */ - printk (("Hardware type : %2.2X%2.2X\n", add[14],add[15])) - printk (("Protocol type : %2.2X%2.2X\n", add[16],add[17])) - printk (("Hardware size : %2.2X\n", add[18])) - printk (("Protocol size : %2.2X\n", add[19])) - printk (("op : %2.2X%2.2X\n", add[20],add[21])) - printk (("Sender Enet addr: ")) - - for ( i=0; i< 5 ; i++) { - printk (( "%x:", add[22 + i])) - } - printk (("%x\n", add[27])) - printk (("Sender IP addr: ")) - - for ( i=0; i< 3 ; i++) { - printk (("%u.", add[28 + i])) - } - printk (("%u\n", add[31])) - printk (("Target Enet addr: ")) - - for ( i=0; i< 5 ; i++) { - printk (( "%x:", add[32 + i])) - } - printk (("%x\n", add[37])) - printk (("Target IP addr: ")) - - for ( i=0; i< 3 ; i++) { - printk (( "%u.", add[38 + i])) - } - printk (("%u\n", add[41])) - } - - if ( add[0] == 0x08 && add[1] == 0x00 ) { - /* an IP packet */ - printk (("*********************IP HEADER******************\n")) - printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15])) - printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] ))) - printk (("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n", - add[18],add[19], add[20], add[21])) - printk (("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n", - add[22],add[23],add[24],add[25])) - printk (("IP packet type: %2.2X code %2.2X\n", add[34],add[35])) - printk (("Source IP address: ")) - - for ( i=0; i< 3 ; i++) { - printk(( "%u.", add[26 + i])) - } - printk(("%u\n", add[29])) - printk(("Destination IP address: ")) - - for ( i=0; i< 3 ; i++) { - printk(( "%u.", add[30 + i])) - } - printk(("%u\n", add[33])) - printk(("********************IP Packet Data*******************\n")) - length -=20; - - for ( i=0; i < length ; i++) { - printk(("0x%2.2x ", add[34+i])) - } - printk(("\n")) - printk(("ICMP checksum: %2.2x %2.2x\n", add[36], add[37])) - printk(("ICMP identifier: %2.2x %2.2x\n", add[38], add[39])) - printk(("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41])) - printk(("print_pkt: completed")) - } -} - -/* - * print_echo - * - * Print the contents of an echo packet - * CANNOT BE CALLED FROM ISR - */ -static void print_echo( - unsigned char *add -) -{ - int i; - short int length; - - printk (("print_echo: begins")) - - if ( add[12] == 0x08 && add[13] == 0x00 ) { - /* an IP packet */ - printk (("Packet Location %p\n", add)) - printk (("Dest ")) - - for (i = 0; i < 6; i++) { - printk ((" %2.2X", add[i])) - } - printk (("\n")) - printk (("Source")) - - for (i = 6; i < 12; i++) { - printk ((" %2.2X", add[i])) - } - printk (("\n")) - printk (("frame type %2.2X%2.2X\n", add[12], add[13])) - - printk (("*********************IP HEADER******************\n")) - printk (("IP version/IPhdr length: %2.2X TOS: %2.2X\n", add[14] , add[15])) - printk (("IP total length: %2.2X %2.2X, decimal %d\n", add[16], add[17], length = (add[16]<<8 | add[17] ))) - printk (("IP identification: %2.2X %2.2X, 3-bit flags and offset %2.2X %2.2X\n", - add[18],add[19], add[20], add[21])) - printk (("IP TTL: %2.2X, protocol: %2.2X, checksum: %2.2X %2.2X \n", - add[22],add[23],add[24],add[25])) - printk (("IP packet type: %2.2X code %2.2X\n", add[34],add[35])) - printk (("Source IP address: ")) - - for ( i=0; i< 3 ; i++) { - printk (("%u.", add[26 + i])) - } - printk (("%u\n", add[29])) - printk (("Destination IP address: ")) - - for ( i=0; i< 3 ; i++) { - printk (("%u.", add[30 + i])) - } - printk (("%u\n", add[33])) - printk(("********************IP Packet Data*******************\n")) - length -=20; - - for ( i=0; i < length ; i++) { - printk(("0x%2.2x ", add[34+i])) - } - printk(("\n")) - printk(("ICMP checksum: %2.2x %2.2x\n", add[36], add[37])) - printk(("ICMP identifier: %2.2x %2.2x\n", add[38], add[39])) - printk(("ICMP sequence nbr: %2.2x %2.2x\n", add[40], add[41])) - printk(("print_echo: completed")) - } -} - -#endif diff --git a/c/src/lib/libbsp/m68k/mvme167/network/uti596.h b/c/src/lib/libbsp/m68k/mvme167/network/uti596.h deleted file mode 100644 index 29e4fed299..0000000000 --- a/c/src/lib/libbsp/m68k/mvme167/network/uti596.h +++ /dev/null @@ -1,369 +0,0 @@ -/* uti596.h: Contains the defines and structures used by the uti596 driver */ - -/* - * EII: March 11: Created v. 0.0 - */ - -#ifndef UTI596_H -#define UTI596_H -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -/* Ethernet statistics */ - -struct enet_statistics{ - int rx_packets; /* total packets received */ - int tx_packets; /* total packets transmitted */ - int rx_errors; /* bad packets received */ - int tx_errors; /* packet transmit problems */ - int rx_dropped; /* no space in buffers */ - int tx_dropped; - int tx_retries_exceeded; /* excessive retries */ - int multicast; /* multicast packets received */ - int collisions; - - /* detailed rx_errors: */ - int rx_length_errors; - int rx_over_errors; /* receiver ring buff overflow */ - int rx_crc_errors; /* recved pkt with crc error */ - int rx_frame_errors; /* recv'd frame alignment error */ - int rx_fifo_errors; /* recv'r fifo overrun */ - int rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ - int tx_aborted_errors; - int tx_carrier_errors; - int tx_fifo_errors; - int tx_heartbeat_errors; - int tx_window_errors; - - /* NIC reset errors */ - int nic_reset_count; /* The number of times uti596reset() has been called. */ -}; - -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -#define CMD_FLEX 0x0008 /* Enable flexible memory model */ - -#define SCB_STAT_CX 0x8000 /* Cmd completes with 'I' bit set */ -#define SCB_STAT_FR 0x4000 /* Frame Received */ -#define SCB_STAT_CNA 0x2000 /* Cmd unit Not Active */ -#define SCB_STAT_RNR 0x1000 /* Receiver Not Ready */ - -#define SCB_CUS_SUSPENDED 0x0100 -#define SCB_CUS_ACTIVE 0x0200 - -#define STAT_C 0x8000 /* Set to 1 after execution */ -#define STAT_B 0x4000 /* 1 : Cmd being executed, 0 : Cmd done. */ -#define STAT_OK 0x2000 /* 1: Command executed ok 0 : Error */ -#define STAT_A 0x1000 /* command has been aborted */ - -#define STAT_S11 0x0800 -#define STAT_S10 0x0400 -#define STAT_S9 0x0200 -#define STAT_S8 0x0100 -#define STAT_S7 0x0080 -#define STAT_S6 0x0040 -#define STAT_S5 0x0020 -#define STAT_MAX_COLLS 0x000F - -#define RBD_STAT_P 0x4000 /* prefetch */ -#define RBD_STAT_F 0x4000 /* used */ - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define CUC_ABORT 0x0400 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 -#define RX_ABORT 0x0040 - -#define RU_SUSPENDED 0x0010 -#define RU_NO_RESOURCES 0x0020 -#define RU_READY 0x0040 - -#define I596_NULL ( ( void * ) 0xffffffff) -#define UTI_596_END_OF_FRAME 0x8000 - -struct i596_tbd; /* necessary forward declaration */ - -enum commands { - CmdNOp = 0, - CmdSASetup = 1, - CmdConfigure = 2, - CmdMulticastList = 3, - CmdTx = 4, - CmdTDR = 5, - CmdDump = 6, - CmdDiagnose = 7 -}; - -/* - * 82596 Dump Command Result - */ -typedef volatile struct i596_dump_result { - unsigned char bf; - unsigned char config_bytes[11]; - unsigned char reserved1[2]; - unsigned char ia_bytes[6]; - unsigned short last_tx_status; - unsigned short tx_crc_byte01; - unsigned short tx_crc_byte23; - unsigned short rx_crc_byte01; - unsigned short rx_crc_byte23; - unsigned short rx_temp_mem01; - unsigned short rx_temp_mem23; - unsigned short rx_temp_mem45; - unsigned short last_rx_status; - unsigned short hash_reg01; - unsigned short hash_reg23; - unsigned short hash_reg45; - unsigned short hash_reg67; - unsigned short slot_time_counter; - unsigned short wait_time_counter; - unsigned short rx_frame_length; - unsigned long reserved2; - unsigned long cb_in3; - unsigned long cb_in2; - unsigned long cb_in1; - unsigned long la_cb_addr; - unsigned long rdb_pointer; - unsigned long int_memory; - unsigned long rfd_size; - unsigned long tbd_pointer; - unsigned long base_addr; - unsigned long ru_temp_reg; - unsigned long tcb_count; - unsigned long next_rb_size; - unsigned long next_rb_addr; - unsigned long curr_rb_size; - unsigned long la_rbd_addr; - unsigned long next_rbd_addr; - unsigned long curr_rbd_addr; - unsigned long curr_rb_count; - unsigned long next_fd_addr; - unsigned long curr_fd_add; - unsigned long temp_cu_reg; - unsigned long next_tb_count; - unsigned long buffer_addr; - unsigned long la_tbd_addr; - unsigned long next_tbd_addr; - unsigned long cb_command; - unsigned long next_cb_addr; - unsigned long curr_cb_addr; - unsigned long scb_cmd_word; - unsigned long scb_pointer; - unsigned long cb_stat_word; - unsigned long mm_lfsr; - unsigned char micro_machine_bit_array[28]; - unsigned char cu_port[16]; - unsigned long mm_alu; - unsigned long reserved3; - unsigned long mm_temp_a_rr; - unsigned long mm_temp_a; - unsigned long tx_dma_b_cnt; - unsigned long mm_input_port_addr_reg; - unsigned long tx_dma_addr; - unsigned long mm_port_reg1; - unsigned long rx_dma_b_cnt; - unsigned long mm_port_reg2; - unsigned long rx_dma_addr; - unsigned long reserved4; - unsigned long bus_t_timers; - unsigned long diu_cntrl_reg; - unsigned long reserved5; - unsigned long sysbus; - unsigned long biu_cntrl_reg; - unsigned long mm_disp_reg; - unsigned long mm_status_reg; - unsigned short dump_status; -} i596_dump_result; - -typedef volatile struct i596_selftest { - unsigned long rom_signature; - unsigned long results; -} i596_selftest; - -/* - * Action commands - * (big endian, linear mode) - */ -typedef volatile struct i596_cmd { - unsigned short status; - unsigned short command; - volatile struct i596_cmd *next; -} i596_cmd; - -typedef volatile struct i596_nop { - i596_cmd cmd; -} i596_nop; - -typedef volatile struct i596_set_add { - i596_cmd cmd; - char data[8]; -} i596_set_add; - -typedef volatile struct i596_configure { - i596_cmd cmd; - char data[16]; -} i596_configure; - -typedef volatile struct i596_tx { - i596_cmd cmd; - volatile struct i596_tbd *pTbd; - unsigned short count; - unsigned short pad; - char data[6]; - unsigned short length; -} i596_tx; - -typedef volatile struct i596_tdr { - i596_cmd cmd; - unsigned long data; -} i596_tdr; - -typedef volatile struct i596_dump { - i596_cmd cmd; - char *pData; -} i596_dump; - -/* - * Transmit buffer descriptor - */ -typedef volatile struct i596_tbd { - unsigned short size; - unsigned short pad; - volatile struct i596_tbd *next; - char *data; -} i596_tbd; - -/* - * Receive buffer descriptor - * (flexible memory structure) - */ -typedef volatile struct i596_rbd { - unsigned short count; - unsigned short offset; - volatile struct i596_rbd *next; - char *data; - unsigned short size; - unsigned short pad; -} i596_rbd; - -/* - * Receive Frame Descriptor - */ -typedef volatile struct i596_rfd { - unsigned short stat; - unsigned short cmd; - volatile struct i596_rfd *next; - i596_rbd *pRbd; - unsigned short count; - unsigned short size; - char data [1532]; -} i596_rfd; - -/* - * System Control Block - */ -typedef volatile struct i596_scb { - unsigned short status; - unsigned short command; - unsigned long cmd_pointer; - unsigned long rfd_pointer; - unsigned long crc_err; - unsigned long align_err; - unsigned long resource_err; - unsigned long over_err; - unsigned long rcvdt_err; - unsigned long short_err; - unsigned short t_off; - unsigned short t_on; - i596_cmd *pCmd; - i596_rfd *pRfd; -} i596_scb; - -/* - * Intermediate System Configuration Pointer - */ -typedef volatile struct i596_iscp { - uint8_t null1; /* Always zero */ - uint8_t busy; /* Busy byte */ - unsigned short scb_offset; /* Not used in linear mode */ - unsigned long scb_pointer; /* Swapped pointer to scb */ - i596_scb *scb; /* Real pointer to scb */ -} i596_iscp; - -/* - * System Configuration Pointer - */ -typedef volatile struct i596_scp { - unsigned long sysbus; /* Only low 8 bits are used */ - unsigned long pad; /* Must be zero */ - unsigned long iscp_pointer; /* Swapped pointer to iscp */ - i596_iscp *iscp; /* Real pointer to iscp */ -} i596_scp; - -/* - * Device Dependent Data Structure - */ -typedef volatile struct uti596_softc { - struct arpcom arpcom; - i596_scp *pScp; /* Block aligned on 16 byte boundary */ - i596_scp *base_scp; /* Unaligned block. Need for free() */ - i596_iscp iscp; - i596_scb scb; - i596_set_add set_add; - i596_configure set_conf; - i596_tdr tdr; - i596_nop nop; - i596_tx *pTxCmd; - i596_tbd *pTbd; - - i596_rfd *pBeginRFA; - i596_rfd *pEndRFA; - i596_rfd *pLastUnkRFD; - i596_rbd *pLastUnkRBD; - i596_rfd *pEndSavedQueue; - i596_cmd *pCmdHead; - i596_cmd *pCmdTail; /* unneeded, as chaining not used, but implemented */ - - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - rtems_id resetDaemonTid; - - struct enet_statistics stats; - int started; - unsigned long rxInterrupts; - unsigned long txInterrupts; - volatile int cmdOk; - unsigned short * pCurrent_command_status; - int resetDone; - unsigned long txRawWait; - i596_rfd *pInboundFrameQueue; - short int rxBdCount; - short int txBdCount; - short int countRFD; - short int savedCount; - i596_rfd *pSavedRfdQueue; - rtems_name semaphore_name; - rtems_id semaphore_id; - char zeroes[64]; - unsigned long rawsndcnt; - int nic_reset; /* flag for requesting that ISR issue a reset quest */ -} uti596_softc_; - -#endif /* UTI596_H */ diff --git a/c/src/lib/libbsp/m68k/uC5282/Makefile.am b/c/src/lib/libbsp/m68k/uC5282/Makefile.am index 0838c41756..5949cb8209 100644 --- a/c/src/lib/libbsp/m68k/uC5282/Makefile.am +++ b/c/src/lib/libbsp/m68k/uC5282/Makefile.am @@ -34,7 +34,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/uC5282/console/console.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/uC5282/btimer/btimer.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/uC5282/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/cache/cache-mcf5282.c diff --git a/c/src/lib/libbsp/m68k/uC5282/network/network.c b/c/src/lib/libbsp/m68k/uC5282/network/network.c deleted file mode 100644 index b8afa0b968..0000000000 --- a/c/src/lib/libbsp/m68k/uC5282/network/network.c +++ /dev/null @@ -1,1013 +0,0 @@ -/* - * RTEMS driver for MCF5282 Fast Ethernet Controller - * - * Author: W. Eric Norum - * - * COPYRIGHT (c) 2005. - * On-Line Applications Research Corporation (OAR). - * - * 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 - - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 1 - -#define FEC_INTC0_TX_VECTOR (64+23) -#define FEC_INTC0_RX_VECTOR (64+27) -#define MII_VECTOR (64+7) /* IRQ7* pin connected to external transceiver */ -#define MII_EPPAR MCF5282_EPORT_EPPAR_EPPA7_LEVEL -#define MII_EPDDR MCF5282_EPORT_EPDDR_EPDD7 -#define MII_EPIER MCF5282_EPORT_EPIER_EPIE7 -#define MII_EPPDR MCF5282_EPORT_EPPDR_EPPD7 - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses three or more buffer descriptors. - */ -#define RX_BUF_COUNT 32 -#define TX_BUF_COUNT 20 -#define TX_BD_PER_BUF 3 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define TX_INTERRUPT_EVENT RTEMS_EVENT_1 -#define RX_INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). - * Round off to nearest multiple of RBUF_ALIGN. - */ -#define MAX_MTU_SIZE 1518 -#define RBUF_ALIGN 4 -#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) - -#if (MCLBYTES < RBUF_SIZE) - #error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct mcf5282_enet_struct { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - mcf5282BufferDescriptor_t *rxBdBase; - mcf5282BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long txInterrupts; - unsigned long miiInterrupts; - unsigned long txRawWait; - unsigned long txRealign; - unsigned long txRealignDrop; - - /* - * Link parameters - */ - enum { link_auto, link_100Full, link_10Half } link; - uint16_t mii_cr; - uint16_t mii_sr2; -}; -static struct mcf5282_enet_struct enet_driver[NIFACES]; - -/* - * Read MII register - * Busy-waits, but transfer time should be short! - */ -static int -getMII(int phyNumber, int regNumber) -{ - MCF5282_FEC_MMFR = (0x1 << 30) | - (0x2 << 28) | - (phyNumber << 23) | - (regNumber << 18) | - (0x2 << 16); - while ((MCF5282_FEC_EIR & MCF5282_FEC_EIR_MII) == 0); - MCF5282_FEC_EIR = MCF5282_FEC_EIR_MII; - return MCF5282_FEC_MMFR & 0xFFFF; -} - -/* - * Write MII register - * Busy-waits, but transfer time should be short! - */ -static void -setMII(int phyNumber, int regNumber, int value) -{ - MCF5282_FEC_MMFR = (0x1 << 30) | - (0x1 << 28) | - (phyNumber << 23) | - (regNumber << 18) | - (0x2 << 16) | - (value & 0xFFFF); - while ((MCF5282_FEC_EIR & MCF5282_FEC_EIR_MII) == 0); - MCF5282_FEC_EIR = MCF5282_FEC_EIR_MII; -} - -static rtems_isr -mcf5282_fec_rx_interrupt_handler( rtems_vector_number v ) -{ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF; - MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_RXF; - enet_driver[0].rxInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].rxDaemonTid, RX_INTERRUPT_EVENT); -} - -static rtems_isr -mcf5282_fec_tx_interrupt_handler( rtems_vector_number v ) -{ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF; - MCF5282_FEC_EIMR &= ~MCF5282_FEC_EIMR_TXF; - enet_driver[0].txInterrupts++; - rtems_bsdnet_event_send(enet_driver[0].txDaemonTid, TX_INTERRUPT_EVENT); -} - -static rtems_isr -mcf5282_mii_interrupt_handler( rtems_vector_number v ) -{ - uint16 sr2; - - enet_driver[0].miiInterrupts++; - getMII(1, 19); /* Read and clear interrupt status bits */ - enet_driver[0].mii_sr2 = sr2 = getMII(1, 17); - if (((sr2 & 0x200) != 0) - && ((MCF5282_FEC_TCR & MCF5282_FEC_TCR_FDEN) == 0)) - MCF5282_FEC_TCR |= MCF5282_FEC_TCR_FDEN; - else if (((sr2 & 0x200) == 0) - && ((MCF5282_FEC_TCR & MCF5282_FEC_TCR_FDEN) != 0)) - MCF5282_FEC_TCR &= ~MCF5282_FEC_TCR_FDEN; -} - -/* - * Allocate buffer descriptors from (non-cached) on-chip static RAM - * Ensure 128-bit (16-byte) alignment - * Allow some space at the beginning for other diagnostic counters - */ -static mcf5282BufferDescriptor_t * -mcf5282_bd_allocate(unsigned int count) -{ - static mcf5282BufferDescriptor_t *bdp = __SRAMBASE.fec_descriptors; - mcf5282BufferDescriptor_t *p = bdp; - - bdp += count; - if ((int)bdp & 0xF) - bdp = (mcf5282BufferDescriptor_t *)((char *)bdp + (16 - ((int)bdp & 0xF))); - return p; -} - -static void -mcf5282_fec_initialize_hardware(struct mcf5282_enet_struct *sc) -{ - int i; - const unsigned char *hwaddr; - rtems_status_code status; - rtems_isr_entry old_handler; - uint32_t clock_speed = bsp_get_CPU_clock_speed(); - - /* - * Issue reset to FEC - */ - MCF5282_FEC_ECR = MCF5282_FEC_ECR_RESET; - rtems_task_wake_after(2); - MCF5282_FEC_ECR = 0; - - /* - * Configuration of I/O ports is done outside of this function - */ -#if 0 - imm->gpio.pbcnt |= MCF5282_GPIO_PBCNT_SET_FEC; /* Set up port b FEC pins */ -#endif - - /* - * Set our physical address - */ - hwaddr = sc->arpcom.ac_enaddr; - MCF5282_FEC_PALR = (hwaddr[0] << 24) | (hwaddr[1] << 16) | - (hwaddr[2] << 8) | (hwaddr[3] << 0); - MCF5282_FEC_PAUR = (hwaddr[4] << 24) | (hwaddr[5] << 16); - - - /* - * Clear the hash table - */ - MCF5282_FEC_GAUR = 0; - MCF5282_FEC_GALR = 0; - - /* - * Set up receive buffer size - */ - MCF5282_FEC_EMRBR = 1520; /* Standard Ethernet */ - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); - sc->txMbuf = malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = mcf5282_bd_allocate(sc->rxBdCount); - sc->txBdBase = mcf5282_bd_allocate(sc->txBdCount); - MCF5282_FEC_ERDSR = (int)sc->rxBdBase; - MCF5282_FEC_ETDSR = (int)sc->txBdBase; - - /* - * Set up Receive Control Register: - * Not promiscuous - * MII mode - * Full duplex - * No loopback - */ - MCF5282_FEC_RCR = MCF5282_FEC_RCR_MAX_FL(MAX_MTU_SIZE) | - MCF5282_FEC_RCR_MII_MODE; - - /* - * Set up Transmit Control Register: - * Full or half duplex - * No heartbeat - */ - if (sc->link == link_10Half) - MCF5282_FEC_TCR = 0; - else - MCF5282_FEC_TCR = MCF5282_FEC_TCR_FDEN; - - /* - * Initialize statistic counters - */ - MCF5282_FEC_MIBC = MCF5282_FEC_MIBC_MIB_DISABLE; - { - vuint32 *vuip = &MCF5282_FEC_RMON_T_DROP; - while (vuip <= &MCF5282_FEC_IEEE_R_OCTETS_OK) - *vuip++ = 0; - } - MCF5282_FEC_MIBC = 0; - - /* - * Set MII speed to <= 2.5 MHz - */ - i = (clock_speed + 5000000 - 1) / 5000000; - MCF5282_FEC_MSCR = MCF5282_FEC_MSCR_MII_SPEED(i); - - /* - * Set PHYS - * LED1 receive status, LED2 link status, LEDs stretched - * Advertise 100 Mb/s, full-duplex, IEEE-802.3 - * Turn off auto-negotiate - * Clear status - */ - setMII(1, 20, 0x24F2); - setMII(1, 4, 0x0181); - setMII(1, 0, 0x0); - rtems_task_wake_after(2); - sc->mii_sr2 = getMII(1, 17); - switch (sc->link) { - case link_auto: - /* - * Enable speed-change, duplex-change and link-status-change interrupts - * Enable auto-negotiate (start at 100/FULL) - */ - setMII(1, 18, 0x0072); - setMII(1, 0, 0x3100); - break; - - case link_10Half: - /* - * Force 10/HALF - */ - setMII(1, 0, 0x0); - break; - - case link_100Full: - /* - * Force 100/FULL - */ - setMII(1, 0, 0x2100); - break; - } - sc->mii_cr = getMII(1, 0); - - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) - (sc->rxBdBase + i)->status = 0; - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - sc->txBdBase[i].status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - /* - * Set up interrupts - */ - status = rtems_interrupt_catch( mcf5282_fec_tx_interrupt_handler, FEC_INTC0_TX_VECTOR, &old_handler ); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5282 FEC TX interrupt handler: %s\n", - rtems_status_text(status)); - bsp_allocate_interrupt(FEC_IRQ_LEVEL, FEC_IRQ_TX_PRIORITY); - MCF5282_INTC0_ICR23 = MCF5282_INTC_ICR_IL(FEC_IRQ_LEVEL) | - MCF5282_INTC_ICR_IP(FEC_IRQ_TX_PRIORITY); - MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT23 | MCF5282_INTC_IMRL_MASKALL); - - status = rtems_interrupt_catch(mcf5282_fec_rx_interrupt_handler, FEC_INTC0_RX_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5282 FEC RX interrupt handler: %s\n", - rtems_status_text(status)); - bsp_allocate_interrupt(FEC_IRQ_LEVEL, FEC_IRQ_RX_PRIORITY); - MCF5282_INTC0_ICR27 = MCF5282_INTC_ICR_IL(FEC_IRQ_LEVEL) | - MCF5282_INTC_ICR_IP(FEC_IRQ_RX_PRIORITY); - MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT27 | MCF5282_INTC_IMRL_MASKALL); - - status = rtems_interrupt_catch(mcf5282_mii_interrupt_handler, MII_VECTOR, &old_handler); - if (status != RTEMS_SUCCESSFUL) - rtems_panic ("Can't attach MCF5282 FEC MII interrupt handler: %s\n", - rtems_status_text(status)); - MCF5282_EPORT_EPPAR &= ~MII_EPPAR; - MCF5282_EPORT_EPDDR &= ~MII_EPDDR; - MCF5282_EPORT_EPIER |= MII_EPIER; - MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT7 | MCF5282_INTC_IMRL_MASKALL); -} - -/* - * Soak up buffer descriptors that have been sent. - */ -static void -fec_retire_tx_bd(volatile struct mcf5282_enet_struct *sc ) -{ - struct mbuf *m, *n; - uint16_t status; - - while ((sc->txBdActiveCount != 0) - && (((status = sc->txBdBase[sc->txBdTail].status) & MCF5282_FEC_TxBD_R) == 0)) { - if ((status & MCF5282_FEC_TxBD_TO1) == 0) { - m = sc->txMbuf[sc->txBdTail]; - MFREE(m, n); - } - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - sc->txBdActiveCount--; - } -} - -static void -fec_rxDaemon (void *arg) -{ - volatile struct mcf5282_enet_struct *sc = (volatile struct mcf5282_enet_struct *)arg; - struct ifnet *ifp = (struct ifnet* )&sc->arpcom.ac_if; - struct mbuf *m; - uint16_t status; - volatile mcf5282BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - rxBd->status = MCF5282_FEC_RxBD_E; - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status |= MCF5282_FEC_RxBD_W; - break; - } - } - - /* - * Input packet handling loop - */ - MCF5282_FEC_RDAR = 0; - - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & MCF5282_FEC_RxBD_E) { - /* - * Clear old events. - */ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_RXF; - - /* - * Wait for packet to arrive. - * Check the buffer descriptor before waiting for the event. - * This catches the case when a packet arrives between the - * `if' above, and the clearing of the RXF bit in the EIR. - */ - while ((status = rxBd->status) & MCF5282_FEC_RxBD_E) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_RXF; - rtems_interrupt_enable(level); - rtems_bsdnet_event_receive (RX_INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - } - } - - /* - * Check that packet is valid - */ - if (status & MCF5282_FEC_RxBD_L) { - /* - * Pass the packet up the chain. - * FIXME: Packet filtering hook could be done here. - */ - struct ether_header *eh; - int len = rxBd->length - sizeof(uint32_t); - - m = sc->rxMbuf[rxBdIndex]; -#ifdef RTEMS_MCF5282_BSP_ENABLE_DATA_CACHE - /* - * Invalidate the cache. The cache is so small that it's - * reasonable to simply invalidate the whole thing. - */ - rtems_cache_invalidate_entire_data(); -#endif - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - eh = mtod(m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input(ifp, eh, m); - - /* - * Allocate a new mbuf - */ - MGETHDR(m, M_WAIT, MT_DATA); - MCLGET(m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod(m, void *); - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & MCF5282_FEC_RxBD_W) | MCF5282_FEC_RxBD_E; - MCF5282_FEC_RDAR = 0; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void -fec_sendpacket(struct ifnet *ifp, struct mbuf *m) -{ - struct mcf5282_enet_struct *sc = ifp->if_softc; - volatile mcf5282BufferDescriptor_t *firstTxBd, *txBd; - uint16_t status; - int nAdded; - - /* - * Free up buffer descriptors - */ - fec_retire_tx_bd(sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - nAdded = 0; - firstTxBd = sc->txBdBase + sc->txBdHead; - - while (m != NULL) { - /* - * Wait for buffer descriptor to become available - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events. - */ - MCF5282_FEC_EIR = MCF5282_FEC_EIR_TXF; - - /* - * Wait for buffer descriptor to become available. - * Check for buffer descriptors before waiting for the event. - * This catches the case when a buffer became available between - * the `if' above, and the clearing of the TXF bit in the EIR. - */ - fec_retire_tx_bd(sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_event_set events; - int level; - - rtems_interrupt_disable(level); - MCF5282_FEC_EIMR |= MCF5282_FEC_EIMR_TXF; - rtems_interrupt_enable(level); - sc->txRawWait++; - rtems_bsdnet_event_receive(TX_INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - fec_retire_tx_bd(sc); - } - } - - /* - * Don't set the READY flag on the first fragment - * until the whole packet has been readied. - */ - status = nAdded ? MCF5282_FEC_TxBD_R : 0; - - /* - * The IP fragmentation routine in ip_output - * can produce fragments with zero length. - */ - txBd = sc->txBdBase + sc->txBdHead; - if (m->m_len) { - char *p = mtod(m, char *); - int offset = (int)p & 0x3; - if (offset == 0) { - txBd->buffer = p; - txBd->length = m->m_len; - sc->txMbuf[sc->txBdHead] = m; - m = m->m_next; - } - else { - /* - * Stupid FEC can't handle misaligned data! - * Move offending bytes to a local buffer. - * Use buffer descriptor TO1 bit to indicate this. - */ - int nmove = 4 - offset; - char *d = (char *)&sc->txMbuf[sc->txBdHead]; - status |= MCF5282_FEC_TxBD_TO1; - sc->txRealign++; - if (nmove > m->m_len) - nmove = m->m_len; - m->m_data += nmove; - m->m_len -= nmove; - txBd->buffer = d; - txBd->length = nmove; - while (nmove--) - *d++ = *p++; - if (m->m_len == 0) { - struct mbuf *n; - sc->txRealignDrop++; - MFREE(m, n); - m = n; - } - } - nAdded++; - if (++sc->txBdHead == sc->txBdCount) { - status |= MCF5282_FEC_TxBD_W; - sc->txBdHead = 0; - } - txBd->status = status; - } - else { - /* - * Toss empty mbufs. - */ - struct mbuf *n; - MFREE(m, n); - m = n; - } - } - if (nAdded) { - txBd->status = status | MCF5282_FEC_TxBD_R - | MCF5282_FEC_TxBD_L - | MCF5282_FEC_TxBD_TC; - if (nAdded > 1) - firstTxBd->status |= MCF5282_FEC_TxBD_R; - MCF5282_FEC_TDAR = 0; - sc->txBdActiveCount += nAdded; - } -} - -void -fec_txDaemon(void *arg) -{ - struct mcf5282_enet_struct *sc = (struct mcf5282_enet_struct *)arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - 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; - fec_sendpacket(ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - - -/* - * Send packet (caller provides header). - */ -static void -mcf5282_enet_start(struct ifnet *ifp) -{ - struct mcf5282_enet_struct *sc = ifp->if_softc; - - rtems_bsdnet_event_send(sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -static void -fec_init(void *arg) -{ - struct mcf5282_enet_struct *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - /* - * Set up hardware - */ - mcf5282_fec_initialize_hardware(sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc("FECtx", 4096, fec_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc("FECrx", 4096, fec_rxDaemon, sc); - } - - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - MCF5282_FEC_RCR |= MCF5282_FEC_RCR_PROM; - else - MCF5282_FEC_RCR &= ~MCF5282_FEC_RCR_PROM; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - MCF5282_FEC_ECR = MCF5282_FEC_ECR_ETHER_EN; -} - - -static void -fec_stop(struct mcf5282_enet_struct *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - MCF5282_FEC_ECR = 0x0; -} - -/* - * Show interface statistics - */ -static void -enet_stats(struct mcf5282_enet_struct *sc) -{ - printf(" Rx Interrupts:%-10lu", sc->rxInterrupts); - printf("Rx Packet Count:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_PACKETS); - printf(" Rx Broadcast:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_BC_PKT); - printf(" Rx Multicast:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_MC_PKT); - printf("CRC/Align error:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_CRC_ALIGN); - printf(" Rx Undersize:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_UNDERSIZE); - printf(" Rx Oversize:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_OVERSIZE); - printf(" Rx Fragment:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_FRAG); - printf(" Rx Jabber:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_JAB); - printf(" Rx 64:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P64); - printf(" Rx 65-127:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P65T0127); - printf(" Rx 128-255:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_P128TO255); - printf(" Rx 256-511:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P256TO511); - printf(" Rx 511-1023:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_P512TO1023); - printf(" Rx 1024-2047:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_R_P1024TO2047); - printf(" Rx >=2048:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_GTE2048); - printf(" Rx Octets:%-10lu", (uint32_t) MCF5282_FEC_RMON_R_OCTETS); - printf(" Rx Dropped:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_R_DROP); - printf(" Rx frame OK:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_FRAME_OK); - printf(" Rx CRC error:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_CRC); - printf(" Rx Align error:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_R_ALIGN); - printf(" FIFO Overflow:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_MACERR); - printf("Rx Pause Frames:%-10lu", (uint32_t) MCF5282_FEC_IEEE_R_FDXFC); - printf(" Rx Octets OK:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_R_OCTETS_OK); - printf(" Tx Interrupts:%-10lu", sc->txInterrupts); - printf("Tx Output Waits:%-10lu", sc->txRawWait); - printf("Tx mbuf realign:%-10lu\n", sc->txRealign); - printf("Tx realign drop:%-10lu", sc->txRealignDrop); - printf(" Tx Unaccounted:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_DROP); - printf("Tx Packet Count:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_PACKETS); - printf(" Tx Broadcast:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_BC_PKT); - printf(" Tx Multicast:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_MC_PKT); - printf("CRC/Align error:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_CRC_ALIGN); - printf(" Tx Undersize:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_UNDERSIZE); - printf(" Tx Oversize:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_OVERSIZE); - printf(" Tx Fragment:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_FRAG); - printf(" Tx Jabber:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_JAB); - printf(" Tx Collisions:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_COL); - printf(" Tx 64:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_P64); - printf(" Tx 65-127:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P65TO127); - printf(" Tx 128-255:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P128TO255); - printf(" Tx 256-511:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_P256TO511); - printf(" Tx 511-1023:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P512TO1023); - printf(" Tx 1024-2047:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_P1024TO2047); - printf(" Tx >=2048:%-10lu\n", (uint32_t) MCF5282_FEC_RMON_T_P_GTE2048); - printf(" Tx Octets:%-10lu", (uint32_t) MCF5282_FEC_RMON_T_OCTETS); - printf(" Tx Dropped:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_DROP); - printf(" Tx Frame OK:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_FRAME_OK); - printf(" Tx 1 Collision:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_1COL); - printf("Tx >1 Collision:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_MCOL); - printf(" Tx Deferred:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_DEF); - printf(" Late Collision:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_LCOL); - printf(" Excessive Coll:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_EXCOL); - printf(" FIFO Underrun:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_MACERR); - printf(" Carrier Error:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_CSERR); - printf(" Tx SQE Error:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_SQE); - printf("Tx Pause Frames:%-10lu\n", (uint32_t) MCF5282_FEC_IEEE_T_FDXFC); - printf(" Tx Octets OK:%-10lu", (uint32_t) MCF5282_FEC_IEEE_T_OCTETS_OK); - printf(" MII interrupts:%-10lu\n", sc->miiInterrupts); - if ((sc->mii_sr2 & 0x400) == 0) { - printf("LINK DOWN!\n"); - } - else { - int speed; - int full; - int fixed; - if (sc->mii_cr & 0x1000) { - fixed = 0; - speed = sc->mii_sr2 & 0x4000 ? 100 : 10; - full = sc->mii_sr2 & 0x200 ? 1 : 0; - } - else { - fixed = 1; - speed = sc->mii_cr & 0x2000 ? 100 : 10; - full = sc->mii_cr & 0x100 ? 1 : 0; - } - printf("Link %s %d Mb/s, %s-duplex.\n", - fixed ? "fixed" : "auto-negotiate", - speed, - full ? "full" : "half"); - } - printf(" EIR:%8.8lx ", (uint32_t) MCF5282_FEC_EIR); - printf("EIMR:%8.8lx ", (uint32_t) MCF5282_FEC_EIMR); - printf("RDAR:%8.8lx ", (uint32_t) MCF5282_FEC_RDAR); - printf("TDAR:%8.8lx\n", (uint32_t) MCF5282_FEC_TDAR); - printf(" ECR:%8.8lx ", (uint32_t) MCF5282_FEC_ECR); - printf(" RCR:%8.8lx ", (uint32_t) MCF5282_FEC_RCR); - printf(" TCR:%8.8lx\n", (uint32_t) MCF5282_FEC_TCR); - printf("FRBR:%8.8lx ", (uint32_t) MCF5282_FEC_FRBR); - printf("FRSR:%8.8lx\n", (uint32_t) MCF5282_FEC_FRSR); - if (sc->txBdActiveCount != 0) { - int i, n; - /* - * Yes, there are races here with adding and retiring descriptors, - * but this diagnostic is more for when things have backed up. - */ - printf("Transmit Buffer Descriptors (Tail %d, Head %d, Unretired %d):\n", - sc->txBdTail, - sc->txBdHead, - sc->txBdActiveCount); - i = sc->txBdTail; - for (n = 0 ; n < sc->txBdCount ; n++) { - if ((sc->txBdBase[i].status & MCF5282_FEC_TxBD_R) != 0) - printf(" %3d: status:%4.4x length:%-4d buffer:%p\n", - i, - sc->txBdBase[i].status, - sc->txBdBase[i].length, - sc->txBdBase[i].buffer); - if (++i == sc->txBdCount) - i = 0; - } - } -} - -static int -fec_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct mcf5282_enet_struct *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: - fec_stop(sc); - break; - - case IFF_UP: - fec_init(sc); - break; - - case IFF_UP | IFF_RUNNING: - fec_stop(sc); - fec_init(sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - enet_stats(sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -int -rtems_fec_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching ) -{ - struct mcf5282_enet_struct *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - const unsigned char *hwaddr; - const char *env; - - /* - * Parse driver name - */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - /* - * Is driver free? - */ - if ((unitNumber <= 0) || (unitNumber > NIFACES)) { - printf("Bad FEC unit number.\n"); - return 0; - } - sc = &enet_driver[unitNumber - 1]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc != NULL) { - printf("Driver already in use.\n"); - return 0; - } - - /* - * Process options - */ - if (config->hardware_address) { - hwaddr = config->hardware_address; - } else if ((hwaddr = bsp_gethwaddr(unitNumber - 1)) == NULL) { - /* Locally-administered address */ - static const unsigned char defaultAddress[ETHER_ADDR_LEN] = { - 0x06, 'R', 'T', 'E', 'M', 'S'}; - printf ("WARNING -- No %s%d Ethernet address specified " - "-- Using default address.\n", unitName, unitNumber); - hwaddr = defaultAddress; - } - printf("%s%d: Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n", - unitName, unitNumber, - hwaddr[0], hwaddr[1], hwaddr[2], - hwaddr[3], hwaddr[4], hwaddr[5]); - memcpy(sc->arpcom.ac_enaddr, hwaddr, ETHER_ADDR_LEN); - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - - 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 = fec_init; - ifp->if_ioctl = fec_ioctl; - ifp->if_start = mcf5282_enet_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; - - /* - * Check for environment overrides - */ - if (((env = bsp_getbenv("IPADDR0_100FULL")) != NULL) - && ((*env == 'y') || (*env == 'Y'))) - sc->link = link_100Full; - else if (((env = bsp_getbenv("IPADDR0_10HALF")) != NULL) - && ((*env == 'y') || (*env == 'Y'))) - sc->link = link_10Half; - else - sc->link = link_auto; - - /* - * Attach the interface - */ - if_attach(ifp); - ether_ifattach(ifp); - return 1; -}; -- cgit v1.2.3