Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1887104
  • 博文数量: 496
  • 博客积分: 12043
  • 博客等级: 上将
  • 技术积分: 4778
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-27 14:26
文章分类

全部博文(496)

文章存档

2014年(8)

2013年(4)

2012年(181)

2011年(303)

2010年(3)

分类: 嵌入式

2012-09-18 13:41:04

cs8900网卡的移植以及cs8900初始化代码分析


    上一篇,总结linux2.6.20.3的移植,在此,并将cs8900的移植过程进行简单的记录,并将我读取的cs8900网卡初始化的流程附上。

    移植过程参照ARM_Linux_Kernel_Porting_(MBA2410).pdf(我上一篇引导部分的内容这里也有,早知道就看看它就没必要 自己花时间跟了),并修改了一些不合适的问题,linux 2.6.20.3参照此步骤,网卡是绝对可以驱动得上的。但是必需要注意网卡硬件的布线,比如片选引脚以及中断引脚等。
    以下的修改内容蓝色为添加红色为原有的,该色为要被替换的。
    (1)修改 arch/arm/mach-s3c2410/Kconfig
       找到config ARCH_SMDK2410修改为如下内容
config ARCH_SMDK2410
    bool "SMDK2410/A9M2410"
    select CPU_S3C2410
    select MACH_SMDK
    select NET_PCI
    select ISA
    help
       Say Y here if you are using the SMDK2410 or the derived module A9M2410
           <
    (2)修改include/asm-arm/arch-s3c2410/map.h
       添加如下的宏定义
   
/* CS8900 */
#define S3C24XX_VA_CS8900 S3C2410_ADDR(0x01300000)
#define S3C2410_PA_CS8900 (0x19000000)
#define S3C24XX_SZ_CS8900 SZ_1M
#define S3C24XX_PA_CS8900 S3C2410_PA_CS8900
    (3)修改arch/arm/mach-s3c2410/mach-s3c2410.c
在static struct map_desc smdk2410_iodesc[] __initdata作如下修改。
static struct map_desc smdk2410_iodesc[] __initdata = {
         IODESC_ENT(CS8900)
};


    (4)修改drivers/net/cs89x0.c文件
      
155 #endif
156 (加入)

#ifdef CONFIG_ARCH_S3C2410
#include
#include
#include
#include
#endif

191 #elif defined(CONFIG_ARCH_PNX010X)
192 #include



193 #include
194 #define CIRRUS_DEFAULT_BASE            IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x2
     00000)       /* = Physical address 0x48200000 */
195 #define CIRRUS_DEFAULT_IRQ             VH_INTC_INT_NUM_CASCADED_INTERRUPT_
    1 /* Event inputs bank 1 - ID 35/bit 3 */
196 static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
197 static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
   #elif defined(CONFIG_ARCH_S3C2410)
   static unsigned int netcard_portlist[] __initdata = { S3C24XX_VA_CS8900 + DEFAULTIOBASE, 0};
   static unsigned int cs8900_irq_map[] = { IRQ_EINT9, 0, 0, 0 };
   #ifdef request_region
   #undef request_region
   #endif
   #ifdef release_region
   #undef release_region
   #endif
   #define request_region(a, s, n) request_mem_region(a, s, n)
   #define release_region(a, s) release_mem_region(a, s)
198 #else
199 static unsigned int netcard_portlist[] __initdata =
200    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0,
    0x2c0, 0x2e0, 0};
201 static unsigned int cs8900_irq_map[] = {10,11,12,5};
202 #endif
                              :
                              :
325         io = dev->base_addr;
326         irq = dev->irq;
327
#ifdef CONFIG_ARCH_S3C2410  __raw_writel((__raw_readl(S3C2410_GPGCON)&~(0x3<<2))|(0x2<<2),S3C2410_GPGCON);
__raw_writel((__raw_readl(S3C2410_EXTINT1)&~(0x7<<4))|(0x4<<4),S3C2410_EXTINT1);
#endif
328         if (net_debug)
329                 printk("cs89x0:cs89x0_probe(0x%x)\n", io);
                                            :
                                            :
350         return ERR_PTR(err);
351 }
352 #endif

353
#if defined(CONFIG_ARCH_S3C2410)
static u16
readword(unsigned long base_addr, int portno)
{
   return __raw_readw(base_addr + portno);
}

static void
writeword(unsigned long base_addr, int portno, u16 value)
{
   __raw_writew(value, base_addr + portno);
}
#elif defined(CONFIG_MACH_IXDP2351)
#if defined(CONFIG_MACH_IXDP2351) //本句删除
                            :
                            :
633          reset_chip(dev);
634
#ifdef CONFIG_ARCH_S3C2410
     lp->force = FORCE_RJ45;
     lp->auto_neg_cnf = IMM_BIT;

     dev->dev_addr[0] = 0x09;
 
     dev->dev_addr[1] = 0x90;
     dev->dev_addr[2] = 0x99;
     dev->dev_addr[3] = 0x09;
     dev->dev_addr[4] = 0x90;
     dev->dev_addr[5] = 0x99;
#endif
                            :
                            :
#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)//该句删除
#if !defined(CONFIG_ARCH_S3C2410) && !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
1314    if (((1 << dev->irq) & lp->irq_map) == 0) {
1315             printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
1316             dev->name, dev->irq, lp->irq_map);


附上补丁,该补丁是直接针对linux2.6.20.3内核的移植以及在友善之臂cs8900网卡的驱动,patch上后make zImage就可以编译并运行。
文件: sbc2410-linux2.6.20.3-with-cs8900.patch.tar.gz
大小: 8KB
下载: 下载

u-boot引导参数:
setenv bootargs root=/dev/nfs rw nfsroot=192.168.1.20:/nfsroot ip=192.168.1.12:192.168.1.20::255.255.255.0:::off mem=64M

