NE2000兼容网卡Linux 2.6驱动移植(AX88796)

来源:互联网 发布:典韦怎么玩 知乎 编辑:程序博客网 时间:2024/05/19 04:02
  
NE2000兼容网卡移植(AX88796)
Ø        定义网卡I/O地址
在S3C2410平台关于内存地址映射的头文件中增加对网卡的支持。
#vi $KERNEL/include/asm-arm/arch-s3c2410/map.h
添加代码:
       #define pAX88796_BASE    (0x10000000) //physical base address
#define vAX88796_BASE    (0xd1000000) //virtual base address
#define AX88796_BASE      (vAX88796_BASE + 0x200) //bank2 base address
Ø        地址映射
将之前定义的网卡物理I/O地址和虚拟I/O地址间的映射关系注册到平台初始化文件中。
#vi $KERNEL/arch/arm/mach-s3c2410/mach-smdk2410.c
修改:
              static struct map_desc smdk2410_iodesc[] __initdata = {
                     //添加如下映射关系
                     //{虚拟地址, 物理地址, 地址空间大小, 设备类型}
{vAX88796_BASE, pAX88796_BASE, SZ_1M, MT_DEVICE},
};
Ø        修改NE2000驱动文件
(基于Uptech 2410-s平台,其使用的是NE2000兼容的AX88796芯片)
#vi $KERNEL/drivers/net/ne.c
添加头文件:
              #include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/map.h>
       修改驱动:
              //根据开发板上网卡和S3C2410的连接,确定外部中断
              #define IRQ_NE2000 IRQ_EINT2
             
              //定义网卡MAC地址
unsigned char ne_defethaddr[] = { 0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01 };
 
//确保总线宽度为16位
#if 0
#if defined(CONFIG_PLAT_MAPPI)
# define DCR_VAL 0x4b
#elif defined(CONFIG_PLAT_OAKS32R)
# define DCR_VAL 0x48    //8-bit
#else
# define DCR_VAL 0x49 //16-bit
#endif
#endif
 
#define DCR_VAL 0x49
 
/*** 这里的代码主要参考THREEWATER的文章 ***/
 
/*
NE2000网卡的初始化代码在do_ne_probe函数中,在该函数调用时,网卡设备的基地址空间、寄存器、中断等资源都未指定,所以在这里为该平台进行资源分配。
*/
#ifndef MODULE
int orig_irq = dev->irq;
#endif
//添加如下代码
static int once = 0;
unsigned int value = 0;
if(once)
{
       return -ENXIO;
}
//设置BWSCON寄存器:Bus Width & Wait Control Register
//这里AX88796在BANK2空间,设置BANK2的16-bit总线和停止状态等信息
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_ST2
| S3C2410_BWSCON_WS2 | S3C2410_BWSCON_DW2_32);
value |= (S3C2410_BWSCON_ST2 | S3C2410_BWSCON_DW2_16);
printk(KERN_INFO"s3c2410_bwscon value %x/n", value);
__raw_writel(value, S3C2410_BWSCON);
 
value = 0;
//设置BANKCON寄存器:Bank Control Register
//设置AX88796所在BANK2空间的时序信息
value = S3C2410_BANKCON_Tacs4
| S3C2410_BANKCON_Tcos4 | S3C2410_BANKCON_Tacc14
| S3C2410_BANKCON_Tcoh4 | S3C2410_BANKCON_Tcah4
| S3C2410_BANKCON_Tacp6 | S3C2410_BANKCON_PMCnorm;
printk(KERN_INFO"s3c2410_bankcon2 value %x/n", value);
__raw_writel(value, S3C2410_BANKCON2);
 
//设置AX88796的中断触发方式为低电平有效
set_irq_type(IRQ_NE2000, IRQT_LOW);
printk(KERN_INFO"ax88796 extIRQ = %x, IRQtype= %x/n",
IRQ_NE2000, IRQT_LOW);
s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);
s3c2410_gpio_pullup(S3C2410_GPF2, 0);
 
//指定AX88796的基地址空间和使用的中断号
if(base_addr == 0)
{
       dev->base_addr = base_addr = AX88796_BASE;
       dev->irq = IRQ_NE2000;
       once++;
}
 
/*
网卡的主要检测工作在ne_probe1函数中完成,其中最主要的是读取和配置网卡的MAC地址等信息。这里对AX88796的MAC地址的设置和典型的网卡不同。一般的网卡通过读取连接在NE2000网卡上的EEPROM的代码,而现在的平台并没有使用配置存储器,所以需要修改ne_probe1函数,设置网卡的MAC地址。
*/
{
       ……
       for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
                     outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
 
}
//添加并修改如下代码
{
       //设置MAC地址
       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;
}
//取消读取EEPROM的代码
#if 0
       for(i = 0; i < 32; 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
 
if (wordlength == 2)
{
#if 0
       for (i = 0; i < 16; i++)
              SA_prom[i] = SA_prom[i+i];
#endif
……
#if 0
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
Ø        开启内核对NE2000兼容网卡的支持
#vi arch/arm/Kconfig
//修改如下代码
config ISA
       bool "ISA support"
       default y
       help
Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff inside your box. Other bus systems are PCI, EISA, MicroChannel (MCA) or VESA. ISA is an older system, now being displaced by PCI; newer boards don't support it. If you have ISA, say Y, otherwise N.
       只有开启了ISA设备支持,在配置内核时,才会在Network device support中出现对于NE2000兼容网卡的支持选项。
Ø        问题解答
(1)       Kernel panic:很有可能是没有做虚拟地址到物理地址的映射,内核在访问虚拟地址的时候,找不到对应的物理地址入口。
(2)       eth0: interrupt from stopped card:看上去是中断问题,但我在移植过程中发现是网卡的虚拟地址设置错误,导致内核访问到了其它不存在的外设上。
(3)       NETDEV WATCHDOG: eth0: transmit timed out:出现这个错误的情况很复杂,我移植的时候碰到过两次,第一次是BANK空间的地址总线没有设置,默认是8bit,应该设成16bit;第二次是网络物理连接故障。出现这些错误,假如不知道如何入手的话,可以在windows下使用sniffer pro进行抓包分析。
原创粉丝点击