📄 haison.c
字号:
配的内存的实际的物理地址*/
tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN, &tp->tx_bufs_dma);
tp->rx_ring = pci_alloc_consistent( tp->pci_dev, RX_BUF_TOT_LEN, &tp->rx_ring_dma);
if((!tp->tx_bufs)||(!tp->rx_ring))
{
free_irq(dev->irq, dev);//释放申请的设备中断号
if(tp->tx_bufs)
{
pci_free_consistent(tp->pci_dev,TX_BUF_TOT_LEN, tp->tx_bufs, tp->tx_bufs_dma);
tp->tx_bufs = NULL;
}
if(tp->rx_ring)
{
pci_free_consistent(tp->pci_dev,RX_BUF_TOT_LEN, tp->rx_ring, tp->rx_ring_dma);
tp->rx_ring = NULL;
}
return -ENOMEM;
}
tp->tx_flag = 0;//(TX_FIFO_THRESH << 11) & 0x003f0000;
rtl8139_init_ring(dev);//初始化收包和发包的缓冲区
rtl8139_hw_start(dev);//初始化硬件
printk("<1>============rtl8139_open function end============\n");
return 0;
}
/////////////////////////////////////////////////
// //
// 为rtl8139四个发送寄存器(描述符) //
// 指定相应的内存空间 //
// //
/////////////////////////////////////////////////
static void rtl8139_init_ring (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
int i;
printk("<1>============rtl8139_init_ring function called============\n");
tp->cur_tx = 0;
tp->dirty_tx = 0;
tp->cur_rx = 0;///////////////////////add////////////////
for (i = 0; i < NUM_TX_DESC; i++)
tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
printk("<1>============rtl8139_init_ring function end============\n");
}
/////////////////////////////////////////////////
// //
// rtl8139进行发送数据包前的操作 //
// //
/////////////////////////////////////////////////
static void rtl8139_hw_start (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
u32 i;
u8 tmp;
printk("<1>============rtl8139_hw_start function called============\n");
/*对芯片进行复位*/
rtl8139_chip_reset(ioaddr);
/*向命令寄存器中写入发送接收使能命令字*/
RTL_W8(CR,CmdTxEnb|CmdRxEnb);
/*接收寄存器设置 */
writel(((1<<12)|(7<<8)|(7<<13)|(1<<7)|(1<<3)|(1<<2)|(1<<1)), ioaddr + RCR);
/* 发送寄存器设置*/
RTL_W32(TCR,0x00000600);//DMA burst size 1024,发送失败时,重发16次
tp->cur_rx = 0;/////////////add//////////////////
/* init Rx ring buffer DMA address */
RTL_W32_F (RBSTART, tp->rx_ring_dma);
/* init Tx buffer DMA addresses */
for(i=0;i<NUM_TX_DESC;i++)
RTL_W32_F(TSAD0 + (i * 4),tp->tx_bufs_dma + (tp->tx_buf[i]-tp->tx_bufs));
/* initialize missed packet counter */
writel(0, ioaddr + MPC);
/* no early-rx interrupts */
writew((readw(ioaddr + MULINT) & 0xF000), ioaddr + MULINT);
/* make sure RxTx has started */
tmp = RTL_R8 (CR);
if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb)))
RTL_W8 (CR, CmdRxEnb | CmdTxEnb);
/*向中断屏蔽寄存器内写入由芯片产生的中断*/
RTL_W16(IMR,INT_MASK);
netif_start_queue (dev);//通知内核芯片已经准备好,可以发送数据包了
printk("<1>============rtl8139_hw_start function end============\n");
}
///////////////////////////////////////////////////
// //
// rtl8139芯片复位操作 ,通过向控制寄存器(CR) //
// 写置位值实现 //
// //
///////////////////////////////////////////////////
static void rtl8139_chip_reset (void *ioaddr)
{
int i;
printk("<1>============rtl8139_chip_reset function called============\n");
/* 向芯片内写入置位值,使其处于发送状态*/
writeb(CmdReset, ioaddr + CR);
// RTL_W8(CR,CmdReset);
/* 通过读出写入的值检查芯片是否真的完成了复位 */
for (i = 1000; i > 0; i--)
{
barrier();//强迫内核立即进行I/O操作
if ((readb(ioaddr + CR) & CmdReset) == 0) break;
//if((RTL_R8(CR)&CmdReset)==0)break;
udelay (10);
}
printk("<1>============rtl8139_chip_reset function end============\n");
}
//////////////////////////////////////
// 中断函数 //
// //
//////////////////////////////////////
static void rtl8139_interrupt(int irq,void *dev_instance,struct pt_regs *regs)
{
struct net_device *dev = (struct net_device*)dev_instance;
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
unsigned short isr = readw(ioaddr + ISR);
printk("<1>============rtl8139_interrupt function called============\n");
writew(0xffff, ioaddr + ISR);
if((isr & TxOK) || (isr & TxErr)) //如果发送完毕或者是发送错误
{
while((tp->dirty_tx != tp->cur_tx) || netif_queue_stopped(dev))
{
unsigned int txstatus = readl(ioaddr + TSD0 + tp->dirty_tx * sizeof(int));
if(!(txstatus & (TxStatOK | TxAborted | TxUnderrun)))
break; /* yet not transmitted */
if(txstatus & TxStatOK)
{
printk("Transmit OK interrupt\n");
tp->stats.tx_bytes += (txstatus & 0x1fff);//统计发送的总的字节数
tp->stats.tx_packets++;//统计发送的包数
}
else
{
printk("Transmit Error interrupt\n");
tp->stats.tx_errors++;//统计发送的包的错误数
}
tp->dirty_tx++;
tp->dirty_tx = tp->dirty_tx % NUM_TX_DESC;
if((tp->dirty_tx == tp->cur_tx) & netif_queue_stopped(dev))
{
printk("waking up queue\n");
netif_wake_queue(dev);
}
}
}
if(isr & RxErr)
{
printk("receive err interrupt\n");
tp->stats.rx_errors++;
}
if(isr & RxOK)
{
printk("receive interrupt received\n");
while((RTL_R8(CR) & RxBufEmpty) == 0)
{
u32 rx_status;
unsigned short rx_size;
unsigned short pkt_size;
struct sk_buff *skb;
if(tp->cur_rx > RX_BUF_LEN)
tp->cur_rx = tp->cur_rx % RX_BUF_LEN;
/* TODO: need to convert rx_status from little to host endian*/
rx_status = le32_to_cpu(*(u32 *)(tp->rx_ring + tp->cur_rx));
rx_size = rx_status >> 16;
/* first two bytes are receive status register
* and next two bytes are frame length
*/
pkt_size = rx_size-4;
/* hand over packet to system */
skb = dev_alloc_skb (pkt_size + 2);//分配一个包
if (skb)
{
skb->dev = dev;
skb_reserve (skb, 2); //修改包头空间
eth_copy_and_sum (skb, &(tp->rx_ring[tp->cur_rx + 4]), pkt_size, 0);
skb_put (skb, pkt_size);//加入数据到包中
skb->protocol = eth_type_trans (skb, dev);//解析包的协议
netif_rx (skb);//把包送到协议层
dev->last_rx = jiffies;//记录收包时间
tp->stats.rx_bytes += pkt_size;//收到包的字节数加1
tp->stats.rx_packets++;//收到包的包数加1
}
else
{
printk("Memory squeeze, dropping packet.\n");
tp->stats.rx_dropped++;
}
/* update tp->cur_rx to next writing location */
tp->cur_rx = (tp->cur_rx + rx_size + 4 + 3) & ~3;
/* update CAPR */
writew(tp->cur_rx-16, ioaddr + CAPR);
if (RTL_R16 (ISR) & RxAckBits)
RTL_W16_F (ISR, RxAckBits);
}
}
if(isr & CableLen)
printk("cable length change interrupt\n");
if(isr & TimeOut)
printk("time interrupt\n");
if(isr & SysErr)
printk("system err interrupt\n");
printk("<1>============rtl8139_interrupt function end============\n");
}
///////////////////////////////////////////////////
// //
// rtl8139开始进行数据包的发送 //
// //
///////////////////////////////////////////////////
static int rtl8139_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
unsigned int entry = tp->cur_tx;
unsigned int len = skb->len;
printk("<1>============rtl8139_start_xmit function called============\n");
if (len < TX_BUF_SIZE)
{
/*如果有一个数据包的长度小于60则仍以60的长度填充*/
if(len < ETH_MIN_LEN)
memset(tp->tx_buf[entry], 0, ETH_MIN_LEN);
/*将数据包拷贝到可以进行DMA传送的内存*/
skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
dev_kfree_skb(skb);
}
else {
dev_kfree_skb(skb);
tp->stats.tx_dropped++;
return 0;
}
RTL_W32_F(TSD0+(entry*sizeof(u32)),tp->tx_flag|max(len,(unsigned int)ETH_MIN_LEN));
dev->trans_start = jiffies;
entry++;
tp->cur_tx = entry % NUM_TX_DESC;//循环转入下一个发送寄存器
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)//如果发送缓冲区已满,则停止发送
netif_stop_queue(dev);
printk("<1>============rtl8139_start_xmit function end============\n");
return 0;
}
/////////////////////////////////////////////////
// //
// ifconfig rtl8139 down 时调用 //
// //
/////////////////////////////////////////////////
static int rtl8139_stop(struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
int ret = 0;
unsigned long flags;
printk("<1>================rtl8139_stop is called===============\n");
netif_stop_queue(dev);//通知内核停止传送
/*停止芯片的发送和接收的DMA处理过程*/
RTL_W8(CR, 0);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16(IMR, 0);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32(MPC);
RTL_W32(MPC, 0);
synchronize_irq ();
free_irq(dev->irq, dev);
rtl8139_tx_clear(tp);
pci_free_consistent(tp->pci_dev,RX_BUF_TOT_LEN, tp->rx_ring, tp->rx_ring_dma);
pci_free_consistent(tp->pci_dev,TX_BUF_TOT_LEN, tp->tx_bufs, tp->tx_bufs_dma);
tp->rx_ring = NULL;
tp->tx_bufs = NULL;
printk("<1>================rtl8139_stop end==============\n");
return 0;
}
////////////////////////////////////////////////
// //
// 清除在 tp->stats.tx_dropped的 Tx packets //
// //
////////////////////////////////////////////////
static void rtl8139_tx_clear(struct rtl8139_private *tp)
{
tp->cur_tx = 0;
tp->dirty_tx = 0;
}
/////////////////////////////////////////////////
// //
// 保存接口的一些统计信息,ifconfig -a时调用 //
// //
/////////////////////////////////////////////////
static struct net_device_stats *rtl8139_get_stats(struct net_device *dev)
{
printk("rtl8139_get_stats is called for the %d times\n",++counter);
struct rtl8139_private *tp = dev->priv;
return &(tp->stats);
}
//////////////////////////////////////////////
// //
// 卸载模块时调用该函数 //
// 命令:rmmod rtl8139 //
// //
//////////////////////////////////////////////
static void rtl8139_rmmod(void)
{
struct rtl8139_private *tp;
tp = rtl8139_dev->priv;
iounmap(tp->mmio_addr);//取消地址映射
pci_release_regions(tp->pci_dev);//释放PCI资源
unregister_netdev(rtl8139_dev);//在全局表中注销设备
//kfree(rtl8139_dev); //释放网络设备
pci_disable_device(tp->pci_dev);//停用PCI设备
//pci_set_drvdata(pdev, NULL); //PCI设备中的设备指针赋空
}
///////////////////////////////////////////////
// //
// 版权等相关描述信息 //
// 加载卸载模块 //
///////////////////////////////////////////////
MODULE_AUTHOR("xaut xi'an shaan'xi china Haison");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("The driver for rtl8139 under linux");
module_init(rtl8139_insmod); //驱动模块的加载
module_exit(rtl8139_rmmod);//驱动模块的卸载
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -