📄 8139too.c
字号:
tp->cur_rx = 0;
/* This is check_duplex() */
if (tp->phys[0] >= 0 || (tp->drv_flags & HAS_MII_XCVR))
{
u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
if (mii_reg5 == 0xffff)
; /* Not there */
else if ((mii_reg5 & 0x0100) == 0x0100
|| (mii_reg5 & 0x00C0) == 0x0040)
tp->full_duplex = 1;
printk(KERN_INFO"%s: Setting %s%s-duplex based on"
" auto-negotiated partner ability %4.4x.\n", dev->name,
mii_reg5 == 0 ? "" :
(mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
tp->full_duplex ? "full" : "half", mii_reg5);
}
if (tp->chipset >= CH_8139A)
{
tmp = RTL_R8 (Config1) & Config1Clear;
tmp |= Cfg1_Driver_Load;
tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
RTL_W8_F (Config1, tmp);
}
else
{
u8 foo = RTL_R8 (Config1) & Config1Clear;
RTL_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));
}
if (tp->chipset >= CH_8139B)
{
tmp = RTL_R8 (Config4) & ~(1<<2);
/* chip will clear Rx FIFO overflow automatically */
tmp |= (1<<7);
RTL_W8 (Config4, tmp);
/* disable magic packet scanning, which is enabled
* when PM is enabled above (Config1) */
RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));
}
/* Lock Config[01234] and BMCR register writes */
RTL_W8_F (Cfg9346, Cfg9346_Lock);
udelay (10);
//初始化接收环缓冲区dma地址
/* init Rx ring buffer DMA address */
#ifdef ZERO_COPY
#else
RTL_W32_F (RxBuf, tp->rx_ring_dma);
#endif
/* init Tx buffer DMA addresses */
for (i = 0; i < NUM_TX_DESC; i++)
RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));
RTL_W32_F (RxMissed, 0);
rtl8139_set_rx_mode (dev);
/* no early-rx interrupts */
RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);
/* make sure RxTx has started */
RTL_W8_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |
CmdRxEnb | CmdTxEnb);
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16_F (IntrMask, rtl8139_intr_mask);
netif_start_queue (dev);
DPRINTK ("EXIT\n");
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void rtl8139_init_ring (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
int i;
DPRINTK ("ENTER\n");
tp->cur_rx = 0;
tp->cur_tx = 0;
tp->dirty_tx = 0;
for (i = 0; i < NUM_TX_DESC; i++)
{
tp->tx_info[i].skb = NULL;
tp->tx_info[i].mapping = 0;
tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
}
DPRINTK ("EXIT\n");
}
static int rtl8139CP_open (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
int retval;
u8 diff; //for 8139C+
u32 txPhyAddr, rxPhyAddr; //for 8139C+
#ifdef RTL8139_DEBUG
void *ioaddr = tp->mmio_addr;
#endif
DPRINTK ("ENTER\n");
retval = request_irq (dev->irq, rtl8139CP_interrupt, SA_SHIRQ, dev->name, dev);
if (retval)
{
DPRINTK ("EXIT, returning %d\n", retval);
return retval;
}
//////////////////////////////////////////////////////////////////////////////
tp->TxDescArrays= kmalloc(NUM_CP_TX_DESC*sizeof(struct CPlusTxDesc)+256 , GFP_KERNEL);
// Tx Desscriptor needs 256 bytes alignment;
txPhyAddr=virt_to_bus(tp->TxDescArrays);
diff=txPhyAddr-((txPhyAddr >> 8)<< 8);
diff=256-diff;
txPhyAddr +=diff;
tp->TxDescArray = (struct CPlusTxDesc *)(tp->TxDescArrays + diff);
tp->RxDescArrays= kmalloc(NUM_CP_RX_DESC*sizeof(struct CPlusRxDesc)+256 , GFP_KERNEL);
// Rx Desscriptor needs 256 bytes alignment;
rxPhyAddr=virt_to_bus(tp->RxDescArrays);
diff=rxPhyAddr-((rxPhyAddr >> 8)<< 8);
diff=256-diff;
rxPhyAddr +=diff;
tp->RxDescArray = (struct CPlusRxDesc *)(tp->RxDescArrays + diff);
if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL)
{
printk(KERN_INFO"Allocate RxDescArray or TxDescArray failed\n");
free_irq(dev->irq, dev);
if (tp->TxDescArrays)
kfree(tp->TxDescArrays);
if (tp->RxDescArrays)
kfree(tp->RxDescArrays);
DPRINTK ("EXIT, returning -ENOMEM\n");
return -ENOMEM;
}
tp->RxBufferRings=kmalloc( CP_RX_BUF_SIZE*NUM_CP_RX_DESC, GFP_KERNEL);
if(tp->RxBufferRings==NULL)
{
printk(KERN_INFO"Allocate RxBufferRing failed\n");
}
//////////////////////////////////////////////////////////////////////////////
tp->full_duplex = tp->duplex_lock;
tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
tp->twistie = 1;
rtl8139CP_init_ring (dev);
rtl8139CP_hw_start (dev);
DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d"
" GP Pins %2.2x %s-duplex.\n",
dev->name, pci_resource_start (tp->pci_dev, 1),
dev->irq, RTL_R8 (MediaStatus),
tp->full_duplex ? "full" : "half");
DPRINTK ("EXIT, returning 0\n");
return 0;
}
/* Start the hardware at open or resume. */
static void rtl8139CP_hw_start (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 i;
u8 tmp;
u16 BasicModeCtrlReg;
u8 MediaStatusReg;
DPRINTK ("ENTER\n");
/* Soft reset the chip. */
RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);
udelay (100);
/* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--)
if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
break;
/* unlock Config[01234] and BMCR register writes */
RTL_W8_F (Cfg9346, Cfg9346_Unlock);
RTL_W16 (CPlusCmd, CPlusTxEnb | CPlusRxEnb | CPlusCheckSumEnb); //C+ mode only
/* Restore our idea of the MAC address. */
RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
/* Must enable Tx/Rx before setting transfer thresholds! */
RTL_W8 (ChipCmd,CmdRxEnb | CmdTxEnb); //C+ mode only
RTL_W8 (CPlusEarlyTxThldReg, CPlusEarlyTxThld); //C+ mode only
i = rtl8139_rx_config | (RTL_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
RTL_W32_F (RxConfig, i);
/* Check this value: the documentation for IFG contradicts ifself. */
RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift)|0x03000000);
tp->CP_cur_rx = 0;
/*
//////////////////////////////////////////////////////////////
RTL_W8_F (Cfg9346, Cfg9346_Unlock);
RTL_W16 (NWayAdvert, AutoNegoAbility10half | AutoNegoAbility10full | AutoNegoAbility100half | AutoNegoAbility100full);
RTL_W16_F (BasicModeCtrl, AutoNegotiationEnable|AutoNegotiationRestart);
RTL_W8_F (Cfg9346, Cfg9346_Lock);
//////////////////////////////////////////////////////////////
*/
MediaStatusReg = RTL_R8(MediaStatus);
BasicModeCtrlReg = RTL_R16(BasicModeCtrl);
/* This is check_duplex() */
if (tp->phys[0] >= 0 || (tp->drv_flags & HAS_MII_XCVR))
{
u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
if (mii_reg5 == 0xffff)
; /* Not there */
else if ((mii_reg5 & 0x0100) == 0x0100
|| (mii_reg5 & 0x00C0) == 0x0040)
tp->full_duplex = 1;
/*
printk(KERN_INFO"%s: Setting %s%s-duplex based on"
" auto-negotiated partner ability %4.4x.\n", dev->name,
mii_reg5 == 0 ? "" :
(mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
tp->full_duplex ? "full" : "half", mii_reg5);
*/
printk(KERN_INFO"%s: Setting %s%s-duplex based on"
" auto-negotiated partner ability %4.4x.\n", dev->name,
(MediaStatusReg & Speed_10) ? "10mbps " : "100mbps ",
(BasicModeCtrlReg & DuplexMode) ? "full" : "half", mii_reg5);
}
if (tp->chipset >= CH_8139A)
{
tmp = RTL_R8 (Config1) & Config1Clear;
tmp |= Cfg1_Driver_Load;
tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
RTL_W8_F (Config1, tmp);
}
else
{
u8 foo = RTL_R8 (Config1) & Config1Clear;
RTL_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));
}
if (tp->chipset >= CH_8139B)
{
tmp = RTL_R8 (Config4) & ~(1<<2);
/* chip will clear Rx FIFO overflow automatically */
tmp |= (1<<7);
RTL_W8 (Config4, tmp);
/* disable magic packet scanning, which is enabled
* when PM is enabled above (Config1) */
RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));
}
RTL_W32 ( CPlusTxStartAddr, virt_to_bus(tp->TxDescArray) ); //C+ mode only
RTL_W32 ( CPlusRxStartAddr, virt_to_bus(tp->RxDescArray) ); //C+ mode only
/* Lock Config[01234] and BMCR register writes */
RTL_W8_F (Cfg9346, Cfg9346_Lock);
udelay (10);
RTL_W32_F (RxMissed, 0);
rtl8139_set_rx_mode (dev);
/* no early-rx interrupts */
RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16_F (IntrMask, rtl8139_intr_mask);
netif_start_queue (dev);
DPRINTK ("EXIT\n");
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void rtl8139CP_init_ring (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
int i;
DPRINTK ("ENTER\n");
//////////////////////////////////////////////////////////////////////////////
tp->CP_cur_rx = 0;
tp->CP_cur_tx = 0;
tp->CP_dirty_tx = 0;
memset(tp->TxDescArray, 0x0, NUM_CP_TX_DESC*sizeof(struct CPlusTxDesc));
memset(tp->RxDescArray, 0x0, NUM_CP_RX_DESC*sizeof(struct CPlusRxDesc));
for (i=0 ; i<NUM_CP_TX_DESC ; i++)
{
tp->Tx_skbuff[i]=NULL;
}
for (i=0; i <NUM_CP_RX_DESC; i++)
{
if(i==(NUM_CP_RX_DESC-1))
tp->RxDescArray[i].status = 0xC0000000+CP_RX_BUF_SIZE;
else
tp->RxDescArray[i].status = 0x80000000+CP_RX_BUF_SIZE;
tp->RxBufferRing[i]= &(tp->RxBufferRings[i*CP_RX_BUF_SIZE]);
tp->RxDescArray[i].buf_addr=virt_to_bus(tp->RxBufferRing[i]);
}
//////////////////////////////////////////////////////////////////////////////
DPRINTK ("EXIT\n");
}
static void rtl8139_tx_clear (struct rtl8139_private *tp)
{
int i;
tp->cur_tx = 0;
tp->dirty_tx = 0;
/* Dump the unsent Tx packets. */
for (i = 0; i < NUM_TX_DESC; i++)
{
struct ring_info *rp = &tp->tx_info[i];
if (rp->mapping != 0)
{
pci_unmap_single (tp->pci_dev, rp->mapping,
rp->skb->len, PCI_DMA_TODEVICE);
rp->mapping = 0;
}
if (rp->skb)
{
dev_kfree_skb (rp->skb);
rp->skb = NULL;
tp->stats.tx_dropped++;
}
}
}
static void rtl8139CP_tx_clear (struct rtl8139_private *tp)
{
int i;
tp->CP_cur_tx=0;
for (i=0 ; i<NUM_CP_TX_DESC ; i++)
{
if ( tp->Tx_skbuff[i]!=NULL )
{
dev_kfree_skb (tp->Tx_skbuff[i]);
tp->Tx_skbuff[i] = NULL;
tp->stats.tx_dropped++;
}
}
}
static void rtl8139_tx_timeout (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u8 tmp8;
DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
"media %2.2x.\n", dev->name,
RTL_R8 (ChipCmd),
RTL_R16 (IntrStatus),
RTL_R8 (MediaStatus));
/* disable Tx ASAP, if not already */
tmp8 = RTL_R8 (ChipCmd);
if (tmp8 & CmdTxEnb)
RTL_W8 (ChipCmd, tmp8 & ~CmdTxEnb);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */
spin_lock_irq (&tp->lock)
;
rtl8139_tx_clear (tp);
spin_unlock_irq (&tp->lock)
;
/* ...and finally, reset everything */
rtl8139_hw_start (dev);
netif_wake_queue (dev);
}
static void rtl8139CP_tx_timeout (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u8 tmp8;
printk ("%s: %s - Transmit timeout, status %2.2x %4.4x "
"media %2.2x.\n", dev->name, __FUNCTION__,
RTL_R8 (ChipCmd),
RTL_R16 (IntrStatus),
RTL_R8 (MediaStatus));
/* disable Tx ASAP, if not already */
tmp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -