// ///////////////////////////////////////////////////// //! Initialize internal PHYs. They must only be controlled //! by MDIO interface // //////////////////////////////////////////////////// static bool InitInternalPHY(void) { unsigned long ulCfgValue = 0; volatile unsigned long* pulPhyCtrl = (volatile unsigned long*)Adr_phy_control; unsigned int uiPhyDat = 0; unsigned int uiPhyDat2 = 0; if(NULL == pulPhyCtrl) return false; ulCfgValue = ((0xE << SRT_phy_control_phy_address) & MSK_phy_control_phy_address) | //set phy's to MDIO Addres 1C, 1D ((0x7 << SRT_phy_control_phy1_mode) & MSK_phy_control_phy1_mode) | //Auto negotitation, AutoMDIX ((0x1 << SRT_phy_control_phy1_automdix) & MSK_phy_control_phy1_automdix) | //AutoMDIX ((0x1 << SRT_phy_control_phy1_enable) & MSK_phy_control_phy1_enable) | //enable phy 1 ((0x7 << SRT_phy_control_phy2_mode) & MSK_phy_control_phy2_mode) | //Auto negotitation, AutoMDIX ((0x1 << SRT_phy_control_phy2_automdix) & MSK_phy_control_phy2_automdix) | //AutoMDIX ((0x1 << SRT_phy_control_phy2_enable) & MSK_phy_control_phy2_enable) | //enable phy 2 ((0x1 << SRT_phy_control_phy_clk_xlatin) & MSK_phy_control_phy_clk_xlatin); //use external 25MHz clock EnableAsicControl(); //reset PHY's *pulPhyCtrl = ulCfgValue | MSK_phy_control_phy_reset; //wait 100us HAL_DELAY_US(100); EnableAsicControl(); //enable PHY's *pulPhyCtrl = ulCfgValue; //200ms delay HAL_DELAY_US(200); //dummy read, to prevent Gunnar bug PhyMDIO(PHY_PORT0_ADDRESS, MDIO_READ, DRV_CB12_CONTROL, &uiPhyDat); //reset PHY uiPhyDat = DRV_CB12_CONTROL_RESET; PhyMDIO(PHY_PORT0_ADDRESS, MDIO_WRITE, DRV_CB12_CONTROL, &uiPhyDat); PhyMDIO(PHY_PORT1_ADDRESS, MDIO_WRITE, DRV_CB12_CONTROL, &uiPhyDat); do { PhyMDIO(PHY_PORT0_ADDRESS, MDIO_READ, DRV_CB12_CONTROL, &uiPhyDat); PhyMDIO(PHY_PORT1_ADDRESS, MDIO_READ, DRV_CB12_CONTROL, &uiPhyDat2); } while( (uiPhyDat & DRV_CB12_CONTROL_RESET) && (uiPhyDat2 & DRV_CB12_CONTROL_RESET) ); //Power down PHY's. Driver is responsible to wake them up PhyMDIO(PHY_PORT0_ADDRESS, MDIO_READ, DRV_CB12_CONTROL, &uiPhyDat); uiPhyDat |= DRV_CB12_CONTROL_POWER_DOWN; PhyMDIO(PHY_PORT0_ADDRESS, MDIO_WRITE, DRV_CB12_CONTROL, &uiPhyDat); PhyMDIO(PHY_PORT1_ADDRESS, MDIO_READ, DRV_CB12_CONTROL, &uiPhyDat); uiPhyDat |= DRV_CB12_CONTROL_POWER_DOWN; PhyMDIO(PHY_PORT1_ADDRESS, MDIO_WRITE, DRV_CB12_CONTROL, &uiPhyDat); return true; }
void hal_plf_pci_init(void) { #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM) HAL_PCI_RESET_ASSERT(); HAL_PCI_CLOCK_DISABLE(); // Set GPIO line direction HAL_GPIO_OUTPUT_ENABLE(PCI_CLK_GPIO); HAL_GPIO_OUTPUT_ENABLE(PCI_RESET_GPIO); HAL_GPIO_OUTPUT_DISABLE(PCI_INTA_GPIO); HAL_GPIO_OUTPUT_DISABLE(PCI_INTB_GPIO); HAL_GPIO_OUTPUT_DISABLE(PCI_INTC_GPIO); HAL_GPIO_OUTPUT_DISABLE(PCI_INTD_GPIO); // configure PCI interrupt lines for active low irq HAL_INTERRUPT_CONFIGURE(INTA, 1, 0); HAL_INTERRUPT_CONFIGURE(INTB, 1, 0); HAL_INTERRUPT_CONFIGURE(INTC, 1, 0); HAL_INTERRUPT_CONFIGURE(INTD, 1, 0); // wait 1ms to satisfy "minimum reset assertion time" of the PCI spec. HAL_DELAY_US(1000); HAL_PCI_CLOCK_CONFIG(); HAL_PCI_CLOCK_ENABLE(); // wait 100us to satisfy "minimum reset assertion time from clock stable" // requirement of the PCI spec. HAL_DELAY_US(100); HAL_PCI_RESET_DEASSERT(); #endif }
static void do_delay(int argc, char *argv[]) { struct option_info opts[1]; int count = 0x00000000; bool count_set; int value; register int i; init_opts(&opts[0], 'c', true, OPTION_ARG_TYPE_NUM, (void**)&count, &count_set, "Number of times to delay"); if (!scan_opts(argc, argv, 1, opts, sizeof(opts) / sizeof(opts[0]), (void*)&value, OPTION_ARG_TYPE_NUM, "amount of time to delay (usec)")) { return; } if (!count_set) { count = 1; } for (i = 0; i < count; i++) { diag_printf("Delaying %d useconds...", value); HAL_DELAY_US(value); diag_printf("Done\n"); } }
static cyg_uint32 phy_read_register(cyg_uint32 address, cyg_uint8 reg) { cyg_uint32 retVal; cyg_uint32 miimcom, miimind; int i; HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMADD , ((((cyg_uint32)address) << 8) | reg)); HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCOM , miimcom); miimcom &= ~MIIMCOM_READ; HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCOM , miimcom); miimcom |= MIIMCOM_READ; HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCOM , miimcom); HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMIND , miimind); i = 0; while ((miimind & MIIMIND_BUSY) == MIIMIND_BUSY && i++ < 500) { // os_printf("."); HAL_DELAY_US(10000); HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMIND , miimind); } //status register HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMSTAT , retVal); // phy_state = qi->regs->miimstat; HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCOM , miimcom); miimcom &= ~MIIMCOM_READ; HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCOM , miimcom); return retVal; }
/*------------------------------------------------------------------- * * FUNCTION NAME: * * DESCRIPTION: * * EXTERNAL EFFECT: Turns on the LXT970 transciever * * PARAMETERS: * * RETURNS: None * * ASSUMPTIONS: * *-------------------------------------------------------------------*/ void EnableResetPHY(volatile t_BCSR *pBCSR) { #ifdef CYGPKG_HAL_POWERPC_TS6 #define ETH_RST_MASK 0x20 /* The FPGA control register on the TS6 board uses the same memory * location as the BCSR register on the VADS board. */ volatile cyg_uint32 *fpga_ctrl = (cyg_uint32 *) pBCSR; volatile cyg_uint32 *fpga_vers; cyg_uint32 value; fpga_vers = fpga_ctrl + 1; value = *fpga_vers; if(value >= 6){ /* version 06 of the FPGA added PHY reset control */ value = *fpga_ctrl; /* Set the PHY reset bit */ value |= ETH_RST_MASK; *fpga_vers = value; /* Give the PHY time to reset */ HAL_DELAY_US(10000); /* Clear the reset bit */ *fpga_vers = value & ~ETH_RST_MASK; } #else // active low FETHIEN on BSCR1, assert reset low pBCSR->bcsr1 &= ~(FETHIEN_ | FETHRST_); // de-assert reset pBCSR->bcsr1 |= FETHRST_; #endif }
/*------------------------------------------------------------------- * * FUNCTION NAME: * * DESCRIPTION: * * EXTERNAL EFFECT: * * PARAMETERS: * * RETURNS: None * * ASSUMPTIONS: * *-------------------------------------------------------------------*/ UINT16 LinkTestPHY() { UINT32 j; UINT16 FrameValue = 0; for (j = 0; j < 50; j++) { HAL_DELAY_US(100000); FrameValue = MdioFrame(READ,0,CHIP_STAT_REG,0); if ( (FrameValue & 0x0200) != 0 ) break; } FrameValue &= 0x3800; switch (FrameValue) { case 0x3800: return HUNDRED_FD; case 0x2800: return HUNDRED_HD; case 0x3000: return TEN_FD; case 0x2000: return TEN_HD; default: return NOTLINKED; } }
static void resetPHY(void) { volatile cyg_uint32 value = 0; //reset phy HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_GP1DAT , value ); value &= ~((cyg_uint32) 0x10); HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_GP1DAT , value ); HAL_DELAY_US(125); HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_GP1DAT , value ); value |= 0x10; HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_GP1DAT , value ); HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCFG , MIIMCFG_RESET); HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCFG , MIIMCFG_CLOCK_DIV_8); HAL_DELAY_US(12500); }
static void delay_us(cyg_int32 usecs) { CYGARC_HAL_SAVE_GP(); #ifdef CYGPKG_KERNEL { cyg_int32 start, elapsed; cyg_int32 usec_ticks, slice; // How many ticks total we should wait for. usec_ticks = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; usec_ticks /= CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000; do { // Spin in slices of 1/2 the RTC period. Allows interrupts // time to run without messing up the algorithm. If we spun // for 1 period (or more) of the RTC, there'd be also problems // figuring out when the timer wrapped. We may lose a tick or // two for each cycle but it shouldn't matter much. slice = usec_ticks % (CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / 2); HAL_CLOCK_READ(&start); do { HAL_CLOCK_READ(&elapsed); elapsed = (elapsed - start); // counts up! if (elapsed < 0) elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; } while (elapsed < slice); // Adjust by elapsed, not slice, since an interrupt may have // been stalling us for some time. usec_ticks -= elapsed; } while (usec_ticks > 0); } #else // CYGPKG_KERNEL #ifdef HAL_DELAY_US // Use a HAL feature if defined HAL_DELAY_US(usecs); #else // If no accurate delay mechanism, just spin for a while. Having // an inaccurate delay is much better than no delay at all. The // count of 10 should mean the loop takes something resembling // 1us on most CPUs running between 30-100MHz [depends on how many // instructions this compiles to, how many dispatch units can be // used for the simple loop, actual CPU frequency, etc] while (usecs-- > 0) { int i; for (i = 0; i < 10; i++); } #endif // HAL_DELAY_US #endif // CYGPKG_KERNEL CYGARC_HAL_RESTORE_GP(); }
static void phy_write_register(cyg_uint32 address, cyg_uint8 reg, cyg_uint32 value) { int i = 0; cyg_uint32 miimind; HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMADD , ((cyg_uint32)address << 8) | reg ); //AN advertisement register HAL_WRITE_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMCON , value); HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMIND , miimind); while (miimind != 0 && i++ < 500) { // os_printf("."); HAL_DELAY_US(10000); HAL_READ_UINT32( CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1_MIIMIND , miimind); } }
// // This function is called to shut down the interface. // static void tsec_eth_stop(struct eth_drv_sc *sc) { struct tsec_eth_info *qi = (struct tsec_eth_info *) sc->driver_private; int i = 0; os_printf("ETH stop\n"); // Mask and clear all interrupt qi->tsec->imask = IMASK_CLEAR_ALL; // No interrupts enabled qi->tsec->ievent = IEVENT_CLEAR_ALL; // Clear all interrupts //Stop DMA qi->tsec->dmactrl |= (DMACTRL_GRS| DMACTRL_GTS); while (i++ < 500 && ((qi->tsec->ievent & (IEVENT_GRSC| IEVENT_GTSC)) != (IEVENT_GRSC| IEVENT_GTSC))) { HAL_DELAY_US(1000); } // Disable TX and RX qi->tsec->maccfg1 &= ~(MACCFG1_RXEN| MACCFG1_TXEN); }
static void delay_us(cyg_int32 usecs) { CYGARC_HAL_SAVE_GP(); #if defined(CYGPKG_KERNEL) && defined(HAL_CLOCK_READ) { cyg_uint32 start, elapsed_hal; cyg_int32 elapsed, elapsed_usec; cyg_int32 slice; cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000; cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period; do { // Spin in slices of 1/2 the RTC period. Allows interrupts // time to run without messing up the algorithm. If we // spun for 1 period (or more) of the RTC, there would also // be problems figuring out when the timer wrapped. We // may lose a tick or two for each cycle but it shouldn't // matter much. // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD // check for a value that would cause a 32 bit signed // multiply to overflow. But this also implies that just // multiplying by ticks_per_usec will yield a good // approximation. Otherwise we need to do the full // multiply+divide to get sufficient accuracy. Note that // this test is actually constant, so the compiler will // eliminate it and only compile the branch that is // selected. if( usecs > usec_per_period/2 ) slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2; else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period ) slice = usecs * ticks_per_usec; else { slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; slice /= usec_per_period; } HAL_CLOCK_READ(&start); do { HAL_CLOCK_READ(&elapsed_hal); elapsed = (elapsed_hal - start); // counts up! if (elapsed < 0) elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; } while (elapsed < slice); // Adjust by elapsed, not slice, since an interrupt may // have been stalling us for some time. if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period ) elapsed_usec = elapsed / ticks_per_usec; else { elapsed_usec = elapsed * usec_per_period; elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; } // It is possible for elapsed_usec to end up zero in some // circumstances and we could end up looping indefinitely. // Avoid that by ensuring that we always decrement usec by // at least 1 each time. usecs -= elapsed_usec ? elapsed_usec : 1; } while (usecs > 0); } #else // CYGPKG_KERNEL #ifdef HAL_DELAY_US // Use a HAL feature if defined HAL_DELAY_US(usecs); #else // If no accurate delay mechanism, just spin for a while. Having // an inaccurate delay is much better than no delay at all. The // count of 10 should mean the loop takes something resembling // 1us on most CPUs running between 30-100MHz [depends on how many // instructions this compiles to, how many dispatch units can be // used for the simple loop, actual CPU frequency, etc] while (usecs-- > 0) { int i; for (i = 0; i < 10; i++); } #endif // HAL_DELAY_US #endif // CYGPKG_KERNEL CYGARC_HAL_RESTORE_GP(); }
void mii_poll_busy(void) { /* check to see if PHY is busy with read or write */ while (MIIIR & 1) HAL_DELAY_US(1); }
// // Initialize the interface - performed at system startup // This function must set up the interface, including arranging to // handle interrupts, etc, so that it may be "started" cheaply later. // static bool tsec_eth_init(struct cyg_netdevtab_entry *tab) { struct eth_drv_sc *sc = (struct eth_drv_sc *) tab->device_instance; struct tsec_eth_info *qi = (struct tsec_eth_info *) sc->driver_private; volatile struct mpq_tsec *tsec = (volatile struct mpq_tsec *) ((unsigned char *) CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1); int speed100 = 0; int full_duplex = 0; int link = 0; bool esa_ok; int i; cyg_uint32 phy_state = 0; cyg_uint32 int_state; HAL_DISABLE_INTERRUPTS(int_state); os_printf("ETH Init\n"); tsec_eth_set_rmii_io(); qi->tsec = tsec; tsec_eth_stop(sc); #ifdef _TSEC_USE_INTS cyg_drv_interrupt_create(TSEC_ETH_INT, 0, (cyg_addrword_t) sc, // Data item passed to interrupt handler (cyg_ISR_t *) tsec_eth_isr, (cyg_DSR_t *) eth_drv_dsr, &tsec_eth_interrupt_handle_err, &tsec_eth_interrupt_err); cyg_drv_interrupt_attach(tsec_eth_interrupt_handle_err); cyg_drv_interrupt_acknowledge(TSEC_ETH_INT); cyg_drv_interrupt_unmask(TSEC_ETH_INT); cyg_drv_interrupt_create(TSEC_ETH_INT + 1, 0, (cyg_addrword_t) sc, // Data item passed to interrupt handler (cyg_ISR_t *) tsec_eth_isr, (cyg_DSR_t *) eth_drv_dsr, &tsec_eth_interrupt_handle_rx, &tsec_eth_interrupt_rx); cyg_drv_interrupt_attach(tsec_eth_interrupt_handle_rx); cyg_drv_interrupt_acknowledge(TSEC_ETH_INT + 1); cyg_drv_interrupt_unmask(TSEC_ETH_INT + 1); cyg_drv_interrupt_create(TSEC_ETH_INT + 2, 0, (cyg_addrword_t) sc, // Data item passed to interrupt handler (cyg_ISR_t *) tsec_eth_isr, (cyg_DSR_t *) eth_drv_dsr, &tsec_eth_interrupt_handle_tx, &tsec_eth_interrupt_tx); cyg_drv_interrupt_attach(tsec_eth_interrupt_handle_tx); cyg_drv_interrupt_acknowledge(TSEC_ETH_INT + 2); cyg_drv_interrupt_unmask(TSEC_ETH_INT + 2); #endif esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET, "tsec_esa", enaddr, CONFIG_ESA); if (!esa_ok) { // Can't figure out ESA os_printf("TSEC_ETH - Warning! ESA unknown\n"); memcpy(&enaddr, &_default_enaddr, sizeof(enaddr)); } resetPHY(); i = 0; while ((tsec->miimind & MIIMIND_BUSY) != 0 && i++ < 500) { // os_printf("."); HAL_DELAY_US(10000); } for (qi->phyAddress = 1; qi->phyAddress < 0x1f; qi->phyAddress++) { phy_state = phy_read_register(qi->phyAddress, MII_PHY_ID1_REG); phy_state = (phy_state & 0xffff) << 16; phy_state |= phy_read_register(qi->phyAddress, MII_PHY_ID2_REG) & 0xffff; if (phy_state == 0xffffffff) { os_printf("The PHY management interface is not available! Hardware problem!\n"); } else { // os_printf("life on 0x%02x, state = 0x%08x\n", qi->phyAddress, phy_state); break; } } createPHYInterrupt(sc); phyAutoNegociate(qi->phyAddress, &link, &speed100, &full_duplex); if (!tsec_eth_reset(sc, enaddr, (full_duplex ? RESET_FULL_DUPLEX : 0x00000000) | (speed100 ? RESET_100MB : 0x00000000))) { return false; } (sc->funs->eth_drv->init)(sc, (unsigned char *) &enaddr); HAL_RESTORE_INTERRUPTS(int_state); #ifdef CYGNUM_DEVS_ETH_POWERPC_TSEC_LINK_MODE_Auto if (!link) { return false; } #endif return true; }
// // [re]Initialize the ethernet controller // Done separately since shutting down the device requires a // full reconfiguration when re-enabling. // when static bool tsec_eth_reset(struct eth_drv_sc *sc, unsigned char *enaddr, int flags) { struct tsec_eth_info *qi = (struct tsec_eth_info *) sc->driver_private; volatile struct mpq_tsec *tsec = (volatile struct mpq_tsec *) ((unsigned char *) CYGARC_IMM_BASE + CYGARC_REG_IMM_TSEC1); volatile struct tsec_bd *rxbd, *txbd; unsigned char *RxBUF, *TxBUF; cyg_uint32 int_state; int i = 0; HAL_DISABLE_INTERRUPTS(int_state); /** * MAC configuration -> MPC8313 User Manual, Chapter 15.6.2.2 * */ // Shut down ethernet controller, in case it is already running // Disable WWR, because of the errata eTSEC5 tsec->dmactrl &= ~(DMACTRL_GRS| DMACTRL_GTS | DMACTRL_WWR); //asm("sync"); tsec->dmactrl |= (DMACTRL_GRS| DMACTRL_GTS); /* FIX??? when should this be enabled?? memory interface snooping */ tsec->dmactrl |= (DMACTRL_TDSEN | DMACTRL_TBDSEN); tsec->attr |= ATTR_RDSEN | ATTR_RBDSEN; /* we clear halt upon transmit rather than let the hw poll */ tsec->dmactrl |= DMACTRL_WOP; while ((tsec->ievent & (IEVENT_GRSC| IEVENT_GTSC)) != (IEVENT_GRSC | IEVENT_GTSC)) { HAL_DELAY_US(1000); if (++i >= 100) { // os_printf("ETH Controller DMA stop failed, return from tsec_eth_reset\n"); HAL_RESTORE_INTERRUPTS(int_state); return false; } } //clear the graceful stop events tsec->ievent = IEVENT_GRSC | IEVENT_GTSC; tsec->dmactrl &= ~(DMACTRL_GRS| DMACTRL_GTS); /* Reset MAC for at least 3 TX clock cycle*/ tsec->maccfg1 = MACCFG1_SOFT_RESET; HAL_DELAY_US(1000); /* this should be long enought !! */ /* Clear soft reset */ tsec->maccfg1 = (MACCFG1_RXFLOW| MACCFG1_TXFLOW); txbd = tsec_eth_txring; rxbd = tsec_eth_rxring; /* Init Rx / Tx ring base */ qi->tbase = qi->txbd = txbd; qi->rbase = qi->rxbd = qi->rnext = rxbd; RxBUF = &tsec_eth_rxbufs[0]; TxBUF = &tsec_eth_txbufs[0]; /* Initialize Rx BDs */ for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_TSEC_RxNUM; i++) { rxbd->length = 0; rxbd->buffer = RxBUF; // interrupts are triggered once every 2 packages rxbd->ctrl = FEC_BD_Rx_Empty | ((i % 1 == 0) ? FEC_BD_Rx_Intr : 0); RxBUF += CYGNUM_DEVS_ETH_POWERPC_TSEC_BUFSIZE_RX; rxbd++; } rxbd--; rxbd->ctrl |= FEC_BD_Rx_Wrap; // Last buffer #if CACHE() HAL_DCACHE_FLUSH(tsec_eth_rxbufs, sizeof(tsec_eth_rxbufs)); HAL_DCACHE_FLUSH(tsec_eth_rxring, sizeof(tsec_eth_rxring)); #endif /* Initialize Tx BDs */ for (i = 0; i < CYGNUM_DEVS_ETH_POWERPC_TSEC_TxNUM; i++) { txbd->length = 0; txbd->buffer = TxBUF; // let interrupts happen every frame txbd->ctrl = FEC_BD_Tx_Intr; TxBUF += CYGNUM_DEVS_ETH_POWERPC_TSEC_BUFSIZE_TX; txbd++; } txbd--; txbd->ctrl |= FEC_BD_Tx_Wrap; // Last buffer #if CACHE() HAL_DCACHE_FLUSH(tsec_eth_txbufs, sizeof(tsec_eth_txbufs)); HAL_DCACHE_FLUSH(tsec_eth_txring, sizeof(tsec_eth_txring)); #endif /* Initialize shared PRAM */ tsec->rbase = tsec->rbptr = (cyg_uint32) (qi->rbase); tsec->tbase = tsec->tbptr = (cyg_uint32) (qi->tbase); /* Init default value */ tsec->maccfg2 = 0x00007000 | MACCFG2_IF_MODE_NIBBLE | MACCFG2_PAD_CRC | ((flags & RESET_FULL_DUPLEX) ? MACCFG2_FULL_DUPLEX : 0x0); tsec->ecntrl = ECNTRL_STEN | ECNTRL_RMM | ((flags & RESET_100MB) ? ECNTRL_R100M : 0); /* Disables all interrupts */ tsec->ievent = IEVENT_CLEAR_ALL; /* Init mask */ tsec->imask = IMASK_CLEAR_ALL; /* Size of receive buffers */ tsec->mrblr = CYGNUM_DEVS_ETH_POWERPC_TSEC_BUFSIZE_RX; /* Minimum size, 64 bytes */ tsec->minflr = 0x00000040; /* Rx / Tx control */ tsec->rctrl = 0x00000000; /* CC: TODO, double check what to do for VLAN tag */ tsec->tctrl = 0x00000000; //tsec->tctrl = 0x4; //related with DMACTRL_TOD /* Largest possible ethernet frame */ tsec->maxfrm = IEEE_8023_MAX_FRAME; //tsec->attr //tsec->fifo_tx_thr //tsec->fifo_tx_starve //tsec->fifo_tx_starve_shutoff // Group address hash tsec->gaddr[0] = 0; tsec->gaddr[1] = 0; tsec->gaddr[2] = 0; tsec->gaddr[3] = 0; tsec->gaddr[4] = 0; tsec->gaddr[5] = 0; tsec->gaddr[6] = 0; tsec->gaddr[7] = 0; tsec->igaddr[0] = 0; tsec->igaddr[1] = 0; tsec->igaddr[2] = 0; tsec->igaddr[3] = 0; tsec->igaddr[4] = 0; tsec->igaddr[5] = 0; tsec->igaddr[6] = 0; tsec->igaddr[7] = 0; // Init MIB memset((void *) &(tsec->rmon), 1, sizeof(struct rmon_tsec)); tsec->rmon.cam1 = 0xFFFFFFFF; tsec->rmon.cam2 = 0xFFFFFFFF; /* Device physical address */ tsec->macstnaddr1 = (cyg_uint32) ((cyg_uint32) enaddr[5] << 24 | (cyg_uint32) enaddr[4] << 16 | (cyg_uint32) enaddr[3] << 8 | (cyg_uint32) enaddr[2]); tsec->macstnaddr2 = (cyg_uint32) ((cyg_uint32) enaddr[1] << 24 | (cyg_uint32) enaddr[0] << 16); tsec->tstat = TSTAT_TXF; tsec->rstat = RSTAT_QHLT | RSTAT_RXF; tsec->dmactrl &= ~(DMACTRL_GRS| DMACTRL_GTS); /* Enable Tx / Rx */ tsec->maccfg1 |= (MACCFG1_RXEN| MACCFG1_TXEN); /* Umask interrupt */ #ifdef _TSEC_USE_INTS tsec->imask = IMASK_DEFAULT; #endif // //debug: // index_in_memory_area = 0; // stopper = 0; HAL_RESTORE_INTERRUPTS(int_state); return true; }