Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4282496
  • 博文数量: 241
  • 博客积分: 15936
  • 博客等级: 上将
  • 技术积分: 25293
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-27 11:22
个人简介

Fedora-ARM

文章分类
文章存档

2016年(3)

2014年(1)

2013年(3)

2012年(50)

2011年(61)

2010年(26)

2009年(27)

2008年(21)

2007年(49)

分类: LINUX

2007-09-18 23:27:29

对于网卡驱动的移植,最好还是懂得一些网卡和网络的知识为好。想要速成的话,我极力推荐您看看zcx3000的专栏他的关于RTL8019的文章总结得很好,使我受益匪浅。感谢zcx3000!!!

URL:http://blog.csdn.net/zcx3000/category/237774.aspx


六、博创2410S所配网卡AX88796NE2000兼容网卡)驱动的移植。

    1)修改arch/arm/目录下的Kconfig文件,增加ISA总线支持,使其在make menuconfig 时出现NE2000的网卡配置选项。

    config ARCH_S3C2410

    bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"

    select GENERIC_GPIO

    select ISA

    help

      Samsung S3C2410X CPU based systems, such as the Simtec Electronics

      BAST (<), the IPAQ 1940 or

      the Samsung SMDK2410 development board (and derivatives).

 

    2)修改include/asm-arm/arch-s3c2410文件夹下的map.h文件。加入AX88796的地址映射。

    /***************tekkaman****************************/

    #define S3C2410_VA_ISA_NET   S3C2410_ADDR(0x02100000)

    #define S3C2410_PA_ISA_NET   __phys_to_pfn(0x10000000)

    #define S3C2410_SZ_ISA_NET   SZ_1M

    /**********************tekkaman********************/

    说明:

    a、根据网上的资料,“#define S3C2410_VA_ISA_NET   S3C2410_ADDR(0x02100000)”的地址可以自己修改,只要不和别的虚拟地址冲突就行。我有试过将起改成“#define S3C2410_VA_ISA_NET   (0xd1000000)”,也就是博创的2.4.18的定义,也可以正常启动。

    b“#define S3C2410_PA_ISA_NET   __phys_to_pfn(0x10000000)”这句困扰了我很久。一开始我的定义是“#define S3C2410_PA_ISA_NET   (0x10000000)”,所以启动后系统就死在了网卡的初始化上,出现Unable to handle kernel paging request at virtual address 的错误。后来我上网查找资料,才知道:原来实地址与虚地址的映射结构 smdk2410_iodesc 里有所变化。第二个参数从原来的 unsigned long physical 变为 unsigned long pfn (Page Frame Number 页帧号)。而从 smdk2410_iodesc 传入的S3C2410_PA_ISA_NET 仍然是一个 physical 值,因此出现以上的错误。只要在物理地址前加上__phys_to_pfn就可以解决这个问题。较详细的讲解请看我的参考资料

【置顶】移植Linux2.6.22.2到博创2410-S(s3c2410A)(1)前面有链接地址)。

   

    3)修改arch/arm/mach-s3c2410文件夹下的mach-smdk2410.c文件。在smdk2410_iodesc 中加入AX88796的地址信息。

     static struct map_desc smdk2410_iodesc[] __initdata = {

  /* nothing here yet */

     {

                .virtual        = S3C2410_VA_ISA_NET,

                .pfn          = S3C2410_PA_ISA_NET,

                .length        = S3C2410_SZ_ISA_NET,

                .type          = MT_DEVICE,

        }

};

    以下修改为选做,可以不改:

     随便在这里取消LCD的初始化,不然启动时会有出错信息(因为我现在的项目用不到,以后有空我会添上LCD的移植和GUI的移植):

static struct platform_device *smdk2410_devices[] __initdata = {

     &s3c_device_usb,

//   &s3c_device_lcd,

     &s3c_device_wdt,

     &s3c_device_i2c,

     &s3c_device_iis,

};

     修改开发板的名称(可以自定义):

     MACHINE_START(SMDK2410, "Tekkaman2410")

 

     4)修改网卡驱动的主要文件drivers/net/ne.c

     a、添加头文件和定义

#include

#include

//**********************tekkaman*************************

#include

#include

#include

#include

#include

#include

 

#define AX88796_BASE   (vAX88796_BASE+0x200)

#define AX88796_IRQ    IRQ_EINT2

#define pAX88796_BASE    S3C2410_PA_ISA_NET

#define vAX88796_BASE    S3C2410_VA_ISA_NET

#define EXTINT_OFF  (IRQ_EINT4 - 4)

 

//**********************tekkaman*****************************

......

     static struct { const char *name8, *name16; unsigned char SAprefix[4];}

bad_clone_list[] __initdata 中增加AX88796 MAC地址前三位(不一定需要):

         {"AX88796", "NE2000-compatible", {0x08, 0x08, 0x08}},

 

     b、确保定义总线宽度为16位。

    

#if defined(CONFIG_PLAT_MAPPI)

#  define DCR_VAL 0x4b

#elif defined(CONFIG_PLAT_OAKS32R)  || \

   defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)

#  define DCR_VAL 0x48      /* 8-bit mode */

#else

#  define DCR_VAL 0x49

#endif

     修改为

#if 0

#if defined(CONFIG_PLAT_MAPPI)

#  define DCR_VAL 0x4b

#elif defined(CONFIG_PLAT_OAKS32R)  || \

   defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)

#  define DCR_VAL 0x48      /* 8-bit mode */

#else

#endif

#endif

#  define DCR_VAL 0x49

    

     c、在do_ne_probe函数中增加配置总线参数、基地址和中断的语句(其参数参考 刘淼 的书)

static int __init do_ne_probe(struct net_device *dev)

