基于fs210平台的dm9000原理及移植

dm9000的原理图如下:

wKioL1OzmQGAEEtZAAL59MpEn5M140.jpg

网卡的移植工作很简单,首先是需要添加目标版的平台设备信息,就可以实现网卡的移植工作,平台设备信息如何添加很重要

添加平台信息的第一步是添加一个platform_device设备信息

首先在arch/arm/mach-s5pv210/mach-smdkv210.c

添加头文件:

#include <linux/dm9000.h>
             #include <linux/irq.h>
             添加platform_device平台设备信息
             struct platform_device {
                     const char * name; // 平台设备名称
                     int id; // 设备的ID 如果是唯一设备,ID = -1,如果设备不是唯一的,ID = 0,1,2,3,4,5
                     struct device dev; //
                     u32 num_resources; //所拥有资源结构体的个数
                     struct resource * resource; //资源结构体指针
                     const struct platform_device_id *id_entry;
                     struct pdev_archdata archdata;
             };
             例如:
             static struct platform_device s5pc100_device_dm9000 = {
                     .name = "dm9000",
                     .id = -1,
                     .num_resources = ARRAY_SIZE(dm9000_resources),
                     .resource = dm9000_resources,
                     .dev = {
                     .        platform_data = &s5pc100_dm9000_platdata,
                     }
             };

struct device 在  include/linux/device.h中的platform_data只是一个指针,可以传送一个地址

用这个地址可以给驱动传动一些特殊的数据,对于dm9000这个网卡芯片需要传送dm9000_plat_data

在网卡驱动中使用了如下的定义:   struct dm9000_plat_data *pdata = pdev->dev.platform_data;

因此我们要传递这个这个platform_data结构体,结构体的定义如下:

/* platform data for platform device structure's platform_data field */
             struct dm9000_plat_data {
                     unsigned int flags;
                     unsigned char dev_addr[6]; // 网卡的mac地址 ,可以不写,如果不写的话,是随机生成一个
                     /* allow replacement IO routines */
                     void (*inblk)(void __iomem *reg, void *data, int len);
                     void (*outblk)(void __iomem *reg, void *data, int len);
                     void (*dumpblk)(void __iomem *reg, int len);
             };

这个是网卡驱动使用的结构体

flags = DM9000_PLATF_16BITONLY, 表示dm9000工作在16位的模式下

在这个文件中定义  include/linux/dm9000.h

/* IO control flags */
             #define DM9000_PLATF_8BITONLY (0x0001)
             #define DM9000_PLATF_16BITONLY (0x0002)
             #define DM9000_PLATF_32BITONLY (0x0004)
             #define DM9000_PLATF_EXT_PHY (0x0008)
             #define DM9000_PLATF_NO_EEPROM (0x0010)
             #define DM9000_PLATF_SIMPLE_PHY (0x0020) /* Use NSR to find LinkStatus */
             dev_addr是网卡的mac地址,
             .dev_addr[0] = 0x00,
             .dev_addr[1] = 0x00,
             .dev_addr[2] = 0x3e,
             .dev_addr[3] = 0x26,
             .dev_addr[4] = 0x0a,
             .dev_addr[5] = 0x00,
             例如:.dev = {
                     .platform_data = & s5pc100_dm9000_plat data,  //表示驱动中要用的数据
             }
             struct resource {
                     resource_size_t start; // 表示资源的开始值
                     resource_size_t end; // 表示资源的结束值
                     const char *name;
                     unsigned long flags; // 资源的类型
                     struct resource *parent, *sibling, *child;
             };
             我们一般只关心这3个字段 start ,end ,flags
             flags:
             /*
             * IO resources have these defined flags.
             */
             #define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
             #define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
             #define IORESOURCE_IO 0x00000100
             #define IORESOURCE_MEM 0x00000200 //内存资源
             #define IORESOURCE_IRQ 0x00000400 //中断资源
             #define IORESOURCE_DMA 0x00000800
             #define IORESOURCE_BUS 0x00001000
             因为在驱动中使用了如下的函数:
             db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
             db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
             db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
             因此我们必须要对成员设置如下:
             static struct resource dm9000_resources[] = {
                     [0] = {
                             .start = 0x88000000,
                             .end = 0x88000000+0x3,
                             .flags = IORESOURCE_MEM,
                     },
                     [1] = {
                             .start = 0x88000000+0x4,
                             .end = 0x88000000+0x4+0x3,
                             .flags = IORESOURCE_MEM,
                     },
                     [2] = {
                             .start = IRQ_EINT(10),
                             .end = IRQ_EINT(10),
                             .flags = IORESOURCE_IRQ|IRQ_TYPE_LEVEL_HIGH,
                     },
             };

为什么驱动要这样设置呢?

因为网卡dm9000这个设备有一个接口, 是dm9000的cmd引脚, 如果cmd = 0 表示的是地址,  cmd=1 表示的数据

cmd这个引脚接到了addr2 ,接到了地址总线, 也就是说我们只需要对addr2的地址产生影响就可以了,因此addr2 =0 表示是index是地址,

addr2 =1 表示对index索引指向的寄存器的内的值data ,因此我们只需要对这两个寄存器设置就可以实现网卡的驱动.

int platform_device_register(struct platform_device *pdev); //注册一个设备

int platform_add_devices(struct platform_device **pdevs, int ndev); //注册多个设备

pdevs: platform_device类型的指针

ndev : 一共有多少个设备


你可能感兴趣的:(嵌入式,dm9000,fs210,dm9000原理)