2020-10-08

本文详细介绍了Linux CPSW网络设备驱动的工作原理,包括网络设备驱动架构、涉及的数据结构和主要操作,如初始化、打开与释放、数据发送与接收流程。此外,还探讨了TI公司CPSW以太网交换驱动的实现,包括匹配、注册和中断处理等功能。
摘要由CSDN通过智能技术生成

Linux cpsw网口驱动分析

  1. 网络设备驱动架构
    linux网络设备驱动程序的体系结构,依次为网络协议接口层,网络设备接口层,提供实际功能的设备驱动功能层以及网络设备与媒介层。
    网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是ARP,还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接受数据。
    网络设备接口层向协议接口层提供统一的用于描述具体网络属性和操作的结构体net_device,该结构体是设备驱动功能层中各函数的容器。
    设备驱动功能层的各函数是网络设备接口层net_device数据结构的具体成员,是驱使网络设备硬件完成相应动作的程序,它通过hard_start_xmit() 函数启动发送操作,并通过网络设备上的中断触发操作。
    网络设备与媒介层是完成数据包发送和接收的物理实体,包括网络适配器和具体的传输媒介,网络适配器被设备驱动功能层中的函数在物理上驱动。

  2. 网络设备驱动涉及的数据结构
    在设计具体的网络设备驱动时,需要完成的主要工作时编写设备驱动功能层的相关函数以填充net_device数据结构的内容并将net_device注册到内核。

struct net_device {
   
	char			name[IFNAMSIZ];
	struct hlist_node	name_hlist;
	char 			*ifalias;
	……
	struct phy_device *phydev;
	struct lock_class_key *qdisc_tx_busylock;
	bool proto_down;
};

网络设备的注册与注销由register_netdev()和unregister_netdev()函数完成。
net_device结构体的分配和网络设备驱动的注册需在网络设备驱动初始化是进行,而net_device结构体的释放和网络设备驱动的注销在设备或驱动被移除的时候执行。
net_device_ops结构体是网络设备的一系列硬件操作行数的集合。

struct net_device_ops {
   
    int         (*ndo_init)(struct net_device *dev);
    void            (*ndo_uninit)(struct net_device *dev);
    int         (*ndo_open)(struct net_device *dev);
    int         (*ndo_stop)(struct net_device *dev);
    netdev_tx_t     (*ndo_start_xmit)(struct sk_buff *skb,
                          struct net_device *dev);
    netdev_features_t   (*ndo_features_check)(struct sk_buff *skb,
                              struct net_device *dev,
                              netdev_features_t features);
    u16         (*ndo_select_queue)(struct net_device *dev,
                            struct sk_buff *skb,
                            void *accel_priv,
                            select_queue_fallback_t fallback);
    void            (*ndo_change_rx_flags)(struct net_device *dev,
                               int flags);
    void            (*ndo_set_rx_mode)(struct net_device *dev);
    int         (*ndo_set_mac_address)(struct net_device *dev,
                               void *addr);
    int         (*ndo_validate_addr)(struct net_device *dev);
    int         (*ndo_do_ioctl)(struct net_device *dev,
                            struct ifreq *ifr, int cmd);
    int         (*ndo_set_config)(struct net_device *dev,
                              struct ifmap *map);
    int         (*ndo_change_mtu)(struct net_device *dev,
                          int new_mtu);
    int         (*ndo_neigh_setup)(struct net_device *dev,
                           struct neigh_parms *);
    void            (*ndo_tx_timeout) (struct net_device *dev);

    struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev,
                             struct rtnl_link_stats64 *storage);
    struct net_device_stats* (*ndo_get_stats)(struct net_device *dev);

    int         (*ndo_vlan_rx_add_vid)(struct net_device *dev,
                               __be16 proto, u16 vid);
    int         (*ndo_vlan_rx_kill_vid)(struct net_device *dev,
                                __be16 proto, u16 vid);
#ifdef CONFIG_NET_POLL_CONTROLLER
    void                    (*ndo_poll_controller)(struct net_device *dev);
    int         (*ndo_netpoll_setup)(struct net_device *dev,
                             struct netpoll_info *info);
    void            (*ndo_netpoll_cleanup)(struct net_device *dev);
#endif

