操作系统:SylixOS
编程环境:RealEvo-IDE3.1
硬件平台:IMX6Q实验箱
《SylixOS网卡驱动框架篇》里提过,网卡驱动的收发功能是通过netdev结构里的transmit和receive两个成员实现的。本篇文章将介绍SylixOS里的LWIP协议栈是如何调用底层网卡驱动里的这两个成员函数的。
整个网卡驱动发送函数的调用关系如图 21所示。
网卡驱动在向SylixOS注册网卡驱动时,需要调用netdev_add函数,这个函数接收一个netdev结构的参数。因为在网卡驱动初始化过程中,已经在底层驱动里实现了netdev下的transmit和receive两个成员。所以netdev_add函数可以通过netdev这个参数找到驱动里的收发功能函数。
netdev_add函数里会调用netifapi_netif_add 来添加API函数,netifapi_netif_add接收的一个函数参数是netdev_netif_init。netifapi_netif_add函数最终会调用netdev_netif_init函数。
netdev_netif_init函数会把netdev_netif_linkoutput赋值给netif结构体下的linkoutput。netdev_netif_linkoutput的具体实现如程序清单 21 所示。
LWIP协议栈里最终调用到底层驱动时,就是通过netif的linkoutput实现的,如程序清单 21所示,netdev_netif_linkoutput会调用宏NETDEV_TRANSMIT,这个宏的实现如程序清单 22 所示。NETDEV_TRANSMIT会调用netdev里的transmit成员函数来进行数据包的发送。
程序清单 21 netdev_netif_linkoutput函数
/* lwip netif linkoutput hook function */ static err_t netdev_netif_linkoutput(struct netif *netif, struct pbuf *p) { netdev_t *netdev = (netdev_t*)(netif->state); int ret; #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); #endif ret = NETDEV_TRANSMIT(netdev, p); #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); #endif if (ret < 0) { return (ERR_IF); } return (ERR_OK); }
程序清单 22NETDEV_TRANSMIT
#define NETDEV_TRANSMIT(netdev, a) (netdev)->drv->transmit((netdev), a)
《SylixOS网卡驱动实现篇》里提到过,网卡驱动里的接收中断使用netdev_notify函数来通知协议栈已经收到数据,并让协议栈调用netdev的receive成员函数来进行接收报文的处理。
接收处理函数enetCoreRecv里接收两个参数,一个是netdev结构体,另一个是input类型的函数。
netdev_notify的具体实现如程序清单 23 所示,里面会通过q_en这个参数来决定是否使用队列的方式来接收,如果不使用,则直接调用宏NETDEV_RECEIVE,否则通过netJobAdd把接收处理函数添加到队列中。不管哪一种方式,最后都会调用netdev下的receive成员函数,而receive的第二个input类型的参数就是程序清单 23 中的netdev_netif_linkinput。
因此,底层驱动的接收处理函数会通过netdev_netif_linkinput把网卡收到的数据一层层的传到协议栈中去进行对应的处理。
程序清单 23 netdev_notify函数
/*if netdev detected a packet in netdev buffer, driver can callthis function to receive this packet. notify:0 can transmit 1: can receive qen:0 do not use netjob queue1:use netjob queue */ int netdev_notify (struct netdev *netdev,netdev_inout inout, int q_en) { if (!netdev || (netdev->magic_no !=NETDEV_MAGIC)) { return (-1); } if (inout != LINK_INPUT) { return (0); } if (q_en) { if (netJobAdd(netdev->drv->receive,netdev, (void*)netdev_netif_linkinput, 0, 0, 0, 0) == 0) { return (0); } else { return (-1); } } NETDEV_RECEIVE(netdev,netdev_netif_linkinput); return (0); }
无
本文出自 “11451177” 博客,请务必保留此出处http://11461177.blog.51cto.com/11451177/1914772
原文地址:http://11461177.blog.51cto.com/11451177/1914772