天天看點

cs8900 移植 Linux-2.6.19.2

移植路上真是荊棘滿路,時不時讓你瘋狂一兩天,卻無可奈何...

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>

繼續閱讀