......

    int         (*ndo_get_lock_subclass)(struct net_device *dev);
    int         (*ndo_set_tx_maxrate)(struct net_device *dev,
                              int queue_index,
                              u32 maxrate);
    int         (*ndo_get_iflink)(const struct net_device *dev);
    int         (*ndo_change_proto_down)(struct net_device *dev,
                             bool proto_down);
    int         (*ndo_fill_metadata_dst)(struct net_device *dev,
                               struct sk_buff *skb);
    void            (*ndo_set_rx_headroom)(struct net_device *dev,
                               int needed_headroom);
};
  1. 网络设备的操作
    3.1 网络设备的初始化
    进行硬件上的准备工作,检查网络设备是否存在,如果存在,则检测设备所使用的硬件资源。进行软件接口上的准备工作,分配net_device结构体并对齐数据和函数指针成员赋值。获得设备的私有信息指针并初始化各成员的值,如果私有信息包括自旋锁或信号量等并发或同步机制,则需对其进行初始化。
    3.2网络设备的打开与释放
    网络设备的打开
    使能设备使用的硬件资源,申请I/O区域,中断和DMA通道等,调用linux内核提供的netif_start_queue()函数,激活设备发送队列.
    3.3网络设备关闭
    调用linux内核提供的netif_stop_queue()函数,停止设备传输包,释放设备所使用的I/O驱动,中断和DMA资源。
    3.4网络设备驱动包发送
    linux网络子系统在发送数据包时,会用驱动程序提供的hard_start_transmit()函数,该函数用于启动数据包的发送。在设备初始化的时候,这个函数指针需被初始化以指向设备的xxx_tx()函数。
    3.5数据包发送流程
    网络设备驱动程序从上层协议传递过来的sk_buff参数获得数据包的有效数据和长度,将有效数据放入临时缓冲区。对于以太网,如果有效数据的长度小于以太网冲突检测所要求数据帧的最小长度ETH_ZLEN,则给临时缓冲区的末尾填充0。设置硬件的寄存器,驱使网络设备进行数据发送操作。
    3.6数据接收流程
    网络设备接收数据的主要方法是由中断引发设备的中断处理函数,中断处理函数判断中断类型,如果为接收中断,则读取接收到的数据,分配sk_buffer数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区,并调用netif_rx()函数将sk_buffer传递给上层协议。
    3.7网络连接状态
    网络适配器硬件电路可以检测出链路上是否有载波,载波反映了网络的连接是
这是一个 SQL 语句,用于向借阅表中插入数据。该表包含以下字段:借阅编号、读者编号、书籍编号、借阅日期、归还日期、借阅状态。每条数据表示一次借阅记录。其中借阅编号、读者编号、书籍编号、借阅日期和借阅状态是必填项,归还日期为可选项,如果借阅状态为“已还”则必须填写归还日期。 具体插入的数据如下: - 借阅编号:100001,读者编号:123413,书籍编号:0001,借阅日期:2020-11-05,归还日期:NULL,借阅状态:借阅 - 借阅编号:100002,读者编号:223411,书籍编号:0002,借阅日期:2020-9-28,归还日期:2020-10-13,借阅状态:已还 - 借阅编号:100003,读者编号:321123,书籍编号:1001,借阅日期:2020-7-01,归还日期:NULL,借阅状态:过期 - 借阅编号:100004,读者编号:321124,书籍编号:2001,借阅日期:2020-10-09,归还日期:2020-10-14,借阅状态:已还 - 借阅编号:100005,读者编号:321124,书籍编号:0001,借阅日期:2020-10-15,归还日期:NULL,借阅状态:借阅 - 借阅编号:100006,读者编号:223411,书籍编号:2001,借阅日期:2020-10-16,归还日期:NULL,借阅状态:借阅 - 借阅编号:100007,读者编号:411111,书籍编号:1002,借阅日期:2020-9-01,归还日期:2020-9-24,借阅状态:已还 - 借阅编号:100008,读者编号:411111,书籍编号:0001,借阅日期:2020-9-25,归还日期:NULL,借阅状态:借阅 - 借阅编号:100009,读者编号:411111,书籍编号:1001,借阅日期:2020-10-08,归还日期:NULL,借阅状态:借阅
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值