首页 > 代码库 > 网卡驱动

网卡驱动

Platform架构的驱动程序便于移植和管理

易变得内容都放在了device

Driver如果需要使用这些易变得内容,统统从device获得。

-------

网卡设备驱动

1.内核中关于网卡设备相关的框架

 

 

技术分享

 

 

网卡设备驱动工作于网络接口层

 

 技术分享

1.1核心数据结构:structnet_device{

   base_addr   I/O基地址

Irq /**/中断号

Net_device_ops  /*网卡设备操作函数集合*/

{

    Ndo_start_xmit  发送函数

}

Alloc_etherdev(....) //申请net_device空间

Register_netdev(...)注册

Unregister_net_device注销

1.2网卡的数据的收发函数   

Ando_start_xmit  发送函数

Net_device *dev指定你哪块网卡发送数据   根据 IP

B)接收函数

  将网卡芯片中收到数据拷贝到DDRAM,形成一个struct sk_buff结构

  然后调用netif_rx...,驱动程序中的接收工作就算完成了

  

1.3struct sk_buff()结构,驱动层发送数据,提交数据的基本数据单位

{   *data

}

 

 

释放 sk_buff dev_free_skb(....)

申请 dev_alloc_skb(...)

 

技术分享

 

 

 

 

有一块网卡在内核中就需要实例化一个struct net_device

 

struct net_device {

 

/*

 * This is the first field of the "visible" part of this structure

 * (i.e. as seen by users in the "Space.c" file).  It is the name

 * of the interface.

 */

charname[IFNAMSIZ];

 

struct pm_qos_request_list pm_qos_req;

 

/* device name hash chain */

struct hlist_nodename_hlist;

/* snmp alias */

char *ifalias;

 

/*

 *I/O specific fields

 *FIXME: Merge these and struct ifmap into one

 */

unsigned longmem_end;/* shared mem end*/

unsigned longmem_start;/* shared mem start*/

unsigned longbase_addr;/* device I/O address*/

unsigned intirq;/* device IRQ number*/

 

/*

 *Some hardware also needs these fields, but they are not

 *part of the usual set specified in Space.c.

 */

 

unsigned longstate;

 

struct list_headdev_list;

struct list_headnapi_list;

struct list_headunreg_list;

。。。

中的

name

 

 

 

 

 

 

 

2.虚拟网卡的设备的设备驱动

 

2.虚拟网卡的设备驱动

#include <linux/netdevice.h>

#include <linux/etherdevice.h>

申请net_device

Xxxx=alloc_etherdev0);

 

设置 net_device    xx->netdev_ops = &xxxxx_ops;

注册net_device    register_netdev

 

Struct   net_device_ops xxxxx_ops =

{

    进一步初始化

   .ndo_init =xxxx,

    .ndo_open = xxxx_open,

    .ndo_start_xmit =xxxxx_xmit,

 

};

 

 

Int xxxx_init(struct net_devicer *dev)

{

  /*和以太网相关的进一步初始化

  ether_setup();

  strcpydev->name,“xxxxx”)

}

 

int xxxx_open(struct net_devicer *dev)

{}

int xxxxx_xmit(struct sk_buff *skb, struct net_device *dev)

{

   printk();

/* 通过硬件发送数据*/

 

 

 

/* 释放传入的skb空间*/

dev_kfree_skb();

}

 

 

 

注销unregister_netdev

Free_netdev()

 

 模块安装完后ifconfig -a 会有个 “”名字

ifconfig xxx(名字) IP地址

 

 

示例代码:

#include <linux/init.h>

#include <linux/module.h>

#include <linux/netdevice.h>

#include <linux/etherdevice.h>

 

 

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("Songmao");

 

#define NETDEV_NAME "eth_first"

 

static struct net_device *virtua_card;

 

 

 

static int virtua_card_init(struct net_device *dev)

{

      printk(KERN_INFO"Netdriv:Entry virtua_card_init");

 

  ether_setup(dev);

  strcpy(dev->name,NETDEV_NAME);

  return 0;

  

}

 

static int virtua_card_open(struct net_device *dev)

{

      printk(KERN_INFO"Netdriv:Entry virtua_card_open");

  return 0;

}

 

