⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 network.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * RTEMS/TCPIP driver for MPC8xx SCC1 Ethernet * *  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 <Darlene.Stewart@iit.nrc.ca> *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca> *  Copyright (c) 1999, National Research Council of Canada * *  $Id: network.c,v 1.9 2002/11/04 22:18:26 joel Exp $ */#include <bsp.h>#include <stdio.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <bsp/irq.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>/* * 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     8#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/* * Per-device data */struct m8xx_enet_struct {        struct arpcom           arpcom;        struct mbuf             **rxMbuf;        struct mbuf             **txMbuf;        int                     acceptBroadcast;        int                     rxBdCount;        int                     txBdCount;        int                     txBdHead;        int                     txBdTail;        int                     txBdActiveCount;        m8xxBufferDescriptor_t  *rxBdBase;        m8xxBufferDescriptor_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;};static struct m8xx_enet_struct enet_driver[NIFACES];static void  m8xx_scc1_ethernet_on(const rtems_irq_connect_data* ptr){}static void  m8xx_scc1_ethernet_off(const rtems_irq_connect_data* ptr){  /*   * Please put relevant code there   */}static void  m8xx_scc1_ethernet_isOn(const rtems_irq_connect_data* ptr){  int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name );  BSP_irq_enabled_at_cpm (ptr->name);}/* * SCC1 interrupt handler */static void m8xx_scc1_interrupt_handler (){    /* Frame received? */	if ((m8xx.scc1.sccm & 0x8) && (m8xx.scc1.scce & 0x8)) {		m8xx.scc1.scce = 0x8;		/* Clear receive frame int */		m8xx.scc1.sccm &= ~0x8; 	/* Disable receive frame ints */		enet_driver[0].rxInterrupts++; /* Rx int has occurred */		rtems_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);	}	/* Buffer transmitted or transmitter error? */	if ((m8xx.scc1.sccm & 0x12) && (m8xx.scc1.scce & 0x12)) {		m8xx.scc1.scce = 0x12;		/* Clear Tx int */		m8xx.scc1.sccm &= ~0x12; 	/* Disable Tx ints */		enet_driver[0].txInterrupts++; /* Tx int has occurred */		rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);	}}#ifdef MPC860T/* * FEC interrupt handler */static void m860_fec_interrupt_handler (){  /*   * Frame received?   */  if (m8xx.fec.ievent & M8xx_FEC_IEVENT_RFINT) {    m8xx.fec.ievent = M8xx_FEC_IEVENT_RFINT;    enet_driver[0].rxInterrupts++;    rtems_event_send (enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);  }    /*   * Buffer transmitted or transmitter error?   */  if (m8xx.fec.ievent & M8xx_FEC_IEVENT_TFINT) {    m8xx.fec.ievent = M8xx_FEC_IEVENT_TFINT;    enet_driver[0].txInterrupts++;    rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT);  }}#endifstatic rtems_irq_connect_data ethernetSCC1IrqData = {  BSP_CPM_IRQ_SCC1,  (rtems_irq_hdl) m8xx_scc1_interrupt_handler,  (rtems_irq_enable) m8xx_scc1_ethernet_on,  (rtems_irq_disable) m8xx_scc1_ethernet_off,  (rtems_irq_is_enabled)m8xx_scc1_ethernet_isOn};/* * Initialize the ethernet hardware */static voidm8xx_enet_initialize (struct m8xx_enet_struct *sc){  int i;  unsigned char *hwaddr;    /*   * Configure port A   * PA15 is enet RxD. Set PAPAR(15) to 1, PADIR(15) to 0.   * PA14 is enet TxD. Set PAPAR(14) to 1, PADIR(14) to 0, PAODR(14) to 0.   * PA7 is input CLK1. Set PAPAR(7) to 1, PADIR(7) to 0.   * PA6 is input CLK2. Set PAPAR(6) to 1, PADIR(6) to 0.   */  m8xx.papar |=  0x303;  m8xx.padir &= ~0x303;  m8xx.paodr &= ~0x2;    /*   * Configure port C   * PC11 is CTS1*. Set PCPAR(11) to 0, PCDIR(11) to 0, and PCSO(11) to 1.   * PC10 is CD1*. Set PCPAR(10) to 0, PCDIR(10) to 0, and PCSO(10) to 1.   */  m8xx.pcpar &= ~0x30;  m8xx.pcdir &= ~0x30;  m8xx.pcso  |=  0x30;    /*   * Connect CLK1 and CLK2 to SCC1 in the SICR.   * CLK1 is TxClk, CLK2 is RxClk. No grant mechanism, SCC1 is directly   * connected to the NMSI pins.   * R1CS = 0b101 (CLK2)   * T1CS = 0b100 (CLK1)   */  m8xx.sicr |= 0x2C;    /*   * Initialize SDMA configuration register   */  m8xx.sdcr = 1;    /*   * 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 = m8xx_bd_allocate(sc->rxBdCount);  sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);  m8xx.scc1p.rbase = (char *)sc->rxBdBase - (char *)&m8xx;  m8xx.scc1p.tbase = (char *)sc->txBdBase - (char *)&m8xx;    /*   * Send "Init parameters" command   */  m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC1);    /*   * Set receive and transmit function codes   */  m8xx.scc1p.rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);  m8xx.scc1p.tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0);    /*   * Set maximum receive buffer length   */  m8xx.scc1p.mrblr = RBUF_SIZE;    /*   * Set CRC parameters   */  m8xx.scc1p.un.ethernet.c_pres = 0xFFFFFFFF;  m8xx.scc1p.un.ethernet.c_mask = 0xDEBB20E3;    /*   * Clear diagnostic counters   */  m8xx.scc1p.un.ethernet.crcec = 0;  m8xx.scc1p.un.ethernet.alec = 0;  m8xx.scc1p.un.ethernet.disfc = 0;    /*   * Set pad value   */  m8xx.scc1p.un.ethernet.pads = 0x8888;    /*   * Set retry limit   */  m8xx.scc1p.un.ethernet.ret_lim = 15;    /*   * Set maximum and minimum frame length   */  m8xx.scc1p.un.ethernet.mflr = 1518;  m8xx.scc1p.un.ethernet.minflr = 64;  m8xx.scc1p.un.ethernet.maxd1 = MAX_MTU_SIZE;  m8xx.scc1p.un.ethernet.maxd2 = MAX_MTU_SIZE;    /*   * Clear group address hash table   */  m8xx.scc1p.un.ethernet.gaddr1 = 0;  m8xx.scc1p.un.ethernet.gaddr2 = 0;  m8xx.scc1p.un.ethernet.gaddr3 = 0;  m8xx.scc1p.un.ethernet.gaddr4 = 0;    /*   * Set our physical address   */  hwaddr = sc->arpcom.ac_enaddr;    m8xx.scc1p.un.ethernet.paddr_h = (hwaddr[5] << 8) | hwaddr[4];  m8xx.scc1p.un.ethernet.paddr_m = (hwaddr[3] << 8) | hwaddr[2];  m8xx.scc1p.un.ethernet.paddr_l = (hwaddr[1] << 8) | hwaddr[0];    /*   * Aggressive retry   */  m8xx.scc1p.un.ethernet.p_per = 0;    /*   * Clear individual address hash table   */  m8xx.scc1p.un.ethernet.iaddr1 = 0;  m8xx.scc1p.un.ethernet.iaddr2 = 0;  m8xx.scc1p.un.ethernet.iaddr3 = 0;  m8xx.scc1p.un.ethernet.iaddr4 = 0;    /*   * Clear temp address   */  m8xx.scc1p.un.ethernet.taddr_l = 0;  m8xx.scc1p.un.ethernet.taddr_m = 0;  m8xx.scc1p.un.ethernet.taddr_h = 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   */  m8xx.scc1.scce = 0xFFFF;    /*   * Set up interrupts   */  if (!BSP_install_rtems_irq_handler (&ethernetSCC1IrqData)) {    rtems_panic ("Can't attach M8xx SCC1 interrupt handler\n");  }  m8xx.scc1.sccm = 0;     /* No interrupts unmasked till necessary */    /*   * Set up General SCC Mode Register   * Ethernet configuration   */  m8xx.scc1.gsmr_h = 0x0;  m8xx.scc1.gsmr_l = 0x1088000c;    /*   * Set up data synchronization register   * Ethernet synchronization pattern   */  m8xx.scc1.dsr = 0xd555;    /*   * Set up protocol-specific mode register   *      No 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   */  m8xx.scc1.psmr = 0x080A | (sc->acceptBroadcast ? 0 : 0x100);    /*   * Enable the TENA (RTS1*) pin   */  m8xx.pcpar |=  0x1;  m8xx.pcdir &= ~0x1;    /*   * Enable receiver and transmitter   */  m8xx.scc1.gsmr_l = 0x1088003c;}#ifdef MPC860T/* * Please organize FEC controller code better by moving code from * m860_fec_initialize_hardware to m8xx_fec_ethernet_on */static void m8xx_fec_ethernet_on(){};static void m8xx_fec_ethernet_off(){};static int m8xx_fec_ethernet_isOn (const rtems_irq_connect_data* ptr){  return BSP_irq_enabled_at_siu (ptr->name);}static rtems_irq_connect_data ethernetFECIrqData = {  BSP_FAST_ETHERNET_CTRL,  (rtems_irq_hdl) m8xx_fec_interrupt_handler,  (rtems_irq_enable) m8xx_fec_ethernet_on,  (rtems_irq_disable) m8xx_fec_ethernet_off,  (rtems_irq_is_enabled)m8xx_fec_ethernet_isOn};static voidm860_fec_initialize_hardware (struct m860_enet_struct *sc){  int i;  unsigned char *hwaddr;  rtems_status_code status;  rtems_isr_entry old_handler;  /*   * Issue reset to FEC   */  m8xx.fec.ecntrl=0x1;  /*    * Put ethernet transciever in reset   */  m8xx.pgcra |= 0x80;  /*   * Configure I/O ports   */  m8xx.pdpar = 0x1fff;  m8xx.pddir = 0x1c58;  /*   * Take ethernet transciever out of reset   */  m8xx.pgcra &= ~0x80;  /*   * Set SIU interrupt level to LVL2   *     */  m8xx.fec.ivec = ((((unsigned) BSP_FAST_ETHERNET_CTRL)/2) << 29);    /*   * Set the TX and RX fifo sizes. For now, we'll split it evenly   */  /* If you uncomment these, the FEC will not work right.  m8xx.fec.r_fstart = ((m8xx.fec.r_bound & 0x3ff) >> 2) & 0x3ff;  m8xx.fec.x_fstart = 0;  */  /*   * Set our physical address   */  hwaddr = sc->arpcom.ac_enaddr;    m8xx.fec.addr_low = (hwaddr[0] << 24) | (hwaddr[1] << 16) |                      (hwaddr[2] << 8)  | (hwaddr[3] << 0);  m8xx.fec.addr_high = (hwaddr[4] << 24) | (hwaddr[5] << 16);  /*   * Clear the hash table   */  m8xx.fec.hash_table_high = 0;  m8xx.fec.hash_table_low  = 0;  /*   * Set up receive buffer size   */  m8xx.fec.r_buf_size = 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 = m8xx_bd_allocate(sc->rxBdCount);  sc->txBdBase = m8xx_bd_allocate(sc->txBdCount);  m8xx.fec.r_des_start = (int)sc->rxBdBase;  m8xx.fec.x_des_start = (int)sc->txBdBase;    /*   * Set up Receive Control Register:   *   Not promiscuous mode   *   MII mode   *   Half duplex   *   No loopback   */  m8xx.fec.r_cntrl = 0x00000006;  /*   * Set up Transmit Control Register:   *   Half duplex   *   No heartbeat   */  m8xx.fec.x_cntrl = 0x00000000;  /*   * Set up DMA function code:   *   Big-endian   *   DMA functino code = 0   */  m8xx.fec.fun_code = 0x78000000;  /*   * Initialize SDMA configuration register   *   SDMA ignores FRZ   *   FEC not aggressive   *   FEC arbitration ID = 0 => U-bus arbitration = 6   *   RISC arbitration ID = 1 => U-bus arbitration = 5   */  m8xx.sdcr = 1;  /*   * Set MII speed to 2.5 MHz for 25 Mhz system clock     */  m8xx.fec.mii_speed = 0x0a;  m8xx.fec.mii_data = 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   */  m8xx.fec.imask = M8xx_FEC_IEVENT_TFINT |                    M8xx_FEC_IEVENT_RFINT;  m8xx.fec.ievent = ~0;  /*   * Set up interrupts   */  if (!BSP_install_rtems_irq_handler (&ethernetFECIrqData))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -