网上关于最新内核移植相关的文章几乎找不到。最新的似乎只有“友善之臂”针对mini2440移植2.6.32.2文档,不能照搬在俺的杂牌板上。特意下载了最新的稳定版本的内核linux-2.6.36,在俺的s3c2440开发板上试试。其中用到了”友善之臂“提供的编译器:
ARM-Linux GCC 4.3.2和根文件系统:Rootfs-Qtopia-Qt4。下面是过程的大概。
1.解压进入原码顶层目录linux-2.6.36,修改Makefile文件
"ARCH ?= arm"
"CROSS_COMPILE ?= /usr/local/arm/4.3.2/bin/arm-linux-"
2. 将原有的arch/arm/mach-s3c2440/mach-mini2440.c删除,将arch/arm/mach-s3c2440/mach- smdk2440.c复制一份,命名为mach-mini2440.c,放在相同的目录下。修改三处mach-mini2440.c的内容先:
1>MACHINE_START(S3C2440, "SMDK2440") ==> MACHINE_START(MINI2440, "MINI2440")
2>s3c24xx_init_clocks(16934400) ==> s3c24xx_init_clocks(12000000)
3>将"smdk_machine_init();"注释掉,否则链接会报错.
3.修改机器码:将”arch/arm/tools/mach-types“文件中的mini2440相关的机器码改成自己的开发板的机器码,俺的改成:“mini2440 MACH_MINI2440 MINI2440 5244”
4make mini2440_defconfig;make;ok可以启动试一下了。由于不同于mini2440开发板,硬件配置不同,启动后错误很多。搭建开发环境,先不理它。
开发环境必须的网卡驱动。”友善之臂“的mini2440开发板用的是DM9000的网卡,俺的开发板用的是cs8900的网卡。只能“google+自力更生”了。
5.将准备好的cs8900.c/cs8900.h两个文件复制到drivers/net/arm目录下
6.在include/net/目录下创建文件smdk2410.h,并添加如下代码:
#define pSMDK2410_ETH_IO __phys_to_pfn(0x19000000)
#define vSMDK2410_ETH_IO 0xE0000000
#define SMDK2410_EHT_IRQ IRQ_EINT9
7.在arch/arm/mach-s3c2440/mach-mini2440.c中加入"include <net/smdk2410.h>"
在struct map_desc smdk2440_iodesc[]中添加cs8900相应的io空间映射:
{vSMDK2410_ETH_IO, pSMDK2410_ETH_IO, SZ_1M, MT_DEVICE}
8.在drivers/net/arm/目录下的Makefile中加入cs8900相关项:
obj-$(CONFIG_ARM_CS8900) += cs8900.o
在drivers/net/arm/目录下的Kconfig中加入cs8900相关项:
config ARM_CS8900
tristate "CS8900 support"
depends on NET_ETHERNET && ARM && (ARCH_SMDK2410 || ARCH_ZL2440 || MACH_MINI2440)
help
Support for CS8900A chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto> as well as <file:Documentation/networking/cs89x0.txt>.
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module will be called
8.make menuconfig选中cs8900选项,去掉dm9000选项。
9.make 之后可以启动了。
下面说一下内核中网卡和cs8900驱动相关的话题:
由于内核更新后,struct net_device结构体及相关宏定义有变化,或造成在2.6.16/2.6.22/2.6.24内核工作的cs8900驱动在2.6.36上不能编译通过。主要修改如下:
1>"IRQT_RISING"改成"IRQ_TYPE_EDGE_RISING"
2>2.6.36内核的net_device中没有“priv“和"mc_list"项”。代码都要作相应修改。
3>以前内核(2.6.16/2.6.22/2.6.24)struct net_device中的函数指针域在2.6.36中都放在struct net_device_ops类型的指针netdev_ops指向的结构体中。也要作相应修改。
附件是修改后的cs8900.c和cs8900.h文件。
文件传不上来。贴上吧。
下面是cs8900.c文件:
#define VERSION_STRING "Cirrus Logic CS8900A driver for Linux (Modified for ZL2440)"
#include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> #include <linux/version.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/ioport.h> #include <linux/pm.h> #include <linux/irq.h> //#include <asm/hardware.h>
#include <asm/io.h> #include <asm/uaccess.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h>
// Added BSt
#include <asm/mach-types.h>
//#ifdef CONFIG_ARCH_SMDK2410
#if 1 //#include "asm/arch-s3c2410/regs-irq.h"
#include "mach/regs-mem.h" //#include "asm/arch/smdk2410.h"
#include "net/smdk2410.h"
#endif
#include "cs8900.h"
//#define FULL_DUPLEX
//#define DEBUG
typedef struct { struct net_device_stats stats; u16 txlen; int char_devnum;
spinlock_t lock; } cs8900_t;
int cs8900_probe (struct net_device *dev); static struct net_device *cs8900_dev ;
#define MAX_EEPROM_SIZE 256
static inline u16 cs8900_read (struct net_device *dev,u16 reg) { outw (reg,dev->base_addr + PP_Address); return (inw (dev->base_addr + PP_Data)); }
static inline void cs8900_write (struct net_device *dev,u16 reg,u16 value) { outw (reg,dev->base_addr + PP_Address); outw (value,dev->base_addr + PP_Data); }
static inline void cs8900_set (struct net_device *dev,u16 reg,u16 value) { cs8900_write (dev,reg,cs8900_read (dev,reg) | value); }
static inline void cs8900_clear (struct net_device *dev,u16 reg,u16 value) { cs8900_write (dev,reg,cs8900_read (dev,reg) & ~value); }
static inline void cs8900_frame_read (struct net_device *dev,struct sk_buff *skb,u16 length) { insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2); }
static inline void cs8900_frame_write (struct net_device *dev,struct sk_buff *skb) { outsw (dev->base_addr,skb->data,(skb->len + 1) / 2); }
#ifdef DEBUG static inline int printable (int c) { return ((c >= 32 && c <= 126) || (c >= 174 && c <= 223) || (c >= 242 && c <= 243) || (c >= 252 && c <= 253)); }
static void dump16 (struct net_device *dev,const u8 *s,size_t len) { int i; char str[128];
if (!len) return;
*str = " ";
for (i = 0; i < len; i++) { if (i && !(i % 4)) strcat (str," "); |