static int virtua_card_stop(struct net_device *dev)

{

      printk(KERN_INFO"Netdriv:Entry virtua_card_stop");

  return 0;

}

 

struct net_device_ops virt_netdev_ops = {

      .ndo_init = virtua_card_init,

  .ndo_open = virtua_card_open,

  .ndo_stop = virtua_card_stop,


};

 

static int __init init_netdriv(void)

{

     int ret = 0;

    

     printk(KERN_ERR"Netdriv:Entry netdriv ...");

 

     virtua_card = alloc_etherdev(0);//0 表示 100字节+0字节

     if(virtua_card==NULL)

     {

          printk(KERN_ERR"Netdriv:Fail for alloc_etherdev");

 return -1;

     }

 printk(KERN_INFO"Netdriv:Success for alloc_etherdev");

 

 virtua_card->netdev_ops = &virt_netdev_ops;

 virtua_card->dev_addr[0] = 0x08;

 

 ret = register_netdev(virtua_card);

 if(ret<0)

 {

      printk(KERN_ERR"Netdriv:Fail for  register_netdev ");

 

 goto fail_register_netdev;

 }

     printk(KERN_INFO"Netdriv:Success for register_netdev ");

 

 return 0;

 

fail_register_netdev:

 

free_netdev(virtua_card);

 

     return 0;

}

 

static void __exit exit_netdriv(void)

{

       printk(KERN_INFO"Netdriv:Entry exit_netdriv");

   unregister_netdev(&virtua_card);

   free_netdev(virtua_card);

}

 

module_init(init_netdriv);

module_exit(exit_netdriv);

 

 

 

 

3.分析硬件

  3.1DM9000芯片datasheet

1)读芯片手册

        

        10M/100

        8bit  16bit

        16k SRAM    TX  SRAM 3K   RX SRAM 13K

        片选

        CMD (高电平。。。。低电平。。。)

        INT

        EECK  高  INT低有效 反之。。。

        EECS 高电平 8bit   低电平16bit

        寄存器的每个bit位的意义?

        怎么往DM9000内部寄存器TCR(0X02)  写入0x55

           0x02??是啥?是index data0x55  他们都是通过SD端口进去的,通过CMD来区分  保证片选被选中(CS#为低电平即选中bank地址),CMD为低电平 地址总线的bit2此时为0  数据总线 0x02

        即: volatile unsigned int *p=0xxxxxx

               *p=0x02

           送数据到DM9000

          数据总线 0xxxxx

          地址总线  0xxxxxx

                     片选CMD ADD高电平

 

        

         第九章 数据收发

          发送数据过程:把要发送写入TX SRAM(DMA)

          设置要发送数据的长度 0xfc 0xfd

          control   reg   bit  1

      

 

 

 

  3.2硬件原理图

 

     1DM9000sd0~sd15连接到了CPU的哪里

     2CMD  连接到CPU哪去了(addr bus bit

     3CS# 连接到CPU哪去了    bank:一个bank就是128M空间

     4INT   连接CPU的中断为。。。

     5EECS  (NC无连接 ) 低电平   16 bit 模式

     6)  EECK   低电平)   INT为高电平有效

 

 

 

     4

      

  

  3.3CPU相关的接口

 

  1SM9000挂在bankn上了,在他地址范围内,当你cpu地址总线上的值是那个范围内都会导致XM0csnn)为低电平,也就是选中其中的片选

4,内核中自带网卡驱动程序是如何完成的,移植网卡驱动需要注意哪些内容

找到内核中DM9000的驱动程序

 driver/net/   变量CONFIG_DM9000      dm9000.c

 

 

DM9000网卡驱动程序是按照平台总线架构完成的

总线

 

 

设备   

 

 

设备驱动  dm9000.c

1)框架

       

 

 

2)发送函数

3)

5.移植网卡驱动问题   resourceplatform_device

         你使用的物理地址

         使用的中断号

         中断的有效状态

         位宽

6.内存控制器的配置

         1)外接设备的位宽

            SROM     

         2)读写时序

             SROM_BCx


本文出自 “毛散人” 博客,请务必保留此出处http://songmao.blog.51cto.com/11700139/1880187

网卡驱动