Linux-2.6.20的cs8900驱动分析(三)

news/2024/11/16 18:30:28/

本博客转载于:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=22535114&id=1773576


三、net_rxnet_send_packet
3.1 net_rx
在这部分将介绍cs8900驱动的两个最重要的函数,内核通过该两个函数实现了数据的收发。net_rx函数的主要功能是从cs8900的片上数据缓冲区中将数据传送给sk_buff缓冲区,sk_buff是网络驱动程序与Linux内核通信的缓冲区。该结构可在\include\linux\skbuff.h中找到。net_rx函数的功能可总结如下:(该总结来源于:http://www.akae.cn/bbs/archiver/?tid-6657.html
A.获取私有数据存放于lp中;
B.获取设备缓冲区状态和缓冲长度;
C.如果状态不为RX_OK则计数接收数据错误次数count_rx_error()
D.分配一个sk_buf区间
E.字对齐,skb_reserve()
F.插入数据到接收口,insw()
G.写入数据;
H.初始化sk_buff结构,eth_type_trans()
I.进入上层接收函数netif_rx()
J.初始化设备的计数;
 
net_rx函数的注解如下所示:
static void net_rx(struct net_device *dev)
{
       struct net_local *lp = netdev_priv(dev);             //lp指向驱动程序的私有数据区
       struct sk_buff *skb;                             //申请skb_buff指针
       int status, length;
 
       int ioaddr = dev->base_addr;                       // 得到cs8900的基地址
       status = readword(ioaddr, RX_FRAME_PORT);       //获取cs8900片上缓冲区的状态
       length = readword(ioaddr, RX_FRAME_PORT);       //获取cs8900片上缓冲区的长度
 
       if ((status & RX_OK) == 0) {    //状态为接收错误,调用count_rx_errors统计错误
              count_rx_errors(status, lp);
              return;
       }
 
       /* Malloc up new buffer. */
       skb = dev_alloc_skb(length + 2);             //分配一个缓冲区,dev_alloc_skb函数以
                   //GFP_ATOMIC 优先级调用alloc_skballoc_skb的功能为分配一个缓冲区
                   //并初始化skb->dataskb->tailskb_head 域。dev_alloc_skballoc_skb的区
                   //别为,前者在skb->dataskb_head之间保留了一些空间,网络 层使用这
                   //一数据空间进行优化工作,驱动程序不该访问该空间。
       if (skb == NULL) {    //skb缓冲区分配失败?
……
              lp->stats.rx_dropped++;  //直接将丢包数加1
              return;
       }
       skb_reserve(skb, 2);      /* longword align L3 header */    //该函数增加skbdatatail
               //该函数可填充缓冲区之 前保留报文头空间,大多数以太网在数据包之前
               //保留2个字节,这样IP头可在14字节的以太网头之 后,在16字节边界上对
               //齐。这里也空了两个字节,这两个自己加上14字节的以太网头刚好16
              //节。 所以这里的主要作用是字对齐。
       skb->dev = dev;
 
       readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);  //skb_put
            //数的作用是更新skb taillen成员,也即在缓冲区尾部添加数据,该函数返
            //skb->tail的先前值。整句代码的含义为, cs8900的数据缓冲区中读取
      //length个字节数据到skb缓冲区。由于readwords是以读取字(两个字 节)为
            //单位,所以length应该保持字对齐,也即length右移一位。
       if (length & 1)       //因为前面length以字对齐,如果length为单字节,
                                   //所以这里应该补上最后一个字节
              skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
……
        skb->protocol=eth_type_trans(skb,dev);  //该函数定义在 linux/net/ethernet/eth.c 中,
                                                 //该处可参见linux设备 驱动程序相关章节
       netif_rx(skb);       //通知内核已经接收到一个数据包,并封装入一个套接字缓冲区
       dev->last_rx = jiffies;                    //更新最后的接收包时间
       lp->stats.rx_packets++;                //接收的总数据包数加1
       lp->stats.rx_bytes += length;         //接收的字节数加上length
}
 
3.1 net_send_packet
       net_send_parcket为内核提供了数据包发送功能,该函数在cs89x0_probe1中被赋予了net_devicehard_start_xmit域,当内核需要发送数据包时,将调用dev-> hard_start_xmit完成最后的数据包发送。该函数被调用的前提是,在调用该函数之前,内核已经将数据包放入了skb缓冲区中。该函数的主要任务有:
A.获取设备私有数据指针
B.加环形锁,spin_lock_irq()
C.检测缓冲区是否为满,若满则调用netif_stop_queue()暂停发送队列;
D.写发送命令和发送长度,writeword()
E.读取发送总线状态readreg()
F.解环形锁,spin_unlock_irq()
G.设置传输时钟计数;
H.释放相应sk_buff, dev_kfree_skb().
下面为此函数的简单注释:
static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
       struct net_local *lp = netdev_priv(dev);            //获得驱动程序的私有数据
 
