📄 r1000_n.c
字号:
val |= PHY_Cap_PAUSE | PHY_Cap_ASYM_PAUSE ;
#endif //end #define R1000_HW_FLOW_CONTROL_SUPPORT
bmcr = PHY_Restart_Auto_Nego|PHY_Enable_Auto_Nego;
if(autoneg==AUTONEG_ENABLE){
priv->autoneg = AUTONEG_ENABLE;
anar = PHY_Cap_10_Half|PHY_Cap_10_Full|PHY_Cap_100_Half|PHY_Cap_100_Full;
gbcr = PHY_Cap_1000_Half|PHY_Cap_1000_Full;
}else{
priv->autoneg = AUTONEG_DISABLE;
if(speed==SPEED_1000){
priv->speed = SPEED_1000;
priv->duplex = DUPLEX_FULL;
anar = PHY_Cap_10_Half|PHY_Cap_10_Full|PHY_Cap_100_Half|PHY_Cap_100_Full;
if((priv->mcfg==MCFG_METHOD_13)||(priv->mcfg==MCFG_METHOD_14)||(priv->mcfg==MCFG_METHOD_15))
gbcr = PHY_Cap_Null;
else
gbcr = PHY_Cap_1000_Half|PHY_Cap_1000_Full;
}else if((speed==SPEED_100)&&(duplex==DUPLEX_FULL)){
priv->speed = SPEED_100;
priv->duplex = DUPLEX_FULL;
anar = PHY_Cap_10_Half|PHY_Cap_10_Full|PHY_Cap_100_Half|PHY_Cap_100_Full;
gbcr = PHY_Cap_Null;
}else if((speed==SPEED_100)&&(duplex==DUPLEX_HALF)){
priv->speed = SPEED_100;
priv->duplex = DUPLEX_HALF;
anar = PHY_Cap_10_Half|PHY_Cap_10_Full|PHY_Cap_100_Half;
gbcr = PHY_Cap_Null;
}else if((speed==SPEED_10)&&(duplex==DUPLEX_FULL)){
priv->speed = SPEED_10;
priv->duplex = DUPLEX_FULL;
anar = PHY_Cap_10_Half|PHY_Cap_10_Full;
gbcr = PHY_Cap_Null;
}else if((speed==SPEED_10)&&(duplex==DUPLEX_HALF)){
priv->speed = SPEED_10;
priv->duplex = DUPLEX_HALF;
anar = PHY_Cap_10_Half;
gbcr = PHY_Cap_Null;
}else{
priv->speed = SPEED_100;
priv->duplex = DUPLEX_FULL;
anar = PHY_Cap_10_Half|PHY_Cap_10_Full|PHY_Cap_100_Half|PHY_Cap_100_Full;
gbcr = PHY_Cap_Null;
}
}
//enable flow control
anar |= val&0xC1F;
ret = r1000_set_speed_duplex(ioaddr,anar,gbcr,bmcr);
return ret;
}
static int r1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd){
if(!netif_running(netdev))
return -EINVAL;
switch(cmd){
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
case SIOCETHTOOL:
return ethtool_ioctl(ifr);
#endif
default:
return -EOPNOTSUPP;
}
}
//======================================================================================================
static int __devinit r1000_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev = NULL;
struct r1000_private *priv = NULL;
unsigned long ioaddr = 0;
static int board_idx = -1;
int i,rc;
// int val=0;
int speed_opt = SPEED_100;
int duplex_opt = DUPLEX_FULL;
int autoneg_opt = AUTONEG_ENABLE;
assert (pdev != NULL);
assert (ent != NULL);
board_idx++;
i = r1000_init_board (pdev, &netdev, &ioaddr);
if (i < 0) {
return i;
}
priv = netdev->priv;
assert (ioaddr != NULL);
assert (netdev != NULL);
assert (priv != NULL);
// Get MAC address //
for (i = 0; i < MAC_ADDR_LEN ; i++){
netdev->dev_addr[i] = RTL_R8( MAC0 + i );
}
netdev->open = r1000_open;
netdev->hard_start_xmit = r1000_start_xmit;
netdev->get_stats = r1000_get_stats;
netdev->stop = r1000_close;
netdev->tx_timeout = r1000_tx_timeout;
netdev->set_multicast_list = r1000_set_rx_mode;
netdev->watchdog_timeo = TX_TIMEOUT;
netdev->irq = pdev->irq;
netdev->base_addr = (unsigned long) ioaddr;
#ifdef R1000_JUMBO_FRAME_SUPPORT
netdev->change_mtu = r1000_change_mtu;
#endif //end #ifdef R1000_JUMBO_FRAME_SUPPORT
netdev->do_ioctl = r1000_ioctl;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
netdev->ethtool_ops = &r1000_ethtool_ops;
#endif
#ifdef R1000_BOTTOM_HALVES
tasklet_init(&priv->r1000_rx_tasklet,r1000_rx_interrupt,(unsigned long)netdev);
tasklet_init(&priv->r1000_tx_tasklet,r1000_tx_interrupt,(unsigned long)netdev);
#endif //R1000_BOTTOM_HALVES
priv = netdev->priv; // private data //
priv->pci_dev = pdev;
priv->ioaddr = ioaddr;
//#ifdef R1000_JUMBO_FRAME_SUPPORT
priv->curr_mtu_size = netdev->mtu;
priv->tx_pkt_len = netdev->mtu + ETH_HDR_LEN;
priv->rx_pkt_len = netdev->mtu + ETH_HDR_LEN;
priv->hw_rx_pkt_len = priv->rx_pkt_len + 8;
//#endif //end #ifdef R1000_JUMBO_FRAME_SUPPORT
DBG_PRINT("-------------------------- \n");
DBG_PRINT("netdev->mtu = %d \n", netdev->mtu);
DBG_PRINT("priv->curr_mtu_size = %d \n", priv->curr_mtu_size);
DBG_PRINT("priv->tx_pkt_len = %d \n", priv->tx_pkt_len);
DBG_PRINT("priv->rx_pkt_len = %d \n", priv->rx_pkt_len);
DBG_PRINT("priv->hw_rx_pkt_len = %d \n", priv->hw_rx_pkt_len);
DBG_PRINT("-------------------------- \n");
spin_lock_init(&priv->lock);
spin_lock_init(&priv->tx_lock);
spin_lock_init(&priv->rx_lock);
rc = register_netdev(netdev);
if(rc){
#ifndef R1000_USE_IO
iounmap ((void *)(netdev->base_addr));
#endif
pci_release_regions(pdev);
pci_disable_device(pdev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
kfree(netdev);
#else
free_netdev(netdev);
#endif
return rc;
}
pci_set_drvdata(pdev,netdev); // pdev->driver_data = data;
printk (KERN_DEBUG "%s: Identified chip type is '%s'.\n",netdev->name,rtl_chip_info[priv->chipset].name);
printk (KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d\n",
netdev->name,
R1000_DRIVER_NAME,
netdev->base_addr,
netdev->dev_addr[0],netdev->dev_addr[1],
netdev->dev_addr[2],netdev->dev_addr[3],
netdev->dev_addr[4],netdev->dev_addr[5],
netdev->irq);
// Config PHY
r1000_hw_PHY_config(netdev);
DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8( 0x82, 0x01 );
if( priv->mcfg < MCFG_METHOD_3 ){
DBG_PRINT("Set PCI Latency=0x40\n");
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
}
if( priv->mcfg == MCFG_METHOD_2 ){
DBG_PRINT("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8( 0x82, 0x01 );
DBG_PRINT("Set PHY Reg 0x0bh = 0x00h\n");
R1000_WRITE_GMII_REG( ioaddr, 0x0b, 0x0000 ); //w 0x0b 15 0 0
}
// if TBI is not endbled
if( !(RTL_R8(PHYstatus) & TBI_Enable) ){
// val = R1000_READ_GMII_REG( ioaddr, PHY_AUTO_NEGO_REG );
//#ifdef R1000_HW_FLOW_CONTROL_SUPPORT
// val |= PHY_Cap_PAUSE | PHY_Cap_ASYM_PAUSE ;
//#endif //end #define R1000_HW_FLOW_CONTROL_SUPPORT
if(speed[board_idx] == -1)
speed[board_idx] = SPEED_1000;
if((duplex[board_idx] == -1) || ((duplex[board_idx] == DUPLEX_HALF) && (speed[board_idx] == SPEED_1000)))
duplex[board_idx] = DUPLEX_FULL;
if(autoneg[board_idx] == -1)
autoneg[board_idx] = AUTONEG_ENABLE;
speed_opt = (board_idx >= MAX_UNITS) ? -1 : speed[board_idx];
duplex_opt = (board_idx >= MAX_UNITS) ? -1 : duplex[board_idx];
autoneg_opt = (board_idx >= MAX_UNITS) ? -1 : autoneg[board_idx];
r1000_set_medium(netdev,speed_opt,duplex_opt,autoneg_opt);
}// end of TBI is not enabled
else{
udelay(100);
DBG_PRINT("1000Mbps Full-duplex operation, TBI Link %s!\n",(RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed" );
}// end of TBI is not enabled
//show some information after the driver is inserted
if(( priv->mcfg == MCFG_METHOD_11 )||( priv->mcfg == MCFG_METHOD_12 ))
printk("Realtek RTL8168/8111 Family PCI-E Gigabit Ethernet Network Adapter\n");
else if((priv->mcfg==MCFG_METHOD_13)||(priv->mcfg==MCFG_METHOD_14)||(priv->mcfg==MCFG_METHOD_15))
printk("Realtek RTL8139/810x Family Fast Ethernet Network Adapter\n");
else
printk("Realtek RTL8169/8110 Family Gigabit Ethernet Network Adapter\n");
printk("Driver version:%s\n",R1000_VERSION);
printk("Released date:%s\n",RELEASE_DATE);
if(RTL_R8(PHYstatus) & LinkStatus){
printk("Link Status:%s\n","Linked");
if(RTL_R8(PHYstatus) & _1000Mbps)
printk("Link Speed:1000Mbps\n");
else if(RTL_R8(PHYstatus) & _100Mbps)
printk("Link Speed:100Mbps\n");
else if(RTL_R8(PHYstatus) & _10Mbps)
printk("Link Speed:10Mbps\n");
printk("Duplex mode:%s\n",RTL_R8(PHYstatus)&FullDup?"Full-Duplex":"Half-Duplex");
}else{
printk("Link Status:%s\n","Not Linked");
}
#ifdef R1000_USE_IO
printk("I/O Base:0x%X(I/O port)\n",(unsigned int)(priv->ioaddr));
#else
printk("I/O Base:0x%X(I/O memory)\n",(unsigned int)(priv->ioaddr));
#endif //R1000_USE_IO
printk("IRQ:%d\n",netdev->irq);
return 0;
}
static void __devexit r1000_remove_one (struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
assert (netdev != NULL);
assert (priv != NULL);
unregister_netdev(netdev);
#ifndef R1000_USE_IO
iounmap ((void *)(netdev->base_addr));
#endif
pci_release_regions (pdev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
kfree(netdev);
#else
free_netdev(netdev);
#endif
pci_set_drvdata (pdev, NULL);
}
static int r1000_open (struct net_device *netdev)
{
struct r1000_private *priv = netdev->priv;
struct pci_dev *pdev = priv->pci_dev;
int retval;
// u8 diff;
// u32 TxPhyAddr, RxPhyAddr;
if( priv->drvinit_fail == 1 ){
printk("%s: Gigabit driver open failed.\n", netdev->name );
return -ENOMEM;
}
retval = request_irq (netdev->irq, r1000_interrupt, SA_SHIRQ, netdev->name, netdev);
if (retval) {
return retval;
}
//2004-05-11
// Allocate tx/rx descriptor space
priv->sizeof_txdesc_space = NUM_TX_DESC * sizeof(struct TxDesc)+256;
priv->txdesc_space = pci_alloc_consistent( pdev, priv->sizeof_txdesc_space, &priv->txdesc_phy_dma_addr );
if( priv->txdesc_space == NULL ){
printk("%s: Gigabit driver alloc txdesc_space failed.\n", netdev->name );
return -ENOMEM;
}
priv->sizeof_rxdesc_space = NUM_RX_DESC * sizeof(struct RxDesc)+256;
priv->rxdesc_space = pci_alloc_consistent( pdev, priv->sizeof_rxdesc_space, &priv->rxdesc_phy_dma_addr );
if( priv->rxdesc_space == NULL ){
printk("%s: Gigabit driver alloc rxdesc_space failed.\n", netdev->name );
return -ENOMEM;
}
if(priv->txdesc_phy_dma_addr & 0xff){
printk("%s: Gigabit driver txdesc_phy_dma_addr is not 256-bytes-aligned.\n", netdev->name );
}
if(priv->rxdesc_phy_dma_addr & 0xff){
printk("%s: Gigabit driver rxdesc_phy_dma_addr is not 256-bytes-aligned.\n", netdev->name );
}
// Set tx/rx descriptor space
priv->TxDescArray = (struct TxDesc *)priv->txdesc_space;
priv->RxDescArray = (struct RxDesc *)priv->rxdesc_space;
{
int i;
struct sk_buff *skb = NULL;
for(i=0;i<NUM_RX_DESC;i++){
skb = R1000_ALLOC_RXSKB(MAX_RX_SKBDATA_SIZE);
if( skb != NULL ) {
skb_reserve (skb, 8); // 16 byte align the IP fields. //
priv->Rx_skbuff[i] = skb;
}
else{
printk("%s: Gigabit driver failed to allocate skbuff.\n", netdev->name);
priv->drvinit_fail = 1;
}
}
}
//////////////////////////////////////////////////////////////////////////////
r1000_init_ring(netdev);
r1000_hw_start(netdev);
// ------------------------------------------------------
DBG_PRINT("FIX PCS -> r1000_request_timer\n");
priv->expire_time = R1000_TIMER_EXPIRE_TIME;
r1000_request_timer( (&priv->r1000_timer), priv->expire_time, r1000_timer_handler, ((void *)netdev) ); //in open()
DBG_PRINT("%s: %s() alloc_rxskb_cnt = %d\n", netdev->name, __FUNCTION__, alloc_rxskb_cnt );
return 0;
}//end of r1000_open (struct net_device *netdev)
static void r1000_hw_PHY_reset(struct net_device *netdev)
{
int val, phy_reset_expiretime = 50;
struct r1000_private *priv = netdev->priv;
unsigned long ioaddr = priv->ioaddr;
DBG_PRINT("%s: Reset RTL8169s PHY\n", netdev->name);
val = ( R1000_READ_GMII_REG( ioaddr, 0 ) | 0x8000 ) & 0xffff;
R1000_WRITE_GMII_REG( ioaddr, 0, val );
do //waiting for phy reset
{
if( R1000_READ_GMII_REG( ioaddr, 0 ) & 0x8000 ){
phy_reset_expiretime --;
udelay(100);
}
else{
break;
}
}while( phy_reset_expiretime >= 0 );
assert( phy_reset_expiretime > 0 );
}
static void r1000_hw_PHY_config (struct net_device *netdev)
{
struct r1000_private *priv = netdev->priv;
void *ioaddr = (void*)priv->ioaddr;
DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n",priv->mcfg,priv->pcfg);
if( priv->mcfg == MCFG_METHOD_4 ){
#if 0
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0001 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1b, 0x841e );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x0e, 0x7bfb );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x09, 0x273a );
#endif
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0002 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x90D0 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1F, 0x0000 );
}else if((priv->mcfg == MCFG_METHOD_2)||(priv->mcfg == MCFG_METHOD_3)){
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1f, 0x0001 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x06, 0x006e );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x08, 0x0708 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x15, 0x4000 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x18, 0x65c7 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x1f, 0x0001 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0x00a1 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0x0008 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x0120 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0x1000 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x0800 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x0000 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x03, 0xff41 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x02, 0xdf60 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x01, 0x0140 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x00, 0x0077 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x7800 );
R1000_WRITE_GMII_REG( (unsigned long)ioaddr, 0x04, 0x7000 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -