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

📄 network.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * RTEMS/TCPIP driver for MPC8260 SCC * * Modified for MPC8260 by Andy Dachs <a.dachs@sstl.co.uk> * Surrey Satellite Technology Limited * *   On the ADS board the ethernet interface is connected to FCC2 *   but in my application I want TCP over HDLC (see README) *   so will use SCC3 as the network interface. I have other plans *   for the FCCs so am unlikely to add true ethernet support to *   this BSP.  Contributions welcome! * * 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_m860_enet_driver_attach determines which one to use. Currently, *  only one may be used at a time. * * W. Eric Norum * Saskatchewan Accelerator Laboratory * University of Saskatchewan * Saskatoon, Saskatchewan, CANADA * eric@skatter.usask.ca * *  $Id: network.c,v 1.3 2002/11/04 14:28:08 joel Exp $ */#include <bsp.h>#include <bsp/irq.h>#include <mpc8260.h>#include <mpc8260/cpm.h>#include <stdio.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <rtems/bspIo.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 "if_hdlcsubr.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")extern void m8xx_dump_brgs( void );/* * 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 MAX_MTU_SIZE	2050*/#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 m8260_hdlc_struct {        struct ifnet            ac_if;        struct mbuf             **rxMbuf;        struct mbuf             **txMbuf;        int                     acceptBroadcast;        int                     rxBdCount;        int                     txBdCount;        int                     txBdHead;        int                     txBdTail;        int                     txBdActiveCount;        m8260BufferDescriptor_t  *rxBdBase;        m8260BufferDescriptor_t  *txBdBase;        rtems_id                rxDaemonTid;        rtems_id                txDaemonTid;        /*         * Statistics         */        unsigned long   rxNotFirst;        unsigned long   rxNotLast;        unsigned long   rxInterrupts;        unsigned long   rxGiant;        unsigned long   rxNonOctet;	unsigned long	rxAbort;        unsigned long   rxBadCRC;        unsigned long   rxOverrun;        unsigned long   rxLostCarrier;        unsigned long   txInterrupts;        unsigned long   txUnderrun;        unsigned long   txLostCarrier;        unsigned long   txRawWait;};static struct m8260_hdlc_struct hdlc_driver[NIFACES];static void  m8xx_scc3_hdlc_on(const rtems_irq_connect_data* ptr){}static void  m8xx_scc3_hdlc_off(const rtems_irq_connect_data* ptr){  /*   * Please put relevant code there   */}static int  m8xx_scc3_hdlc_isOn(const rtems_irq_connect_data* ptr){  return BSP_irq_enabled_at_cpm (ptr->name);}/* * SCC interrupt handler * TBD: Can we work out which SCC generated the interrupt from the *      value of v? If so we can use the same handler for multiple *      SCCs. */static voidm8xx_scc3_interrupt_handler (){  /*   * Frame received?   */  if ((m8260.scc3.sccm & M8260_SCCE_RXF) &&      (m8260.scc3.scce & M8260_SCCE_RXF) ) {    m8260.scc3.scce = M8260_SCCE_RXF;/*    m8260.scc3.sccm &= ~M8260_SCCE_RXF; */    hdlc_driver[0].rxInterrupts++;    rtems_event_send (hdlc_driver[0].rxDaemonTid, INTERRUPT_EVENT);/*    printk( "Rx " );*/  }  /*   * Buffer transmitted or transmitter error?   */  if ((m8260.scc3.sccm & (M8260_SCCE_TX | M8260_SCCE_TXE) ) &&      (m8260.scc3.scce & (M8260_SCCE_TX | M8260_SCCE_TXE) )) {    m8260.scc3.scce = M8260_SCCE_TX | M8260_SCCE_TXE;/*    m8260.scc3.sccm &= ~(M8260_SCCE_TX | M8260_SCCE_TXE); */    hdlc_driver[0].txInterrupts++;    rtems_event_send (hdlc_driver[0].txDaemonTid, INTERRUPT_EVENT);/*    printk( "Tx " );*/  }#if 0  m8260.sipnr_l = M8260_SIMASK_SCC3; /* Clear SCC3 interrupt-in-service bit */#endif}static rtems_irq_connect_data hdlcSCC3IrqData = {  BSP_CPM_IRQ_SCC3,  (rtems_irq_hdl) m8xx_scc3_interrupt_handler,  (rtems_irq_enable) m8xx_scc3_hdlc_on,  (rtems_irq_disable) m8xx_scc3_hdlc_off,  (rtems_irq_is_enabled)m8xx_scc3_hdlc_isOn};/* * Initialize the SCC hardware * Configure I/O ports for SCC3 * Internal Tx clock, External Rx clock */static voidm8260_scc_initialize_hardware (struct m8260_hdlc_struct *sc){  int i;  int brg;/*  unsigned char *hwaddr;*/  rtems_status_code status;/*  rtems_isr_entry old_handler;*/  /* RxD PB14 */  m8260.pparb |=  0x00020000;  m8260.psorb &= ~0x00020000;  m8260.pdirb &= ~0x00020000;  /* RxC (CLK5) PC27 */  m8260.pparc |=  0x00000010;  m8260.psorc &= ~0x00000010;  m8260.pdirc &= ~0x00000010;  /* TxD PD24 and TxC PD10 (BRG4) */  m8260.ppard |=  0x00200080;  m8260.psord |=  0x00200000;  m8260.psord &= ~0x00000080;  m8260.pdird |=  0x00200080;  /* External Rx Clock from CLK5 */  if( m8xx_get_clk( M8xx_CLK_5 ) == -1 )    printk( "Error allocating CLK5 for network device.\n" );  else    m8260.cmxscr |= 0x00002000;  /* Internal Tx Clock from BRG4 */  if( (brg = m8xx_get_brg(M8xx_BRG_4, 8000000 )) == -1 )    printk( "Error allocating BRG for network device\n" );  else    m8260.cmxscr |= ((unsigned)brg << 8);  /*   * 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);  m8260.scc3p.rbase = (char *)sc->rxBdBase - (char *)&m8260;  m8260.scc3p.tbase = (char *)sc->txBdBase - (char *)&m8260;    /*   * Send "Init parameters" command   */  m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3 );  /*   * Set receive and transmit function codes   */  m8260.scc3p.rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS;  m8260.scc3p.tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS;    /*   * Set maximum receive buffer length   */  m8260.scc3p.mrblr = RBUF_SIZE;  m8260.scc3p.un.hdlc.c_mask = 0xF0B8;  m8260.scc3p.un.hdlc.c_pres = 0xFFFF;  m8260.scc3p.un.hdlc.disfc  = 0;  m8260.scc3p.un.hdlc.crcec  = 0;  m8260.scc3p.un.hdlc.abtsc  = 0;  m8260.scc3p.un.hdlc.nmarc  = 0;  m8260.scc3p.un.hdlc.retrc  = 0;  m8260.scc3p.un.hdlc.rfthr  = 1;  m8260.scc3p.un.hdlc.mflr   = RBUF_SIZE;  m8260.scc3p.un.hdlc.hmask  = 0x0000;	/* promiscuous */  m8260.scc3p.un.hdlc.haddr1 = 0xFFFF;	/* Broadcast address */  m8260.scc3p.un.hdlc.haddr2 = 0xFFFF;	/* Station address */  m8260.scc3p.un.hdlc.haddr3 = 0xFFFF;	/* Dummy */  m8260.scc3p.un.hdlc.haddr4 = 0xFFFF;	/* Dummy */  /*   * Send "Init parameters" command   *//*  m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3 );*/  /*   * 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;  m8260.scc3.sccm = 0;     /* No interrupts unmasked till necessary */  /*   * Clear any outstanding events   */  m8260.scc3.scce = 0xFFFF;  /*   * Set up interrupts   */  status = BSP_install_rtems_irq_handler (&hdlcSCC3IrqData);/*  printk( "status = %d, Success = %d\n", status, RTEMS_SUCCESSFUL );*/  if (status != 1 /*RTEMS_SUCCESSFUL*/ ) {    rtems_panic ("Can't attach M8260 SCC3 interrupt handler: %s\n",		 rtems_status_text (status));  }  m8260.scc3.sccm = 0;     /* No interrupts unmasked till necessary */#if 0  /*   * Set up interrupts   */  status = rtems_interrupt_catch (m8260_scc3_interrupt_handler,				  PPC_IRQ_CPM_SCC3,				  &old_handler);  if (status != RTEMS_SUCCESSFUL) {    rtems_panic ("Can't attach M8260 SCC3 interrupt handler: %s\n",		 rtems_status_text (status));  }  m8260.sipnr_l = M8260_SIMASK_SCC3; /* clear pending event */  m8260.simr_l |= M8260_SIMASK_SCC3; /* Enable SCC interrupt */#endif  m8260.scc3.gsmr_h  = 0;  m8260.scc3.gsmr_l  = 0x10000000;  m8260.scc3.dsr     = 0x7E7E;	/* flag character */  m8260.scc3.psmr    = 0x2000;	/* 2 flags between Tx'd frames *//*  printk("scc3 init\n" ); */  m8260.scc3.gsmr_l |=  0x00000030;  /* Set ENR and ENT to enable Rx and Tx */}/* * 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 voidm8260Enet_retire_tx_bd (struct m8260_hdlc_struct *sc){  rtems_unsigned16 status;  int i;  int nRetired;  struct mbuf *m, *n;    i = sc->txBdTail;  nRetired = 0;  while ((sc->txBdActiveCount != 0)         &&  (((status = (sc->txBdBase + i)->status) & M8260_BD_READY) == 0)) {    /*     * See if anything went wrong     */    if (status & (M8260_BD_UNDERRUN |                  M8260_BD_CTS_LOST)) {      /*       * Check for errors which stop the transmitter.       */      if( status & M8260_BD_UNDERRUN ) {          hdlc_driver[0].txUnderrun++;                /*         * Restart the transmitter         */        /* FIXME: this should get executed only if using the SCC */        m8xx_cp_execute_cmd (M8260_CR_OP_RESTART_TX | M8260_CR_SCC3);      }      if (status & M8260_BD_CTS_LOST)        hdlc_driver[0].txLostCarrier++;    }    nRetired++;    if (status & M8260_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;  }}/* * reader task */static voidscc_rxDaemon (void *arg){  struct m8260_hdlc_struct *sc = (struct m8260_hdlc_struct *)arg;  struct ifnet *ifp = &sc->ac_if;  struct mbuf *m;  rtems_unsigned16 status;  m8260BufferDescriptor_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 = M8260_BD_EMPTY | M8260_BD_INTERRUPT;    if (++rxBdIndex == sc->rxBdCount) {      rxBd->status |= M8260_BD_WRAP;      break;    }  }/*  m8260.scc3.sccm |= M8260_SCCE_RXF;*/  /*   * Input packet handling loop   */  rxBdIndex = 0;  for (;;) {    rxBd = sc->rxBdBase + rxBdIndex;        /*     * Wait for packet if there's not one ready     */    if ((status = rxBd->status) & M8260_BD_EMPTY) {      /*       * Clear old events       */      m8260.scc3.scce = M8260_SCCE_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) & M8260_BD_EMPTY) {        rtems_event_set events;        /*         * Unmask RXF (Full frame received) event         */        m8260.scc3.sccm |= M8260_SCCE_RXF;/*        printk( "Rxdwait "); */        

⌨️ 快捷键说明

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