移植cs8900a驱动
参考资料
<设备驱动程序>>
<设备驱动开发详解>>
http://weibing.blogbus.com/logs/4467465.html
http://blog.chinaunix.net/u1/34474/showart_400516.html
感谢这些高手的分享~
PS:2.6.18的源码包,直接在源码包自带的drivers/net目录下的cs89x0.c基础上修改!
修改/drivers/net/目录下的Kconfig,Cs89x0.c cs89xo.h 而不是修改/drivers/net/arm/目录下的Kconfig,因为就是因为这个小失误困扰了我很久,难怪明明编译进了内核,怎么一点调试信息都没打印出来呢,郁闷阿呵呵,都怪自己粗心!
cs8900中一些读写的函数
static u16
readword(unsigned long base_addr, int portno)
{
return inw(base_addr + portno);
}
unsigned inw(unsigned port);,读取一个16位的数据
static void
writeword(unsigned long base_addr, int portno, u16 value)
{
outw(value, base_addr + portno);
}
void outw(unsigned short word,unsigned port);
static void
readwords(unsigned long base_addr, int portno, void *buf, int length)
{
u8 *buf8 = (u8 *)buf;//强制指针类型转变,将void转为int
do {
u16 tmp16;
tmp16 = readword(base_addr, portno);
*buf8++ = (u8)tmp16;
*buf8++ = (u8)(tmp16 >> 8);
} while (--length);
}
移植步骤
1 drivers/net目录下的cs89x0.c cs89x0.h两个文件,
其中在cs89x0.h头文件的前面加入#define CONFIG_ARCH_SMDK2410 1 //tangcc
cs89x0.c 这个文件具体如何修改,参见上传的源码包
cs8900压缩包
2 #include ,具体如何修改这个文件
....
/* memory controller registers */
/*CS8900 2009nian5yue5*/
#define pCS8900_BASE __phys_to_pfn(0x19000300)//将smdk2410_iodesc接收到的物理地址转换为map_desc能识别的pfn
#define vCS8900_BASE S3C2410_ADDR(0x04000000)//映射虚拟地址,虚拟地址0xF4000000
#define S3C24XX_SZ_CS8900 SZ_1M
为什么要定义pCS8900_BASE为__phys_to_pfn(0x19000300)
pCS8900_BASE
3 linux/arch/arm/mach-s3c2410/mach-smdk2410.c
这个文件的改动较多,包括了添加地址映射和cs8900的设备信息等等
有几个重要的文件,我们首先要了解~
(1)include/linux目录下的platform_device.h文件,有一段这样的代码
struct platform_device {
const char * name;
u32 id;
struct device dev;
u32 num_resources;
struct resource * resource;
};
我们需要利用到platform_device结构体来添加cs8900的设备信息。
(2)include/asm/mach/map.h,这个文件定义了map_desc结构体,
struct map_desc {
unsigned long virtual;
unsigned long pfn; 这里有变化,以前是unsigned long physical
unsigned long length;
unsigned int type;
};
#define MT_DEVICE 0
我们要注意的是map_desc结构体的变化。以前的是unsigned long physical,也就是物理地址的意思,但现在变成了unsigned long pfn既页桢地址了,也就是物理地址要右移12位,即要传递给map_desc结构体的必须是页桢地址,而不再是以前的物理地址。
前面定义到的define pCS8900_BASE __phys_to_pfn(0x19000300),__phys_to_pfn宏就是完成了物理地址到页桢地址的转换,在include/asm-arm/memory.h中定义到了
/*
* Convert a physical address to a Page Frame Number and back
*/
#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
阅读了上面的结构体代码以后,这样我们再修改代码就糊里糊涂的了呵呵
打开linux/arch/arm/mach-s3c2410/mach-smdk2410.c
在smdk2410_iodesc[]数组内加入
static struct map_desc smdk2410_iodesc[] __initdata = {
{vCS8900_BASE,pCS8900_BASE,SZ_1M,MT_DEVICE} 注意这里的中括号是要添加的
};
将pCS8900_BASE(已经转换成页桢的形式了)的值映射到vCS8900_BASE的虚拟地址空间去。前面已经提到了smdk2410_iodesc[]接收到的还是物理地址,但map_desc结构体需要的是物理地址的页桢地址,需要通过__phys_to_pfn转换
另外还要添加cs8900的设备信息,设备信息代码照理应该添加在linux/arch/arm/mach-s3c2410/devs.c文件中,添加在devs.c文件中行不行我还没试过。但我参照网上的资料添加直接添加在mach_smdk2410.c文件中了。
/*添加 CS8900的资源信息 */
static struct resource s3c_cs89x0_resources[] = {
[0] = {
.start = 0x19000300,
.end = 0x19000300 + 16,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_EINT9,
.end = IRQ_EINT9,
.flags = IORESOURCE_IRQ,
},
};
// 添加设备信息
static struct platform_device s3c_cs89x0 = {
.name = "cirrus-cs89x0",
.num_resources = ARRAY_SIZE(s3c_cs89x0_resources),
.resource = s3c_cs89x0_resources, 参照源码,上面说明了可以不定义.dev结构
};
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_cs8900,//2009-5-10
};
这个文件修改到此结束。
4 修改/drivers/net/Kconfig文件
config CS89x0
tristate "CS89x0 support"
---help---
depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X) 将这条语句移到了---help---下面,相当于去掉了这个条件
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.
5 进行配置
make menuconfig
出现配置界面进行配置:
选中如下的选项:
Device drivers ---->
Network device support --->
[*] Ethernet (10 or 100Mbit)
<*> Generic Media Independent Interface device support
< > SMC 91C9x/91C1xxx support
< > DM9000 support
<*> CS89x0 support 将cs8900编译到内核
[ ] Pocket and portable adapters
做成镜像形式,用tftp 下载并bootm,终于出现了cs89x0的信息
可以检测到cs8900了不过好像有点出错信息
loop: loaded (max 8 devices)
cs89x0:cs89x0_probe(0x0)
cs89x0.c: v2.4.3-pre1 Russell Nelson , Andrew Morton
eth0: cs8900 rev K found at 0xf4000300
cs89x0: Extended EEPROM checksum bad and no Cirrus EEPROM, relying on command le
cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 00:0c:29:fd:0b:13
cs89x0_probe1() successful
cs89x0:cs89x0_probe(0x0)
cs89x0: request_region(0xf4000300, 0x10) failed
可以在cs89x0_probe1里加个静态变量,第一次时置1,以后直接返回。待会看看
cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP
申请中断I/O区域失败。但是ping 和ifconfig命令都可以用了。
挂载NFS时出错了,提示protocol 不对,经过检查,原来是我内核配置时没有选上呵呵,
│<*> NFS file system support │ │
│ │[*] Provide NFSv3 client support │ │
│ │[*] Provide client support for the NFSv3 ACL protocol extension │ │
│ │[*] Provide NFSv4 client support (EXPERIMENTAL) │ │
│ │[*] Allow direct I/O on NFS files (EXPERIMENTAL)
全都选上以后,再挂载,虽然有一些RPC什么的出错,但还是挂载上了汗。网卡驱动马马虎虎的移植成功了哈哈