移植路上真是荊棘滿路,時不時讓你瘋狂一兩天,卻無可奈何...
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
int set_irq_type(unsigned int irq, unsigned int type);
而網上的那個cs8900.c驅動比較老,與Linux-2.6.19.2帶的cs89x0相差很大(據說這個驅動也沒有使用新的驅動模型,不知道,這裡應該與dm9000比較一下)。導緻出現很多錯誤,不能編譯 cs8900.c ,一天就這樣在郁悶中過去...
cs89x0:cs89x0_probe(0x0)
Unable to handle kernel paging request at virtual address f400030a
pgd = c0004000
[f400030a] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in:
CPU: 0
PC is at readword+0x1c/0x2c
LR is at cs89x0_probe1+0xec/0x874
pc : [] lr : [] Not tainted
sp : c032feb0 ip : c032fec0 fp : c032febc
r10: f4000300 r9 : 00000000 r8 : 00000000
r7 : c0f3b800 r6 : c0f3ba60 r5 : c0f3b800 r4 : f4000300
r3 : f400030a r2 : 00000000 r1 : f400030a r0 : f4000300
Flags: NzCv IRQs on FIQs on Mode SVC_32 Segment kernel
Control: 717F
Table: 30004000 DAC: 00000017
Process swapper (pid: 1, stack limit = 0xc032e250)
Stack: (0xc032feb0 to 0xc0330000)
fea0: c032ff4c c032fec0 c001bec8 c0139fa8
fec0: ffffffff c0f3b803 0000000a c032ff4c ffffffff 00000002 c0f3b800 ffffffff
fee0: c032ff30 c032fef0 c00fa694 c00f9e88 0000000a ffffffff ffffffff 00000002
ff00: 3f0c47ff 00000000 c0f3b800 00000000 00000000 00000000 00000000 c0021290
ff20: c032ff3c c002619c c0f3b800 00000000 00000000 00000000 00000000 c0021290
ff40: c032ff6c c032ff50 c001c6e0 c001bdec c0026164 00000001 00000000 c00217a4
ff60: c032ff88 c032ff70 c001bb04 c001c660 00000001 00000000 c032e000 c032ffa0
ff80: c032ff8c c001bbd0 c001bad0 00000000 c0021208 c032fff4 c032ffa4 c0027100
ffa0: c001bb48 00000001 c0027e24 c003caf4 00000000 00000000 c0027058 c0043128
ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
ffe0: 00000000 00000000 00000000 c032fff8 c0043128 c0027068 0a00003e e5dc3001
Backtrace:
[] (readword+0x0/0x2c) from [] (cs89x0_probe1+0xec/0x874)
[] (cs89x0_probe1+0x0/0x874) from [] (cs89x0_probe+0x90/0x1)
[] (cs89x0_probe+0x0/0x108) from [] (probe_list2+0x44/0x78)
r7 = C00217A4 r6 = 00000000 r5 = 00000001 r4 = C0026164
[] (probe_list2+0x0/0x78) from [] (net_olddevs_init+0x98/0x)
r6 = C032E000 r5 = 00000000 r4 = 00000001
[] (net_olddevs_init+0x0/0xdc) from [] (init+0xa8/0x274)
r5 = C0021208 r4 = 00000000
[] (init+0x0/0x274) from [] (do_exit+0x0/0x7d8)
Code: e0801001 e3510201 e1a03001 328334f2 (e1d300b0)
Kernel panic - not syncing: Attempted to kill init!
#ifndef __ASM_ARCH_SMDK2410_H
#define __ASM_ARCH_SMDK2410_H
#define SMDK2410_PA_CS8900A_BASE __phys_to_pfn(S3C2410_CS3 + 0x01000000) /* nGCS3 +0x01000000 */
#define SMDK2410_VA_CS8900A_BASE S3C2410_ADDR(0x04000000) /* 0xF4000000 */
#endif /* __ASM_ARCH_SMDK2410_H */
虛位址改多少無所謂,如0xE0000000,隻要不和其它裝置沖突就行。
下面總結一下整個移植過程:
1. include/asm-arm/arch-s3c2410/map.h
添加:
/* CS8900 */
#define S3C24XX_VA_CS8900 S3C2410_ADDR(0x04000000)
#define S3C2410_PA_CS8900 __phys_to_pfn(0x19000000)
#define S3C24XX_SZ_CS8900 SZ_1M
#define S3C24XX_PA_CS8900 S3C2410_PA_CS8900
2. arch/arm/mach-s3c2410/mach-smdk2410.c
修改
static struct map_desc smdk2410_iodesc[] __initdata={
{S3C24XX_VA_CS8900IO, S3C2410_PA_CS8900, S3C24XX_SZ_CS8900, S3C24XX_SZ_CS8900, MT_DEVICE}
};
3. include/asm-arm/irq.h
添加
4. drivers/net/cs89x0.c
下面是我的 diff
--- ../linux2/linux-2.6.19.2/drivers/net/cs89x0.c 2007-01-11 03:10:37.000000000 +0800
+++ drivers/net/cs89x0.c 2007-02-04 21:16:42.000000000 +0800
@@ -96,6 +96,9 @@
: PNX010X platform support
+ : SMDK2410 platform support, fixed bug with signed ioaddr
+
*/
/* Always include 'config.h' first in case the user wants to turn on
@@ -194,6 +197,27 @@
#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};
+#elif defined(CONFIG_ARCH_S3C2410) //Added weibing
+#include
+static unsigned int netcard_portlist[] __initdata = {S3C24XX_VA_CS8900+0x300, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_EINT9, 0, 0, 0};
+/*
+#ifdef request_region
+#undef request_region
+#endif
+#ifdef release_region
+#undef release_region
+#define request_region(a,s,n) request_mem_region(a,s,n)
+#define release_region(a,s) release_mem_region(a,s)
+*/
#else
static unsigned int netcard_portlist[] __initdata =
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -246,7 +270,7 @@
/* Index to functions, as function prototypes. */
-static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
+static int cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular);
static int net_open(struct net_device *dev);
static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t net_interrupt(int irq, void *dev_id);
@@ -324,6 +348,10 @@
io = dev->base_addr;
irq = dev->irq;
+#ifdef CONFIG_ARCH_S3C2410 //Added weibing
+ __raw_writel((__raw_readl(S3C2410_GPGCON)&~(0x3+ __raw_writel((__raw_readl(S3C2410_EXTINT1)&~(0x7+#endif
if (net_debug)
printk("cs89x0:cs89x0_probe(0x%x)\n", io);
@@ -386,6 +414,18 @@
{
outw(value, base_addr + (portno }
+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);
static u16
readword(unsigned long base_addr, int portno)
@@ -507,7 +547,7 @@
*/
static int __init
-cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
+cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular)
struct net_local *lp = netdev_priv(dev);
static unsigned version_printed;
@@ -638,7 +678,18 @@
the driver will always do *something* instead of complain that
adapter_cnf is 0. */
-#ifdef CONFIG_SH_HICOSH4
+#if defined CONFIG_ARCH_S3C2410
+ lp->force=FORCE_RJ45;
+ lp->auto_neg_cnf=IMM_BIT;
+ dev->dev_addr[0]=0x09; /*setMACaddress*/
+ dev->dev_addr[1]=0x90;
+ dev->dev_addr[2]=0x99;
+ dev->dev_addr[3]=0x09;
+ dev->dev_addr[4]=0x90;
+ dev->dev_addr[5]=0x99;
+#elif defined CONFIG_SH_HICOSH4
if (1) {
/* For the HiCO.SH4 board, things are different: we don't
have EEPROM, but there is some data in flash, so we go
@@ -1036,7 +1087,7 @@
#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
- int ioaddr = dev->base_addr;
+ unsigned int ioaddr = dev->base_addr;
#endif
int reset_start_time;
@@ -1278,7 +1329,7 @@
int i;
int ret;
-#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */
+#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410) /* uses irq#1, so this won't work */
if (dev->irq /* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
@@ -1309,7 +1360,7 @@
else
{
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
+#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);
@@ -1324,6 +1375,9 @@
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
write_irq(dev, lp->chip_type, dev->irq);
+#if defined(CONFIG_ARCH_S3C2410)
+ set_irq_type(dev->irq, IRQT_RISING);
ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);
if (ret) {
if (net_debug)
@@ -1394,7 +1448,7 @@
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);
}
-#ifdef CONFIG_ARCH_PNX010X
+#if defined(CONFIG_ARCH_PNX0105) || defined(CONFIG_ARCH_S3C2410)
result = A_CNF_10B_T;
if (!result) {
@@ -1577,7 +1631,8 @@
struct net_device *dev = dev_id;
struct net_local *lp;
- int ioaddr, status;
+ unsigned int ioaddr;
+ int status;
int handled = 0;
ioaddr = dev->base_addr;
@@ -1683,7 +1738,7 @@
struct sk_buff *skb;
int status, length;
status = readword(ioaddr, RX_FRAME_PORT);
length = readword(ioaddr, RX_FRAME_PORT);
5.重新編譯,重新啟動,重新happy...
好了,現在可以挂NFS了,玩玩去...
...... ......
現在又有一不像問題的問題,網卡工作正常,但啟動是提示申請 io 注冊失敗,request_region(0xf4000300, 0x10) failed 。
cs89x0.c: v2.4.3-pre1 Russell Nelson [email protected]>, 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 09:90:99:09:90:99
cs89x0_probe1() successful
cs89x0: request_region(0xf4000300, 0x10) failed
cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP
更改虛位址也無效,追蹤一下,在 kernel/resource.c 裡出現問題。不知為什麼資源沖突了,我看網上移植cs8900到2.4版也有這個問題...不理,先向下跳,回過頭來在處理它...
<a href="http://www.gelato.unsw.edu.au/lxr/source/kernel/resource.c#L445">445</a>
<a href="http://www.gelato.unsw.edu.au/lxr/source/kernel/resource.c#L454">454</a>