{

     unsigned long base_addr = dev->base_addr;

#ifdef NEEDS_PORTLIST

     int orig_irq = dev->irq;

#endif

//******************************tekkaman********************************

static int once=0;

     if (once) {

      return -ENXIO;

}

     unsigned int value;

 

value = __raw_readl(S3C2410_BWSCON);

value &= ~(S3C2410_BWSCON_WS2|S3C2410_BWSCON_ST2|S3C2410_BWSCON_DW2_32);

value |= (S3C2410_BWSCON_ST2|S3C2410_BWSCON_DW2_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_BANKCON2);

set_irq_type(AX88796_IRQ,IRQ_TYPE_LEVEL_LOW );

s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);

s3c2410_gpio_pullup(S3C2410_GPF2, 0);

if(base_addr==0){

     dev->base_addr = base_addr = AX88796_BASE ;

  dev->irq = AX88796_IRQ;

  once++;

  }

//***********************************tekkaman************************************

     SET_MODULE_OWNER(dev);

 

     /* First check any supplied i/o locations. User knows best. */

     if (base_addr > 0x1ff) /* Check a single specified location. */

         return ne_probe1(dev, base_addr);

     else if (base_addr != 0)    /* Don't probe at all. */

         return -ENXIO;

......

     d、修改ne_probe1函数

     增加自定义的网卡MAC地址(这个地址可以自行修改,但是MAC也有一定的规则,最重要的是千万不要把它配置为广播或组播地址,请参考网络的相关书籍):

static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)

{

     int i;

     unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman

     unsigned char SA_prom[32];

     int wordlength = 2;

......

     增加网卡MAC地址的配置语句,屏蔽通过EEPROM配置网卡的语句

......

         struct {unsigned char value, offset; } program_seq[] =

         {

              {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/

              {0x48,   EN0_DCFG},    /* Set byte-wide (0x48) access. */

              {0x00,   EN0_RCNTLO},  /* Clear the count regs. */

              {0x00,   EN0_RCNTHI},

              {0x00,   EN0_IMR}, /* Mask completion irq. */

              {0xFF,   EN0_ISR},

              {E8390_RXOFF, EN0_RXCR},    /* 0x20  Set to monitor */

              {E8390_TXOFF, EN0_TXCR},    /* 0x02  and loopback mode. */

              {32, EN0_RCNTLO},

              {0x00,   EN0_RCNTHI},

              {0x00,   EN0_RSARLO},  /* DMA starting at 0x0000. */

              {0x00,   EN0_RSARHI},

              {E8390_RREAD+E8390_START, E8390_CMD},

         };

 

         for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)

              outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);

 

     }

//****************************************tekkaman*********************************

{

 unsigned char *ep;

 ep = (unsigned char * ) &ne_defethaddr[0];

 ne_defethaddr[5]++;

 

 for(i=0;i<6;i++) {

  SA_prom[i] = ep[i];

}

 

 SA_prom[14] = SA_prom[15]=0x57;

 wordlength =2;

}

//****************************************tekkaman*********************************

#if 0    //tekkaman

 

     for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {

         SA_prom[i] = inb(ioaddr + NE_DATAPORT);

         SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);

         if (SA_prom[i] != SA_prom[i+1])

              wordlength = 1;

     }

#endif   //tekkaman

     if (wordlength == 2)

     {

#if 0   //tekkaman

         for (i = 0; i < 16; i++)

              SA_prom[i] = SA_prom[i+i];

 

         /* We must set the 8390 for word mode. */

         outb_p(DCR_VAL, ioaddr + EN0_DCFG);

         start_page = NESM_START_PG;

 

         /*

          * Realtek RTL8019AS datasheet says that the PSTOP register

          * shouldn't exceed 0x60 in 8-bit mode.

          * This chip can be identified by reading the signature from

          * the  remote byte count registers (otherwise write-only)...

          */

         if ((DCR_VAL & 0x01) == 0 &&         /* 8-bit mode */

             inb(ioaddr + EN0_RCNTLO) == 0x50 &&

             inb(ioaddr + EN0_RCNTHI) == 0x70)

              stop_page = 0x60;

         else

              stop_page = NESM_STOP_PG;

#endif   //tekkaman

         outb_p(0x49, ioaddr + EN0_DCFG);

         start_page = NESM_START_PG;

         stop_page = NESM_STOP_PG;

 

     } else {

         start_page = NE1SM_START_PG;

         stop_page  = NE1SM_STOP_PG;

     }

......

     屏蔽自定检测中断号的语句(参考 刘淼 的书)

 

......

#if 0  //tekkaman

     if (dev->irq < 2)

     {

         unsigned long cookie = probe_irq_on();

         outb_p(0x50, ioaddr + EN0_IMR);  /* Enable one interrupt. */

         outb_p(0x00, ioaddr + EN0_RCNTLO);

         outb_p(0x00, ioaddr + EN0_RCNTHI);

         outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */

         mdelay(10);        /* wait 10ms for interrupt to propagate */

         outb_p(0x00, ioaddr + EN0_IMR);      /* Mask it again. */

         dev->irq = probe_irq_off(cookie);

         if (ei_debug > 2)

              printk(" autoirq is %d\n", dev->irq);

     } else if (dev->irq == 2)

         /* Fixup for users that don't know that IRQ 2 is really IRQ 9,

            or don't know which one to set. */

         dev->irq = 9;

#endif   //tekkaman

     if (! dev->irq) {

         printk(" failed to detect IRQ line.\n");

         ret = -EAGAIN;

         goto err_out;

     }

    

    AX88697的移植到此结束!

待续:【置顶】移植Linux2.6.22.2到博创2410-S(s3c2410A)(3)

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