Chinaunix首页 | 论坛 | 博客
  • 博客访问: 635739
  • 博文数量: 205
  • 博客积分: 7891
  • 博客等级: 少将
  • 技术积分: 2168
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-29 13:16
文章分类

全部博文(205)

文章存档

2015年(4)

2014年(5)

2013年(1)

2012年(4)

2011年(51)

2010年(86)

2009年(45)

2008年(9)

分类: 嵌入式

2010-05-22 11:11:29


移植Linux2.6.22.2到友善之臂SBC2440V4(s3c2440AL)(双网卡)
   昨天成功移植了U-Boot到SBC2440V4,今天把Linux2.6.22.2也移植上去。其实有了前面2410-S的移植经验以后,移植到 SBC2440V4是一件很简单的事(虽然也碰到了点麻烦)。在移植时我基本都是按照
【置顶】移植Linux2.6.22.2到博创2410- S(s3c2410A)(1)

【置顶】移植Linux2.6.22.2到博创2410- S(s3c2410A)(3)
来移植的,只是稍加改动就好。在这里我就不在具体的讲了,我只详述一下与移植到2410-S不同的地方。
这次移植除了使用我以前的移植纪录外,还重点参考了:
(0)S3C2440英文数据手册
(1)《linux内核中设置CPU工作频率》URL:

http://blog.chinaunix.net/u1/42456/showart_339915.html
(2)DM9000英文数据手册
(3)cs8900a驱动移植笔记  URL: /webelec/article/15/79/Article_1119.htm
(4)WeiBing博客中的文章
cs8900 移植 Linux-2.6.19.2

(5)友善之臂SBC2440V4原理图

首先,Linux2.6.22.2本身就支持s3c2440处理器,由于2410和2440基本兼容,所以在linux源码里2440的很多文件是和 2410共用的。所以在按照我移植2410记录的基础上,主要修改如下:

