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/powerpc/gen5200/Makefile.am | 2 +- .../libbsp/powerpc/gen5200/network_5200/network.c | 1581 -------------------- 2 files changed, 1 insertion(+), 1582 deletions(-) delete mode 100644 c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c (limited to 'c/src/lib/libbsp/powerpc/gen5200') diff --git a/c/src/lib/libbsp/powerpc/gen5200/Makefile.am b/c/src/lib/libbsp/powerpc/gen5200/Makefile.am index 66c7379c36..f72583af21 100644 --- a/c/src/lib/libbsp/powerpc/gen5200/Makefile.am +++ b/c/src/lib/libbsp/powerpc/gen5200/Makefile.am @@ -104,7 +104,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/gen5200/start/uboot_supp librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/gen5200/start/bestcomm.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network_5200/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/gen5200/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/cache/cache.c diff --git a/c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c b/c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c deleted file mode 100644 index 2e11915b26..0000000000 --- a/c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c +++ /dev/null @@ -1,1581 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS generic MPC5200 BSP | -+-----------------------------------------------------------------+ -| Partially based on the code references which are named below. | -| Adaptions, modifications, enhancements and any recent parts of | -| the code are: | -| Copyright (c) 2005 | -| 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 MPC5200 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 MPC860 by Jay Monkman (jmonkman@frasca.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__ 1 -#define __BSD_VISIBLE 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* #define ETH_DEBUG */ - -#define FEC_BD_LAST TASK_BD_TFD -#define FEC_BD_INT TASK_BD_INT -#define FEC_BD_READY SDMA_BD_MASK_READY - -/* - * 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 64 -#define TX_BUF_COUNT 64 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -#define FEC_EVENT RTEMS_EVENT_0 - -/* Task number assignment */ -#define FEC_RECV_TASK_NO TASK_FEC_RX -#define FEC_XMIT_TASK_NO TASK_FEC_TX - - -/* BD and parameters are stored in SRAM(refer to sdma.h) */ -#define MPC5200_FEC_BD_BASE ETH_BD_BASE - -/* FEC transmit watermark settings */ -#define MPC5200_FEC_X_WMRK_64 0x0 /* or 0x1 */ -#define MPC5200_FEC_X_WMRK_128 0x2 -#define MPC5200_FEC_X_WMRK_192 0x3 - -/* RBD bits definitions */ -#define MPC5200_FEC_RBD_EMPTY 0x8000 /* Buffer is empty */ -#define MPC5200_FEC_RBD_WRAP 0x2000 /* Last BD in ring */ -#define MPC5200_FEC_RBD_INT 0x1000 /* Interrupt */ -#define MPC5200_FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */ -#define MPC5200_FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */ -#define MPC5200_FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */ -#define MPC5200_FEC_RBD_MC 0x0040 /* The received frame is multicast frame */ -#define MPC5200_FEC_RBD_LG 0x0020 /* Frame length violation */ -#define MPC5200_FEC_RBD_NO 0x0010 /* Nonoctet align frame */ -#define MPC5200_FEC_RBD_SH 0x0008 /* Short frame, FEC does not support SH and this bit is always cleared */ -#define MPC5200_FEC_RBD_CR 0x0004 /* CRC error */ -#define MPC5200_FEC_RBD_OV 0x0002 /* Receive FIFO overrun */ -#define MPC5200_FEC_RBD_TR 0x0001 /* The receive frame is truncated */ -#define MPC5200_FEC_RBD_ERR (MPC5200_FEC_RBD_LG | \ - MPC5200_FEC_RBD_NO | \ - MPC5200_FEC_RBD_CR | \ - MPC5200_FEC_RBD_OV | \ - MPC5200_FEC_RBD_TR) - -/* TBD bits definitions */ -#define MPC5200_FEC_TBD_READY 0x8000 /* Buffer is ready */ -#define MPC5200_FEC_TBD_WRAP 0x2000 /* Last BD in ring */ -#define MPC5200_FEC_TBD_INT 0x1000 /* Interrupt */ -#define MPC5200_FEC_TBD_LAST 0x0800 /* Buffer is last in frame */ -#define MPC5200_FEC_TBD_TC 0x0400 /* Transmit the CRC */ -#define MPC5200_FEC_TBD_ABC 0x0200 /* Append bad CRC */ - -/* MII-related definitios */ -#define MPC5200_FEC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */ -#define MPC5200_FEC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */ -#define MPC5200_FEC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */ -#define MPC5200_FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */ -#define MPC5200_FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */ -#define MPC5200_FEC_MII_DATA_TA 0x00020000 /* Turnaround */ -#define MPC5200_FEC_MII_DATA_DATAMSK 0x0000fff /* PHY data field */ - -#define MPC5200_FEC_MII_DATA_RA_SHIFT 0x12 /* MII Register address bits */ -#define MPC5200_FEC_MII_DATA_PA_SHIFT 0x17 /* MII PHY address bits */ - -#define FEC_INTR_MASK_USED \ -(FEC_INTR_LCEN |FEC_INTR_CRLEN |\ - FEC_INTR_XFUNEN|FEC_INTR_XFERREN|FEC_INTR_RFERREN) - -typedef enum { - FEC_STATE_RESTART_0, - FEC_STATE_RESTART_1, - FEC_STATE_NORMAL, -} mpc5200_fec_state; - -/* - * Device data - */ -typedef struct { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - mpc5200_fec_state state; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - 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; - - struct rtems_mdio_info mdio; - int phyAddr; - bool phyInitialized; -} mpc5200_fec_context; - -static mpc5200_fec_context enet_driver[NIFACES]; - -static void mpc5200_fec_send_event(rtems_id task) -{ - rtems_bsdnet_event_send(task, FEC_EVENT); -} - -static void mpc5200_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 mpc5200_fec_stop_dma(void) -{ - TaskStop(FEC_RECV_TASK_NO); - TaskStop(FEC_XMIT_TASK_NO); -} - -static void mpc5200_fec_request_restart(mpc5200_fec_context *self) -{ - self->state = FEC_STATE_RESTART_0; - mpc5200_fec_send_event(self->txDaemonTid); - mpc5200_fec_send_event(self->rxDaemonTid); -} - -static void mpc5200_fec_start_dma_and_controller(void) -{ - TaskStart(FEC_RECV_TASK_NO, 1, FEC_RECV_TASK_NO, 1); - TaskStart(FEC_XMIT_TASK_NO, 1, FEC_XMIT_TASK_NO, 1); - - mpc5200.ecntrl |= FEC_ECNTRL_OE | FEC_ECNTRL_EN; -} - -/* - * Function: MPC5200_eth_addr_filter_set - * - * Description: Set individual address filter for unicast address and - * set physical address registers. - * - * Returns: void - * - * Notes: - * - */ -static void mpc5200_eth_addr_filter_set(mpc5200_fec_context *self) { - 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 */ - - /* - * Get the mac address of ethernet controller - */ - mac = (unsigned char *)(&self->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 itself 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) - { - - mpc5200.iaddr1 = (1 << (crc - 32)); - mpc5200.iaddr2 = 0; - - } - else - { - - mpc5200.iaddr1 = 0; - mpc5200.iaddr2 = (1 << crc); - - } - - /* - * Set physical address - */ - mpc5200.paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3]; - mpc5200.paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808; - - } - -static int mpc5200_eth_mii_transfer( - int phyAddr, - unsigned regAddr, - uint32_t data -) -{ - int timeout = 0xffff; - - mpc5200.ievent = FEC_INTR_MII; - - mpc5200.mii_data = MPC5200_FEC_MII_DATA_ST - | MPC5200_FEC_MII_DATA_TA - | (phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT) - | (regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT) - | data; - - while (timeout > 0 && (mpc5200.ievent & FEC_INTR_MII) == 0) { - --timeout; - } - - return timeout > 0 ? 0 : -1; -} - -/* FIXME: Make this static, this needs a fix in an application */ -int mpc5200_eth_mii_read( - int phyAddr, - void *arg, - unsigned regAddr, - uint32_t *retVal -) -{ - int rv = mpc5200_eth_mii_transfer( - phyAddr, - regAddr, - MPC5200_FEC_MII_DATA_OP_RD - ); - - *retVal = mpc5200.mii_data & 0xffff; - - return rv; -} - -static int mpc5200_eth_mii_write( - int phyAddr, - void *arg, - unsigned regAddr, - uint32_t data -) -{ - return mpc5200_eth_mii_transfer( - phyAddr, - regAddr, - MPC5200_FEC_MII_DATA_OP_WR | data - ); -} - - -/* - * Reset a running ethernet driver including the hardware FIFOs and the FEC. - */ -static void mpc5200_fec_reset(mpc5200_fec_context *self) -{ - volatile int delay; - /* - * Clear FIFO status registers - */ - mpc5200.rfifo_status &= FEC_FIFO_STAT_ERROR; - mpc5200.tfifo_status &= FEC_FIFO_STAT_ERROR; - - /* - * reset the FIFOs - */ - mpc5200.reset_cntrl = 0x03000000; - - for (delay = 0;delay < 16*4;delay++) {}; - - mpc5200.reset_cntrl = 0x01000000; - - /* - * Issue a reset command to the FEC chip - */ - mpc5200.ecntrl |= FEC_ECNTRL_RESET; - - /* - * wait at least 16 clock cycles - */ - for (delay = 0;delay < 16*4;delay++) {}; -} - - -/* - * Function: mpc5200_fec_off - * - * Description: Stop the FEC and disable the ethernet SmartComm tasks. - * This function "turns off" the driver. - * - * Returns: void - * - * Notes: - * - */ -static void mpc5200_fec_off(mpc5200_fec_context *self) - { - int counter = 0xffff; - - -#if defined(ETH_DEBUG) - uint32_t phyStatus; - int i; - - for(i = 0; i < 9; i++) - { - - mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); - printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); - - } - - for(i = 16; i < 21; i++) - { - - mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); - printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); - - } -#endif /* ETH_DEBUG */ - - /* - * block FEC chip interrupts - */ - mpc5200.imask = 0; - - /* - * issue graceful stop command to the FEC transmitter if necessary - */ - mpc5200.x_cntrl |= FEC_XCNTRL_GTS; - - /* - * wait for graceful stop to register - * FIXME: add rtems_task_wake_after here, if it takes to long - */ - while((counter--) && (!(mpc5200.ievent & FEC_INTR_GRA))); - - mpc5200_fec_stop_dma(); - - /* - * Disable transmit / receive interrupts - */ - bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO); - bestcomm_glue_irq_disable(FEC_RECV_TASK_NO); - - /* - * Disable the Ethernet Controller - */ - mpc5200.ecntrl &= ~(FEC_ECNTRL_OE | FEC_ECNTRL_EN); -} - -/* - * MPC5200 FEC interrupt handler - */ -static void mpc5200_fec_irq_handler(rtems_irq_hdl_param handle) -{ - mpc5200_fec_context *self = (mpc5200_fec_context *) handle; - volatile uint32_t ievent; - - ievent = mpc5200.ievent; - - mpc5200.ievent = ievent; - /* - * check errors, update statistics - */ - if (ievent & FEC_INTR_LATE_COL) { - self->txLateCollision++; - } - if (ievent & FEC_INTR_COL_RETRY) { - self->txRetryLimit++; - } - if (ievent & FEC_INTR_XFIFO_UN) { - self->txUnderrun++; - } - if (ievent & FEC_INTR_XFIFO_ERR) { - self->txFIFOError++; - } - if (ievent & FEC_INTR_RFIFO_ERR) { - self->rxFIFOError++; - } - /* - * fatal error ocurred? - */ - if (ievent & (FEC_INTR_XFIFO_ERR | FEC_INTR_RFIFO_ERR)) { - mpc5200.imask &= ~(FEC_INTR_XFERREN | FEC_INTR_RFERREN); - mpc5200_fec_request_restart(self); - } -} - -static void mpc5200_smartcomm_rx_irq_handler(void *arg) -{ - mpc5200_fec_context *self = arg; - - ++self->rxInterrupts; - mpc5200_fec_send_event(self->rxDaemonTid); - SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_RECV_TASK_NO); - bestcomm_glue_irq_disable(FEC_RECV_TASK_NO); -} - -static void mpc5200_smartcomm_tx_irq_handler(void *arg) -{ - mpc5200_fec_context *self = arg; - - ++self->txInterrupts; - mpc5200_fec_send_event(self->txDaemonTid); - SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_XMIT_TASK_NO); - bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO); -} - -static void mpc5200_fec_init_mib(mpc5200_fec_context *self) -{ - memset(RTEMS_DEVOLATILE(uint8_t *, &mpc5200.RES [0]), 0, 0x2e4); - mpc5200.mib_control = 0x40000000; -} - -/* - * Function: mpc5200_fec_initialize_hardware - * - * Description: Configure the MPC5200 FEC registers and enable the - * SmartComm tasks. This function "turns on" the driver. - * - * Returns: void - * - * Notes: - * - */ -static void mpc5200_fec_initialize_hardware(mpc5200_fec_context *self) -{ - /* We want at most 2.5MHz */ - uint32_t div = 2 * 2500000; - uint32_t mii_speed = (IPB_CLOCK + div - 1) / div; - - /* - * Reset mpc5200 FEC - */ - mpc5200_fec_reset(self); - mpc5200_fec_init_mib(self); - - /* - * Clear FEC-Lite interrupt event register (IEVENT) - */ - mpc5200.ievent = FEC_INTR_CLEAR_ALL; - - /* - * Set interrupt mask register - */ - mpc5200.imask = FEC_INTR_MASK_USED; - /* - * Set FEC-Lite receive control register (R_CNTRL) - * frame length=1518, MII mode for 18-wire-transceiver - */ - mpc5200.r_cntrl = ((ETHER_MAX_LEN << FEC_RCNTRL_MAX_FL_SHIFT) - | FEC_RCNTRL_FCE - | FEC_RCNTRL_MII_MODE); - - /* - * Set FEC-Lite transmit control register (X_CNTRL) - * full-duplex, heartbeat disabled - */ - mpc5200.x_cntrl = FEC_XCNTRL_FDEN; - - - - /* - * Set MII_SPEED = IPB clock / (2 * mii_speed)) - * and do not drop the Preamble. - */ - mpc5200.mii_speed = mii_speed << 1; - - /* - * Set Opcode/Pause Duration Register - */ - mpc5200.op_pause = 0x00010020; - - /* - * Set Rx FIFO alarm and granularity value - */ - mpc5200.rfifo_cntrl = (FEC_FIFO_CNTRL_FRAME - | (0x7 << FEC_FIFO_CNTRL_GR_SHIFT)); - mpc5200.rfifo_alarm = 0x0000030c; - - /* - * Set Tx FIFO granularity value - */ - mpc5200.tfifo_cntrl = (FEC_FIFO_CNTRL_FRAME - | (0x7 << FEC_FIFO_CNTRL_GR_SHIFT)); - - /* - * Set transmit fifo watermark register (X_WMRK), default = 64 - */ - mpc5200.tfifo_alarm = 0x00000100; /* 256 bytes */ - mpc5200.x_wmrk = FEC_XWMRK_256; /* 256 bytes */ - - /* - * Set individual address filter for unicast address - * and set physical address registers. - */ - mpc5200_eth_addr_filter_set(self); - - /* - * Set multicast address filter - */ - mpc5200.gaddr1 = 0x00000000; - mpc5200.gaddr2 = 0x00000000; - - /* - * enable CRC in finite state machine register - */ - mpc5200.xmit_fsm = FEC_FSM_CRC | FEC_FSM_ENFSM; -} - - /* - * Initialize PHY(LXT971A): - * - * Generally, on power up, the LXT971A reads its configuration - * pins to check for forced operation, If not cofigured for - * forced operation, it uses auto-negotiation/parallel detection - * to automatically determine line operating conditions. - * If the PHY device on the other side of the link supports - * auto-negotiation, the LXT971A auto-negotiates with it - * using Fast Link Pulse(FLP) Bursts. If the PHY partner does not - * support auto-negotiation, the LXT971A automatically detects - * the presence of either link pulses(10Mbps PHY) or Idle - * symbols(100Mbps) and sets its operating conditions accordingly. - * - * When auto-negotiation is controlled by software, the following - * steps are recommended. - * - * Note: - * The physical address is dependent on hardware configuration. - * - * Returns: void - * - * Notes: - * - */ -static void mpc5200_fec_initialize_phy(mpc5200_fec_context *self) -{ - if (self->phyInitialized) { - return; - } else { - self->phyInitialized = true; - } - - /* - * Reset PHY, then delay 300ns - */ - mpc5200_eth_mii_write(self->phyAddr, self, 0x0, 0x8000); - - rtems_task_wake_after(2); - - /* MII100 */ - - /* - * Set the auto-negotiation advertisement register bits - */ - mpc5200_eth_mii_write(self->phyAddr, self, 0x4, 0x01e1); - - /* - * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation - */ - mpc5200_eth_mii_write(self->phyAddr, self, 0x0, 0x1200); - - /* - * Wait for AN completion - */ -#if 0 - int timeout = 0x100; - uint32_t phyStatus; - do - { - - rtems_task_wake_after(2); - - if((timeout--) == 0) - { - -#if defined(ETH_DEBUG) - printf ("MPC5200FEC PHY auto neg failed." "\r\n"); -#endif - - } - - if(mpc5200_eth_mii_read(self->phyAddr, self, 0x1, &phyStatus) != true) - { - -#if defined(ETH_DEBUG) - printf ("MPC5200FEC PHY auto neg failed: 0x%04" PRIx32 ".\r\n", phyStatus); -#endif - - return; - - } - - } while((phyStatus & 0x0020) != 0x0020); - -#endif -#if ETH_PROMISCOUS_MODE - mpc5200.r_cntrl |= 0x00000008; /* set to promiscous mode */ -#endif - -#if ETH_LOOP_MODE - mpc5200.r_cntrl |= 0x00000001; /* set to loop mode */ -#endif - -#if defined(ETH_DEBUG) - int i; - uint32_t phyStatus; - /* - * Print PHY registers after initialization. - */ - for(i = 0; i < 9; i++) - { - - mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); - printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); - - } - - for(i = 16; i < 21; i++) - { - - mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus); - printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus); - - } -#endif /* ETH_DEBUG */ - - } - -static void mpc5200_fec_restart(mpc5200_fec_context *self, rtems_id otherDaemon) -{ - if (self->state == FEC_STATE_RESTART_1) { - mpc5200_fec_initialize_hardware(self); - mpc5200_fec_initialize_phy(self); - mpc5200_fec_start_dma_and_controller(); - self->state = FEC_STATE_NORMAL; - } else { - self->state = FEC_STATE_RESTART_1; - } - - mpc5200_fec_send_event(otherDaemon); - while (self->state != FEC_STATE_NORMAL) { - mpc5200_fec_wait_for_event(); - } -} - -/* - * Send packet (caller provides header). - */ -static void mpc5200_fec_tx_start(struct ifnet *ifp) - { - - mpc5200_fec_context *self = ifp->if_softc; - - ifp->if_flags |= IFF_OACTIVE; - - mpc5200_fec_send_event(self->txDaemonTid); - - } - -static TaskBD1_t *mpc5200_fec_init_tx_dma(int bdCount, struct mbuf **mbufs) -{ - TaskSetupParamSet_t param = { - .NumBD = bdCount, - .Size = { - .MaxBuf = ETHER_MAX_LEN - }, - .Initiator = 0, - .StartAddrSrc = 0, - .IncrSrc = sizeof(uint32_t), - .SzSrc = sizeof(uint32_t), - .StartAddrDst = (uint32) &mpc5200.tfifo_data, - .IncrDst = 0, - .SzDst = sizeof(uint32_t) - }; - int bdIndex = 0; - - TaskSetup(FEC_XMIT_TASK_NO, ¶m); - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - mbufs [bdIndex] = NULL; - } - - return (TaskBD1_t *) TaskGetBDRing(FEC_XMIT_TASK_NO); -} - -#if 0 -static void mpc5200_fec_requeue_and_discard_tx_frames( - int bdIndex, - int bdCount, - TaskBD1_t *bdRing, - struct mbuf **mbufs -) -{ - int bdStop = bdIndex; - struct mbuf *previous = NULL; - - do { - struct mbuf *current = NULL; - uint32 status = 0; - TaskBD1_t *bd = NULL; - - if (bdIndex > 1) { - --bdIndex; - } else { - bdIndex = bdCount - 1; - } - - current = mbufs [bdIndex]; - mbufs [bdIndex] = NULL; - - status = bdRing [bdIndex].Status; - bdRing [bdIndex].Status = 0; - - if (current != NULL) { - if ((status & FEC_BD_LAST) != 0) { - if (previous != NULL) { - IF_PREPEND(&ifp->if_snd, previous); - } - } - } else { - break; - } - - previous = current; - } while (bdIndex != bdStop); -} -#endif - -static void mpc5200_fec_discard_tx_frames( - int bdCount, - struct mbuf **mbufs -) -{ - int bdIndex = 0; - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - struct mbuf *m = mbufs [bdIndex]; - - if (m != NULL) { - mbufs [bdIndex] = NULL; - m_free(m); - } - } -} - -static void mpc5200_fec_reset_tx_dma( - int bdCount, - TaskBD1_t *bdRing, - struct mbuf **mbufs, - struct mbuf *m -) -{ - TaskStop(FEC_XMIT_TASK_NO); - TaskBDReset(FEC_XMIT_TASK_NO); - mpc5200_fec_discard_tx_frames(bdCount, mbufs); - while (m != NULL) { - m = m_free(m); - } -} - -static struct mbuf *mpc5200_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 mpc5200_fec_transmit( - struct ifnet *ifp, - int bdCount, - TaskBD1_t *bdRing, - struct mbuf **mbufs, - int *bdIndexPtr, - struct mbuf **mPtr, - TaskBD1_t **firstPtr -) -{ - bool bdShortage = false; - int bdIndex = *bdIndexPtr; - struct mbuf *m = *mPtr; - TaskBD1_t *first = *firstPtr; - - while (true) { - TaskBD1_t *bd = &bdRing [bdIndex]; - - if (bd->Status == 0) { - struct mbuf *done = mbufs [bdIndex]; - bool isFirst = false; - - if (done != NULL) { - m_free(done); - mbufs [bdIndex] = NULL; - } - - m = mpc5200_fec_next_fragment(ifp, m, &isFirst); - if (m != NULL) { - uint32 status = (uint32) m->m_len; - - mbufs [bdIndex] = m; - - rtems_cache_flush_multiple_data_lines(mtod(m, void *), m->m_len); - - if (isFirst) { - first = bd; - } else { - status |= FEC_BD_READY; - } - - bd->DataPtr [0] = mtod(m, uint32); - - if (m->m_next != NULL) { - bd->Status = status; - } else { - bd->Status = status | FEC_BD_INT | FEC_BD_LAST; - first->Status |= FEC_BD_READY; - SDMA_TASK_ENABLE(SDMA_TCR, FEC_XMIT_TASK_NO); - } - - 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 void mpc5200_fec_tx_daemon(void *arg) -{ - mpc5200_fec_context *self = arg; - struct ifnet *ifp = &self->arpcom.ac_if; - int bdIndex = 0; - int bdCount = self->txBdCount; - struct mbuf **mbufs = &self->txMbuf [0]; - struct mbuf *m = NULL; - TaskBD1_t *bdRing = mpc5200_fec_init_tx_dma(bdCount, mbufs); - TaskBD1_t *first = NULL; - bool bdShortage = false; - - while (true) { - if (bdShortage) { - bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO); - } - mpc5200_fec_wait_for_event(); - - if (self->state != FEC_STATE_NORMAL) { - mpc5200_fec_reset_tx_dma(bdCount, bdRing, mbufs, m); - mpc5200_fec_restart(self, self->rxDaemonTid); - bdIndex = 0; - m = NULL; - first = NULL; - } - - bdShortage = mpc5200_fec_transmit( - ifp, - bdCount, - bdRing, - mbufs, - &bdIndex, - &m, - &first - ); - } -} - -static struct mbuf *mpc5200_fec_add_mbuf(struct ifnet *ifp, TaskBD1_t *bd) -{ - struct mbuf *m = NULL; - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - - /* XXX: The dcbi operation does not work properly */ - rtems_cache_flush_multiple_data_lines(mtod(m, void *), ETHER_MAX_LEN); - - bd->DataPtr [0] = mtod(m, uint32); - bd->Status = ETHER_MAX_LEN | FEC_BD_READY; - - return m; -} - -static TaskBD1_t *mpc5200_fec_init_rx_dma( - struct ifnet *ifp, - int bdCount, - struct mbuf **mbufs -) -{ - TaskSetupParamSet_t param = { - .NumBD = bdCount, - .Size = { - .MaxBuf = ETHER_MAX_LEN - }, - .Initiator = 0, - .StartAddrSrc = (uint32) &mpc5200.rfifo_data, - .IncrSrc = 0, - .SzSrc = sizeof(uint32_t), - .StartAddrDst = 0, - .IncrDst = sizeof(uint32_t), - .SzDst = sizeof(uint32_t) - }; - TaskBD1_t *bdRing = NULL; - int bdIndex = 0; - - TaskSetup(FEC_RECV_TASK_NO, ¶m); - bdRing = (TaskBD1_t *) TaskGetBDRing(FEC_RECV_TASK_NO); - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - mbufs [bdIndex] = mpc5200_fec_add_mbuf(ifp, &bdRing [bdIndex]); - } - - return bdRing; -} - -static void mpc5200_fec_reset_rx_dma(int bdCount, TaskBD1_t *bdRing) -{ - int bdIndex = 0; - - TaskStop(FEC_RECV_TASK_NO); - TaskBDReset(FEC_RECV_TASK_NO); - - for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) { - bdRing [bdIndex].Status = ETHER_MAX_LEN | FEC_BD_READY; - } -} - -static int mpc5200_fec_ether_input( - struct ifnet *ifp, - int bdIndex, - int bdCount, - TaskBD1_t *bdRing, - struct mbuf **mbufs -) -{ - while (true) { - TaskBD1_t *bd = &bdRing [bdIndex]; - struct mbuf *m = mbufs [bdIndex]; - uint32 status = 0; - int len = 0; - struct ether_header *eh = NULL; - - SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_RECV_TASK_NO); - status = bd->Status; - - if ((status & FEC_BD_READY) != 0) { - break; - } - - eh = mtod(m, struct ether_header *); - - len = (status & 0xffff) - ETHER_HDR_LEN - ETHER_CRC_LEN; - m->m_len = len; - m->m_pkthdr.len = len; - m->m_data = mtod(m, char *) + ETHER_HDR_LEN; - - ether_input(ifp, eh, m); - - mbufs [bdIndex] = mpc5200_fec_add_mbuf(ifp, bd); - - if (bdIndex < bdCount - 1) { - ++bdIndex; - } else { - bdIndex = 0; - } - } - - return bdIndex; -} - -static void mpc5200_fec_rx_daemon(void *arg) -{ - mpc5200_fec_context *self = arg; - struct ifnet *ifp = &self->arpcom.ac_if; - int bdIndex = 0; - int bdCount = self->rxBdCount; - struct mbuf **mbufs = &self->rxMbuf [0]; - TaskBD1_t *bdRing = mpc5200_fec_init_rx_dma(ifp, bdCount, mbufs); - - while (true) { - bestcomm_glue_irq_enable(FEC_RECV_TASK_NO); - mpc5200_fec_wait_for_event(); - - bdIndex = mpc5200_fec_ether_input(ifp, bdIndex, bdCount, bdRing, mbufs); - - if (self->state != FEC_STATE_NORMAL) { - mpc5200_fec_reset_rx_dma(bdCount, bdRing); - mpc5200_fec_restart(self, self->txDaemonTid); - bdIndex = 0; - } - } -} - -/* - * Initialize and start the device - */ -static void mpc5200_fec_init(void *arg) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - mpc5200_fec_context *self = (mpc5200_fec_context *)arg; - struct ifnet *ifp = &self->arpcom.ac_if; - - if(self->txDaemonTid == 0) - { - size_t rxMbufTableSize = self->rxBdCount * sizeof(*self->rxMbuf); - size_t txMbufTableSize = self->txBdCount * sizeof(*self->txMbuf); - - /* - * Allocate a set of mbuf pointers - */ - self->rxMbuf = malloc(rxMbufTableSize, M_MBUF, M_NOWAIT); - self->txMbuf = malloc(txMbufTableSize, M_MBUF, M_NOWAIT); - - if(!self->rxMbuf || !self->txMbuf) - rtems_panic ("No memory for mbuf pointers"); - - /* - * DMA setup - */ - bestcomm_glue_init(); - mpc5200.sdma.ipr [0] = 4; /* always initiator */ - mpc5200.sdma.ipr [3] = 6; /* eth rx initiator */ - mpc5200.sdma.ipr [4] = 5; /* eth tx initiator */ - - /* - * Set up interrupts - */ - bestcomm_glue_irq_install(FEC_RECV_TASK_NO, - mpc5200_smartcomm_rx_irq_handler, - self); - bestcomm_glue_irq_install(FEC_XMIT_TASK_NO, - mpc5200_smartcomm_tx_irq_handler, - self); - sc = rtems_interrupt_handler_install( - BSP_SIU_IRQ_ETH, - "FEC", - RTEMS_INTERRUPT_UNIQUE, - mpc5200_fec_irq_handler, - self - ); - if(sc != RTEMS_SUCCESSFUL) { - rtems_panic ("Can't attach MPC5x00 FEX interrupt handler\n"); - } - - /* - * Start driver tasks - */ - self->txDaemonTid = rtems_bsdnet_newproc("FEtx", 4096, mpc5200_fec_tx_daemon, self); - self->rxDaemonTid = rtems_bsdnet_newproc("FErx", 4096, mpc5200_fec_rx_daemon, self); - } - - mpc5200_fec_request_restart(self); - - /* - * Set flags appropriately - */ - if(ifp->if_flags & IFF_PROMISC) - mpc5200.r_cntrl |= 0x08; - else - mpc5200.r_cntrl &= ~0x08; - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -static void enet_stats (mpc5200_fec_context *self) -{ - if (self->phyAddr >= 0) { - struct ifnet *ifp = &self->arpcom.ac_if; - int media = IFM_MAKEWORD(0, 0, 0, self->phyAddr); - int rv = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t) &media); - - if (rv == 0) { - rtems_ifmedia2str(media, NULL, 0); - printf ("\n"); - } else { - printf ("PHY communication error\n"); - } - } - printf (" Rx Interrupts:%-8lu", self->rxInterrupts); - printf (" Rx Not First:%-8lu", self->rxNotFirst); - printf (" Rx Not Last:%-8lu\n", self->rxNotLast); - printf (" Rx Giant:%-8lu", self->rxGiant); - printf (" Rx Non-octet:%-8lu", self->rxNonOctet); - printf (" Rx Bad CRC:%-8lu\n", self->rxBadCRC); - printf (" Rx FIFO Error:%-8lu", self->rxFIFOError); - printf (" Rx Collision:%-8lu", self->rxCollision); - - printf (" Tx Interrupts:%-8lu\n", self->txInterrupts); - printf (" Tx Deferred:%-8lu", self->txDeferred); - printf (" Tx Late Collision:%-8lu", self->txLateCollision); - printf (" Tx Retransmit Limit:%-8lu\n", self->txRetryLimit); - printf (" Tx Underrun:%-8lu", self->txUnderrun); - printf (" Tx FIFO Error:%-8lu", self->txFIFOError); - printf (" Tx Misaligned:%-8lu\n", self->txMisaligned); -} - -static int32_t mpc5200_fec_setMultiFilter(struct ifnet *ifp) -{ - /*mpc5200_fec_context *self = ifp->if_softc; */ - /* XXX anything to do? */ - return 0; -} - - -/* - * Driver ioctl handler - */ -static int mpc5200_fec_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) - { - mpc5200_fec_context *self = ifp->if_softc; - int error = 0; - - switch(command) - { - - 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, &self->arpcom) - : ether_delmulti(ifr, &self->arpcom); - - if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) - error = mpc5200_fec_setMultiFilter(ifp); - else - error = 0; - } - break; - } - - case SIOCSIFFLAGS: - - switch(ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - - case IFF_RUNNING: - - mpc5200_fec_off(self); - - break; - - case IFF_UP: - - mpc5200_fec_init(self); - - break; - - case IFF_UP | IFF_RUNNING: - - mpc5200_fec_off(self); - mpc5200_fec_init(self); - - break; - - default: - break; - - } - - break; - - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = rtems_mii_ioctl(&self->mdio, self, command, (int *) data); - break; - - case SIO_RTEMS_SHOW_STATS: - - enet_stats(self); - - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - - error = EINVAL; - - break; - - } - - return error; - - } - - -/* - * Attach the MPC5200 fec driver to the system - */ -static int rtems_mpc5200_fec_driver_attach(struct rtems_bsdnet_ifconfig *config) - { - mpc5200_fec_context *self; - 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; - - } - - self = &enet_driver[unitNumber - 1]; - ifp = &self->arpcom.ac_if; - - if(ifp->if_softc != NULL) - { - - printf ("Driver already in use.\n"); - return 0; - - } - - self->mdio.mdio_r = mpc5200_eth_mii_read; - self->mdio.mdio_w = mpc5200_eth_mii_write; - - /* - * 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 *)self->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 *)self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else - { - /* 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"); - } - -#else /* NVRAM_CONFIGURE != 1 */ - - if(config->hardware_address) - { - - memcpy(self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - - } - else - { - - /* 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"); - - } - -#endif /* NVRAM_CONFIGURE != 1 */ -#ifdef HAS_UBOOT - if ((self->arpcom.ac_enaddr[0] == 0) && - (self->arpcom.ac_enaddr[1] == 0) && - (self->arpcom.ac_enaddr[2] == 0)) { - memcpy( - (void *)self->arpcom.ac_enaddr, - bsp_uboot_board_info.bi_enetaddr, - ETHER_ADDR_LEN - ); - } -#endif - if(config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - if(config->rbuf_count) - self->rxBdCount = config->rbuf_count; - else - self->rxBdCount = RX_BUF_COUNT; - - if(config->xbuf_count) - self->txBdCount = config->xbuf_count; - else - self->txBdCount = TX_BUF_COUNT; - - self->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = self; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = mpc5200_fec_init; - ifp->if_ioctl = mpc5200_fec_ioctl; - ifp->if_start = mpc5200_fec_tx_start; - ifp->if_output = ether_output; - 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_mpc5200_fec_driver_attach_detach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - if (attaching) { - return rtems_mpc5200_fec_driver_attach(config); - } - else { - return 0; - } -} - - -- cgit v1.2.3