⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 haison.c

📁 8139网卡驱动 for linux/unix 只针对2.4内核 其他内核不保证可用
💻 C
📖 第 1 页 / 共 2 页
字号:
    配的内存的实际的物理地址*/
	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 + -