Board logo

标题: 嵌入式Linux网络驱动程序的开发及实现原理 03 [打印本页]

作者: samwalton    时间: 2013-10-18 14:43     标题: 嵌入式Linux网络驱动程序的开发及实现原理 03

 2.3.2打开(或关闭)网络设备
  系统响应ifconfig命令时,打开(关闭)一个网络接口。ifconfig命令开始会调用ioctl(SIOCSIFADDR)来将地址赋予接口。响应SIOCSIFADDR由内核来完成,与设备无关。接着,ifconfig命令会调用ioctl(SIOCSIFFLAGS)设置dev->flag的IFF_UP位来打开设备,这个调用会使设备的open方法得到调用。(当ifconfig调用ioctl(SIOCSIFFLAGS)清除dev->flag的IFF_UP位时,设备的stop方法将被调用)
  实例中利用cs8900_start()函数打开网络设备,主要完成的工作:
  a.通过set_irq_type()向内核注册网络设备的中断处理程序;
  b.通过cs8900_set()设置CS8900A网卡中各控制寄存器和配置寄存器;
  c.通过内核中netif_start_queue()函数开启网络接口的数据传输队列;
  2.3.3网络数据包的发送
  数据包的发送和接收是网络驱动程序中实现的两个最重要的任务。当网络设备被激活时,net_device结构中的open方法被调用,它负责打开设备并调用net_device结构中的hard_header函数指针建立硬件帧头信息。最后通过函数dev_queue_xmit()来调用net_device结构中的hard_start_xmit方法把存放在sk_buff中的数据发送到网络物理设备。如果发送成功,则在hard_start_xmit中释放sk_buff并返回0;如果硬件设备忙暂时无法处理,则返回1。网络硬件在发送完数据包后会产生中断,把dev->tbusy置0,通知系统可以再次发送。
  实例中,hard_start_xmit方法即为网络设备数据发送函数cs8900_send_start(),该函数实现把数据发送到以太网上,由网络协议接口层函数dev_queue_xmit()对其调用。cs8900_send_start()中主要完成的工作:
  a.发送数据前关闭中断,中止网络设备的数据传输队列;
  b.向CS8900A寄存器TxCMD中写入传送数据命令控制字,向寄存器TxLength中写入待发送数据帧长度;
  c.通过cs8900_read()反复读取CS8900A总线状态寄存器BusST信息,直到其已经准备好接收来自主机的数据;
  d.调用cs8900_frame_write()将待发数据送入CS8900A的sk_buff中,硬件设备会将数据帧发送到以太网上;
  e.记录数据帧的发送时刻,打开中断,释放sk_buff缓存,函数返回0;
  2.3.4网络数据包的接收和中断处理
  网络设备是异步地接收外来的数据包并且主动的“请求”将硬件获得的数据包压入内核。网络设备接收数据包是通过中断实现的。对于网络接口,接收到新数据包,发送完成或者报告错误信息及连接状态等都会触发中断,通常中断处理程序通过检测硬件状态寄存器判断是哪种情况。

  当设备收到数据后会产生一个中断,由硬件通知驱动程序有数据包到达。在中断处理程序中驱动程序申请一块sk_buff(一般定义为skb)缓冲区,然后从硬件读出数据放到申请好的缓冲区里,接下来填充sk_buff中的部分信息:包括接收到数据的设备结构体指针填入skb->dev;收到数据帧的类型填入skb->protocol;把指针skb->mac.raw指向硬件数据并丢弃硬件针头(skb_pull);设置skb->pkt_type,标明链路层数据类型。最后调用协议接口层函数netif_rx() 把接收到的数据包传输到网络上层协议处理。这里,netif_rx()只是负责把数据放入工作队列就返回,真正的处理是在中断返回以后,这样可减少中断处理的时间。几乎每个中断处理程序的编写都要涉及底半部机制,这样可以保证中断的高效处理。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0