基于网络设备框架的驱动分析

基于网络设备框架的驱动分析

所谓网络设备,其实是一个概念而非实体,网卡仅仅是网络设备中的一部分。

1.网络设备的特性

  • 网络设备是比较特殊的,它不以文件形式存在,不符合Linux中“一切皆是文件”的哲学。应用程序若想联网,不是通过/dev下的文件,而是直接通过系统API(比如socket)调用网络驱动来联网
  • 为什么呢?原因是应用层对于网络读写方式其实是很固定的(相比于字符设备各种千奇百怪的功能),所以没必要以灵活的文件形式提供接口,API形式其实就够了

2.网络设备驱动的结构

这里写图片描述

由此不难看出,和块设备驱动相同,都是内核的顶层负责通用的上层逻辑,然后硬件差异由具体硬件驱动负责。驱动工程师只要完成极少的硬件相关的部分

3.网卡简介

下面介绍硬件相关的部分,以常见的DM9000为例。

  • DM9000其实是通过s5pv210的SROM接口来直接挂载在总线上的,所谓的SROM接口其实是一种对外部开放总线的方式,通过这个接口,网卡可以直接通过总线访问,对于程序员来说就仿佛在访问SOC内部的SFR,网卡芯片与SOC直接的通信过程就可以不用关心了。简而言之,这个网卡芯片就像集成在SOC内部一样。s5pv210的内存映射表有关SROM的部分:
    这里写图片描述
  • 接下来看看我们板子上网卡的具体接法:
    这里写图片描述
  • 通过上图,我们还能得出很多重要信息:由接口data0-data15可知,SROM接口使用了16位宽度。由接口CSn1可知,网卡接了SROM的bank1的片选脚,所以网卡处在0x88000000开头的内存地址
  • dm9000的地址接口和数据接口是复用的,CMD接在了ADDR2(一根地址总线),当CMD为1时data0-data15传输的是数据,而当CMD为0时传输的是地址。不难得出,如果要写dm9000的内部寄存器,我们是往0x88000000先写地址,再往0x88000000+0b100(即4)写数据。(但有时要加上0x300的偏移量,详见后文)

4.网卡配置实例

网卡的配置分为两步:早期soc内部的SROM初始化,和网卡驱动负责的硬件本身的初始化

早期的初始化

  • 这部分与驱动无关,是初始化soc内部的SROM接口配置,所以每一种soc的初始化过程和SROM寄存器是不一样的。不过我们还是可以找出一些共性
  • 进入mach-smdkc110.c的 smdkc110_machine_init函数,检查DM9000相关的部分,发现调用了smdkc110_dm9000_set函数来初始化DM9000,其定义:
static void __init smdkc110_dm9000_set(void)
{
    unsigned int tmp;

    tmp = ((0<<28)|(0<<24)|(5<<16)|(0<<12)|(0<<8)|(0<<4)|(0<<0));
    __raw_writel(tmp, S5P_SROM_BC1);

    tmp = __raw_readl(S5P_SROM_BW);
    tmp &= ~(0xf << 4);
    tmp |= (1<<7) | (1<<6) | (1<<5) | (1<<4); // dm9000 16bit
    __raw_writel(tmp, S5P_SROM_BW);

    tmp = __raw_readl(S5PV210_MP01CON);
    tmp &= ~(0xf << 4);
    tmp |= (2 << 4);

    __raw_writel(tmp, S5PV210_MP01CON);
}

  • 一眼看出,这段代码用“先读再改后写”的方法在配SROM相关的寄存器。通过查芯片手册,我们很容易得知这段代码做了什么
  • SROM_BW寄存器主要负责各个bank的数据总线的宽度设置,不同的位分别设置不同的bank,由于定义了宏DM9000_16BIT_DATA,故此寄存器配置为16位模式,并且配置的是bank5,byteenable位设置成0(不使用UB/LB),waitenable位设成0(禁止等待),addrmode设为0(半字对齐)。我们修改为bank1,此外,原厂的很多设置都是有问题的,必须修改为byteenable位设置成1(使用UB/LB),waitenable位设成1(使能等待),addrmode设为1(字节对齐),至于这些参数到底怎么选择,其实都是一些约定俗成的套路,特别是dm9000作为一款历史悠久的老芯片,很多设置的方法都已经固化了,通过网络可以很轻松查到
  • 最后原厂配置了MP01CON_REG这个寄存器,这个寄存器其实就是配置了引脚MP01,原厂将其设为复用功能,即SROM接口中的bank1片选引脚

网卡本身的配置

网卡本身的驱动是基于platform总线的,所以有关网卡的可配置项都在platform_device中

  • 不难找到dm9000的platform_device:
struct platform_device s5p_device_dm9000 = {
    .name       = "dm9000",
    .id     =  0,
    .num_resources  = ARRAY_SIZE(s5p_dm9000_resources),
    .resource   = s5p_dm9000_resources,
    .dev        = {
        .platform_data = &s5p_dm9000_platdata,
    }
};
  • 观察后发现,主要的配置项还是在s5p_dm9000_resources和s5p_dm9000_platdata中
static struct resource s5p_dm9000_resources[] = {
    [0] = {
        .start = S5P_PA_DM9000,
        .end   = S5P_PA_DM9000 + 3, 
        .flags = IORESOURCE_MEM,
    },
    [1] = {
#if defined(CONFIG_DM9000_16BIT)
        .start = S5P_PA_DM9000 + 4,
        .end   = S5P_PA_DM9000 + 7,
        .flags = IORESOURCE_MEM,
#else
        .start = S5P_PA_DM9000 + 1,
        .end   = S5P_PA_DM9000 + 1,
        .flags = IORESOURCE_MEM,
#endif
    },
    [2] = {
        .start = /*IRQ_EINT10*/IRQ_EINT10,
        .end   = /*IRQ_EINT10*/IRQ_EINT10,
        .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
    }
};
  • S5P_PA_DM9000代表的正是dm9000的基地址,0x88000000。由s5pv210的内存映射表可知bank1就在该地址
  • 但此处有坑,很玄学,居然有可能不工作,需要改成0x88000300才行,至于原因的话网上众说纷纭,一种比较合理的说法是:DM9000有不同的版本,其中有的内部自带0x300的偏移量…故只用bank的基地址是不行的,需要加上0x300。但其实我个人不认同这一观点,因为加上去的0x300地址是soc内存空间的地址,而不是dm9000内部寄存器的地址,更何况只有一根ADDR2接在dm9000上,照理说这0x300加不加根本没区别,所以我觉得可能是s5pv210内部的SROM相关的bug,等以后验证一下
  • .end元素,个人猜测可能与发送数据时的地址有关,等到以后有空测试一下就知道了
  • IRQ_EINT10代表了当有数据从dm9000传输至soc时,使用哪个外部中断,通过原理图不难得知,我们接了一个EINT10引脚
static struct dm9000_plat_data s5p_dm9000_platdata = {
#if defined(CONFIG_DM9000_16BIT)
    .flags = DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
#else
    .flags = DM9000_PLATF_8BITONLY | DM9000_PLATF_NO_EEPROM,
#endif
    .dev_addr = {0x00,0x09,0xc0,0xff,0xec,0x48},
    //.dev_addr = {0x00,0x09,0xc0,0xff,0x11,0x33},
};
  • s5p_dm9000_platdata这个结构体内主要是一些地址比较重要,还不清楚是干什么的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值