一、开发板选项的选择。
System Type  --->      
   S3C2440 Machines  --->   
   
  • SMDK2440
       
  • SMDK2440 with S3C2440 CPU module
    留下这两项就够了,S3C2400 Machines  ---> 、S3C2410 Machines  --->、S3C2412 Machines  --->、S3C2442 Machines  --->、S3C2443 Machines  --->里的项目全部“N”掉。

    这两个选项是区分你的目标芯片是2410还是2440的关键选项!!
    二、系统初始化时的芯片晶振频率的修改,修改arch/arm/mach-s3c2440/mach- smdk2440.c
    ......
        static void __init smdk2440_map_io(void)
    {
        s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
    }
    ......
    如果没有改这个参数,系统启动时到了"done, booting the kernel."之后就会出现乱码现象或是没有输出。我一开始就碰到了这个麻烦。出现此类乱码或没有输出现象的另一个原因可能是你的bootloader 对CPU的主频和分频的设置不正确。SBC2440V4的设置最好是时钟频率405MHz,分频比为1:4:8,不然有可能出现上述现象。请看参考资料 (1)。
    三、开发板四个LED指示灯的驱动修改
       SBC2440V4和SMDK2440一样有四个LED指示灯。指示用的GPIO口不一样。参考SBC2440V4的硬件说明书,修改/arch /arm/plat-s3c24xx/common-smdk.c如下:
    ......
    static struct s3c24xx_led_platdata smdk_pdata_led4 = {
        .gpio        = S3C2410_GPB5,
        .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
        .name        = "led4",
        .def_trigger    = "timer",
    };
    static struct s3c24xx_led_platdata smdk_pdata_led5 = {
        .gpio        = S3C2410_GPB6,
        .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
        .name        = "led5",
        .def_trigger    = "nand-disk",
    };
    static struct s3c24xx_led_platdata smdk_pdata_led6 = {
        .gpio        = S3C2410_GPB7,
        .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
        .name        = "dm9000",
    };
    static struct s3c24xx_led_platdata smdk_pdata_led7 = {
        .gpio        = S3C2410_GPB8,
        .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
        .name        = "cs89x0",
    };
    ......
    void __init smdk_machine_init(void)
    {
        /* Configure the LEDs (even if we have no LED support)*/
        s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPB5_OUTP);    s3c2410_gpio_cfgpin(S3C2410_GPB6, S3C2410_GPB6_OUTP);    s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPB7_OUTP);    s3c2410_gpio_cfgpin(S3C2410_GPB8, S3C2410_GPB8_OUTP);    s3c2410_gpio_setpin(S3C2410_GPB5, 1);    s3c2410_gpio_setpin(S3C2410_GPB6, 1);    s3c2410_gpio_setpin(S3C2410_GPB7, 0);    s3c2410_gpio_setpin(S3C2410_GPB8, 0);
        if (machine_is_smdk2443())
            smdk_nand_info.twrph0 = 50;
        s3c_device_nand.dev.platform_data = &smdk_nand_info;
        platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
        s3c2410_pm_init();
    }
    ......
    修改成功的现象,启动时LED1和LED2会亮一下;nand flash 读写时LED2会闪动;dm9000有网络活动时,LED3会亮;cs8900有网络活动时,LED4会亮。由于dm9000是作为NFS挂载的网卡,所 以LED3亮的时间比较多。

    四、修改/driver/net/Kconfig文件,使其在配置时出现cs89x0的选项。
    ......
    config CS89x0
    tristate "CS89x0 support"
    ---help---
    depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
       Support for CS89x0 chipset based Ethernet cards. If you have a
       network (Ethernet) card of this type, say Y and read the
       Ethernet-HOWTO, available from
        as well as
       .
       To compile this driver as a module, choose M here and read
       .  The module will be
       called cs89x0.
    就是使 depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)那一句失效。我是把它放到了 ---help---下面,你也可以把它删了。

    以下是双网卡的移植,首先要说明的是如果都编译进内核中,双网卡在启动时会无法挂载NFS,会出现IP配置 失败的提示。单独编译时都不会出现这种情况。原因我不知道。(那位大侠如果解决了记得通知一声) 经过多次试验发现:要实现双网卡,又要挂载NFS根文件系统最好的配置是将DM9000编译进内核(速度快),将
    CS8900作为模块在启动后挂载。以下的移植就是针对这种情况修改的。
    五、修改/driver/net/cs89x0.c文件,使其匹配SBC2440V4和cs8900的硬件 配置。(并添加LED4在有网络操作时点亮的功能)......
    #include
    #include
    #include
    #include
    #if ALLOW_DMA
    #include
    #endif

    #include "cs89x0.h"
    //**********************tekkaman*************************
    #include
    #include
    #include
    #include
    #include
    #include

    #define CS8900_BASE   (S3C2440_VA_ISA_CS8900)
    #define CS8900_IRQ    IRQ_EINT9
    //**********************tekkaman*****************************

    static char version[] __initdata =
    "cs89x0.c: v2.4.3-pre1 Russell Nelson , Andrew Morton \n
    [/email]
    ";
    DEFINE_LED_TRIGGER(cs89x0_led_trigger);

    #define DRV_NAME "cs89x0"
    ......
    #define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
    static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
    static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
    #else
    static unsigned int netcard_portlist[] __initdata = {CS8900_BASE, 0};
    static unsigned int cs8900_irq_map[] = {CS8900_IRQ,0};

    #endif
    /* Index to functions, as function prototypes. */
    static int cs89x0_probe1(struct net_device *dev,unsigned int ioaddr, int modular);
    ......
    //static int get_eeprom_cksum(int off, int len, int *buffer);
    ......
    struct net_device * __init cs89x0_probe(int unit)
    {
    struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
    unsigned int *port;
    int err = 0;
    unsigned int irq;
    unsigned int io;
    //tekkaman
    static int once=0;
    unsigned int value;
    //tekkaman

    if (!dev)
      return ERR_PTR(-ENODEV);
    sprintf(dev->name, "eth%d", unit);
    netdev_boot_setup_check(dev);
    //******************************tekkaman********************************
         if (once) {
          return -ENXIO;
    }

    value = __raw_readl(S3C2410_BWSCON);
    value &= ~(S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_32);
    value |= (S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_16);
    __raw_writel(value, S3C2410_BWSCON);

    value=0;
    value = (S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
    __raw_writel(value,S3C2410_BANKCON3);

    set_irq_type(CS8900_IRQ,IRQ_TYPE_EDGE_RISING );
    s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
    s3c2410_gpio_pullup(S3C2410_GPG1, 0);

    if(dev->base_addr==0){
    dev->base_addr = CS8900_BASE ;
    dev->irq = CS8900_IRQ;
    once++;

    }
    led_trigger_register_simple("cs89x0", &cs89x0_led_trigger);

    //***********************************tekkaman************************************
    io = dev->base_addr;
    irq = dev->irq;
    ......
    }
    ......
    #else
    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);
    }
    #endif
    ......
    #if 0
    static int  __init
    get_eeprom_cksum(int off, int len, int *buffer)
    {
    int i, cksum;
    cksum = 0;
    for (i = 0; i
    ......
    static int __init
    cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular)
    {
    struct net_local *lp = netdev_priv(dev);
    static unsigned version_printed;
    int i;
    int tmp;
    unsigned rev_type = 0;
    // int eeprom_buff[CHKSUM_LEN];
    int retval;
    unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x27,0x12,0};//tekkaman
    SET_MODULE_OWNER(dev);
    /* Initialize the device structure. */
    if (!modular) {
      memset(lp, 0, sizeof(*lp));
      spin_lock_init(&lp->lock);
    #ifndef MODULE
    #if ALLOW_DMA
      if (g_cs89x0_dma) {
       lp->use_dma = 1;
       lp->dma = g_cs89x0_dma;
       lp->dmasize = 16; /* Could make this an option... */
      }
    #endif
    // lp->force = g_cs89x0_media__force;
      lp->force = (FORCE_RJ45 | FORCE_FULL);
      lp->auto_neg_cnf=IMM_BIT;

    ......
    #if 0
            if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
           (EEPROM_OK|EEPROM_PRESENT)) {
             /* Load the MAC. */
      for (i=0; i dev_addr[i*2] = Addr & 0xFF;
              dev->dev_addr[i*2+1] = Addr >> 8;
      }
    ......
      if (net_debug > 1)
       printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
        dev->name, lp->adapter_cnf);
            }
    #endif
      for (i = 0; i dev_addr = ne_defethaddr;
                            }

      
            /* allow them to force multiple transceivers.  If they force multiple, autosense */
            {
      int count = 0;
      if (lp->force & FORCE_RJ45) {lp->adapter_cnf |= A_CNF_10B_T; count++; }
      if (lp->force & FORCE_AUI)  {lp->adapter_cnf |= A_CNF_AUI; count++; }
      if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_10B_2; count++; }
      if (count > 1)   {lp->adapter_cnf |= A_CNF_MEDIA_AUTO; }
      else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; }
      else if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_MEDIA_AUI; }
      else if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_MEDIA_10B_2; }
            }
    ......
    static int
    detect_tp(struct net_device *dev)
    {
    ......
    if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
      return DETECTED_NONE;
      lp->force = (FORCE_RJ45 | FORCE_FULL);
      lp->auto_neg_cnf=IMM_BIT;

    if (lp->chip_type == CS8900) {
                    switch (lp->force & 0xf0) {
    ......
    }
    ......
    static int
    net_open(struct net_device *dev)
    {
    ......
      if (i >= CS8920_NO_INTS) {
       writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
       printk(KERN_ERR "cs89x0: can't get an interrupt\n");
       ret = -EAGAIN;
       goto bad_out;
      }
    }
    else
    #endif
    {
    #if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410)
      if (((1 irq) & lp->irq_map) == 0) {
       printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                   dev->name, dev->irq, lp->irq_map);
       ret = -EAGAIN;
       goto bad_out;
      }
    #endif
    ......
    /* set the Ethernet address */
    for (i=0; i dev_addr[i*2] | (dev->dev_addr[i*2+1]
    /* while we're testing the interface, leave interrupts disabled */
    writereg(dev, PP_BusCTL, MEMORY_ON);
    /* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
    if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
                    lp->linectl = LOW_RX_SQUELCH;
    else
                    lp->linectl = 0;
    lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T ;
            /* check to make sure that they have the "right" hardware available */
    switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
    case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
    case A_CNF_MEDIA_AUI:   result = lp->adapter_cnf & A_CNF_AUI; break;
    case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
            default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
            }
    ......
    }
    ......
    static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
    {
    struct net_local *lp = netdev_priv(dev);
    led_trigger_event(cs89x0_led_trigger, LED_FULL);
    ......
    led_trigger_event(cs89x0_led_trigger, LED_OFF);
    return 0;
    }
    /* The typical workload of the driver:
       Handle the network interface interrupts. */
    static irqreturn_t net_interrupt(int irq, void *dev_id)
    {
    struct net_device *dev = dev_id;
    struct net_local *lp;
    unsigned int ioaddr, status;
      int handled = 0;
    ......
    }
    ......
    static void
    net_rx(struct net_device *dev)
    {
    struct net_local *lp = netdev_priv(dev);
    struct sk_buff *skb;
    int status, length;
    led_trigger_event(cs89x0_led_trigger, LED_FULL);
    unsigned int ioaddr = dev->base_addr;
    status = readword(ioaddr, RX_FRAME_PORT);
    length = readword(ioaddr, RX_FRAME_PORT);
    ......
    led_trigger_event(cs89x0_led_trigger, LED_OFF);
    }
    ......
    #ifdef MODULE
    static struct net_device *dev_cs89x0;
    /*
    * Support the 'debug' module parm even if we're compiled for non-debug to
    * avoid breaking someone's startup scripts
    */
    static unsigned int io=CS8900_BASE;
    static unsigned int irq=CS8900_IRQ;

    static int debug;
    static char media[8]="rj45";
    static int duplex=-1;
    static int use_dma;   /* These generate unused var warnings if ALLOW_DMA = 0 */
    static int dma;
    static int dmasize=16;   /* or 64 */
    module_param(io, uint, 0);
    module_param(irq,  uint, 0);
    module_param(debug, int, 0);
    ......
    int __init init_module(void)
    {
    struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
    struct net_local *lp;
    int ret = 0;
    #if DEBUGGING
    net_debug = debug;
    #else
    debug = 0;
    #endif
    //tekkaman
    unsigned int value;

    value = __raw_readl(S3C2410_BWSCON);
    value &= ~(S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_32);
    value |= (S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_16);
    __raw_writel(value, S3C2410_BWSCON);

    value=0;
    value = (S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
    __raw_writel(value,S3C2410_BANKCON3);

    set_irq_type(CS8900_IRQ,IRQ_TYPE_EDGE_RISING );
    s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
    s3c2410_gpio_pullup(S3C2410_GPG1, 0);
    led_trigger_register_simple("cs89x0", &cs89x0_led_trigger);

    //tekkaman
    if (!dev)
      return -ENOMEM;
    ......
    }
    ......
    特别说明:除了总线配置语句一定要加,否则网 卡运行时会出现“time out”的错误之外,还有一个十分重要的地方:在驱动中存储 基地址 和中断 的变量一点要统一定义为unsigned int 否则会出错。

    六、修改/driver/net/dm9000.c文件,使其匹配SBC2440V4和DM9000的硬件配置(并添加LED3在有网络操作时点亮的功能)

    ......
    #include    //LED驱动头文件
    ......
    //**********************tekkaman*************************
    #include
    #include
    #include
    #include
    #include
    #include
    #define DM9000_IRQ    IRQ_EINT7

    //**********************tekkaman*****************************
    /*
    * Transmit timeout, default 5 seconds.
    */
    static int watchdog = 5000;
    module_param(watchdog, int, 0400);
    MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
    DEFINE_LED_TRIGGER(dm9000_led_trigger);
    ......
    static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
          int value);
    //static u16 read_srom_word(board_info_t *, int);
    static void dm9000_rx(struct net_device *);
    static void dm9000_hash_table(struct net_device *);
    //tekkaman
    #undef DM9000_PROGRAM_EEPROM
    //tekkaman
    #ifdef DM9000_PROGRAM_EEPROM
    static void program_eeprom(board_info_t * db);
    #endif
    ......
    #if  0
    //def CONFIG_NET_POLL_CONTROLLER

    /*
    *Used by netconsole
    */
    static void dm9000_poll_controller(struct net_device *dev)
    {
    disable_irq(dev->irq);
    dm9000_interrupt(dev->irq,dev);
    enable_irq(dev->irq);
    }
    #endif

    ......
    static int
    dm9000_probe(struct platform_device *pdev)
    {
    struct dm9000_plat_data *pdata = pdev->dev.platform_data;
    struct board_info *db; /* Point a board information structure */
    struct net_device *ndev;
    unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman
    unsigned long base;
    int ret = 0;
    int iosize;
    int i;
    u32 id_val;
    //******************************tekkaman********************************
    unsigned int value;
    static int once=0;
         if (once) {
          return -ENXIO;
    }
    //tekkaman
    value = __raw_readl(S3C2410_BWSCON);
    value &= ~(S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_32);
    value |= (S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_16);
    __raw_writel(value, S3C2410_BWSCON);
    value=0;
    value = (S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
    __raw_writel(value,S3C2410_BANKCON4);

    set_irq_type(DM9000_IRQ,IRQ_TYPE_LEVEL_HIGH );
    s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_EINT7);
    s3c2410_gpio_pullup(S3C2410_GPF7, 0);
    //******************************tekkaman********************************

    /* Init network device */
    ndev = alloc_etherdev(sizeof (struct board_info));
    if (!ndev) {
      printk("%s: could not allocate device.\n", CARDNAME);
      return -ENOMEM;
    }
    ......

    #if  0
    def CONFIG_NET_POLL_CONTROLLER
    ndev->poll_controller  = &dm9000_poll_controller;
    #endif
    #ifdef DM9000_PROGRAM_EEPROM
    program_eeprom(db);
    #endif
    db->msg_enable       = NETIF_MSG_LINK;
    db->mii.phy_id_mask  = 0x1f;
    db->mii.reg_num_mask = 0x1f;
    db->mii.force_media  = 0;
    db->mii.full_duplex  = 0;
    db->mii.dev      = ndev;
    db->mii.mdio_read    = dm9000_phy_read;
    db->mii.mdio_write   = dm9000_phy_write;
    /* Read SROM content */
    //tekkaman
    /* for (i = 0; i srom) = read_srom_word(db, i);
    */
    /* Set Node Address */
      for (i = 0; i dev_addr = ior(db, i+DM9000_PAR);

    //tekkaman
    if (!is_valid_ether_addr(ndev->dev_addr)) {
      /* try reading from mac */
      printk("%s: Invalid ethernet MAC address."
       " Load ne_defethaddr !! \n ", ndev->name);
      for (i = 0; i dev_addr = ne_defethaddr;

    }
    if (!is_valid_ether_addr(ndev->dev_addr))
      printk("%s: Invalid ethernet MAC address.  Please "
             "set using ifconfig\n", ndev->name);
    ......
    /*
    * Initilize dm9000 board
    */
    static void
    dm9000_init_dm9000(struct net_device *dev)
    {
    board_info_t *db = (board_info_t *) dev->priv;
    PRINTK1("entering %s\n",__FUNCTION__);
    ......
    /* Init Driver variable */
    db->tx_pkt_cnt = 0;
    db->queue_pkt_len = 0;
    dev->trans_start = 0;
    spin_lock_init(&db->lock);
    }

    static int
    dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
    {

    board_info_t *db = (board_info_t *) dev->priv;
    PRINTK3("dm9000_start_xmit\n");
    led_trigger_event(dm9000_led_trigger, LED_FULL);
    if (db->tx_pkt_cnt > 1)
      return 1;
    ......
    led_trigger_event(dm9000_led_trigger, LED_OFF);
    return 0;
    }
    ......
    static void
    dm9000_rx(struct net_device *dev)
    {
    board_info_t *db = (board_info_t *) dev->priv;
    struct dm9000_rxhdr rxhdr;
    struct sk_buff *skb;
    u8 rxbyte, *rdptr;
    bool GoodPacket;
    int RxLen;

    /* Check packet ready or not */
    do {
      led_trigger_event(dm9000_led_trigger, LED_FULL);
      ior(db, DM9000_MRCMDX); /* Dummy read */
    ......
    led_trigger_event(dm9000_led_trigger, LED_OFF);
    } while (rxbyte == DM9000_PKT_RDY);
    }
    /*
    *  Read a word data from SROM
    */
    #if 0
    static u16
    read_srom_word(board_info_t * db, int offset)
    {
    iow(db, DM9000_EPAR, offset);
    iow(db, DM9000_EPCR, EPCR_ERPRR);
    mdelay(8);  /* according to the datasheet 200us should be enough,
           but it doesn't work */
    iow(db, DM9000_EPCR, 0x0);
    return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH)
    ......
    static int __init
    dm9000_init(void)
    {
    printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);

    led_trigger_register_simple("dm9000", &dm9000_led_trigger);
    return platform_driver_register(&dm9000_driver); /* search board and register */
    }
    ......

    特别说明:static int dm9000_probe(struct platform_device *pdev)函数中的总线配置语句一定要加,否则网卡运行时会 出现“time out”的错误。
    七、修改文件/arch/arm/mach-s3c2440/mach-smdk2440.c,增加对DM9000和CS8900的配置信息。
    ......
    #include #define DM9000_BASE   (vDM9000_BASE)#define DM9000_IRQ    IRQ_EINT7#define pDM9000_BASE    S3C2440_PA_ISA_DM9000#define vDM9000_BASE    S3C2440_VA_ISA_DM9000#define CS8900_BASE   (vCS8900_BASE)#define CS8900_IRQ    IRQ_EINT9#define pCS8900_BASE    S3C2440_PA_ISA_CS8900#define vCS8900_BASE    S3C2440_VA_ISA_CS8900
    static struct map_desc smdk2440_iodesc[] __initdata = {    /* ISA IO Space map (memory space selected by A24) */    {        .virtual    = (u32)S3C24XX_VA_ISA_WORD,        .pfn        = __phys_to_pfn(S3C2410_CS1),        .length        = 0x10000,        .type        = MT_DEVICE,    }, {        .virtual    = (u32)S3C24XX_VA_ISA_WORD + 0x10000,        .pfn        = __phys_to_pfn(S3C2410_CS1 + (1        .length        = SZ_4M,        .type        = MT_DEVICE,    }, {        .virtual    = (u32)S3C24XX_VA_ISA_BYTE,        .pfn        = __phys_to_pfn(S3C2410_CS1),        .length        = 0x10000,        .type        = MT_DEVICE,    }, {        .virtual    = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,        .pfn        = __phys_to_pfn(S3C2410_CS1 + (1        .length        = SZ_4M,        .type        = MT_DEVICE,    }, {        .virtual        = S3C2440_VA_ISA_DM9000,                .pfn          = S3C2440_PA_ISA_DM9000,                .length        = S3C2440_SZ_ISA_DM9000,                .type          = MT_DEVICE,        }, {        .virtual        = S3C2440_VA_ISA_CS8900,                .pfn          = S3C2440_PA_ISA_CS8900,                .length        = S3C2440_SZ_ISA_CS8900,                .type          = MT_DEVICE,        }
    };......
    struct dm9000_plat_data tekkaman2440_dm9000 = {        .flags= DM9000_PLATF_16BITONLY};static struct resource s3c2440_dm9000_resource[] = {    [0] = {        .start = DM9000_BASE,        .end   = DM9000_BASE + 0xff,        .flags = IORESOURCE_MEM,    },    [1] = {        .start = DM9000_IRQ,        .end   = DM9000_IRQ,        .flags = IORESOURCE_IRQ,    }};struct platform_device s3c_device_dm9000 = {    .name          = "dm9000",    .id          = -1,    .num_resources      = ARRAY_SIZE(s3c2440_dm9000_resource),    .resource      = s3c2440_dm9000_resource,    .dev              = {        .platform_data = &tekkaman2440_dm9000,    }};
    static struct platform_device *smdk2440_devices[] __initdata = {
        &s3c_device_usb,
        &s3c_device_lcd,
        &s3c_device_wdt,
        &s3c_device_i2c,
        &s3c_device_iis,
        &s3c_device_dm9000
    };
    ......

    八、修改文件/include/asm-arm/arch-s3c2410/map.h,增加DM9000和CS8900的配置信息。
    ......
    /* ISA style IO, for each machine to sort out mappings for, if it
    * implements it. We reserve two 16M regions for ISA.
    */
    #define S3C24XX_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
    #define S3C24XX_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)
        /***************tekkaman****************************/#define S3C2440_VA_ISA_DM9000   S3C2410_ADDR(0x02100300)#define S3C2440_PA_ISA_DM9000   __phys_to_pfn(0x20000300)#define S3C2440_SZ_ISA_DM9000   SZ_1M#define S3C2440_VA_ISA_CS8900   S3C2410_ADDR(0x02200300)#define S3C2440_PA_ISA_CS8900   __phys_to_pfn(0x19000300)#define S3C2440_SZ_ISA_CS8900   SZ_1M    /**********************tekkaman********************/
    ......
    特别说明:至于CS8900的物理地址的配置#define S3C2440_PA_ISA_CS8900   __phys_to_pfn(0x19000300),不一定非得0x19000300,也可以是0x1B000300、0x1D000300、 0x1F000300,这是由于SBC2440V4的CS8900连接基本和SDMK2410的是一样的,使用了ADDR24脚作为类似使能的管脚。这样 的设计是为了系统扩展的方便。
    九、配置内核
      Networking  --->     Networking options  --->        
  •    IP: kernel level autoconfiguration
            [ ]     IP: DHCP support        [ ]     IP: BOOTP support         [ ]     IP: RARP support   
       
    如果你的cs8900是编译进内核,这三项最好要去掉。如果你和我一样是编译成模块,“Y”、“M”和“N”都无所谓。
    Device Drivers  --->      Network device support  --->      Ethernet (10 or 100Mbit)  --->              
  • Ethernet (10 or 100Mbit)         ---   Generic Media Independent Interface device support            SMC 91C9x/91C1xxx support
              DM9000 support          CS89x0 support  
    如果双网卡都编译进内核中,在启动时会无法挂载NFS,会出现IP配置失败的提示。单独编译时都不会出现这种情况。


        最后就是make zImage 和make modules。将/drivers/net/cs89x0.ko复制到根文件系统中,启动后挂载。以下是我系统的一些信息:
    [Tekkaman2440@SBC2410]#cd /lib/modules/
    [
    Tekkaman2440@SBC2410]#insmod cs89x0.ko
    eth%d: cs8900 rev K found at 0xf2200300 cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 08:08:08:08:27:12
    [
    Tekkaman2440@SBC2410]#ifconfig eth1 192.168.0.22
    eth1: using full-duplex 10Base-T (RJ-45)
    [
    Tekkaman2440@SBC2410]#ping 192.168.0.1
    PING 192.168.0.1 (192.168.0.1): 56 data bytes
    64 bytes from 192.168.0.1: seq=0 ttl=64 time=4.977 ms
    64 bytes from 192.168.0.1: seq=1 ttl=64 time=0.633 ms
    64 bytes from 192.168.0.1: seq=2 ttl=64 time=0.617 ms
    64 bytes from 192.168.0.1: seq=3 ttl=64 time=0.601 ms
    64 bytes from 192.168.0.1: seq=4 ttl=64 time=0.640 ms
    64 bytes from 192.168.0.1: seq=5 ttl=64 time=0.621 ms
    64 bytes from 192.168.0.1: seq=6 ttl=64 time=0.723 ms
    64 bytes from 192.168.0.1: seq=7 ttl=64 time=0.623 ms
    --- 192.168.0.1 ping statistics ---
    8 packets transmitted, 8 packets received, 0% packet loss
    round-trip min/avg/max = 0.601/1.179/4.977 ms
    [
    Tekkaman2440@SBC2410]#ifconfig
    eth0      Link encap:Ethernet  HWaddr 08:08:08:08:12:27
              inet addr:192.168.1.2  Bcast:192.168.1.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:3485 errors:0 dropped:0 overruns:0 frame:0
              TX packets:2382 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:2704784 (2.5 MiB)  TX bytes:422360 (412.4 KiB)
              Interrupt:51 Base address:0x300
    eth1      Link encap:Ethernet  HWaddr 08:08:08:08:27:12
              inet addr:192.168.0.22  Bcast:192.168.0.255  Mask:255.255.255.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:36 errors:0 dropped:0 overruns:0 frame:0
              TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:4513 (4.4 KiB)  TX bytes:826 (826.0 B)
              Interrupt:53 Base address:0x300
    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              UP LOOPBACK RUNNING  MTU:16436  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  • 阅读(784) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~