cs8900初始化代码分析

    整个代码分析由上叙述的的修改过程作为指导
    static struct map_desc smdk2410_iodesc[] __initdata = {
         IODESC_ENT(CS8900)
    };
    让我们看一下
IODESC_ENT(CS8900)宏定义在arch/arm/mach-s3c2410/cup.h中的代码部分
#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }

    经过宏替换,原来的部分将被替换为如下的式子
  
static struct map_desc smdk2410_iodesc[] __initdata = {
    {(unsigned long)S3C24XX_VA_CS8900,
     
__phys_to_pfn(S3C24XX_PA_CS8900)
     
S3C24XX_SZ_CS8900,
      MT_DEVICE
};
};


    而其中的那些宏也就是我们在include/asm-arm/arch-s3c2410/map.h定义的那4个宏
    #define S3C24XX_VA_CS8900 S3C2410_ADDR(0x01300000)
    #define S3C2410_PA_CS8900 (0x19000000)
    #define S3C24XX_SZ_CS8900 SZ_1M
    #define S3C24XX_PA_CS8900 S3C2410_PA_CS8900

    其中
S3C24XX_VA_CS8900 是CS8900的物理地址映射到虚拟内存页上的地址
        S3C2410_PA_CS8900 是实际CS8900所在的物理地址
        S3C24XX_SZ_CS8900 是为CS8900申请的虚拟内存空间的大小,这里设置为1M.


    smdk2410_iodesc[]结构体数组会在系统为设备io的时候进行调用,该部分调用在以下的文件中:
    arch/arm/mach-s3c2410/mach-smdk2410.c 中的smdk2410_map_io 函数内,函数实现如下:
   

static void __init smdk2410_map_io(void)
{
    s3c24xx_init_io(smdk2410_iodesc,ARRAY_SIZE(smdk2410_iodesc));
    s3c24xx_init_clocks(0);
    s3c24xx_init_uarts(smdk2410_uartcfgs,ARRAY_SIZE(smdk2410_uartcfgs));
    s3c24xx_set_board(&smdk2410_board);
}

    该函数会在系统读取完s3c2410的cpuId后执行运行。

 当系统启动后,需要初始化CS8900该部分工作从 drivers/net/Space.c里的net_olddevs_init(void)函数开始。

static int __init net_olddevs_init(void)
{
    int num;

#ifdef CONFIG_SBNI
    for (num = 0; num < 8; ++num)
        sbni_probe(num);
#endif
#ifdef CONFIG_TR
    for (num = 0; num < 8; ++num)
        if (!trif_probe(num))
            trif_probe2(num);
#endif
    for (num = 0; num < 8; ++num)
        ethif_probe2(num);

#ifdef CONFIG_COPS
    cops_probe(0);
    cops_probe(1);
    cops_probe(2);
#endif
#ifdef CONFIG_LTPC
    ltpc_probe();
#endif

    return 0;
}

如上代码的标红语句ethif_probe2(num);这个语句用来查询系统中所存在的网卡设备最多支持8个设备。
该函数也定义在Space.c中
   

static void __init ethif_probe2(int unit)
{
    unsigned long base_addr = netdev_boot_base("eth", unit);

    if (base_addr == 1)
        return;

    (void)(probe_list2(unit, m68k_probes, base_addr == 0) &&
        probe_list2(unit, eisa_probes, base_addr == 0) &&
        probe_list2(unit, mca_probes, base_addr == 0) &&
        probe_list2(unit, isa_probes, base_addr == 0) &&
        probe_list2(unit, parport_probes, base_addr == 0));
}
  
    在上面的代码中有一个比较特别的函数
probe_list2,这个函数用来调用特定的网卡设备所对应的初始化函数,而这个初始化函数能否被调用又是由系统编译前的裁减工作所确定的。以我们当前as8900网卡为例,来说明这点
static struct devprobe2 isa_probes[] __initdata = {
  :
  :
#ifdef CONFIG_CS89x0
     {cs89x0_probe, 0},
#endif
  :
  :

   
因此在函数
probe_list2内实际调用的初始化函数为cs89x0_probe函数。probe_list2的代码如下:

static int __init probe_list2(int unit, struct devprobe2 *p, int autoprobe)
{
    struct net_device *dev;
    for (; p->probe; p++) {
        if (autoprobe && p->status)
            continue;
        dev = p->probe(unit);//该部分就实际调用cs89x0_probe
        if (!IS_ERR(dev))
            return 0;
        if (autoprobe)
            p->status = PTR_ERR(dev);
    }
    return -ENODEV;
}

我们随后就可以进入drivers/net/cs89x0.c文件中超找该函数cs89x0_probe。该函数的主要代码流程将以伪代码的方式给出:

(1)调用netdev_boot_setup_check(dev);遍历已有的网络设备,以确定当前要初始化的设备是否已经存在。(这些设备可以通过在引导过程中传入网络设置参数进行初始化设置)
(2)初始化CS8900的功能引脚。(这部分是由我们自己添加的)
(3)cs89x0_probe1(dev, *port, 0)调用该函数进行初始化探测工作,包括设备ID,初始化芯片,设置MAC地址(由我们添加),分配内存空间。
(4)当成功初始化设备后返回一个net_device的结构,作为这个设别的标识。

以上写的并不够详细,因为本身也没有过多的对它进行研究,只是在移植的过程中调试流程时的记录文档,作为备份以后补全。


阅读(1214) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

5407225732012-09-19 09:36:27

猎头职位推荐:嵌入式软/硬件架构师,工作地点深圳 待遇32W-43W/年,各位做嵌入式电子产品的朋友都可以看,有兴趣者请联系:E-mail: z242086@vastsea.com ,QQ: 2425886002。