……
 
       spin_lock_irq(&lp->lock);         //获得自旋锁,以便进入临界区
       netif_stop_queue(dev);    //通知内核暂停内核与驱动程序间的数据传递,也即告诉
                                              //内核不要向skb缓冲区填充数据。
 
       /* initiate a transmit sequence */  //初始化cs8900的发送对列,主要为写命令和数
                                                         //据长度,为数据发送做准备
       writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
       writeword(dev->base_addr, TX_LEN_PORT, skb->len);
 
       /* Test to see if the chip has allocated memory for the packet * /       //查看cs8900是否为
                                                                                      //发送分配了地址空间。
       if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
           …….
              spin_unlock_irq(&lp->lock);
              if (net_debug) printk("cs89x0: Tx buffer not free!\n");
              return 1;
       }
       /* Write the contents of the packet */
       writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);   //将数
                                                                                                               //据交给cs8900发送
       spin_unlock_irq(&lp->lock);         //发送结束,释放自旋锁
       lp->stats.tx_bytes += skb->len;    //累加发送的总字节数
       dev->trans_start = jiffies;             //更新最后的传输时间
       dev_kfree_skb (skb);                  //发送完毕,释放skb缓冲区
    ……
       return 0;
}
总结:
       cs8900驱动中,主要简解了驱动程序中的部分重要函数,包括初始化、打开/关闭网络驱动和发送/接收数据。对于其余的驱动程序代码,如超时处理、状态获取等函数没做解释,它们的实现也比较简单。由于自己板子上没有EEPROM,所以也没有分析与EEPROM相关部分的代码。DMA部分好像编译进去会错,所以也没有去分析,以后有时间再去弄弄DMA部分。


http://www.ppmy.cn/news/249137.html

相关文章

CS8900A网络驱动程序移植

上图为开发板上的网卡原理图,可得到: 1.CS8900A的访问基址为0x19000000 2.总线位宽为16 3.中断引脚为EINT9 驱动文件drivers/net/cs89x0.c既可以编进内核,也可以编译为一个可加载模块。编译进内核时,它的入口函数为cs89x0_pro…

LT8900低成本的无线电收发器 2.4G射频芯片 CMOS射频收发器

LT8900低成本的2.4GHz无线电收发器 概述 LT8900是一个低成本,完全集成CMOS射频收发器,GFSK数据调制解调器,和数据包框架,优化用于中GHz ISM波段。 它包含发射接收射频合成器,和数字调制解调器功能,少数外…

中兴服务器售后,中兴全兼容智能视讯服务器ZXMVC8900

全兼容智能视讯服务器ZXMVC8900 中兴全兼容智能视讯服务器ZXMVC8900采用电信交换机架构设计,全面支持ITU-T H.323、H.320协议,可通过不同网络(IP、ISDN、DDN、SDH、ATM、卫星等)接入用户终端,并组织召开视频会议。 XMVC8900具有全兼容各种网络…

STM32驱动JQ8900语音模块

上次写了esp32驱动JQ8900模块,我做设计一般会把外设先在esp32上实现一般,再移植到比较复杂的stm32上去。直接上正常运行的干货代码。 文章目录 一、硬件准备二、程序编写1.jq8900.c2.jq8900.h3.main.c 三、音频替换总结 一、硬件准备 STM32F10x系列任意…

Linux 下 cs8900a 的移植说明

Linux 下 cs8900a 的移植说明 为 cs8900a 建立编译菜单 1. 拷贝到文件把 cs8900a 的压缩包拷贝到 arm 用户下的 dev_home/localapps/ [armlocalhost localapps]$ tar xzvf cs8900a.tar.gz [armlocalhost localapps]$cd cs8900a [armlocalhost cs8900a]$cp cs8900a.c $KERNEL/l…

LD3320语音识别模块+JQ8900-TF语音模块实现简单的语音交互控制

玩这个真的要感谢头条的强大推荐,清明节回家的大巴车上,无聊的刷着头条,很智能的给我推荐了一款语音识别模块,一直很想自己试着玩一把的我,按奈不住,点开视频看到了介绍,接着我就淘宝一下&#…

八重州8900如何解锁_八重贵族怪胎之路

八重州8900如何解锁 Dealing with computers day in and day out can be a harrowing experience. In difficult times, or even when things are idle, finding some spirituality can help cope with the experience—Techies: I give you the Eightfold Noble Geek Path. 日…

stm32通过 一线串口通信控制JQ8900-16P语音模块

今天玩玩语音模块,用到了所谓的一线串口通信(就是用一个IO口发脉冲)不说了,上代码 JQ8900-16P语音模块资料自取:链接:https://pan.baidu.com/s/1O3P1Ro4Rc4cVMACuJVdqaA 提取码:1u4p 接线&a…