if_fec.c

来自「eCos操作系统源码」· C语言 代码 · 共 711 行 · 第 1/2 页

C
711
字号
    E_fcc->iaddr_l  = 0;    E_fcc->minflr   = FEC_MIN_FLR;    E_fcc->taddr_h  = 0;    E_fcc->taddr_m  = 0;    E_fcc->taddr_l  = 0;    E_fcc->pad_ptr  = FEC_PRAM_TIPTR; // No special padding char ...    E_fcc->cf_type  = 0;    E_fcc->maxd1    = FEC_PRAM_MAXD;    E_fcc->maxd2    = FEC_PRAM_MAXD;    // FCC register initialization     IMM->fcc_regs[FCC2].fcc_gfmr = FEC_GFMR_INIT;     IMM->fcc_regs[FCC2].fcc_psmr = FEC_PSMR_INIT;    IMM->fcc_regs[FCC2].fcc_dsr  = FEC_DSR_INIT;#ifdef CYGPKG_NET    // clear the events of FCC2    IMM->fcc_regs[FCC2].fcc_fcce = 0xFFFF0000;       IMM->fcc_regs[FCC2].fcc_fccm = FEC_EV_TXE | FEC_EV_TXB | FEC_EV_RXF;    // Set up to handle interrupts    cyg_drv_interrupt_create(FEC_ETH_INT,                             0,  // Highest //CYGARC_SIU_PRIORITY_HIGH,                             (cyg_addrword_t)sc, //  Data passed to ISR                             (cyg_ISR_t *)fec_eth_isr,                             (cyg_DSR_t *)eth_drv_dsr,                             &fec_eth_interrupt_handle,                             &fec_eth_interrupt);    cyg_drv_interrupt_attach(fec_eth_interrupt_handle);    cyg_drv_interrupt_acknowledge(FEC_ETH_INT);    cyg_drv_interrupt_unmask(FEC_ETH_INT);#else    // Mask the interrupts     IMM->fcc_regs[FCC2].fcc_fccm = 0;#endif    // Issue Init RX & TX Parameters Command for FCC2    while ((IMM->cpm_cpcr & CPCR_FLG) != CPCR_READY_TO_RX_CMD);         IMM->cpm_cpcr = CPCR_INIT_TX_RX_PARAMS |      CPCR_FCC2_CH |      CPCR_MCN_FEC |       CPCR_FLG;              /* ISSUE COMMAND */        while ((IMM->cpm_cpcr & CPCR_FLG) != CPCR_READY_TO_RX_CMD);     // Initialize upper level driver for ecos    (sc->funs->eth_drv->init)(sc, (unsigned char *)&enaddr);    return true;} //// This function is called to "start up" the interface.  It may be called// multiple times, even when the hardware is already running.  It will be// called whenever something "hardware oriented" changes and should leave// the hardware ready to send/receive packets.//static voidfec_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;      // Enable the device :   // Set the ENT/ENR bits in the GFMR -- Enable Transmit/Receive  qi->fcc_reg->fcc_gfmr |= (FEC_GFMR_EN_Rx | FEC_GFMR_EN_Tx);  }//// This function is called to shut down the interface.//static voidfec_eth_stop(struct eth_drv_sc *sc){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;    // Disable the device :   // Clear the ENT/ENR bits in the GFMR -- Disable Transmit/Receive  qi->fcc_reg->fcc_gfmr &= ~(FEC_GFMR_EN_Rx | FEC_GFMR_EN_Tx);}//// This function is called for low level "control" operations//static intfec_eth_control(struct eth_drv_sc *sc, unsigned long key,                void *data, int length){  switch (key) {  case ETH_DRV_SET_MAC_ADDRESS:    return 0;    break;  default:    return 1;    break;  }}//// This function is called to see if another packet can be sent.// It should return the number of packets which can be handled.// Zero should be returned if the interface is busy and can not send any more.//static intfec_eth_can_send(struct eth_drv_sc *sc){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;  volatile struct fec_bd *txbd = qi->txbd;  int cache_state;  HAL_DCACHE_IS_ENABLED(cache_state);#ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_INVALIDATE(fec_eth_txring,                           8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM);  }#endif  return ((txbd->ctrl & (FCC_BD_Tx_TC | FCC_BD_Tx_Ready)) == 0);}//// This routine is called to send data to the hardware.static void fec_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,              int total_len, unsigned long key){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;  struct fec_bd *txbd, *txfirst;  volatile char *bp;  int i, txindex, cache_state;  HAL_DCACHE_IS_ENABLED(cache_state);#ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_INVALIDATE(fec_eth_txring,                           8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM);  }#endif   // Find a free buffer  txbd = txfirst = qi->txbd;  while (txbd->ctrl & FEC_BD_Tx_Ready) {    // This buffer is busy, move to next one    if (txbd->ctrl & FEC_BD_Tx_Wrap) {      txbd = qi->tbase;    } else {      txbd++;    }    if (txbd == txfirst) {#ifdef CYGPKG_NET      panic ("No free xmit buffers");#else      os_printf("FEC Ethernet: No free xmit buffers\n");#endif    }  }  // Remember the next buffer to try  if (txbd->ctrl & FEC_BD_Tx_Wrap) {    qi->txbd = qi->tbase;  } else {    qi->txbd = txbd+1;  }  txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);  qi->txkey[txindex] = key;  // Set up buffer  txbd->length = total_len;  bp = txbd->buffer;  for (i = 0;  i < sg_len;  i++) {    memcpy((void *)bp, (void *)sg_list[i].buf, sg_list[i].len);    bp += sg_list[i].len;  }  // Make sure no stale data buffer ...  if (cache_state) {    HAL_DCACHE_FLUSH(txbd->buffer, txbd->length);  }  // Send it on it's way  txbd->ctrl |= FEC_BD_Tx_Ready | FEC_BD_Tx_Last | FEC_BD_Tx_TC;#ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_FLUSH(fec_eth_txring,                      8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM);    }#endif  }//// This function is called when a packet has been received.  It's job is// to prepare to unload the packet from the hardware.  Once the length of// the packet is known, the upper layer of the driver can be told.  When// the upper layer is ready to unload the packet, the internal function// 'fec_eth_recv' will be called to actually fetch it from the hardware.//static voidfec_eth_RxEvent(struct eth_drv_sc *sc){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;  struct fec_bd *rxbd;  int cache_state;  HAL_DCACHE_IS_ENABLED(cache_state);#ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_INVALIDATE(fec_eth_rxring,                           8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_RxNUM);  }#endif  rxbd = qi->rnext;  while ((rxbd->ctrl & FEC_BD_Rx_Empty) == 0) {    qi->rxbd = rxbd;  // Save for callback    // This is the right way of doing it, but dcbi has a bug ...    //    if (cache_state) {    //      HAL_DCACHE_INVALIDATE(rxbd->buffer, rxbd->length);     //    }    (sc->funs->eth_drv->recv)(sc, rxbd->length);    if (cache_state) {      HAL_DCACHE_FLUSH(rxbd->buffer, rxbd->length);     }    rxbd->ctrl |= FEC_BD_Rx_Empty;    if (rxbd->ctrl & FEC_BD_Rx_Wrap) {      rxbd = qi->rbase;    } else {      rxbd++;    }  }  // Remember where we left off  qi->rnext = (struct fec_bd *)rxbd;  // Make sure no stale data#ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_FLUSH(fec_eth_rxring,                      8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_RxNUM);  }#endif}//// This function is called as a result of the "eth_drv_recv()" call above.// It's job is to actually fetch data for a packet from the hardware once// memory buffers have been allocated for the packet.  Note that the buffers// may come in pieces, using a scatter-gather list.  This allows for more// efficient processing in the upper layers of the stack.//static voidfec_eth_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;  unsigned char *bp;  int i;    bp = (unsigned char *)qi->rxbd->buffer;  for (i = 0;  i < sg_len;  i++) {    if (sg_list[i].buf != 0) {      memcpy((void *)sg_list[i].buf, bp, sg_list[i].len);      bp += sg_list[i].len;    }  }}static voidfec_eth_TxEvent(struct eth_drv_sc *sc, int stat){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;  struct fec_bd *txbd;  int txindex, cache_state;  // Make sure no stale data  HAL_DCACHE_IS_ENABLED(cache_state);#ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_INVALIDATE(fec_eth_txring,                           8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM);  }#endif  txbd = qi->tnext;  // Note: TC field is used to indicate the buffer has/had data in it  while ( (txbd->ctrl & (FEC_BD_Tx_TC | FEC_BD_Tx_Ready)) == FEC_BD_Tx_TC ) {    txindex = ((unsigned long)txbd - (unsigned long)qi->tbase) / sizeof(*txbd);    (sc->funs->eth_drv->tx_done)(sc, qi->txkey[txindex], 0);    txbd->ctrl &= ~FEC_BD_Tx_TC;    if (txbd->ctrl & FEC_BD_Tx_Wrap) {      txbd = qi->tbase;    } else {      txbd++;    }  }  // Remember where we left off  qi->tnext = (struct fec_bd *)txbd;  // Make sure no stale data  #ifndef FEC_BDs_NONCACHED  if (cache_state) {    HAL_DCACHE_FLUSH(fec_eth_txring,                      8*CYGNUM_DEVS_ETH_POWERPC_QUICC2_TxNUM);  }#endif}//// Interrupt processing//static void          fec_eth_int(struct eth_drv_sc *sc){  struct fec_eth_info *qi = (struct fec_eth_info *)sc->driver_private;  unsigned long iEvent;  while ((iEvent = qi->fcc_reg->fcc_fcce) != 0){    // Writing 1's clear fcce, Writing 0's have no effect    qi->fcc_reg->fcc_fcce = iEvent;     // Tx Done or Tx Error    if ( iEvent & (FEC_EV_TXB | FEC_EV_TXE) ) {           fec_eth_TxEvent(sc, iEvent);    }      // Complete or non-complete frame receive    if (iEvent & (FEC_EV_RXF | FEC_EV_RXB) ) {          fec_eth_RxEvent(sc);    }  }    }//// Interrupt vector//static int          fec_eth_int_vector(struct eth_drv_sc *sc){    return (FEC_ETH_INT);}

⌨️ 快捷键说明

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