Ignore:
Timestamp:
Jul 9, 2006, 10:05:27 AM (14 years ago)
Author:
Thomas Doerfler <Thomas.Doerfler@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
9807f04
Parents:
a650ebb1
Message:

applied patches for PR1117/1118/1119/1120

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c

    ra650ebb1 rc9b005a9  
    7979#define SDMA_BD_TFD     0x08000000      /*< Transmit Frame Done         */
    8080#define SDMA_BD_INT     0x04000000      /*< Interrupt on frame done     */
    81 #define SDMA_BD_RX_NUM  32 /* Number of receive buffer descriptors      */
    82 #define SDMA_BD_TX_NUM  48 /* Number of transmit buffer descriptors     */
     81#define SDMA_BD_RX_NUM  64 /* Number of receive buffer descriptors      */
     82#define SDMA_BD_TX_NUM  64 /* Number of transmit buffer descriptors     */
    8383
    8484#define SET_BD_STATUS(bd, stat) {               \
     
    128128 */
    129129#define INTERRUPT_EVENT RTEMS_EVENT_1
     130#define FATAL_INT_EVENT RTEMS_EVENT_3
    130131
    131132/*
     
    198199
    199200
     201#define FEC_INTR_MASK_USED \
     202(FEC_INTR_LCEN  |FEC_INTR_CRLEN |\
     203 FEC_INTR_XFUNEN|FEC_INTR_XFERREN|FEC_INTR_RFERREN)
     204
    200205/*
    201206 * Device data
     
    236241  };
    237242
    238 uint8_t tx_shadow_buffer[TX_BUF_COUNT][(ETHER_MAX_LEN+3)&~3];
    239 
    240243static struct mpc5200_enet_struct enet_driver[NIFACES];
    241244
    242245extern int taskTable;
     246static void mpc5200_fec_restart(struct mpc5200_enet_struct *sc);
    243247
    244248
     
    276280    if (bdi != rxBdIndex) {
    277281      rtems_panic("network rx buffer indices out of sync");
     282    }
     283  }
     284}
     285
     286/*
     287 * Function:    mpc5200_fec_rx_bd_cleanup
     288 *
     289 * Description: put all mbufs pending in rx BDs back to buffer pool
     290 *
     291 * Returns:             void
     292 *
     293 */
     294static void mpc5200_fec_rx_bd_cleanup(struct mpc5200_enet_struct *sc) {
     295  int rxBdIndex;
     296  struct mbuf *m,*n;
     297
     298  /*
     299   * Drain RX buffer descriptor ring.
     300   */
     301  for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) {
     302    n = sc->rxMbuf[rxBdIndex];
     303    while (n != NULL) {
     304      m = n;
     305      MFREE(m,n);
    278306    }
    279307  }
     
    493521 */
    494522static int mpc5200_fec_reset(struct mpc5200_enet_struct *sc) {
     523  volatile int delay;
    495524  /*
    496525   * Clear FIFO status registers
     
    500529 
    501530  /*
    502    *
    503    */
     531   * reset the FIFOs
     532   */
     533  mpc5200.reset_cntrl = 0x03000000;
     534
     535  for (delay = 0;delay < 16*4;delay++) {};
     536
    504537  mpc5200.reset_cntrl = 0x01000000;
    505538 
     
    512545   * wait at least 16 clock cycles
    513546   */
    514   rtems_task_wake_after(2);
     547  for (delay = 0;delay < 16*4;delay++) {};
    515548 
    516549  return TRUE;
     
    555588
    556589 /*
    557   * mask FEC chip interrupts
    558   */
    559   mpc5200.imask = FEC_INTR_MASK_ALL;
     590  * block FEC chip interrupts
     591  */
     592  mpc5200.imask = 0;
    560593
    561594 /*
     
    566599 /*
    567600  * wait for graceful stop to register
     601  * FIXME: add rtems_task_wake_after here, if it takes to long
    568602  */
    569603  while((counter--) && (!(mpc5200.ievent & FEC_INTR_GRA)));
     
    585619  mpc5200.ecntrl &= ~(FEC_ECNTRL_OE | FEC_ECNTRL_EN);
    586620
    587   }
    588 
     621  /*
     622   * cleanup all buffers
     623   */
     624  mpc5200_fec_rx_bd_cleanup(sc);
     625
     626  }
     627
     628/*
     629 * MPC5200 FEC interrupt handler
     630 */
     631void mpc5200_fec_irq_handler(rtems_irq_hdl_param handle)
     632{
     633  struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *) handle;
     634  volatile uint32_t ievent;
     635
     636  ievent = mpc5200.ievent;
     637
     638  mpc5200.ievent = ievent;
     639  /*
     640   * check errors, update statistics
     641   */
     642  if (ievent & FEC_INTR_LATE_COL) {
     643    sc->txLateCollision++;
     644  }
     645  if (ievent & FEC_INTR_COL_RETRY) {
     646    sc->txRetryLimit++;
     647  }
     648  if (ievent & FEC_INTR_XFIFO_UN) {
     649    sc->txUnderrun++;
     650  }
     651  if (ievent & FEC_INTR_XFIFO_ERR) {
     652    sc->txUnderrun++;
     653  }
     654  if (ievent & FEC_INTR_RFIFO_ERR) {
     655    sc->rxOverrun++;
     656  }
     657  /*
     658   * fatal error ocurred?
     659   */
     660  if (ievent & (FEC_INTR_XFIFO_ERR | FEC_INTR_RFIFO_ERR)) {
     661    mpc5200.imask &= ~(FEC_INTR_XFERREN | FEC_INTR_RFERREN);
     662    rtems_event_send(enet_driver[0].rxDaemonTid, FATAL_INT_EVENT);
     663  }
     664}
    589665
    590666/*
     
    593669void mpc5200_smartcomm_rx_irq_handler(rtems_irq_hdl_param unused)
    594670  {
    595   volatile uint32_t ievent;
    596 
    597   ievent = mpc5200.ievent;
    598 
    599 
    600671 /* Frame received? */
    601672  if(GET_SDMA_PENDINGBIT(FEC_RECV_TASK_NO))
     
    618689void mpc5200_smartcomm_tx_irq_handler(rtems_irq_hdl_param unused)
    619690  {
    620   volatile uint32_t ievent;
    621 
    622   ievent = mpc5200.ievent;
    623 
    624 
    625691 /* Buffer transmitted or transmitter error? */
    626692  if(GET_SDMA_PENDINGBIT(FEC_XMIT_TASK_NO))
     
    653719  *
    654720  */
    655 static void mpc5200_fec_retire_tbd(struct mpc5200_enet_struct *sc)
     721static void mpc5200_fec_retire_tbd(struct mpc5200_enet_struct *sc,
     722                                   boolean force)
    656723{
    657724  struct mbuf *n;
     
    663730 
    664731  while ((sc->txBdActiveCount > 0) &&
    665          (bdRing[sc->txBdTail].Status == 0x0)) {
     732         (force || (bdRing[sc->txBdTail].Status == 0x0))) {
    666733    if (sc->txMbuf[sc->txBdTail] != NULL) {
    667734      /*
     
    678745}
    679746
     747 /*
     748  * Function:        mpc5200_fec_tx_bd_requeue
     749  *
     750  * Description:        put buffers back to interface output queue
     751  *
     752  * Returns:            void
     753  *
     754  * Notes:
     755  *
     756  */
     757static void mpc5200_fec_tx_bd_requeue(struct mpc5200_enet_struct *sc)
     758{
     759  /*
     760   * Clear already transmitted BDs first. Will not work calling same
     761   * from fecExceptionHandler(TFINT).
     762   */
     763 
     764  while (sc->txBdActiveCount > 0) {
     765    if (sc->txMbuf[sc->txBdHead] != NULL) {
     766      /*
     767       * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs
     768       */
     769      IF_PREPEND(&(sc->arpcom.ac_if.if_snd),sc->txMbuf[sc->txBdHead]);
     770      sc->txMbuf[sc->txBdHead] = NULL;
     771    }
     772    sc->txBdActiveCount--;
     773    if(--sc->txBdHead < 0) {
     774      sc->txBdHead = sc->txBdCount-1;
     775    }   
     776  }
     777}
    680778
    681779static void mpc5200_fec_sendpacket(struct ifnet *ifp,struct mbuf *m) {
     
    694792  * Free up buffer descriptors
    695793  */
    696   mpc5200_fec_retire_tbd(sc);
     794  mpc5200_fec_retire_tbd(sc,FALSE);
    697795
    698796 /*
     
    729827       * an interrupt.
    730828       */
    731       mpc5200_fec_retire_tbd(sc);
     829      mpc5200_fec_retire_tbd(sc,FALSE);
    732830     
    733831      while((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
     
    736834                                   RTEMS_WAIT | RTEMS_EVENT_ANY,
    737835                                   RTEMS_NO_TIMEOUT, &events);
    738         mpc5200_fec_retire_tbd(sc);
     836        mpc5200_fec_retire_tbd(sc,FALSE);
    739837      }
    740838    }
     
    769867                            ? TASK_BD_TFD | TASK_BD_INT
    770868                            : 0);
    771     /*
    772      * Don't set the READY flag till the
    773      * whole packet has been readied.
    774      */
     869      /*
     870       * Don't set the READY flag till the
     871       * whole packet has been readied.
     872       */
    775873      if (firstBd != NULL) {
    776874        status |= (uint32)SDMA_BD_MASK_READY;
     
    822920  rtems_event_set events;
    823921
    824   for(;;)
    825     {
     922  for(;;) {
    826923   /*
    827924    * Wait for packet
    828925    */
     926    bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO);
    829927    rtems_bsdnet_event_receive(START_TRANSMIT_EVENT|INTERRUPT_EVENT,
    830928                               RTEMS_EVENT_ANY | RTEMS_WAIT,
     
    9451043    bestcomm_glue_irq_enable(FEC_RECV_TASK_NO);
    9461044     
    947     rtems_bsdnet_event_receive (INTERRUPT_EVENT,
     1045    rtems_bsdnet_event_receive (INTERRUPT_EVENT | FATAL_INT_EVENT,
    9481046                                RTEMS_WAIT | RTEMS_EVENT_ANY,
    9491047                                RTEMS_NO_TIMEOUT, &events);
    950 
     1048    if (events & FATAL_INT_EVENT) {
     1049      /*
     1050       * fatal interrupt ocurred, so reinit fec and restart bestcomm tasks
     1051       */
     1052      mpc5200_fec_restart(sc);
     1053      rxBdIndex = 0;
     1054    }
    9511055  }
    9521056}
     
    9661070static void mpc5200_fec_initialize_hardware(struct mpc5200_enet_struct *sc)
    9671071  {
    968   int            timeout;
    969   unsigned short phyAddr = 0;
    9701072
    9711073 /*
     
    9821084  * Set interrupt mask register
    9831085  */
    984   mpc5200.imask = (FEC_INTR_HBEEN
    985                  | FEC_INTR_BREN
    986                  | FEC_INTR_BTEN
    987                  | FEC_INTR_GRAEN
    988                  | FEC_INTR_LATE_COL
    989                  | FEC_INTR_COL_RETRY
    990                  | FEC_INTR_XFIFO_UN
    991                  | FEC_INTR_XFIFO_ERR
    992                  | FEC_INTR_RFIFO_ERR
    993                  | FEC_INTR_TFINT
    994                  );
     1086  mpc5200.imask = FEC_INTR_MASK_USED;
    9951087  /*
    9961088   * Set FEC-Lite receive control register (R_CNTRL)
     
    10551147  */
    10561148  mpc5200.xmit_fsm = FEC_FSM_CRC | FEC_FSM_ENFSM;
     1149  }
    10571150
    10581151 /*
     
    10761169  *   The physical address is dependent on hardware configuration.
    10771170  *
    1078   */
     1171  * Returns:            void
     1172  *
     1173  * Notes:
     1174  *
     1175  */
     1176static void mpc5200_fec_initialize_phy(struct mpc5200_enet_struct *sc)
     1177  {
     1178  int            timeout;
     1179  unsigned short phyAddr = 0;
     1180
    10791181
    10801182 /*
     
    11811283 * set up sdma tasks for ethernet
    11821284 */
    1183 static void mpc5200_sdma_task_setup(void) {
     1285static void mpc5200_sdma_task_setup(struct mpc5200_enet_struct *sc) {
    11841286  TaskSetupParamSet_t   rxParam;        /* RX task setup parameters     */
    11851287  TaskSetupParamSet_t   txParam;        /* TX task setup parameters     */
     
    11881290   * Setup the SDMA RX task.
    11891291   */
    1190   rxParam.NumBD        = SDMA_BD_RX_NUM;
     1292  rxParam.NumBD        = sc->rxBdCount;
    11911293  rxParam.Size.MaxBuf  = ETHER_MAX_LEN;
    11921294  rxParam.Initiator    = 0;
     
    12021304   * Setup the TX task.
    12031305   */
    1204   txParam.NumBD        = SDMA_BD_TX_NUM;
     1306  txParam.NumBD        = sc->txBdCount;
    12051307  txParam.Size.MaxBuf  = ETHER_MAX_LEN;
    12061308  txParam.Initiator    = 0;
     
    12161318}
    12171319
     1320void mpc5200_fec_irq_on(const rtems_irq_connect_data* ptr)
     1321{
     1322  mpc5200.imask = FEC_INTR_MASK_USED;
     1323}
     1324
     1325
     1326int mpc5200_fec_irq_isOn(const rtems_irq_connect_data* ptr)
     1327{
     1328  return mpc5200.imask != 0;
     1329}
     1330
     1331
     1332void mpc5200_fec_irq_off(const rtems_irq_connect_data* ptr)
     1333{
     1334  mpc5200.imask = 0;
     1335}
     1336
    12181337
    12191338/*
     
    12241343  struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg;
    12251344  struct ifnet *ifp = &sc->arpcom.ac_if;
     1345  rtems_irq_connect_data fec_irq_data = {
     1346    BSP_SIU_IRQ_ETH,
     1347    mpc5200_fec_irq_handler, /* rtems_irq_hdl           */
     1348    (rtems_irq_hdl_param)sc, /* (rtems_irq_hdl_param)   */
     1349    mpc5200_fec_irq_on,      /* (rtems_irq_enable)      */
     1350    mpc5200_fec_irq_off,     /* (rtems_irq_disable)     */
     1351    mpc5200_fec_irq_isOn     /* (rtems_irq_is_enabled)  */
     1352  };
     1353
    12261354
    12271355  if(sc->txDaemonTid == 0)
     
    12401368      bestcomm_glue_init();
    12411369
    1242       mpc5200_sdma_task_setup();
     1370      mpc5200_sdma_task_setup(sc);
    12431371   
    12441372      /*
     
    12511379                                mpc5200_smartcomm_tx_irq_handler,
    12521380                                NULL);
     1381      if(!BSP_install_rtems_irq_handler (&fec_irq_data)) {
     1382        rtems_panic ("Can't attach MPC5x00 FEX interrupt handler\n");
     1383      }
     1384
    12531385      /* mpc5200_fec_tx_bd_init(sc); */
    12541386      mpc5200_fec_rx_bd_init(sc);
     
    12581390       */
    12591391      mpc5200_fec_initialize_hardware(sc);
     1392      /*
     1393       * Set up the phy
     1394       */
     1395      mpc5200_fec_initialize_phy(sc);
    12601396      /*
    12611397       * Set priority of different initiators
     
    13231459}
    13241460
     1461/*
     1462 * restart the driver, reinit the fec
     1463 * this function is responsible to reinitialize the FEC in case a fatal
     1464 * error has ocurred. This is needed, wen a RxFIFO Overrun or a TxFIFO underrun
     1465 * has ocurred. In these cases, the FEC is automatically disabled, and
     1466 * both FIFOs must be reset and the BestComm tasks must be restarted
     1467 *
     1468 * Note: the daemon tasks will continue to run
     1469 * (in fact this function will be called in the context of the rx daemon task)
     1470 */
     1471#define NEW_SDMA_SETUP
     1472
     1473static void mpc5200_fec_restart(struct mpc5200_enet_struct *sc)
     1474{
     1475  /*
     1476   * FIXME: bring Tx Daemon into idle state
     1477   */
     1478#ifdef NEW_SDMA_SETUP
     1479  /*
     1480   * cleanup remaining receive mbufs
     1481   */
     1482  mpc5200_fec_rx_bd_cleanup(sc);
     1483#endif
     1484  /*
     1485   * Stop SDMA tasks
     1486   */
     1487  TaskStop( rxTaskId);
     1488  TaskStop( txTaskId);
     1489  /*
     1490   * FIXME: wait, until Tx Daemon is in idle state
     1491   */
     1492
     1493  /*
     1494   * Disable transmit / receive interrupts
     1495   */
     1496  bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO);
     1497  bestcomm_glue_irq_disable(FEC_RECV_TASK_NO);
     1498#ifdef NEW_SDMA_SETUP
     1499  /*
     1500   * recycle pending tx buffers
     1501   * FIXME: try to extract pending Tx buffers
     1502   */
     1503#if 0
     1504  mpc5200_fec_tx_bd_requeue(sc);
     1505#else
     1506  mpc5200_fec_retire_tbd(sc,TRUE);
     1507#endif
     1508#endif
     1509  /*
     1510   * re-initialize the FEC hardware
     1511   */
     1512  mpc5200_fec_initialize_hardware(sc);
     1513
     1514#ifdef NEW_SDMA_SETUP
     1515  /*
     1516   * completely reinitialize Bestcomm tasks
     1517   */
     1518  mpc5200_sdma_task_setup(sc);
     1519
     1520  /*
     1521   * reinit receive mbufs
     1522   */
     1523  mpc5200_fec_rx_bd_init(sc);
     1524#endif
     1525  /*
     1526   * Clear SmartDMA task interrupt pending bits.
     1527   */
     1528  TaskIntClear( rxTaskId );
     1529 
     1530  /*
     1531   * Enable the SmartDMA receive/transmit task.
     1532   */
     1533  TaskStart( rxTaskId, 1, rxTaskId, 1 );
     1534  TaskStart( txTaskId, 1, txTaskId, 1 );
     1535  /*
     1536   * reenable rx/tx interrupts
     1537   */
     1538  bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO);
     1539  bestcomm_glue_irq_enable(FEC_RECV_TASK_NO);
     1540  /*
     1541   * (re-)init fec hardware
     1542   */
     1543  mpc5200_fec_initialize_hardware(sc);
     1544  /*
     1545   * reenable fec FIFO error interrupts
     1546   */
     1547  mpc5200.imask = FEC_INTR_MASK_USED;
     1548  /*
     1549   * Enable FEC-Lite controller
     1550   */
     1551  mpc5200.ecntrl |= (FEC_ECNTRL_OE | FEC_ECNTRL_EN);
     1552}
     1553
    13251554
    13261555/*
Note: See TracChangeset for help on using the changeset viewer.