热门关键字:  ubuntu  分区  Fedora  linux系统进程  函数

当前位置 :| 主页>Linux教程>内核研究>

学习内核---Linux网卡驱动分析

来源: 作者: 时间:2008-03-05 Tag: 点击:

  ④判断发送缓存是否已经满了,如果满了在发就覆盖数据了,要停发。
  if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
  netif_stop_queue (dev);
  谈完了发送,我们开始谈接收,当有数据从网线上过来时,网卡产生一个中断,调用的中断服务程序是rtl8139_interrupt,它主要做了三件事。
  ①从网卡的中断状态寄存器中读出状态值进行分析,status = readw(ioaddr+IntrStatus);
  if ((status &(PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
  RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
  goto out;
  上面代码说明如果上面这9种情况均没有的表示没什么好处理的了,退出。
  ② if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver))/* Rx interrupt */
  rtl8139_rx_interrupt (dev, tp, ioaddr);
  如果是以上4种情况,属于接收信号,调用rtl8139_rx_interrupt进行接收处理。
  ③ if (status & (TxOK | TxErr)) {
  spin_lock (&tp->lock);
  rtl8139_tx_interrupt (dev, tp, ioaddr);
  spin_unlock (&tp->lock);
  }
  如果是传输完成的信号,就调用rtl8139_tx_interrupt进行发送善后处理。
  下面我们先来看看接收中断处理函数rtl8139_rx_interrupt,在这个函数中主要做了下面四件事
  ①这个函数是一个大循环,循环条件是只要接收缓存不为空就还可以继续读取数据,循环不会停止,读空了之后就跳出。
  int ring_offset = cur_rx % RX_BUF_LEN;
  rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
  rx_size = rx_status >> 16;
  上面三行代码是计算出要接收的包的长度。
  ②根据这个长度来分配包的数据结构
  skb = dev_alloc_skb (pkt_size + 2);
  ③如果分配成功就把数据从接收缓存中拷贝到这个包中
  eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
  这个函数在include/linux/etherdevice.h中,实质还是调用了memcpy()。
  static inline void eth_copy_and_sum(struct sk_buff*dest, unsigned char *src, int len, int base)
  {
  memcpy(dest->data, src, len);
  }
  现在我们已经熟知,&rx_ring[ring_offset + 4]就是接收缓存,也是源地址,而skb->data就是包的数据地址,也是目的地址,一目了然。
  ④把这个包送到Linux协议栈去进行下一步处理
  skb->protocol = eth_type_trans (skb, dev);
  netif_rx (skb);
  在netif_rx()函数执行完后,这个包的数据就脱离了网卡驱动范畴,而进入了Linux网络协议栈里面,把这些数据包的以太网帧头,IP 头,TCP 头都脱下来,最后把数据送给了应用程序,不过协议栈不再本文讨论范围内。netif_rx函数在net/core/dev.c,中。
  而rtl8139_remove_one则基本是rtl8139_init_one的逆过程。
  到此,本文已经将Linux驱动程序的框架勾勒了出来。


相关文章:
精通initramfs构建step by step
Linux利用kexec迅速切换内核
进程上下文VS中断上下文
内核通知链 学习笔记
linux spi子系统驱动分析
menuconfig 配置选项
《Linux操作系统内核实习》之练习一
udev详解
什么叫微内核,宏内核?
Linux 信号signal处理机制
开发简单的 Linux2.6 内核模块
删除内核的perl脚本
Linux2.6内核usb gadget驱动移植
GCC hacks in the Linux kernel
iomem
kernel学习的想法
让自己的驱动支持udev
linux内核编译步骤
内核的等待队列
Linux内核wait_queue深入分析
升级和删除内核
SD卡驱动分析2
Linux Kernel VDSO本地权限提升漏洞
内核中的TCP的追踪分析-15-TCP(IPV4)的客户端与
linux 2.6内核可加载模块的编译
内核模块HelloWorld
在环回接口上发送一个数据报
ARP初始化
1分钟编译FreeBSD内核
linux设备模型之uart驱动架构分析