Exemplo n.º 1
0
// ///////////////////////////////////////////////////// 
//! 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;
}
Exemplo n.º 2
0
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
}
Exemplo n.º 3
0
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");
  }
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/*-------------------------------------------------------------------
*
* 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
}
Exemplo n.º 6
0
/*-------------------------------------------------------------------
*
* 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;
  }

}
Exemplo n.º 7
0
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);

}
Exemplo n.º 8
0
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();
}
Exemplo n.º 9
0
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);
	}

}
Exemplo n.º 10
0
//
// 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);
}
Exemplo n.º 11
0
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();
}
Exemplo n.º 12
0
void mii_poll_busy(void)
{
  /* check to see if PHY is busy with read or write */
  while (MIIIR & 1)
    HAL_DELAY_US(1);
}
Exemplo n.º 13
0
//
// 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;
}
Exemplo n.º 14
0
//
// [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;
}