📄 freedev_lan91c111.c
字号:
for(i=15;i>=0;i--)
{
clock_phy_bit(dev, mgmt_value |
FREEDEV_LAN91C111_MGMT_MDOE_MSK |
((value >> i) & 0x1));
}
IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr,old_bank);
return;
}
/*-----------------------------------------------------------------------------------*
*
* reset_device(freedev_lan91c111_if *dev):
*
* Reset the device and get it into a known state
*
*
*-----------------------------------------------------------------------------------*/
static err_t reset_device(freedev_lan91c111_if *dev)
{
alt_u16 register_value;
alt_u16 chip_id;
err_t ret_code = ERR_OK;
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("reset_device()\n"));
IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 3);
chip_id = IORD_FREEDEV_LAN91C111_REV(dev->base_addr);
if (( chip_id & FREEDEV_LAN91C111_CHIP_ID) !=
FREEDEV_LAN91C111_CHIP_ID )
{
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("Not an SMC91C111 chip\n"));
ret_code = ERR_IF;
goto exit;
}
/* Bank 0 */
IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 0);
/*There are a bug in altera_avalon_lan91c111.c,modify by free_electron
* IOWR_FREEDEV_LAN91C111_RCR( dev->base_addr,
FREEDEV_LAN91C111_RCR_SOFTRST_OFST);
*/
IOWR_FREEDEV_LAN91C111_RCR( dev->base_addr,
FREEDEV_LAN91C111_RCR_SOFTRST_MSK);
/* a very generous reset pulse */
usleep(1000);
IOWR_FREEDEV_LAN91C111_RCR(dev->base_addr, 0);
/* This should be plenty of time for the device to settle */
usleep(5000);
/* Reset the MMU */
IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 2);
IOWR_FREEDEV_LAN91C111_MMUCR( dev->base_addr,
FREEDEV_LAN91C111_MMUCR_RESET_MSK);
do {
register_value = IORD_FREEDEV_LAN91C111_MMUCR(dev->base_addr);
}while(register_value & FREEDEV_LAN91C111_MMUCR_BUSY_MSK);
exit:
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("reset_device() exit = %d\n", ret_code));
return ret_code;
}
/*
* set_mac_address
*
* Configure the MAC address of the SMSC chip
*/
static err_t set_mac_address(freedev_lan91c111_if* dev)
{
struct netif* netif = dev->lwip_dev_list.dev.netif;
IOWR_FREEDEV_LAN91C111_BSR(dev->base_addr, 1);
IOWR_FREEDEV_LAN91C111_IAR0(dev->base_addr,
netif->hwaddr[0]);
IOWR_FREEDEV_LAN91C111_IAR1(dev->base_addr,
netif->hwaddr[1]);
IOWR_FREEDEV_LAN91C111_IAR2(dev->base_addr,
netif->hwaddr[2]);
IOWR_FREEDEV_LAN91C111_IAR3(dev->base_addr,
netif->hwaddr[3]);
IOWR_FREEDEV_LAN91C111_IAR4(dev->base_addr,
netif->hwaddr[4]);
IOWR_FREEDEV_LAN91C111_IAR5(dev->base_addr,
netif->hwaddr[5]);
return ERR_OK;
}
/*
* configure_phy
*
* reset the PHY and auto negotiate for the link capabilities
*
*/
static err_t configure_phy(freedev_lan91c111_if *dev)
{
int timeout, i;
alt_u16 value, old_value;
err_t ret_code = ERR_OK;
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("configure_phy()\n"));
/* Read the ID register let's just check we've detected the correct PHY */
value = read_phy_register(dev,
FREEDEV_LAN91C111_PHY_ID1_REG);
if (value != FREEDEV_LAN91C111_PHY_COMPANY_ID)
{
ret_code = ERR_IF;
goto exit;
}
value = read_phy_register(dev,
FREEDEV_LAN91C111_PHY_ID2_REG);
if ((value & 0xfff0) != FREEDEV_LAN91C111_PHY_MFCT_ID )
{
ret_code = ERR_IF;
goto exit;
}
/* Reset the PHY */
write_phy_register( dev,
FREEDEV_LAN91C111_PHY_CONTROL_REG,
FREEDEV_LAN91C111_PHY_CONTROL_RST_MSK);
/* Spec says wait 50 mS */
usleep(50000);
/* Let's just check it's out of reset */
value = read_phy_register(dev,
FREEDEV_LAN91C111_PHY_CONTROL_REG);
if (value & FREEDEV_LAN91C111_PHY_CONTROL_RST_MSK)
{
ret_code = ERR_IF;
goto exit;
}
/* Turn off Auto negotiation til we're ready for it */
write_phy_register( dev,
FREEDEV_LAN91C111_PHY_CONTROL_REG , 0);
/* We'll auto negotiate the capabilities
* 20051227 Free-electron modify orange LED is 10M/100M link,
* green LED is Rx/Tx
* */
IOWR_FREEDEV_LAN91C111_BSR(dev->base_addr, 0);
/*IOWR_FREEDEV_LAN91C111_RPCR(dev->base_addr,
FREEDEV_LAN91C111_RPCR_ANEG_MSK |
FREEDEV_LAN91C111_RPCR_LS2A_MSK |
FREEDEV_LAN91C111_RPCR_LS1A_MSK |
FREEDEV_LAN91C111_RPCR_LS2B_MSK |
FREEDEV_LAN91C111_RPCR_LS1B_MSK |
FREEDEV_LAN91C111_RPCR_LS0B_MSK ); */
IOWR_FREEDEV_LAN91C111_RPCR(dev->base_addr,
FREEDEV_LAN91C111_RPCR_ANEG_MSK |
FREEDEV_LAN91C111_RPCR_LS2B_MSK );
/* Start the Auto Negotiation process */
/* Try to negotiate, we have a go at this five times if it fails */
i = 5;
do
{
write_phy_register( dev,
FREEDEV_LAN91C111_PHY_CONTROL_REG,
FREEDEV_LAN91C111_PHY_CONTROL_ANEG_EN_MSK |
FREEDEV_LAN91C111_PHY_CONTROL_ANEG_RST_MSK);
/*
* Spec says wait 1500 mS after turning on auto negotiation before
* reading the ANEG_ACK bit see section 7.7.12
*/
usleep(1500000);
/* This may take a few seconds */
timeout = 20;
do
{
value = read_phy_register(dev, FREEDEV_LAN91C111_PHY_STATUS_REG);
timeout --;
usleep(500000);
}while (!(value & FREEDEV_LAN91C111_PHY_STATUS_ANEG_ACK_MSK)
&& (timeout > 0));
i --;
}
while( (i != 0) && (timeout == 0));
if (timeout == 0)
{
ret_code = ERR_IF;
goto exit;
}
if (value & FREEDEV_LAN91C111_PHY_STATUS_REM_FLT_MSK)
{
/*
* We may wish to come up with a sensible default here,
*set to 10MBits, CSMA?
*/
ret_code = ERR_IF;
goto exit;
}
/*
* Find out what we've negotiated so that we can configure the MAC
* takes a few reads to stabilise
*/
old_value = read_phy_register(dev,
FREEDEV_LAN91C111_PHY_INT_STATUS_REG);
value = read_phy_register(dev,
FREEDEV_LAN91C111_PHY_INT_STATUS_REG);
while(value != old_value)
{
old_value = value;
value = read_phy_register(dev,
FREEDEV_LAN91C111_PHY_INT_STATUS_REG);
}
if (value & FREEDEV_LAN91C111_PHY_INT_SPDDET_MSK)
{
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("100MBits/s\n"));
}
else
{
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("10MBits/s\n"));
}
if (value & FREEDEV_LAN91C111_PHY_INT_DPLXDET_MSK)
{
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("Full Duplex\n"));
/* Set the MAC for Full Duplex */
value = IORD_FREEDEV_LAN91C111_TCR(dev->base_addr);
value |= FREEDEV_LAN91C111_TCR_SWFDUP_MSK;
IOWR_FREEDEV_LAN91C111_TCR(dev->base_addr,value);
}
else
{
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("Half Duplex\n"));
}
exit:
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("configure_phy() exit = %d\n", ret_code));
return ret_code;
}
/*
* allocate_tx_packet
*
* Allocate (within the device) the one packet we will use for all transmissions
*/
static err_t allocate_tx_packet( freedev_lan91c111_if *dev )
{
alt_u16 value;
alt_u8 byte_value;
int timeout;
err_t ret_code = ERR_OK;
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("allocate_tx_packet()\n"));
IOWR_FREEDEV_LAN91C111_BSR(dev->base_addr, 2);
value = IORD_FREEDEV_LAN91C111_MMUCR(dev->base_addr);
value |= FREEDEV_LAN91C111_MMUCR_ALLOC_MSK;
IOWR_FREEDEV_LAN91C111_MMUCR(dev->base_addr, value);
/* Wait for the command to complete */
timeout = 10;
do
{
byte_value = IORD_FREEDEV_LAN91C111_IST(dev->base_addr);
usleep(100000);
timeout --;
}
while((!(byte_value & FREEDEV_LAN91C111_INT_ALLOC_INT_MSK)) &&
(timeout > 0));
if (timeout == 0)
{
ret_code = ERR_IF;
goto exit;
}
/* Save the allocated packet number for future use */
byte_value = IORD_FREEDEV_LAN91C111_ARR(dev->base_addr);
if (byte_value & FREEDEV_LAN91C111_ARR_FAILED_MSK)
{
ret_code = ERR_IF;
goto exit;
}
dev->tx_packet_no = byte_value & ~FREEDEV_LAN91C111_ARR_FAILED_MSK;
exit:
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("allocate_tx_packet() exit = %d\n", ret_code));
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t low_level_init(freedev_lan91c111_if *dev)
{
/*
* Need to have a pointer to a generice lwip_dev
* This is so that the get_mac_addr function interface
* is device agnostic
*/
alt_lwip_dev* lwip_dev = &dev->lwip_dev_list.dev;
err_t ret_code = ERR_OK;
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE, ("low_level_init()\n"));
/*
* Read the MAC address out of flash
*/
ret_code = get_mac_addr(lwip_dev);
if (ret_code != ERR_OK)
{
goto exit;
}
/* Set MAC hardware address length */
lwip_dev->netif->hwaddr_len = 6;
ret_code = reset_device(dev);
if (ret_code != ERR_OK)
{
goto exit;
}
ret_code = set_mac_address(dev);
if (ret_code != ERR_OK)
{
goto exit;
}
ret_code = configure_phy(dev);
if (ret_code != ERR_OK)
{
goto exit;
}
ret_code = allocate_tx_packet(dev);
if (ret_code != ERR_OK)
{
goto exit;
}
/* maximum transfer unit */
dev->lwip_dev_list.dev.netif->mtu = 1500;
/* broadcast capability */
dev->lwip_dev_list.dev.netif->flags = NETIF_FLAG_BROADCAST;
dev->semaphore = sys_sem_new(1);
if (dev->semaphore == NULL)
{
ret_code = ERR_MEM;
goto exit;
}
dev->arp_semaphore = sys_sem_new(1);
if (dev->arp_semaphore == NULL)
{
ret_code = ERR_MEM;
goto exit;
}
/* Turn on Rx & Tx */
IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 0);
IOWR_FREEDEV_LAN91C111_RCR( dev->base_addr,
FREEDEV_LAN91C111_RCR_STRIP_CRC_MSK |
FREEDEV_LAN91C111_RCR_RXEN_MSK);
IOWR_FREEDEV_LAN91C111_TCR( dev->base_addr,
FREEDEV_LAN91C111_TCR_TXENA_MSK |
FREEDEV_LAN91C111_TCR_PAD_EN_MSK);
/*
* From this point on we don't change banks again, bank 2 is all that's needed
* for Rx, TX and interrupt handling
*/
IOWR_FREEDEV_LAN91C111_BSR( dev->base_addr, 2);
/*
* Let's make sure no interupts are enabled
*/
IOWR_FREEDEV_LAN91C111_MSK(dev->base_addr, 0);
/*
* Install ISR and turn on interrupts
*
* If you're counting stats then we also turn on the RCV_OVRN
* interrupt and increment the error counter for each interrupt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -